rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | # |
| 3 | # Copyright Statement: |
| 4 | # -------------------- |
| 5 | # This software is protected by Copyright and the information contained |
| 6 | # herein is confidential. The software may not be copied and the information |
| 7 | # contained herein may not be used or disclosed except with the written |
| 8 | # permission of MediaTek Inc. (C) 2018 |
| 9 | # |
| 10 | # BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| 11 | # THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| 12 | # RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON |
| 13 | # AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| 14 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| 15 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| 16 | # NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| 17 | # SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| 18 | # SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH |
| 19 | # THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO |
| 20 | # NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S |
| 21 | # SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. |
| 22 | # |
| 23 | # BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE |
| 24 | # LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| 25 | # AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| 26 | # OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO |
| 27 | # MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| 28 | # |
| 29 | # THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE |
| 30 | # WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF |
| 31 | # LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND |
| 32 | # RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER |
| 33 | # THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). |
| 34 | # |
| 35 | #***************************************************************************** |
| 36 | #* |
| 37 | #* Filename: |
| 38 | #* --------- |
| 39 | #* AutoAdjustInputSection.pl |
| 40 | #* |
| 41 | #* Project: |
| 42 | #* -------- |
| 43 | #* |
| 44 | #* |
| 45 | #* Description: |
| 46 | #* ------------ |
| 47 | #* This scripts is used to parse the configuration of Auto-Placement symbols with order. |
| 48 | #* |
| 49 | #* Author: |
| 50 | #* ------- |
| 51 | #* Frank Hu (mtk12175) |
| 52 | #* |
| 53 | #****************************************************************************/ |
| 54 | |
| 55 | use strict; |
| 56 | use warnings; |
| 57 | |
| 58 | BEGIN { push @INC , './tools/' } # add additional library path |
| 59 | use FileInfoParser; |
| 60 | use CommonUtility; |
| 61 | use File::Basename; |
| 62 | use File::Spec; |
| 63 | |
| 64 | package Type; |
| 65 | use constant Log => 0; |
| 66 | use constant Warning => 1; |
| 67 | use constant Fatal => 2; |
| 68 | package main; |
| 69 | |
| 70 | my ($ToolChainBase, $themf, $INFOMAKELOG, $LDSFileName) = (@ARGV); |
| 71 | |
| 72 | &msg_handler(Type::Log, "Input file: $ToolChainBase, $themf, $INFOMAKELOG, $LDSFileName\n"); |
| 73 | my $ConfigfileDir = "./interface/layout/InputSection/"; |
| 74 | if(!-e $ConfigfileDir) { |
| 75 | &msg_handler(Type::Warning, "$ConfigfileDir does not exist, thus ignore this step ..."); |
| 76 | exit 0; |
| 77 | } |
| 78 | |
| 79 | my %MAKEFILE_OPTIONS; |
| 80 | my %CmplOption; |
| 81 | my %RelOption; |
| 82 | |
| 83 | FileInfo::PreProcess($themf, \%MAKEFILE_OPTIONS, $INFOMAKELOG, \%CmplOption, \%RelOption,1); |
| 84 | |
| 85 | my ($Readelf, $AR, $GCC); |
| 86 | my ($Project, $Flavor); |
| 87 | my ($Original_Project, $Original_Flavor); |
| 88 | my ($LibPath1Prefix, $LibPath2Prefix); |
| 89 | my ($tempdir, $tempInputFolder); |
| 90 | |
| 91 | &GetEnvInfo(); |
| 92 | |
| 93 | #record all the config info |
| 94 | my %ConfigInfoHash; |
| 95 | #record all the used lib and obj |
| 96 | my %libObjHash; |
| 97 | #extract the info of all symbols of a .obj |
| 98 | my %SymLogInfoHash; |
| 99 | #extract the info of all sections of a .obj |
| 100 | my %SecLogInfoHash; |
| 101 | #create a link between symbol name and the actual symbol name in .obj |
| 102 | my %SymConvertHash; |
| 103 | #check if duplicated symbols exist between different .ldf files |
| 104 | my %SymCheckCrossFiles; |
| 105 | #check if group name is unique in different lds files |
| 106 | my %SecCheck; |
| 107 | |
| 108 | opendir(DIR, $ConfigfileDir) || &msg_handler(Type::Fatal, "Fail to open $ConfigfileDir: $!", __LINE__); |
| 109 | my @FileList = grep { /\.ldf$/ && -f "$ConfigfileDir/$_" && !/^sample\.ldf$/ } readdir(DIR); |
| 110 | close DIR; |
| 111 | |
| 112 | map { &ParseConfigFile("$ConfigfileDir/$_") } (@FileList); |
| 113 | |
| 114 | &ParseLibObj(); |
| 115 | &CheckUserConfiguration(); |
| 116 | |
| 117 | &UpdateLDS($LDSFileName); |
| 118 | |
| 119 | &CleanTempFiles(); |
| 120 | |
| 121 | exit 0; |
| 122 | |
| 123 | sub GetEnvInfo |
| 124 | { |
| 125 | $AR = File::Spec->rel2abs($ToolChainBase."ar"); |
| 126 | $GCC = $ToolChainBase."gcc"; |
| 127 | $Readelf = File::Spec->rel2abs($ToolChainBase."readelf"); |
| 128 | |
| 129 | &msg_handler(Type::Fatal, "GCC tool does not exist", __LINE__) unless(-e $Readelf and -e $AR and -e $GCC); |
| 130 | |
| 131 | my $RelPath = File::Basename::dirname($INFOMAKELOG); |
| 132 | my $AbsPath = File::Spec->rel2abs($RelPath); |
| 133 | |
| 134 | $Original_Project = $MAKEFILE_OPTIONS{"ORIGINAL_PROJECT_NAME"}; |
| 135 | $Original_Flavor = $MAKEFILE_OPTIONS{"ORIGINAL_FLAVOR"}; |
| 136 | |
| 137 | if($AbsPath =~ m|/mcu/build/(\w+)/(\w+)/|) { |
| 138 | ($Project, $Flavor) = ($1, $2); |
| 139 | } |
| 140 | else { |
| 141 | &msg_handler(Type::Fatal, "Fail to get project and flavor", __LINE__); |
| 142 | } |
| 143 | |
| 144 | ($tempdir) = ($LDSFileName =~ /(.*)custom/); |
| 145 | $tempdir .= "tmp/"; |
| 146 | |
| 147 | $LibPath1Prefix = File::Spec->rel2abs("./mtk_rel/$Original_Project/$Original_Flavor/TARGET/lib/"); |
| 148 | $LibPath2Prefix = File::Spec->rel2abs("./build/$Project/$Flavor/bin/lib/"); |
| 149 | |
| 150 | $tempInputFolder = $tempdir . "CustomInputSection"; |
| 151 | system("rm -rf $tempInputFolder") if(-e $tempInputFolder); |
| 152 | system("mkdir -p $tempInputFolder"); |
| 153 | $? == 0 or &msg_handler(Type::Fatal, "Making $tempInputFolder failed $?", __LINE__); |
| 154 | |
| 155 | my $OptFile = $tempdir."PreProcessOpt.txt"; |
| 156 | my $cmpOpt = undef; |
| 157 | #Gather compiler options |
| 158 | foreach my $key ( keys %CmplOption ) { |
| 159 | next if($key eq lc $key); |
| 160 | if (defined $CmplOption{$key}) { |
| 161 | $cmpOpt .= " -D$key=$CmplOption{$key}"; |
| 162 | } else { |
| 163 | $cmpOpt .= " -D$key"; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | open (FILE, "> $OptFile") or &msg_handler(Type::Fatal, "$OptFile: open file error!", __LINE__); |
| 168 | print FILE $cmpOpt; |
| 169 | close FILE; |
| 170 | } |
| 171 | |
| 172 | sub ParseConfigFile |
| 173 | { |
| 174 | my ($ConfigFile) = (@_); |
| 175 | my $FileName = File::Basename::basename($ConfigFile); |
| 176 | |
| 177 | my $OptFile = $tempdir."PreProcessOpt.txt"; |
| 178 | #Preprocess CustomInputSection.txt |
| 179 | my $cmd = "$GCC -x c -E -undef \@$OptFile $ConfigFile"; |
| 180 | my $output = qx($cmd); |
| 181 | $? == 0 or &msg_handler(Type::Fatal, "$ConfigFile preprosseing failed $?\n$output", __LINE__, $FileName); |
| 182 | |
| 183 | #Tidy preprocessor output |
| 184 | my $tempOutput = undef; |
| 185 | map{ $tempOutput .= $_."\n" if (!($_ =~ /^#/)); } (split /\n/, $output); |
| 186 | |
| 187 | my ($SubSection, $SecName, $PreSecName, $bFlag, $sFlag) = (undef, undef, undef, 0, 0); |
| 188 | my %UniqHash; |
| 189 | my (@TotalSecArray, @TotalSymArray, @SecNameArray); |
| 190 | my $BreakRegExp = "[\\*]{20}\\s[<]\\s(GROUP_CFG_\\w+)\\s[>]\\s[\\*]{20}"; |
| 191 | |
| 192 | #split entire config file into several configuration groups. |
| 193 | foreach my $line (split /\n/, $tempOutput) { |
| 194 | if($bFlag == 0) { |
| 195 | $bFlag = 1 if(($line =~ m/^\[Symbol\]\s+\[Obj\]\s+\[Lib\]$/)); |
| 196 | next; |
| 197 | } |
| 198 | next if($line =~ m/^\s*$/); |
| 199 | |
| 200 | if($line =~ m/^\s*$BreakRegExp\s*$/) { |
| 201 | $SecName = $1; |
| 202 | &msg_handler(Type::Fatal, "$SecName has been deifned in $SecCheck{$SecName}", __LINE__, $FileName) if(exists $SecCheck{$SecName}); |
| 203 | $SecCheck{$SecName} = $FileName; |
| 204 | $sFlag = 1; |
| 205 | if(defined $SubSection) { |
| 206 | push @TotalSecArray, $SubSection; |
| 207 | push @SecNameArray, $PreSecName; |
| 208 | undef $SubSection; |
| 209 | undef $PreSecName; |
| 210 | } |
| 211 | next; |
| 212 | } |
| 213 | $SubSection .= $line."\n" if($sFlag == 1); |
| 214 | $PreSecName = $SecName; |
| 215 | } |
| 216 | push @TotalSecArray, $SubSection if(defined $SubSection); |
| 217 | push @SecNameArray, $PreSecName if(defined $SubSection); |
| 218 | |
| 219 | &msg_handler(Type::Fatal, "The num of section name is not equal to section num", __LINE__, $FileName) if($#TotalSecArray != $#SecNameArray); |
| 220 | for (my $i = 0; $i <= $#TotalSecArray; $i++) { |
| 221 | my @SymArray = (); |
| 222 | my $align; |
| 223 | my @tempArray = split /\n/, $TotalSecArray[$i]; |
| 224 | foreach my $line (@tempArray) { |
| 225 | if($line =~ m/^(\S+)\s+(\S+)\s+(\S+)\s*$/) { |
| 226 | if(exists $UniqHash{$1.$2.$3}) { |
| 227 | &msg_handler(Type::Warning, "[Duplicated Lines]: $line", __LINE__, $FileName); |
| 228 | next; |
| 229 | } |
| 230 | else { |
| 231 | $UniqHash{$1.$2.$3} = 0; |
| 232 | } |
| 233 | |
| 234 | if(not exists $SymCheckCrossFiles{$1.$2.$3}) { |
| 235 | $SymCheckCrossFiles{$1.$2.$3} = $FileName; |
| 236 | push @SymArray, [$1, $2, $3]; |
| 237 | $libObjHash{$3}{$2} = 0; |
| 238 | } |
| 239 | else { |
| 240 | my $preLdf = $SymCheckCrossFiles{$1.$2.$3}; |
| 241 | &msg_handler(Type::Warning, "$1 has been defined in $preLdf", __LINE__, $FileName); |
| 242 | next; |
| 243 | } |
| 244 | } elsif ($line =~ m/^ALIGN:(\w+)$/){ |
| 245 | $align = $1; |
| 246 | } else { |
| 247 | my $msg = "Illegal Line Format: $line"; |
| 248 | &msg_handler(Type::Fatal, "Illegal Line Format: $line", __LINE__, $FileName); |
| 249 | next; |
| 250 | } |
| 251 | } |
| 252 | $ConfigInfoHash{$FileName}{$SecNameArray[$i]}{"ALIGN"} = $align if($#SymArray >= 0); |
| 253 | $ConfigInfoHash{$FileName}{$SecNameArray[$i]}{"LIST"} = \@SymArray if($#SymArray >= 0); |
| 254 | } |
| 255 | &msg_handler(Type::Warning, "$FileName is an invalid file", __LINE__, $FileName) unless(exists $ConfigInfoHash{$FileName}); |
| 256 | } |
| 257 | |
| 258 | sub ParseLibObj |
| 259 | { |
| 260 | foreach my $lib (keys %libObjHash) { |
| 261 | my $LibPath1 = $LibPath1Prefix . "/" . $lib; |
| 262 | my $LibPath2 = $LibPath2Prefix . "/" . $lib; |
| 263 | my $LibPath = (-e $LibPath1) ? $LibPath1 : $LibPath2; |
| 264 | if(!-e $LibPath) { |
| 265 | delete $libObjHash{$lib}; |
| 266 | next; |
| 267 | } |
| 268 | |
| 269 | my @ObjArray = keys %{$libObjHash{$lib}}; |
| 270 | foreach my $obj (@ObjArray) { |
| 271 | my $ExtractObj = $lib . $obj; |
| 272 | my $SymLog = $ExtractObj . "." . "symbols.log"; |
| 273 | my $SecLog = $ExtractObj . "." . "sections.log"; |
| 274 | |
| 275 | next if(-f $SymLog && -f $SecLog); #have been parsed before. |
| 276 | my $tmp_dir = $tempdir . "CustomInputSection/"; |
| 277 | chdir ($tmp_dir) or &msg_handler(Type::Fatal, "Fail to dir to $tmp_dir", __LINE__); |
| 278 | |
| 279 | #extract the obj from lib |
| 280 | system("$AR -x $LibPath $obj 2> /dev/null"); |
| 281 | unless(-f $obj) { |
| 282 | delete $libObjHash{$lib}{$obj}; |
| 283 | next; |
| 284 | } |
| 285 | |
| 286 | #move the obj to certain folder |
| 287 | system("mv $obj $ExtractObj"); |
| 288 | $? == 0 or &msg_handler(Type::Fatal, "$ExtractObj moving failed", __LINE__); |
| 289 | |
| 290 | #generate SYM log |
| 291 | system("$Readelf --syms -W $ExtractObj > $SymLog"); |
| 292 | $? == 0 or &msg_handler(Type::Fatal, "Generating $SymLog failed", __LINE__); |
| 293 | |
| 294 | #generate SECTION log |
| 295 | system("$Readelf -S -W $ExtractObj > $SecLog"); |
| 296 | $? == 0 or &msg_handler(Type::Fatal, "Generating $SecLog failed", __LINE__); |
| 297 | |
| 298 | &ParseSymAndSecLog($SymLog, $SecLog, $lib, $obj); |
| 299 | chdir ($ENV{'PWD'}) or &msg_handler(Type::Fatal, "Fail to dir to $ENV{'PWD'}", __LINE__); |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | sub ParseSymAndSecLog |
| 305 | { |
| 306 | my ($tempSymLog, $tempSecLog, $tempLib, $tempObj) = (@_); |
| 307 | my $key = $tempLib . $tempObj; |
| 308 | |
| 309 | open SYM_LOG, "< $tempSymLog" or &msg_handler(Type::Fatal, "Fail to open $tempSymLog", __LINE__); |
| 310 | while(my $line = <SYM_LOG>) { |
| 311 | # 17: 00000024 40 FUNC LOCAL DEFAULT [MIPS16] 9 ev_cmp_f |
| 312 | if($line =~ m/^\s*\d+\s*:\s*\S+\s+(\d+).*\s+(\d+)\s+(\w+)$/) { |
| 313 | my ($Symbol, $index, $size) = ($3, $2, $1); |
| 314 | $SymConvertHash{$Symbol} = $Symbol; |
| 315 | $SymLogInfoHash{$key}{$Symbol}{'index'} = $index; |
| 316 | $SymLogInfoHash{$key}{$Symbol}{'size'} = $size; |
| 317 | } |
| 318 | } |
| 319 | close SYM_LOG; |
| 320 | |
| 321 | open SEC_LOG, "< $tempSecLog" or &msg_handler(Type::Fatal, "Fail to open $tempSecLog", __LINE__); |
| 322 | while(my $line = <SEC_LOG>) { |
| 323 | # [22] .text.evshed_give PROGBITS 00000000 000bbc 00002c 00 AX 0 0 4 |
| 324 | if($line =~ m/^\s*\[\s*(\d+)\s*\]\s+(\S+)\s+/) { |
| 325 | my ($index, $Section) = ($1, $2); |
| 326 | if($Section =~ m/^(\.?\w+)\.\w+$/) { |
| 327 | $SecLogInfoHash{$key}{$index}{'type'} = $1; |
| 328 | $SecLogInfoHash{$key}{$index}{'valid'} = 'true'; |
| 329 | } |
| 330 | elsif($Section =~ m/^[^\.]*$/) { |
| 331 | $SecLogInfoHash{$key}{$index}{'type'} = $Section; |
| 332 | $SecLogInfoHash{$key}{$index}{'valid'} = 'false'; |
| 333 | } |
| 334 | } |
| 335 | } |
| 336 | close SEC_LOG; |
| 337 | } |
| 338 | |
| 339 | sub CheckUserConfiguration |
| 340 | { |
| 341 | foreach my $ldf (keys %ConfigInfoHash) { |
| 342 | my $FileName = $ldf; |
| 343 | #check the validity of user config |
| 344 | foreach my $group (keys %{$ConfigInfoHash{$ldf}}) { |
| 345 | my @FinalSymList = (); |
| 346 | my $CheckSectionType = undef; |
| 347 | |
| 348 | foreach my $item (@{$ConfigInfoHash{$ldf}{$group}{"LIST"}}) { |
| 349 | my $SectionType = undef; |
| 350 | my $SymName = $item->[0]; |
| 351 | my $key = $item->[2] . $item->[1]; |
| 352 | my $SymNameInObj; |
| 353 | |
| 354 | if(not exists $libObjHash{$item->[2]}) { #lib does not exist |
| 355 | my $tips = $item->[2] . " does not exist."; |
| 356 | &msg_handler(Type::Warning, "$SymName not found in Group" . "[$group]" . ": $tips", __LINE__, $FileName); |
| 357 | next; |
| 358 | } |
| 359 | elsif(not exists $libObjHash{$item->[2]}{$item->[1]}) { #obj can't be found in lib |
| 360 | my $tips = $item->[1] . " not exists in " . $item->[2]; |
| 361 | &msg_handler(Type::Warning, "$SymName not found in Group" . "[$group]" . ": $tips", __LINE__, $FileName); |
| 362 | next; |
| 363 | } |
| 364 | |
| 365 | if(not exists $SymConvertHash{$SymName}) { #the symbol not exists |
| 366 | my $tips = "If your symbol type is C++, please use the full name in MAP/SYM, such as [ipfcore_task_init] -> [_Z17ipfcore_task_initv]"; |
| 367 | &msg_handler(Type::Warning, "$SymName can't be found in Group" . "[$group]" . ", $tips", __LINE__, $FileName); |
| 368 | next; |
| 369 | } |
| 370 | else { |
| 371 | $SymNameInObj = $SymConvertHash{$SymName}; |
| 372 | } |
| 373 | |
| 374 | my $index = $SymLogInfoHash{$key}{$SymNameInObj}{'index'}; |
| 375 | |
| 376 | if(not exists $SecLogInfoHash{$key}{$index}) { #the input section does not exist |
| 377 | &msg_handler(Type::Warning, "can't find the input section of $SymNameInObj in Group" . "[$group]", __LINE__, $FileName); |
| 378 | next; |
| 379 | } |
| 380 | |
| 381 | if($SecLogInfoHash{$key}{$index}{'valid'} eq 'false') { #unsupported section type |
| 382 | $SectionType = $SecLogInfoHash{$key}{$index}{'type'}; |
| 383 | my $NewType = $SectionType . '.' . $item->[0]; |
| 384 | my $tips = "Unsupported Inputsection: " . $item->[0] . " -> $SectionType in Group" . "[$group]" . ", please use __attribute__ ((sections(\"$NewType\"))) to re-try."; |
| 385 | &msg_handler(Type::Warning, $tips, __LINE__, $FileName); |
| 386 | $CheckSectionType = undef; |
| 387 | next; |
| 388 | } |
| 389 | |
| 390 | $SectionType = $SecLogInfoHash{$key}{$index}{'type'}; |
| 391 | $CheckSectionType = $SectionType if(not defined $CheckSectionType); |
| 392 | if($CheckSectionType ne $SectionType) { #Inputsection type mismatch within one group |
| 393 | my $msg = "Inputsection type mismatch in Group" . "[$group]: " . $item->[0] . " -> " . $SectionType; |
| 394 | &msg_handler(Type::Warning, $msg, __LINE__, $FileName); |
| 395 | next; |
| 396 | } |
| 397 | |
| 398 | push @{$item}, $SymLogInfoHash{$key}{$SymNameInObj}{'size'}, $CheckSectionType; |
| 399 | push @FinalSymList, $item; |
| 400 | } |
| 401 | if($#FinalSymList >= 0) { |
| 402 | $ConfigInfoHash{$ldf}{$group}{"LIST"} = \@FinalSymList; |
| 403 | } |
| 404 | else { |
| 405 | delete $ConfigInfoHash{$ldf}{$group}{"LIST"}; |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | sub UpdateLDS |
| 412 | { |
| 413 | my ($LDSFile) = (@_); |
| 414 | my $output = undef; |
| 415 | open LDS, "< $LDSFile" or &msg_handler(Type::Fatal, "Fail to open $LDSFile", __LINE__); |
| 416 | my $CacheLineSize = undef; |
| 417 | |
| 418 | while(my $line = <LDS>) { |
| 419 | #get the cache line size |
| 420 | $CacheLineSize = $1 if($line =~ m/^\s*CACHELINESIZE\s*=\s*(\d+);$/); |
| 421 | |
| 422 | if($line =~ m/^(\s*)\*\s*\(\s*(\.?)(\w+)(\*?)\s*\)$/) { |
| 423 | my $suffix = ($4 eq '*') ? '.*' : ''; |
| 424 | my ($space, $ResultLine) = ($1, undef); |
| 425 | my $RegularPattern = ($2 eq '.') ? ('\.' . $3) : $3; |
| 426 | foreach my $ldf (keys %ConfigInfoHash) { |
| 427 | foreach my $group (keys %{$ConfigInfoHash{$ldf}}) { |
| 428 | my $GroupType = $ConfigInfoHash{$ldf}{$group}{"LIST"}->[0]->[4]; |
| 429 | next unless($GroupType =~ m/^$RegularPattern$suffix$/); |
| 430 | |
| 431 | my ($SubLine, $GroupSize) = (undef, 0); |
| 432 | $SubLine = "$space$group\$\$Base = .;\n"; |
| 433 | foreach my $item (@{$ConfigInfoHash{$ldf}{$group}{"LIST"}}) { |
| 434 | my ($sym, $obj, $size, $type) = ($item->[0], $item->[1], $item->[3], $item->[4]); |
| 435 | $SubLine .= "${space}*$obj ($type.$sym.*)\n" . "${space}*$obj ($type.$sym)\n"; |
| 436 | $GroupSize += $size; |
| 437 | } |
| 438 | $SubLine .= "$space$group\$\$Limit = . ;\n$space$group\$\$Length = ABSOLUTE($group\$\$Limit - $group\$\$Base);\n\n"; |
| 439 | if (defined $ConfigInfoHash{$ldf}{$group}{"ALIGN"}){ |
| 440 | $SubLine = "\n" . $space . ". = ALIGN($ConfigInfoHash{$ldf}{$group}{\"ALIGN\"});" . "\n" . $SubLine; |
| 441 | } else{ |
| 442 | #if total size > 32, align 64B to gain L2$, else, align 32B |
| 443 | my $AlignSize = (($GroupSize > 32) ? 64 : ((defined $CacheLineSize) ? $CacheLineSize : 32)); |
| 444 | $SubLine = "\n" . $space . ". = ALIGN($AlignSize);" . "\n" . $SubLine; |
| 445 | } |
| 446 | $ResultLine .= $SubLine; |
| 447 | #avoid multiple match |
| 448 | delete $ConfigInfoHash{$ldf}{$group}; |
| 449 | } |
| 450 | } |
| 451 | $line = $ResultLine . $line if(defined $ResultLine); |
| 452 | } |
| 453 | $output .= $line; |
| 454 | } |
| 455 | close LDS; |
| 456 | |
| 457 | open LDS, "> $LDSFile" or &msg_handler(Type::Fatal, "Fail to open $LDSFile", __LINE__); |
| 458 | print LDS $output; |
| 459 | close LDS; |
| 460 | |
| 461 | &msg_handler(Type::Log, "\nLDS is updated successfully ^O^, please check $LDSFileName.", __LINE__); |
| 462 | } |
| 463 | |
| 464 | sub CleanTempFiles |
| 465 | { |
| 466 | system("rm -rf $tempInputFolder"); |
| 467 | $? == 0 or &msg_handler(Type::Fatal, "Deleting $tempInputFolder failed $?", __LINE__); |
| 468 | |
| 469 | my $OptFile = $tempdir."PreProcessOpt.txt"; |
| 470 | system("rm -f $OptFile"); |
| 471 | $? == 0 or &msg_handler(Type::Fatal, "Deleting $OptFile failed $?", __LINE__); |
| 472 | } |
| 473 | |
| 474 | sub msg_handler |
| 475 | { |
| 476 | my ($type, $msg, $line_no, $file_name) = (@_); |
| 477 | my $prompt_prefix; |
| 478 | if($type == Type::Log) { |
| 479 | print $msg . "\n"; |
| 480 | } |
| 481 | elsif($type == Type::Warning) { |
| 482 | $prompt_prefix = ">> AAIS Warning : "; |
| 483 | my $location = (defined $file_name) ? "[$file_name] " : ""; |
| 484 | print $prompt_prefix . $location . $msg . "\n"; |
| 485 | } |
| 486 | elsif($type == Type::Fatal) { |
| 487 | $prompt_prefix = ">> *** AAIS Fatal : "; |
| 488 | my $location = (defined $file_name) ? "[$file_name] " : ""; |
| 489 | $location .= "[at line $line_no] "; |
| 490 | die $prompt_prefix . $location . $msg . "\n"; |
| 491 | } |
| 492 | } |