Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perlmod / AnalyzeDiag / 1.07 / lib / site_perl / 5.8.0 / AnalyzeDiag / Logfile.pm
CommitLineData
86530b38
AT
1# ========== Copyright Header Begin ==========================================
2#
3# OpenSPARC T2 Processor File: Logfile.pm
4# Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5# 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6#
7# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; version 2 of the License.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21#
22# For the avoidance of doubt, and except that if any non-GPL license
23# choice is available it will apply instead, Sun elects to use only
24# the General Public License version 2 (GPLv2) at this time for any
25# software where a choice of GPL license versions is made
26# available with the language indicating that GPLv2 or any later version
27# may be used, or where a choice of which version of the GPL is applied is
28# otherwise unspecified.
29#
30# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31# CA 95054 USA or visit www.sun.com if you need additional information or
32# have any questions.
33#
34# ========== Copyright Header End ============================================
35package AnalyzeDiag::Logfile;
36
37use strict;
38use warnings;
39use File::Spec;
40use Math::BigInt;
41
42use AnalyzeDiag::Output;
43
44use fields qw(filename);
45
46###############################################################################
47
48sub create_from_dir {
49 my $class = shift;
50 my $dir = shift;
51
52 my $vcslog = File::Spec->catfile($dir, 'sim.log');
53 my $saslog = File::Spec->catfile($dir, 'sas.log');
54
55 my $log;
56 if(-e $vcslog) {
57 # RTL Run
58 $log = AnalyzeDiag::Logfile::Rtl->new();
59 $log->filename($vcslog);
60 } elsif(-e $saslog) {
61 # Simulator Run
62 $log = AnalyzeDiag::Logfile::Mom->new();
63 $log->filename($saslog);
64 } else {
65 script_die "Cannot find '$vcslog' or '$saslog'.\n";
66 }
67 return $log;
68}
69
70###############################################################################
71
72sub new {
73 my $this = shift;
74
75 unless (ref $this) {
76 $this = fields::new($this);
77 }
78
79 return $this;
80}
81
82###############################################################################
83
84sub filename {
85 my $this = shift;
86 my $filename = shift;
87 $this->{filename} = $filename if defined $filename;
88 return $this->{filename};
89}
90
91###############################################################################
92
93sub get_cycle_period {
94 my $this = shift;
95
96 script_die "Can't get_cycle_period on abstract superclass!\n";
97}
98
99###############################################################################
100
101sub get_times_for_pcs {
102 my $this = shift;
103 my $pclist = shift;
104
105 my %pchash = map { $_ => [] } @$pclist;
106 my %shortpc = map { $_ => $_ } @$pclist;
107
108 foreach (values %shortpc) { s/^0+// }
109 %shortpc = reverse %shortpc;
110
111 debug "get_times_for_pcs: shortpc hash ->\n";
112 foreach my $pc (keys %shortpc) {
113 debug " short=$pc, long=$shortpc{$pc}\n";
114 }
115
116 my $fh = IO::File->new("<$this->{filename}") or
117 script_die "Can't open '$this->{filename}': $!\n";
118
119 $this->search_file_for_pcs($fh, \%pchash, \%shortpc);
120
121 return \%pchash;
122}
123
124###############################################################################
125
126sub search_file_for_pcs {
127 my $this = shift;
128 my $fh = shift;
129 my $pchash = shift;
130 my $shortpc = shift;
131
132 my $ref = ref $this;
133 script_die "Error: search_file_for_pcs not implemented for $ref!\n";
134}
135
136###############################################################################
137
138sub subtract_times {
139 my $this = shift;
140 my $arg1 = shift;
141 my $arg2 = shift;
142
143 if(ref $arg1 and ref $arg2) {
144 script_die "Error: subtract_times args are different lengths!\n"
145 unless @$arg1 == @$arg2;
146
147 my @results;
148 foreach my $i ( 0 .. (@$arg1 - 1) ) {
149 my $diff = $this->subtract_times($arg1->[$i], $arg2->[$i]);
150 push @results, $diff;
151 }
152
153 return @results;
154 } elsif(not ref $arg1 and not ref $arg2) {
155 my $bi1 = Math::BigInt->new($arg1);
156 my $bi2 = Math::BigInt->new($arg2);
157 my $diff = $bi1->bsub($bi2)->bstr();
158 return $diff;
159 } else {
160 script_die "Error: subtract times needs two ref args or two scalar ".
161 "args, not one of each!\n";
162 }
163}
164
165###############################################################################
166
167sub to_cycles {
168 my $this = shift;
169 my $arg = shift;
170
171 if(ref $arg) {
172 my @results;
173 foreach my $elem (@$arg) {
174 my $cycles = $this->to_cycles($elem);
175 push @results, $cycles;
176 }
177 return @results;
178 } else {
179 my $period = $this->get_cycle_period();
180 return $arg if $period == 1;
181 my $num = Math::BigInt->new($arg);
182 my $quotient = Math::BigInt->new('0');
183 my $remainder = Math::BigInt->new('0');
184 ($quotient, $remainder) = $num->bdiv($period);
185 if ( $remainder > ($period - $remainder ) ) {
186 $num->binc();
187 }
188 $num->bstr();
189 return $num;
190 }
191}
192
193###############################################################################
194###############################################################################
195
196package AnalyzeDiag::Logfile::Rtl;
197
198use strict;
199use warnings;
200
201use IO::File;
202
203use AnalyzeDiag::Output;
204
205use base qw(AnalyzeDiag::Logfile);
206use fields qw(cycle_period);
207
208our $Freq_Regex_m1 = qr/Info:\s*Selected Core Clock Frequency\s(\d+)\s*MHz/;
209our $Pll_Regex_m1 = qr/pll_clk frequency\s*=\s*(\d+)/;
210our $Cmp_div_Regex_m1 = qr/cmp_clk divider\s*=\s*(\d+)/;
211our $Cmp_clk_period_Regex_m1 = qr/cmp_clk period\s*=\s*(\d+)/;
212our $Hex_Regex = qr/[\da-f]+/;
213
214###############################################################################
215
216sub new {
217 my $this = shift;
218
219 $this = fields::new($this);
220
221 return $this;
222}
223
224###############################################################################
225
226sub get_cycle_period {
227 my $this = shift;
228 return $this->{cycle_period} if defined $this->{cycle_period};
229
230 my $fh = IO::File->new("<$this->{filename}") or
231 script_die "Can't open '$this->{filename}': $!\n";
232
233 # Used to be this was the only divider, so old versions of the model
234 # didn't print it out. Make it the default so we can handle old and
235 # new.
236 my $cmp_clk_divider = 2;
237 my $pll_freq;
238
239 while(<$fh>) {
240 if(/$Cmp_clk_period_Regex_m1/) {
241 # I found the period I'm looking for. This trumps everything else.
242 my $period_ps = $1;
243 script_die "Found clock period of 0! in '$this->{filename}'!\n"
244 unless $period_ps;
245 $this->{cycle_period} = $period_ps;
246 chat "Found cycle_period spelled out: $period_ps\n", 2;
247 last;
248 } elsif(/$Pll_Regex_m1/) {
249 $pll_freq = $1;
250 chat "Found PLL frequency: $pll_freq\n", 2;
251 } elsif(/$Cmp_div_Regex_m1/) {
252 $cmp_clk_divider = $1;
253 chat "Found CMP clock divider: $cmp_clk_divider\n", 2;
254 } elsif(/$Freq_Regex_m1/) {
255 # Time's up. Any timing-related messages that haven't shown up
256 # by now aren't coming
257 if(defined $pll_freq) {
258 my $pll_period;
259 # HACK! These are periods hardcoded from cmp_clk.v.
260 # Hopefully, we're using a version of hte model that has the
261 # "cmp_period" defined, so we don't have to use this.
262 my %pll_periods = (
263 2000 => 250,
264 2200 => 227,
265 2333 => 214,
266 2334 => 214, # from old sys_clk.v
267 2400 => 208,
268 2550 => 196,
269 2600 => 192,
270 2800 => 179,
271 default => 208,
272 );
273 $pll_period = exists $pll_periods{$pll_freq} ?
274 $pll_periods{$pll_freq} : $pll_periods{default};
275 my $period_ps = $pll_period * 2 * $cmp_clk_divider;
276 $this->{cycle_period} = $period_ps;
277 chat "Computed cycle_period from PLL ($pll_freq) and div ".
278 "($cmp_clk_divider): $period_ps\n", 2;
279 } else {
280 # Couldn't find anything but the frequency message. Use that.
281 my $freq = $1;
282 my $period_ps = int(1 / $freq * 1000000);
283 $this->{cycle_period} = $period_ps;
284 chat "Guessed at cycle_period from frequency ($freq): $period_ps\n";
285 }
286 last;
287 }
288 }
289
290 script_die "Could not find clock frequency in '$this->{filename}'\n"
291 unless defined $this->{cycle_period};
292
293 return $this->{cycle_period};
294}
295
296###############################################################################
297
298sub search_file_for_pcs {
299 my $this = shift;
300 my $fh = shift;
301 my $pchash = shift;
302 my $shortpc = shift;
303
304 my $last_inst;
305 my $this_inst;
306
307 my @work;
308
309
310 while(<$fh>) {
311 # Find time for PC, don't commit it yet since we don't know if it will
312 # be restarted
313 if(/^ \( (\d+) \) Info-perm \s* thread \( $Hex_Regex \) \s*
314 pc \( 0* ($Hex_Regex) \)/ox
315 )
316 {
317 my ($time, $pc) = ($1, $2);
318 next unless exists $shortpc->{$pc};
319
320 my $long_pc = $shortpc->{$pc};
321 if(exists $pchash->{$long_pc}) {
322 chat " Found pc=$pc, time=$time\n";
323 push @work, [$long_pc, $time];
324 }
325 }
326 elsif(/^ \d+ \: pc-MATCH .* val \s* = \s* 0* ($Hex_Regex) \s* $/ox)
327 {
328
329 my $pc = $1;
330 next unless exists $shortpc->{$pc};
331 my $long_pc = $shortpc->{$pc};
332
333 my $entry = shift @work;
334 script_die "Parse error in log file: Bad pc $entry->[0] ".
335 "(expected $long_pc)!\n" unless $long_pc eq $entry->[0];
336
337 if(not defined $last_inst or $last_inst ne 'retry') {
338 my $time = $entry->[1];
339 chat "PC=$long_pc, time=$time\n";
340 push @{$pchash->{$long_pc}}, $time;
341 } else {
342 debug "Retry!\n";
343 }
344
345 }
346 # Keep track of which instruction was the last one
347 elsif(/^ \d+ \:sas\> \s+ \d+ \: \s+ \[swvp.*\] \s+
348 \<v\: $Hex_Regex \> \s+ \<p\: $Hex_Regex \> \s+ (\S+)/ox
349 )
350 {
351 $last_inst = $this_inst;
352 $this_inst = $1;
353 }
354 }
355
356}
357
358###############################################################################
359###############################################################################
360###############################################################################
361
362package AnalyzeDiag::Logfile::Mom;
363
364use strict;
365use warnings;
366
367use AnalyzeDiag::Output;
368
369use base qw(AnalyzeDiag::Logfile);
370use fields qw();
371
372###############################################################################
373
374sub new {
375 my $this = shift;
376
377 $this = fields::new($this);
378
379 return $this;
380}
381
382###############################################################################
383
384sub get_cycle_period {
385 my $this = shift;
386 return 1;
387}
388
389###############################################################################
390
391sub search_file_for_pcs {
392 my $this = shift;
393 my $fh = shift;
394 my $pchash = shift;
395 my $shortpc = shift;
396
397 my $last_inst;
398 my $this_inst;
399
400 my @work;
401
402
403 while(<$fh>) {
404
405 if(/^ \@(\d+): \s+ \d+ \.pc \= ($Hex_Regex) \s+ \[ .* \s+ latency=\d+ \s+
406 (\S+) /ox)
407 {
408 my ($time, $pc, $this_inst) = ($1, $2, $3);
409 $pc =~ s/^0+//;
410
411 next unless exists $shortpc->{$pc};
412 my $long_pc = $shortpc->{$pc};
413 chat "FOUND PC=$pc\n";
414 chat " Last inst = $last_inst\n" if defined $last_inst;
415 if(not defined $last_inst or $last_inst ne 'retry') {
416 chat "PC=$long_pc, time=$time\n";
417 push @{$pchash->{$long_pc}}, $time;
418 }
419
420 $last_inst = $this_inst;
421
422 }
423
424 }
425
426}
427
428###############################################################################
429###############################################################################
4301;