Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | |
2 | use strict; | |
3 | use IO::Handle; | |
4 | use Getopt::Long; | |
5 | ||
6 | sub update_regs; | |
7 | sub print_regs; | |
8 | sub error; | |
9 | sub b2h; | |
10 | sub format_time; | |
11 | ||
12 | $SIG{__WARN__} = sub {die $_[0]}; | |
13 | ||
14 | # Initialize and defines all kinds of variables | |
15 | #---------------------------------------------- | |
16 | $| = 1; # autoflush | |
17 | my(@gl); # global register level per thread | |
18 | my(@tl); # trap level per thread | |
19 | my(@cwp); # current window pointer per thread | |
20 | my($logfile); # what file to read | |
21 | ||
22 | # global, FP, integer, asi registers | |
23 | my(@gregs, @fpregs, @regs, @asi_reg); | |
24 | ||
25 | my($pc, $inst); # program counter, instructions | |
26 | my(%diag_code, %label); # disassembled diag code and labels | |
27 | my($time, $spc, $thr, $proc, $reg, $val, $win, $instr, $tmp); | |
28 | my(@instr_list); # instruction list | |
29 | my($PROG) = ($0=~ m%([^/]+)$%); # regreport real name | |
30 | ||
31 | my(%miss); # additional info - less important | |
32 | my(%notintlb); # additional info - less important | |
33 | ||
34 | my($i, $k); | |
35 | my $version = '1.NN'; | |
36 | ||
37 | print "===============================================\n"; | |
38 | print "=== OpenSPARC T1 Vlog Version $version ===\n"; | |
39 | print "===============================================\n"; | |
40 | ||
41 | my @Options = qw( debug sas mom h help ccx l2 dram cycles sort! perf); | |
42 | my %opt = (); | |
43 | $opt{debug} = 0; | |
44 | $opt{sas} = 0; | |
45 | $opt{mom} = 0; | |
46 | $opt{h} = 0; | |
47 | $opt{help} = 0; | |
48 | $opt{ccx} = 0; | |
49 | $opt{l2} = 0; | |
50 | $opt{dram} = 0; | |
51 | $opt{cycles} = 0; | |
52 | $opt{sort} = 1; | |
53 | $opt{perf} = 0; | |
54 | ||
55 | GetOptions(\%opt, @Options) or die "Error in arguments!\n"; | |
56 | my($debug) = $opt{debug}; | |
57 | my($sas) = $opt{sas}; | |
58 | my($mom) = $opt{mom}; | |
59 | my($ccx) = $opt{ccx}; | |
60 | my($l2) = $opt{l2}; | |
61 | my($dram) = $opt{dram}; | |
62 | my($h) = $opt{h}; | |
63 | my($help) = $opt{help}; | |
64 | my($cycles) = $opt{cycles}; | |
65 | my($sorti) = $opt{sort}; | |
66 | my($perf) = $opt{perf}; | |
67 | ||
68 | ||
69 | if($h || $help) { | |
70 | print "===============================================\n"; | |
71 | print "=== Version $PROG ===\n"; | |
72 | print "Usage: vlog [logfilename|path_to_sim.log] [-debug -h -ccx -l2 -dram -cycles -[no]sort] [-perf] \n"; | |
73 | print "-ccx prints ccx related messages\n"; | |
74 | print "-l2 prints l2 related messages\n"; | |
75 | print "-dram prints dram related messages\n"; | |
76 | print "-h prints out this screen\n"; | |
77 | print "-debug is for script debug\n"; | |
78 | print " It will probably be obsoleted in the future \n"; | |
79 | print "-cycles prints the cycles and not the time \n"; | |
80 | print "-sort will sort sim.log according to time stamps first [default is on]\n"; | |
81 | print "-perf will print all kinds of performance data - I, D miss e.t.c.\n"; | |
82 | print "-mom Special mom sas.log file processing\n"; | |
83 | print "===============================================\n"; | |
84 | print "Examples:\n"; | |
85 | print "vlog -ccx -l2 -dram >! vlog.log\n"; | |
86 | print "vlog >! vlog.log\n"; | |
87 | print "vlog <my_path>/sim.log >! vlog.log\n"; | |
88 | print "===============================================\n"; | |
89 | exit 0; | |
90 | } | |
91 | ||
92 | if($debug) { print "Debug mode on\n"; } | |
93 | if($sas) { print "sas mode\n"; } | |
94 | if($mom) { print "mom mode\n"; } | |
95 | if($sorti) { print "sort mode\n"; } | |
96 | if($perf) { print "perf mode\n"; } | |
97 | ||
98 | #========================================== | |
99 | # initialize register hashes. | |
100 | #========================================== | |
101 | for ($i = 0; $i < 32; $i++){ | |
102 | $tl[$i] = 5; | |
103 | $gl[$i] = 3; | |
104 | $cwp[$i] = 0; | |
105 | $asi_reg[$i] = "x"; | |
106 | for ($k = 0; $k < 32; $k++){ | |
107 | $gregs[$i][$k] = "x"; | |
108 | } | |
109 | $gregs[$i][0] = 0x0; | |
110 | $gregs[$i][8] = 0x0; | |
111 | $gregs[$i][16] = 0x0; | |
112 | $gregs[$i][24] = 0x0; | |
113 | ||
114 | for ($k = 0; $k < 64; $k++){ | |
115 | $fpregs[$i][$k] = "x"; | |
116 | } | |
117 | ||
118 | for ($k = 0; $k < 256; $k++){ | |
119 | $regs[$i][$k] = "x"; | |
120 | } | |
121 | } | |
122 | ||
123 | ||
124 | #========================================== | |
125 | # figure out logfile to read | |
126 | #========================================== | |
127 | my $logfilename = $mom ? "sas.log" : "sim.log"; | |
128 | ||
129 | if($#ARGV >= 0){ | |
130 | ||
131 | my @pathname = split '/' , $ARGV[0]; | |
132 | if($pathname[$#pathname] =~ /$logfilename/){ | |
133 | $#pathname--; | |
134 | } | |
135 | if(scalar(@pathname)){ | |
136 | chdir join '/', @pathname or die "cannot change dir\n"; | |
137 | print "changed dir to "; | |
138 | }else{ | |
139 | print "current dir is "; | |
140 | } | |
141 | my $temp = `pwd`; | |
142 | print "$temp\n"; | |
143 | } | |
144 | ||
145 | $logfile= (-f $logfilename) ? $logfilename : | |
146 | (-f "$logfilename.gz") ? "$logfilename.gz" : | |
147 | &error("Logfile $logfilename or $logfilename.gz not found"); | |
148 | ||
149 | ||
150 | print "\n===== Opening $logfile ======\n"; | |
151 | #------------------------------------- | |
152 | # log file in N1 is unsorted mess. | |
153 | # sort it unless soritng is disabled. | |
154 | # sort by forking a sorting process. | |
155 | #------------------------------------- | |
156 | if($sorti && !$mom){ | |
157 | my $pid = open(VCS, "-|"); | |
158 | unless (defined $pid){die "cannot fork $!\n"} | |
159 | if(!$pid){sorti();} | |
160 | } | |
161 | else{ | |
162 | if($logfile =~ /\.gz$/) { | |
163 | open(VCS, "gunzip -c $logfile |") || die "cannot open gunzip -c $logfile"; | |
164 | }else{ | |
165 | open(VCS, "< $logfile") || die "cannot open $logfile"; | |
166 | } | |
167 | } | |
168 | ||
169 | #============================================================ | |
170 | ||
171 | # get the labels inside the diag.s | |
172 | if((! -f "symbol.tbl") &&(-f "symbol.tbl.gz")){ | |
173 | system("gunzip symbol.tbl.gz"); | |
174 | } | |
175 | ||
176 | if(! -f "symbol.tbl") {print "no symbol.tbl\n"; exit 0;} | |
177 | open(SYM , "symbol.tbl") || die " BAD BAD symbol.tbl opening"; | |
178 | while(<SYM>){ | |
179 | chop; | |
180 | s/\.\w+\.//g; | |
181 | my @symline = split /\s+/; | |
182 | if($#symline != 3){die "something is wrong with symbol.tbl\n";} | |
183 | ||
184 | my $pc = truncate_len($symline[1]); | |
185 | if(exists $label{$pc} and $label{$pc} eq 'main'){ | |
186 | next; | |
187 | } | |
188 | $label{$pc} = $symline[0]; | |
189 | print "label $label{$pc}, $pc\n" if($debug); | |
190 | } | |
191 | ||
192 | # disassemble the diag. | |
193 | #--------------------- | |
194 | my(@diag_exe_files) = `ls diag*.exe*`; | |
195 | if(!(@diag_exe_files)){ | |
196 | print "Warning: No diag.\*exe files!!!\n"; | |
197 | } | |
198 | else{ | |
199 | my($exe_file, $exe_file_gz); | |
200 | foreach $exe_file (@diag_exe_files){ | |
201 | chop $exe_file; | |
202 | $exe_file_gz = $exe_file . ".gz"; | |
203 | if(!(-e $exe_file) && (-e $exe_file_gz)){ system("gunzip $exe_file_gz"); } | |
204 | print "Will extract instruction info from: $exe_file \n"; | |
205 | ||
206 | open(DIS, "g_objdump -m sparc:v9B -d $exe_file | ") || die "BAD objdump"; | |
207 | while(<DIS>){ | |
208 | s/^\s+//; | |
209 | if(/^([a-f\d]+):\s+.. .. .. ..\s+(.*)$/) { | |
210 | $pc = truncate_len($1); | |
211 | $inst = $2; | |
212 | ||
213 | $inst =~ s/\s*!.*$//; | |
214 | if($inst =~ /\((\d+)\)/){ # convert from decimal to hex. | |
215 | my $inst_left = $` . '(0x'; | |
216 | my $inst_cent = sprintf("%lx",$1); | |
217 | my $inst_right = ')' . $'; | |
218 | my $asi_str = asi_mnem($inst_cent); | |
219 | $inst = $inst_left . $inst_cent . ' ' . $asi_str . $inst_right; | |
220 | } | |
221 | $diag_code{$pc}= $inst; | |
222 | } | |
223 | ||
224 | } ### of while... | |
225 | close(DIS); | |
226 | ||
227 | } ### of foreach | |
228 | } # of if | |
229 | ||
230 | ||
231 | $| = 0; # autoflush | |
232 | #============================================================ | |
233 | my $found_ctime = 0; | |
234 | my $pll_freq = 0; | |
235 | my $cmp_clk_divider = 0; | |
236 | my($ctime) = 0; | |
237 | ||
238 | # the main loop: | |
239 | #--------------- | |
240 | while(<VCS>) { | |
241 | chop; | |
242 | ||
243 | s/-MATCH/-updated/g; | |
244 | ||
245 | if(/MISMATCH/) { print ;print "\n"; next;} | |
246 | elsif(/timeout/i) { print ;print "\n"; next;} | |
247 | elsif(/error/i) { print ;print "\n"; next;} | |
248 | elsif(/fail/i) { print ;print "\n"; next;} | |
249 | elsif(/wrong/i) { print ;print "\n"; next;} | |
250 | elsif(/good trap/i) { print ;print "\n"; next;} | |
251 | ||
252 | # some messing around needed to calculate the clock period. | |
253 | #---------------------------------------------------------- | |
254 | elsif(/cmp_clk period\s*=\s*(\d+)/){ | |
255 | $ctime = $1; | |
256 | print "cycle time is $ctime\n"; | |
257 | die "Found clock period of 0!\n" unless $ctime; | |
258 | $found_ctime = 1; | |
259 | } | |
260 | elsif(!$found_ctime && /cmp_clk divider\s*=\s*(\d+)/){ | |
261 | $cmp_clk_divider = $1; | |
262 | print "cmp_clk_divider is $cmp_clk_divider\n"; | |
263 | } | |
264 | elsif(!$found_ctime && /pll_clk frequency\s*=\s*(\d+)/i){ | |
265 | $pll_freq = $1; | |
266 | print "pll_freq time is $pll_freq\n"; | |
267 | } | |
268 | elsif(!$found_ctime && /Selected Core Clock Frequency\s(\d+)\s*MHz/){ | |
269 | if($pll_freq && $cmp_clk_divider){ | |
270 | my $pll_period; | |
271 | my %pll_periods = ( # HACK! These are periods hardcoded from cmp_clk.v. | |
272 | 2000 => 250, # Hopefully, we're using a version of hte model that has the | |
273 | 2200 => 227, # "cmp_period" defined, so we don't have to use this. | |
274 | 2333 => 214, | |
275 | 2334 => 214, | |
276 | 2400 => 208, | |
277 | 2550 => 196, | |
278 | 2600 => 192, | |
279 | 2800 => 179, | |
280 | default => 208, | |
281 | ); | |
282 | $pll_period = exists $pll_periods{$pll_freq} ? $pll_periods{$pll_freq} : $pll_periods{default}; | |
283 | $ctime = $pll_period * 2 * $cmp_clk_divider; | |
284 | print "Computed cycle_period from PLL ($pll_freq) and div ". "($cmp_clk_divider): $ctime\n"; | |
285 | } else { | |
286 | # Couldn't find anything but the frequency message. Use that. | |
287 | #------------------------------------------------------------ | |
288 | my $freq = $1; | |
289 | $ctime = int(1 / $freq * 1000000); | |
290 | print "Guessed at cycle_period from frequency ($freq): $ctime\n"; | |
291 | } | |
292 | $found_ctime = 1; | |
293 | } | |
294 | #============================= | |
295 | # example line: | |
296 | #567: [th02] <v:0x0000000000134000> < not in tlb > | |
297 | # this is not very important`. It was nice to the perofrmace | |
298 | # debuggers. | |
299 | #============================= | |
300 | elsif(/th([\dabcdef]+)\]\s+\<v:0x(\w+)>.*not in tlb/i){ | |
301 | $spc = $1 / 4; | |
302 | $thr = $1 % 4; | |
303 | $val = truncate_len($2); | |
304 | $notintlb{$spc}{$thr}{$val} = 1; | |
305 | print "switch on tlb message $_\n" if($debug); | |
306 | } | |
307 | # this is VERY IMPORTANT - the register updates: | |
308 | elsif(/^(\d+):.*reg.updated\s*->\s*spc.(\d).\s*thread.(\d)/){ | |
309 | $time = format_time($1, $ctime, $cycles); | |
310 | $spc = $2; | |
311 | $thr = $3; | |
312 | $proc = 4 * $spc + $thr; | |
313 | ||
314 | if(/float_reg.updated.*reg#\((\w+)\).*val = (\w+)/){ | |
315 | $reg = "%" . $1; | |
316 | $val = $2; | |
317 | ||
318 | printf "%-10s: C%dT%d\t\tFPREG UPDATE <%s = %s>\n", $time, $spc, $thr, $reg, $val; | |
319 | update_regs; | |
320 | ||
321 | my @chars = split //, $val; | |
322 | if($#chars > 7){ | |
323 | if($reg =~ /%[df](\d+)/){ | |
324 | my $newreg = $1 + 1; | |
325 | $reg = "%f" . $newreg; | |
326 | $val = substr $val, 8; | |
327 | update_regs; | |
328 | } | |
329 | else{ | |
330 | die " $time: something is wrong with FP updates\n"; | |
331 | } | |
332 | } | |
333 | } | |
334 | elsif(/window.(\w+).*reg#\((\w+)\).*val = (\w+)/){ | |
335 | $win = $1; | |
336 | $reg = "%" . $2; | |
337 | $val = $3; | |
338 | printf "%-10s: C%dT%d\t\tREG UPDATE <%s = %s> in window %s\n", $time, $spc, $thr, $reg, $val, $win; | |
339 | update_regs; | |
340 | } | |
341 | elsif(/asi_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
342 | $asi_reg[$proc] = $2; | |
343 | printf "%-10s: C%dT%d\t\tASI REG UPDATE <ASI = $2> in window %s\n", $time, $spc, $thr, $1; | |
344 | } | |
345 | elsif(/canrestore_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
346 | printf "%-10s: C%dT%d\t\tCANRESTORE REG UPDATE <CANRESTORE = $2> in window %s\n", $time, $spc, $thr, $1; | |
347 | } | |
348 | elsif(/cansave_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
349 | printf "%-10s: C%dT%d\t\tCANSAVE REG UPDATE <CANSAVE = $2> in window %s\n", $time, $spc, $thr, $1; | |
350 | } | |
351 | elsif(/ccr_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
352 | printf "%-10s: C%dT%d\t\tCCR REG UPDATE <CCR = $2> in window %s\n", $time, $spc, $thr, $1; | |
353 | } | |
354 | elsif(/cleanwin_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
355 | printf "%-10s: C%dT%d\t\tCLEANWIN REG UPDATE <CLEANWIN = $2> in window %s\n", $time, $spc, $thr, $1; | |
356 | } | |
357 | elsif(/cwp_reg.updated.*window.(\w+).*val = (\w+)/){ | |
358 | printf "%-10s: C%dT%d\t\tCWP REG UPDATE <CWP = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
359 | $cwp[$proc] = $1; | |
360 | } | |
361 | elsif(/hpstate_reg.updated.*window.(\w+).*val = (\w+)/){ | |
362 | printf "%-10s: C%dT%d\t\tHPSTATE REG UPDATE <HPSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
363 | } | |
364 | elsif(/htba_reg.updated.*window.(\w+).*val = (\w+)/){ | |
365 | printf "%-10s: C%dT%d\t\tHTBA REG UPDATE <HTBA = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
366 | } | |
367 | elsif(/hstate2_reg.updated.*window.(\w+).*val = (\w+)/){ | |
368 | printf "%-10s: C%dT%d\t\tHSTATE2 REG UPDATE <HSTATE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
369 | } | |
370 | elsif(/hstate3_reg.updated.*window.(\w+).*val = (\w+)/){ | |
371 | printf "%-10s: C%dT%d\t\tHSTATE3 REG UPDATE <HSTATE3 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
372 | } | |
373 | elsif(/otherwin_reg.updated.*window.(\w+).*val = (\w+)/){ | |
374 | printf "%-10s: C%dT%d\t\tOTHERWIN REG UPDATE <OTHERWIN = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
375 | } | |
376 | elsif(/pil_reg.updated.*window.(\w+).*val = (\w+)/){ | |
377 | printf "%-10s: C%dT%d\t\tPIL REG UPDATE <PIL = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
378 | } | |
379 | elsif(/pstate_reg.updated.*window.(\w+).*val = (\w+)/){ | |
380 | printf "%-10s: C%dT%d\t\tPSTATE REG UPDATE <PSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
381 | } | |
382 | elsif(/tba_reg.updated.*window.(\w+).*val = (\w+)/){ | |
383 | printf "%-10s: C%dT%d\t\tTBA REG UPDATE <TBA = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
384 | } | |
385 | elsif(/tl_reg.updated.*window.(\w+).*val = (\w+)/){ | |
386 | $tl[$proc] = $2; | |
387 | printf "%-10s: C%dT%d\t\tTL REG UPDATE <TL = %d>\n", $time, $spc, $thr, $tl[$proc]; | |
388 | } | |
389 | elsif(/gl_reg.updated.*window.(\w+).*val = 0*(\w+)/){ | |
390 | $gl[$proc] = $2; | |
391 | printf "%-10s: C%dT%d\t\tGL REG UPDATE <GL = $2>\n", $time, $spc, $thr; | |
392 | } | |
393 | elsif(/tstate1_reg.updated.*window.(\w+).*val = (\w+)/){ | |
394 | printf "%-10s: C%dT%d\t\tTSTATE1 REG UPDATE <TSTATE1 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
395 | } | |
396 | elsif(/tstate2_reg.updated.*window.(\w+).*val = (\w+)/){ | |
397 | printf "%-10s: C%dT%d\t\tTSTATE2 REG UPDATE <TSTATE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
398 | } | |
399 | elsif(/ttype1_reg.updated.*window.(\w+).*val = (\w+)/){ | |
400 | printf "%-10s: C%dT%d\t\tTTYPE1 REG UPDATE <TTYPE1 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
401 | } | |
402 | elsif(/ttype2_reg.updated.*window.(\w+).*val = (\w+)/){ | |
403 | printf "%-10s: C%dT%d\t\tTTYPE2 REG UPDATE <TTYPE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
404 | } | |
405 | elsif(/wstate_reg.updated.*window.(\w+).*val = (\w+)/){ | |
406 | printf "%-10s: C%dT%d\t\tWSTATE REG UPDATE <WSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
407 | } | |
408 | elsif(/hstick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){ | |
409 | printf "%-10s: C%dT%d\t\tHSTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
410 | } | |
411 | elsif(/stick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){ | |
412 | printf "%-10s: C%dT%d\t\tSTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
413 | } | |
414 | elsif(/tick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){ | |
415 | printf "%-10s: C%dT%d\t\tTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
416 | } | |
417 | elsif(/y_reg.updated.*window.(\w+).*val = (\w+)/){ | |
418 | printf "%-10s: C%dT%d\t\tY REG UPDATE <Y = %s> in window %s\n", $time, $spc, $thr, $2, $1; | |
419 | } | |
420 | else{ | |
421 | print "$_ - an undetected register\n" if ($debug); | |
422 | } | |
423 | } | |
424 | #================================ | |
425 | # VERY IMPORTANT - PC extraction | |
426 | # the notintlb and miss info | |
427 | # is just nice to have. | |
428 | # everything else is crucial. | |
429 | #================================ | |
430 | elsif(!$sas && /info-perm/i){ | |
431 | if(/^.(\d+).info-perm\s+thread.([\dabcdef]+).\s+pc.(\w+)/i){ | |
432 | $time = format_time($1, $ctime, $cycles); | |
433 | $proc = hex ($2); | |
434 | $spc = int ($proc / 4); | |
435 | $thr = $proc % 4 ; | |
436 | $val = truncate_len($3); | |
437 | } | |
438 | else{ | |
439 | die "See this\n$_\nsomething is wrong with the PC extraction\n"; | |
440 | } | |
441 | ||
442 | $instr = $diag_code{$val}; | |
443 | if($label{$val}){ | |
444 | printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr; | |
445 | printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val}; | |
446 | } | |
447 | ||
448 | if($instr){ | |
449 | my($notintlb, $imiss, $dmiss, $short_val); | |
450 | $val =~ /(\w{8})$/; | |
451 | $short_val = $1; | |
452 | if((exists $miss{I}{$spc}{$thr}{$short_val}) && ( $miss{I}{$spc}{$thr}{$short_val} == 1) && $perf){ | |
453 | $imiss = 'IMISS'; | |
454 | $miss{I}{$spc}{$thr}{$short_val} = 0; | |
455 | } | |
456 | else{ | |
457 | $imiss = ''; | |
458 | } | |
459 | ||
460 | if((exists $miss{D}{$spc}{$thr}{$short_val}) && ( $miss{D}{$spc}{$thr}{$short_val} == 1) && $perf){ | |
461 | $dmiss = 'DMISS'; | |
462 | $miss{D}{$spc}{$thr}{$short_val} = 0; | |
463 | } | |
464 | else{ | |
465 | $dmiss = ''; | |
466 | } | |
467 | ||
468 | if(exists $notintlb{$spc}{$thr}{$val} && $notintlb{$spc}{$thr}{$val} && $perf){ | |
469 | $notintlb = "not in tlb"; | |
470 | $notintlb{$spc}{$thr}{$val} = 0; | |
471 | print "switch off tlb message $_\n" if($debug); | |
472 | } | |
473 | else{ | |
474 | $notintlb = ''; | |
475 | } | |
476 | if($instr =~ /%asi/){ | |
477 | my $asi_str = asi_mnem($asi_reg[$proc]); | |
478 | $instr =~ s/%asi/%asi ($asi_reg[$proc] $asi_str)/; | |
479 | } | |
480 | ||
481 | printf "%-10s: C%dT%d v%-12s \t%-30s $notintlb $imiss $dmiss\n", $time, $spc, $thr, $val, $instr; | |
482 | $instr =~ s/[,\[\]]//g; | |
483 | if($instr =~ /%fp\W|%sp\W|%fp$|%sp$/){ | |
484 | $instr =~ s/%fp/%i6/g; | |
485 | $instr =~ s/%sp/%o6/g; | |
486 | } | |
487 | ||
488 | @instr_list = split /\s+/, $instr; | |
489 | print_regs; | |
490 | } | |
491 | else{ | |
492 | printf "%-10s: C%dT%d v%-12s \tWARNING probably illegal instruction - could not translate\n", $time, $spc, $thr, $val; | |
493 | } | |
494 | } | |
495 | ||
496 | #==================================== | |
497 | # also very important - SAS only runs | |
498 | #==================================== | |
499 | elsif($sas && /^\((\d+)\):sas>\s+\d+:\s+\[th([\dabcdef]+)\]\s+<v:0x(\w+)>\s+<p:0*(\w+)>\s(.*)/){ | |
500 | $time = format_time($1, $ctime, $cycles); | |
501 | $proc = hex ($2); | |
502 | $spc = $proc / 4; | |
503 | $thr = $2 % 4; | |
504 | $val = truncate_len($3); | |
505 | my($pa) = $4; | |
506 | $instr = $5; | |
507 | ||
508 | if(exists $label{$val}){ | |
509 | printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr; | |
510 | printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val}; | |
511 | } | |
512 | ||
513 | printf "%-10s: C%dT%d v%-12s \t%-30s \(pa=%-12s\)\n", $time, $spc, $thr, $val, $instr, $pa; | |
514 | $instr =~ s/[,\[\]]//g; | |
515 | @instr_list = split /\s+/, $instr; | |
516 | print_regs; | |
517 | } | |
518 | ||
519 | # example line: | |
520 | #@1101: 0000.pc=00000000000400ac inst[lstore] in switch stage /wo speculation, latency=0 | |
521 | elsif($mom && /^\@(\d+):\s+(\d+)\.pc=(\w+)\s+inst/){ | |
522 | $time = format_time($1, $ctime, $cycles); | |
523 | my $proc = $2 + 0; | |
524 | $spc = $proc / 4; | |
525 | $thr = $proc % 4; | |
526 | $val = truncate_len($3); | |
527 | ||
528 | if(exists $diag_code{$val}){ | |
529 | $instr = $diag_code{$val}; | |
530 | } | |
531 | else{ | |
532 | $instr = "Instruction not found"; | |
533 | } | |
534 | if($label{$val}){ | |
535 | printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr; | |
536 | printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val}; | |
537 | } | |
538 | ||
539 | printf "%-10s: C%dT%d v%-12s \t%-30s\n", $time, $spc, $thr, $val, $instr; | |
540 | } | |
541 | ||
542 | ||
543 | #============================= | |
544 | # print CCX info. | |
545 | #============================= | |
546 | elsif($ccx && (/^(\d+):Info cpu.(\d). cpx.*->\s*(\w+)/)) { | |
547 | $time = format_time($1, $ctime, $cycles); | |
548 | $spc = $2; | |
549 | my($rawpkt) = $3; | |
550 | ||
551 | my($pkt) = process_cpx_pkt($rawpkt); | |
552 | print "debug cpx: $_\n" if($debug); | |
553 | printf "%-10s: C${spc}T$pkt\n", $time; | |
554 | next; | |
555 | } | |
556 | elsif(/^(\d+):Info cpu.(\d). pcx.*->\s*(\w+)/) { | |
557 | $time = format_time($1, $ctime, $cycles); | |
558 | $spc= $2; | |
559 | my($rawpkt) = $3; | |
560 | ||
561 | my($pkt) = process_pcx_pkt($rawpkt); | |
562 | print "debug pcx: $_\n" if($debug); | |
563 | if($ccx){ | |
564 | printf "%-10s: C$spc$pkt\n", $time; | |
565 | } | |
566 | if($pkt =~ /^T(\d).*([id])fill_req.*addr\s+\w*(\w{8})\s/i){ | |
567 | my $thr = $1; | |
568 | my $iord = $2; | |
569 | my $addr = $3; | |
570 | $miss{$iord}{$spc}{$thr}{$addr} = 1; | |
571 | print " setting $iord $spc $thr $addr miss \n" if($debug); | |
572 | } | |
573 | ||
574 | next; | |
575 | } | |
576 | # l2 bank info | |
577 | #============== | |
578 | elsif($l2 && /^(\d+):\s+(L2 bank.*)/) { | |
579 | $time = format_time($1, $ctime, $cycles); | |
580 | my $rawpkt = $2; | |
581 | if($rawpkt =~ /core\s+(\d+),\s+thread\s+(\d+)/){ | |
582 | $spc = $1; | |
583 | $thr = $2; | |
584 | printf "%-10s: C${spc}T${thr}\t$rawpkt\n", $time; | |
585 | } | |
586 | else{ | |
587 | printf "%-10s: \t$rawpkt\n", $time; | |
588 | } | |
589 | next; | |
590 | } | |
591 | # dram info | |
592 | elsif($dram && /^(\d+):\s*(DRAM.*)/) { | |
593 | $time = format_time($1, $ctime, $cycles); | |
594 | my $rawpkt = $2; | |
595 | printf "%-10s: $rawpkt\n", $time; | |
596 | next; | |
597 | } | |
598 | elsif($dram && /^(\d+):\s*(L2_DRAM.*)/) { | |
599 | $time = format_time($1, $ctime, $cycles); | |
600 | my $rawpkt = $2; | |
601 | printf "%-10s: $rawpkt\n", $time; | |
602 | next; | |
603 | } | |
604 | elsif(/bad/i) { print "$_\n"; } | |
605 | } # while | |
606 | ||
607 | close(VCS); | |
608 | print "\nBye\n"; | |
609 | ||
610 | #========================== | |
611 | ||
612 | sub error { | |
613 | my($msg)= @_; | |
614 | STDOUT->autoflush(1); | |
615 | STDERR->autoflush(1); | |
616 | print STDERR "ERR: $msg!\n"; | |
617 | exit(1); | |
618 | } | |
619 | ||
620 | #========================== | |
621 | # updates the register values | |
622 | # this is per thread. | |
623 | # I am modeling all registers per thread as one big flat | |
624 | # register file, index by register window number * N + register number | |
625 | # where N = 8 for globals and 16 for others | |
626 | #========================== | |
627 | sub update_regs { | |
628 | ||
629 | my($reg_num); | |
630 | ||
631 | if($reg =~ /%r(\d+)/){ | |
632 | if($1 < 8){ # global reg. | |
633 | $reg_num = 8 *$win + $1; | |
634 | $gregs[$proc][$reg_num] = $val; | |
635 | print "C${spc}T${thr} debug updating global $reg to $gregs[$proc][$1] reg num = $reg_num\n" if($debug); | |
636 | } | |
637 | else{ # not a global reg. | |
638 | $reg_num = $win*16 + 31 - $1; | |
639 | $regs[$proc][$reg_num] = $val; | |
640 | print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num = $reg_num\n" if($debug); | |
641 | } | |
642 | } | |
643 | elsif($reg =~ /%g(\d+)/){ # global reg | |
644 | $reg_num = 8 * $win + $1; | |
645 | $gregs[$proc][$reg_num] = $val; | |
646 | print "C${spc}T${thr} debug updating $reg to $gregs[$proc][$reg_num] reg_num: $reg_num\n" if($debug); | |
647 | } | |
648 | elsif($reg =~ /%i(\d+)/){ # input reg | |
649 | $reg_num = $win*16 + $1; | |
650 | $regs[$proc][$reg_num] = $val; | |
651 | print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug); | |
652 | } | |
653 | elsif($reg =~ /%l(\d+)/){ # local reg | |
654 | $reg_num = $win*16 + 8 + $1; | |
655 | $regs[$proc][$reg_num] = $val; | |
656 | print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug); | |
657 | } | |
658 | elsif($reg =~ /%o(\d+)/){ # output reg | |
659 | $reg_num = $win*16 + 16 + $1; | |
660 | $regs[$proc][$reg_num] = $val; | |
661 | print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug); | |
662 | } | |
663 | elsif($reg =~ /%f(\d+)/){ # FP reg. | |
664 | $reg_num = $1; | |
665 | $fpregs[$proc][$reg_num] = $val; | |
666 | print "C${spc}T${thr} debug updating $reg to $fpregs[$proc][$reg_num] reg_num: $reg_num\n" if($debug); | |
667 | } | |
668 | elsif($reg =~ /%d(\d+)/){ # should not come here. | |
669 | print "%d stuff, man, don't know what to do yet.\n"; | |
670 | exit 1; | |
671 | } | |
672 | } | |
673 | ||
674 | #----------------------------------------------------------------- | |
675 | ||
676 | # prints the relevant registers for the instruction/PC which found it. | |
677 | sub print_regs{ | |
678 | ||
679 | my($needs_print) = 0; | |
680 | my($e, $reg_num); | |
681 | ||
682 | if($instr =~ /%(r|g|l|i|o|f|d)\d+/){ | |
683 | $needs_print = 1; | |
684 | printf " C%dT%d\t\told reg values: ", $spc, $thr; | |
685 | } | |
686 | if($needs_print){ | |
687 | foreach $e (@instr_list){ | |
688 | ||
689 | if($e =~ /%r(\d+)/){ | |
690 | my $rnumh = $1; | |
691 | if($rnumh < 8) { $e =~ s/%r/%g/; } | |
692 | elsif(($rnumh >= 8) && ($rnumh < 16)) { $e =~ s/%r/%o/; } | |
693 | elsif(($rnumh >= 16) && ($rnumh < 24)) { $e =~ s/%r/%l/; } | |
694 | elsif(($rnumh >= 24) && ($rnumh < 32)) { $e =~ s/%r/%i/; } | |
695 | else { die "something is wrong with register number $rnumh\n";} | |
696 | } | |
697 | ||
698 | if($e =~ /%g(\d+)/){ | |
699 | $reg_num = $gl[$proc] * 8 + $1; | |
700 | printf "%s= %s ", $e, $gregs[$proc][$reg_num]; | |
701 | } | |
702 | elsif($e =~ /%i(\d+)/){ | |
703 | $reg_num = $cwp[$proc]*16 + $1; | |
704 | printf "%s= %s ", $e, $regs[$proc][$reg_num]; | |
705 | } | |
706 | elsif($e =~ /%l(\d+)/){ | |
707 | $reg_num = $cwp[$proc]*16 + 8 + $1; | |
708 | printf "%s= %s ", $e, $regs[$proc][$reg_num]; | |
709 | } | |
710 | elsif($e =~ /%o(\d+)/){ | |
711 | $reg_num = $cwp[$proc]*16 + 16 + $1; | |
712 | printf "%s= %s ", $e, $regs[$proc][$reg_num]; | |
713 | } | |
714 | elsif($e =~ /%f(\d+)/){ | |
715 | $reg_num = $1; | |
716 | printf "%s= %s ", $e, $fpregs[$proc][$reg_num]; | |
717 | } | |
718 | elsif($e =~ /%d(\d+)/){ | |
719 | print "%d stuff, man, don't know what to do yet.\n"; | |
720 | exit 1; | |
721 | } | |
722 | } | |
723 | print "\n"; | |
724 | } | |
725 | } | |
726 | ||
727 | ||
728 | #==================================================================== | |
729 | # makes sense of the PCX packet | |
730 | #==================================================================== | |
731 | sub process_pcx_pkt{ | |
732 | ||
733 | my %ReqTyps = | |
734 | ( | |
735 | '00000' => 'Dfill_Req', | |
736 | '10000' => 'Ifill_Req', | |
737 | '00001' => 'ST', | |
738 | '00111' => 'STQ(1)', | |
739 | '00010' => 'CAS(1)', | |
740 | '00011' => 'CAS(2)', | |
741 | '00110' => 'SWP_Ldstb', | |
742 | '00100' => 'Stream_loads', | |
743 | '00101' => 'Stream_store', | |
744 | '01001' => 'Int', | |
745 | '01010' => 'FP(1)', | |
746 | '01011' => 'FP(2)', | |
747 | '01100' => 'blank', | |
748 | '01101' => 'Fwd_req', | |
749 | '01110' => 'Fwd_reply' | |
750 | ); | |
751 | ||
752 | my $rawpkt = shift @_; | |
753 | my $vld = substr $rawpkt, 0, 1; | |
754 | my $rawtype = substr $rawpkt, 1, 5; | |
755 | my $nc = substr $rawpkt, 6, 1; | |
756 | my $cpuid = substr $rawpkt, 7, 3; | |
757 | my $thrid = substr $rawpkt, 10, 2; | |
758 | my $inv = substr $rawpkt, 12, 1; | |
759 | my $pf = substr $rawpkt, 13, 1; | |
760 | my $binit = substr $rawpkt, 14, 1; | |
761 | my $repl = substr $rawpkt, 15, 2; | |
762 | my $size = substr $rawpkt, 17, 3; | |
763 | my $rawaddr = substr $rawpkt, 20, 40; | |
764 | my $rawdata = substr $rawpkt, 60, 64; | |
765 | ||
766 | my $addr = b2h($rawaddr); | |
767 | my $data = b2h($rawdata); | |
768 | ||
769 | my $type = "illegal"; | |
770 | $type = $ReqTyps{$rawtype} if (defined $ReqTyps{$rawtype}); | |
771 | ||
772 | my $reqid = 'TX'; | |
773 | if ($thrid eq '00'){ $reqid = 'T0'; } | |
774 | elsif($thrid eq '01'){ $reqid = 'T1'; } | |
775 | elsif($thrid eq '10'){ $reqid = 'T2'; } | |
776 | elsif($thrid eq '11'){ $reqid = 'T3'; } | |
777 | ||
778 | my $pkt = "$reqid\tPCX: $type nc $nc cpuid $cpuid thrid $thrid inv $inv pf $pf binit $binit repl $repl size $size addr $addr data $data"; | |
779 | return $pkt; | |
780 | } | |
781 | #==================================================================== | |
782 | # makes sense of the CPX packet | |
783 | #==================================================================== | |
784 | sub process_cpx_pkt{ | |
785 | ||
786 | my %RtnTyps = | |
787 | ( | |
788 | '0000' => 'Dfill', | |
789 | '0001' => 'Ifill', | |
790 | '0010' => 'Strm_Load', | |
791 | '0011' => 'Evict_Inv', | |
792 | '0100' => 'Store_Ack', | |
793 | '0101' => 'Flush', | |
794 | '0110' => 'Strm_Store_Ack', | |
795 | '0111' => 'Int', | |
796 | '1000' => 'FP', | |
797 | '1001' => 'blank', | |
798 | '1010' => 'Fwd_req', | |
799 | '1011' => 'Fwd_Reply', | |
800 | '1100' => 'Err', | |
801 | ); | |
802 | ||
803 | my $rawpkt = shift @_; | |
804 | my $vld = substr $rawpkt, 0, 1; | |
805 | my $rawtype = substr $rawpkt, 1, 4; | |
806 | my $l2miss = substr $rawpkt, 5, 1; | |
807 | my $err = substr $rawpkt, 6, 2; | |
808 | my $nc = substr $rawpkt, 8, 1; | |
809 | my $shared = substr $rawpkt, 9, 7; | |
810 | my $thrbits = substr $rawpkt, 9, 2; | |
811 | my $rsvd = substr $rawpkt, 16, 1; | |
812 | my $rawdata = substr $rawpkt, 17, 128; | |
813 | ||
814 | my $type = "illegal"; | |
815 | $type = $RtnTyps{$rawtype} if (defined $RtnTyps{$rawtype}); | |
816 | ||
817 | my $data = b2h($rawdata); | |
818 | ||
819 | my $thread = 'x'; | |
820 | if($thrbits eq '00'){ | |
821 | $thread = '0'; | |
822 | } | |
823 | elsif($thrbits eq '01'){ | |
824 | $thread = '1'; | |
825 | } | |
826 | elsif($thrbits eq '10'){ | |
827 | $thread = '2'; | |
828 | } | |
829 | elsif($thrbits eq '11'){ | |
830 | $thread = '3'; | |
831 | } | |
832 | ||
833 | ||
834 | my $pkt = "$thread\t\tCPX: $type l2miss $l2miss err $err nc $nc shared $shared rsvd $rsvd data $data"; | |
835 | return $pkt; | |
836 | } | |
837 | #==================================================================== | |
838 | # binary to hex. | |
839 | #==================================================================== | |
840 | sub b2h{ | |
841 | ||
842 | my $in = shift @_; | |
843 | ||
844 | if($in =~ /x/i){ | |
845 | return "xxxxxxxx"; | |
846 | } | |
847 | ||
848 | my @inlist = split //, $in; | |
849 | ||
850 | my ($res, $i, $digit, @num, $strres); | |
851 | ||
852 | while (@inlist){ | |
853 | $res = 0; | |
854 | $i = shift @inlist; | |
855 | $res = 2 * $res + $i; | |
856 | $i = shift @inlist; | |
857 | $res = 2 * $res + $i; | |
858 | $i = shift @inlist; | |
859 | $res = 2 * $res + $i; | |
860 | $i = shift @inlist; | |
861 | $res = 2 * $res + $i; | |
862 | ||
863 | $digit = sprintf "%lx", $res; | |
864 | push @num, $digit; | |
865 | } | |
866 | ||
867 | $strres = join '', @num; | |
868 | ||
869 | return $strres; | |
870 | ||
871 | } | |
872 | ||
873 | #==================================================================== | |
874 | #truncate PC length from the MSB zeroes (or FF-s) | |
875 | #==================================================================== | |
876 | sub truncate_len{ | |
877 | ||
878 | my $pc = $_[0]; | |
879 | my($length) = length($pc); | |
880 | my($va_length) = 12; | |
881 | ||
882 | if($length>$va_length){ | |
883 | $pc =~ /(.{$va_length})$/; | |
884 | $pc = $1; | |
885 | } | |
886 | elsif($pc=~ /^f/i) { | |
887 | $pc= 'f' x ($va_length-$length) . $pc; | |
888 | } | |
889 | else { | |
890 | $pc= '0' x ($va_length-$length) . $pc; | |
891 | } | |
892 | print "pc= $pc\n" if($debug); | |
893 | $pc; | |
894 | } | |
895 | ||
896 | #==================================================================== | |
897 | ||
898 | #==================================================================== | |
899 | # sorti: sorts the input file in a special way. | |
900 | # very simple - the RTL messages are ordered and the SAS | |
901 | # messages are ordered, so all we need is merge sorting. | |
902 | # Notes: | |
903 | #------- | |
904 | # disambiguate lines on the same timetick. - register updates, | |
905 | # and info-perm messages | |
906 | #==================================================================== | |
907 | sub sorti{ | |
908 | ||
909 | if($logfile =~ /\.gz$/) { | |
910 | open(VCSRAW1, "gunzip -c $logfile | egrep 'sas|MAT|trig' | ") || die "cannot open gunzip -c $logfile"; | |
911 | open(VCSRAW2, "gunzip -c $logfile | egrep -v 'sas|MAT|trig' | ") || die "cannot open gunzip -c $logfile"; | |
912 | }else{ | |
913 | open(VCSRAW1, "egrep 'sas|MAT|trig' $logfile | ") || die "cannot open $logfile"; | |
914 | open(VCSRAW2, "egrep -v 'sas|MAT|trig' $logfile | ") || die "cannot open $logfile"; | |
915 | } | |
916 | ||
917 | my $curtime1 = 0; | |
918 | my $curtime2 = 0; | |
919 | my $gets1 = 1; | |
920 | my $gets2 = 1; | |
921 | my $s1line; | |
922 | my $s2line; | |
923 | ||
924 | while(1) { | |
925 | ||
926 | # get the vcsraw1 | |
927 | #---------------- | |
928 | if($gets1){ | |
929 | $s1line = <VCSRAW1>; | |
930 | if(!$s1line){ | |
931 | if($s2line){ | |
932 | print $s2line; | |
933 | } | |
934 | while(<VCSRAW2>){ | |
935 | print; | |
936 | } | |
937 | last; | |
938 | } | |
939 | else{ | |
940 | if($s1line =~ /^(\d+)\s*:.*(gl|tl|pstate)_reg-M/) { | |
941 | $curtime1 = $1 + 3; | |
942 | }elsif($s1line =~ /^(\d+)\s*:.*reg-M/) { | |
943 | $curtime1 = $1 + 10; | |
944 | }elsif($s1line =~ /^(\d+)\s*:/) { | |
945 | $curtime1 = $1 + 0; | |
946 | }elsif($s1line =~ /^\((\d+)\)\s*:/) { | |
947 | $curtime1 = $1 + 0; | |
948 | } | |
949 | } | |
950 | } | |
951 | ||
952 | # get the vcsraw2 | |
953 | #---------------- | |
954 | if($gets2){ | |
955 | $s2line = <VCSRAW2>; | |
956 | if(!$s2line){ | |
957 | if($s1line){ | |
958 | print $s1line; | |
959 | } | |
960 | while(<VCSRAW1>){ | |
961 | print; | |
962 | } | |
963 | last; | |
964 | } | |
965 | else{ | |
966 | if($s2line =~ /^\((\d+)\)Info-p/) { | |
967 | $curtime2 = $1 + 5; | |
968 | }elsif($s2line =~ /^(\d+)\s*:/) { | |
969 | $curtime2 = $1 + 0; | |
970 | }elsif($s2line =~ /^\((\d+)\)\s*:/) { | |
971 | $curtime2 = $1 + 0; | |
972 | } | |
973 | } | |
974 | } | |
975 | ||
976 | if($curtime1 < $curtime2){ | |
977 | print $s1line; | |
978 | $gets2 = 0; | |
979 | $gets1 = 1; | |
980 | } | |
981 | else{ | |
982 | print $s2line; | |
983 | $gets2 = 1; | |
984 | $gets1 = 0; | |
985 | } | |
986 | } | |
987 | ||
988 | close(VCSRAW1); | |
989 | close(VCSRAW2); | |
990 | ||
991 | exit; | |
992 | ||
993 | } | |
994 | ||
995 | #======================================================= | |
996 | # print ASI mnemonics to make debugging more pleasurable. | |
997 | #======================================================= | |
998 | sub asi_mnem{ | |
999 | my %asis = ( | |
1000 | "4", "ASI_NUCLEUS", | |
1001 | "c", "ASI_NUCLEUS_LITTLE", | |
1002 | "10", "ASI_AS_IF_USER_PRIMARY", | |
1003 | "11", "ASI_AS_IF_USER_SECONDARY", | |
1004 | "14", "ASI_REAL_MEM", | |
1005 | "15", "ASI_REAL_IO", | |
1006 | "16", "ASI_BLOCK_AS_IF_USER_PRIMARY", | |
1007 | "17", "ASI_BLOCK_AS_IF_USER_SECONDARY", | |
1008 | "18", "ASI_AS_IF_USER_PRIMARY_LITTLE", | |
1009 | "19", "ASI_AS_IF_USER_SECONDARY_LITTLE", | |
1010 | "1c", "ASI_REAL_MEM_LITTLE", | |
1011 | "1d", "ASI_REAL_IO_LITTLE", | |
1012 | "1e", "ASI_BLOCK_AS_IF_USER_P_LITTLE", | |
1013 | "1f", "ASI_BLOCK_AS_IF_USER_S_LITTLE", | |
1014 | "20", "ASI_SCRATCHPAD", | |
1015 | "21", "ASI_MMU", | |
1016 | "22", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_P", | |
1017 | "23", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_S", | |
1018 | "24", "ASI_QUAD_LDD", | |
1019 | "25", "ASI_QUEUE", | |
1020 | "26", "ASI_QUAD_LDD_REAL", | |
1021 | "27", "ASI_NUCLEUS_BLK_INIT_ST_QUAD_LDD", | |
1022 | "2a", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_P_LITTLE", | |
1023 | "2b", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_S_LITTLE", | |
1024 | "2c", "ASI_QUAD_LDD_LITTLE", | |
1025 | "2e", "ASI_QUAD_LDD_REAL_LITTLE", | |
1026 | "2f", "ASI_NUCLEUS_BLK_INIT_ST_QUAD_LDD_P_LITTLE", | |
1027 | "30", "UNDEFINED", | |
1028 | "31", "ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0", | |
1029 | "32", "ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1", | |
1030 | "33", "ASI_DMMU_CTXT_ZERO_CONFIG", | |
1031 | "35", "ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0", | |
1032 | "36", "ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1", | |
1033 | "37", "ASI_IMMU_CTXT_ZERO_CONFIG", | |
1034 | "38", "ASI_DTSB_TAG_TARGET", | |
1035 | "39", "ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0", | |
1036 | "3a", "ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1", | |
1037 | "3b", "ASI_DMMU_CTXT_NONZERO_CONFIG", | |
1038 | "3d", "ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0", | |
1039 | "3e", "ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1", | |
1040 | "3f", "ASI_IMMU_CTXT_NONZERO_CONFIG", | |
1041 | "40", "ASI_STREAM_MA", | |
1042 | "42", "ASI_SPARC_BIST_CONTROL_OR_INST_MASK_REG_OR_LSU_DIAG_REG", | |
1043 | "43", "ASI_ERROR_INJECT_REG", | |
1044 | "44", "ASI_STM_CTL_REG", | |
1045 | "45", "ASI_LSU_CTL_REG", | |
1046 | "46", "ASI_DCACHE_DATA", | |
1047 | "47", "ASI_DCACHE_TAG", | |
1048 | "48", "ASI_INTR_DISPATCH_STATUS_OBSOLETE", | |
1049 | "49", "ASI_INTR_RECEIVE_OBSOLETE", | |
1050 | "4a", "ASI_OBSOLETE", | |
1051 | "4b", "ASI_SPARC_ERROR_EN_REG", | |
1052 | "4c", "ASI_SPARC_ERROR_STAT_REG", | |
1053 | "4d", "ASI_SPARC_ERROR_ADDR_REG", | |
1054 | "4e", "ASI_ECACHE_TAG_DATA", | |
1055 | "4f", "ASI_HYP_SCRATCHPAD", | |
1056 | "50", "ASI_IMMU", | |
1057 | "51", "ASI_IMMU_TSB_8KB_PTR_REG", | |
1058 | "52", "ASI_IMMU_TSB_64KB_PTR_REG", | |
1059 | "54", "ASI_ITLB_DATA_IN_REG", | |
1060 | "55", "ASI_ITLB_DATA_ACCESS_REG", | |
1061 | "56", "ASI_ITLB_TAG_READ_REG", | |
1062 | "57", "ASI_IMMU_DEMAP", | |
1063 | "58", "ASI_DMMU", | |
1064 | "59", "ASI_DMMU_TSB_8KB_PTR_REG", | |
1065 | "5a", "ASI_DMMU_TSB_64KB_PTR_REG", | |
1066 | "5b", "ASI_DMMU_TSB_DIRECT_PTR_REG", | |
1067 | "5c", "ASI_DTLB_DATA_IN_REG", | |
1068 | "5d", "ASI_DTLB_DATA_ACCESS_REG", | |
1069 | "5e", "ASI_DTLB_TAG_READ_REG", | |
1070 | "5f", "ASI_DMMU_DEMAP", | |
1071 | "60", "ASI_TLB_INVALIDATE_ALL", | |
1072 | "66", "ASI_ICACHE_INSTR", | |
1073 | "67", "ASI_ICACHE_TAG", | |
1074 | "72", "ASI_SWVR_INTR_RECEIVE", | |
1075 | "73", "ASI_SWVR_UDB_INTR_W", | |
1076 | "74", "ASI_SWVR_UDB_INTR_R", | |
1077 | "80", "ASI_PRIMARY", | |
1078 | "81", "ASI_SECONDARY", | |
1079 | "82", "ASI_PRIMARY_NO_FAULT", | |
1080 | "83", "ASI_SECONDARY_NO_FAULT", | |
1081 | "88", "ASI_PRIMARY_LITTLE", | |
1082 | "89", "ASI_SECONDARY_LITTLE", | |
1083 | "8a", "ASI_PRIMARY_NOFAULT_LITTLE", | |
1084 | "8b", "ASI_SECONDARY_NOFAULT_LITTLE", | |
1085 | "e2", "ASI_BLK_INIT_ST_QUAD_LDD_P", | |
1086 | "e3", "ASI_BLK_INIT_ST_QUAD_LDD_S", | |
1087 | "ea", "ASI_BLK_INIT_ST_QUAD_LDD_P_LITTLE", | |
1088 | "eb", "ASI_BLK_INIT_ST_QUAD_LDD_S_LITTLE", | |
1089 | "f0", "ASI_BLK_P", | |
1090 | "f1", "ASI_BLK_S", | |
1091 | "f8", "ASI_BLK_P_LITTLE", | |
1092 | "f9", "ASI_BLK_S_LITTLE" | |
1093 | ); | |
1094 | ||
1095 | my $mykey = $_[0]; | |
1096 | ||
1097 | if(exists $asis{$mykey}){ | |
1098 | return $asis{$mykey}; | |
1099 | } | |
1100 | else { | |
1101 | return ""; | |
1102 | } | |
1103 | ||
1104 | } | |
1105 | #============================================ | |
1106 | ||
1107 | # print cycles or timeticks. | |
1108 | #============================================ | |
1109 | sub format_time | |
1110 | { | |
1111 | my $time = $_[0]; | |
1112 | my $ctime = $_[1]; | |
1113 | my $cycles = $_[2]; | |
1114 | ||
1115 | if($cycles){ | |
1116 | if($ctime){ | |
1117 | $time = int ($time /$ctime); | |
1118 | $time = 'c' . $time; | |
1119 | } | |
1120 | else { die "something is wrong with ctime\n" } | |
1121 | } | |
1122 | $time; | |
1123 | } | |
1124 | ||
1125 | #============================================ |