# ========== Copyright Header Begin ==========================================
# OpenSPARC T2 Processor File: Logfile.pm
# Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
# 4150 Network Circle, Santa Clara, California 95054, U.S.A.
# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# For the avoidance of doubt, and except that if any non-GPL license
# choice is available it will apply instead, Sun elects to use only
# the General Public License version 2 (GPLv2) at this time for any
# software where a choice of GPL license versions is made
# available with the language indicating that GPLv2 or any later version
# may be used, or where a choice of which version of the GPL is applied is
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# ========== Copyright Header End ============================================
package AnalyzeDiag
::Logfile
;
###############################################################################
my $vcslog = File
::Spec
->catfile($dir, 'sim.log');
my $saslog = File
::Spec
->catfile($dir, 'sas.log');
$log = AnalyzeDiag
::Logfile
::Rtl
->new();
$log = AnalyzeDiag
::Logfile
::Mom
->new();
script_die
"Cannot find '$vcslog' or '$saslog'.\n";
###############################################################################
$this = fields
::new
($this);
###############################################################################
$this->{filename
} = $filename if defined $filename;
return $this->{filename
};
###############################################################################
script_die
"Can't get_cycle_period on abstract superclass!\n";
###############################################################################
my %pchash = map { $_ => [] } @
$pclist;
my %shortpc = map { $_ => $_ } @
$pclist;
foreach (values %shortpc) { s/^0+// }
%shortpc = reverse %shortpc;
debug
"get_times_for_pcs: shortpc hash ->\n";
foreach my $pc (keys %shortpc) {
debug
" short=$pc, long=$shortpc{$pc}\n";
my $fh = IO
::File
->new("<$this->{filename}") or
script_die
"Can't open '$this->{filename}': $!\n";
$this->search_file_for_pcs($fh, \
%pchash, \
%shortpc);
###############################################################################
sub search_file_for_pcs
{
script_die
"Error: search_file_for_pcs not implemented for $ref!\n";
###############################################################################
if(ref $arg1 and ref $arg2) {
script_die
"Error: subtract_times args are different lengths!\n"
foreach my $i ( 0 .. (@
$arg1 - 1) ) {
my $diff = $this->subtract_times($arg1->[$i], $arg2->[$i]);
} elsif(not ref $arg1 and not ref $arg2) {
my $bi1 = Math
::BigInt
->new($arg1);
my $bi2 = Math
::BigInt
->new($arg2);
my $diff = $bi1->bsub($bi2)->bstr();
script_die
"Error: subtract times needs two ref args or two scalar ".
"args, not one of each!\n";
###############################################################################
foreach my $elem (@
$arg) {
my $cycles = $this->to_cycles($elem);
my $period = $this->get_cycle_period();
return $arg if $period == 1;
my $num = Math
::BigInt
->new($arg);
my $quotient = Math
::BigInt
->new('0');
my $remainder = Math
::BigInt
->new('0');
($quotient, $remainder) = $num->bdiv($period);
if ( $remainder > ($period - $remainder ) ) {
###############################################################################
###############################################################################
package AnalyzeDiag
::Logfile
::Rtl
;
use base
qw(AnalyzeDiag::Logfile);
use fields
qw(cycle_period);
our $Freq_Regex_m1 = qr/Info:\s*Selected Core Clock Frequency\s(\d+)\s*MHz/;
our $Pll_Regex_m1 = qr/pll_clk frequency\s*=\s*(\d+)/;
our $Cmp_div_Regex_m1 = qr/cmp_clk divider\s*=\s*(\d+)/;
our $Cmp_clk_period_Regex_m1 = qr/cmp_clk period\s*=\s*(\d+)/;
our $Hex_Regex = qr/[\da-f]+/;
###############################################################################
$this = fields
::new
($this);
###############################################################################
return $this->{cycle_period
} if defined $this->{cycle_period
};
my $fh = IO
::File
->new("<$this->{filename}") or
script_die
"Can't open '$this->{filename}': $!\n";
# Used to be this was the only divider, so old versions of the model
# didn't print it out. Make it the default so we can handle old and
if(/$Cmp_clk_period_Regex_m1/) {
# I found the period I'm looking for. This trumps everything else.
script_die
"Found clock period of 0! in '$this->{filename}'!\n"
$this->{cycle_period
} = $period_ps;
chat
"Found cycle_period spelled out: $period_ps\n", 2;
} elsif(/$Pll_Regex_m1/) {
chat
"Found PLL frequency: $pll_freq\n", 2;
} elsif(/$Cmp_div_Regex_m1/) {
chat
"Found CMP clock divider: $cmp_clk_divider\n", 2;
} elsif(/$Freq_Regex_m1/) {
# Time's up. Any timing-related messages that haven't shown up
# HACK! These are periods hardcoded from cmp_clk.v.
# Hopefully, we're using a version of hte model that has the
# "cmp_period" defined, so we don't have to use this.
2334 => 214, # from old sys_clk.v
$pll_period = exists $pll_periods{$pll_freq} ?
$pll_periods{$pll_freq} : $pll_periods{default};
my $period_ps = $pll_period * 2 * $cmp_clk_divider;
$this->{cycle_period
} = $period_ps;
chat
"Computed cycle_period from PLL ($pll_freq) and div ".
"($cmp_clk_divider): $period_ps\n", 2;
# Couldn't find anything but the frequency message. Use that.
my $period_ps = int(1 / $freq * 1000000);
$this->{cycle_period
} = $period_ps;
chat
"Guessed at cycle_period from frequency ($freq): $period_ps\n";
script_die
"Could not find clock frequency in '$this->{filename}'\n"
unless defined $this->{cycle_period
};
return $this->{cycle_period
};
###############################################################################
sub search_file_for_pcs
{
# Find time for PC, don't commit it yet since we don't know if it will
if(/^ \
( (\d
+) \
) Info
-perm \s
* thread \
( $Hex_Regex \
) \s
*
pc \
( 0* ($Hex_Regex) \
)/ox
my ($time, $pc) = ($1, $2);
next unless exists $shortpc->{$pc};
my $long_pc = $shortpc->{$pc};
if(exists $pchash->{$long_pc}) {
chat
" Found pc=$pc, time=$time\n";
push @work, [$long_pc, $time];
elsif(/^ \d+ \: pc-MATCH .* val \s* = \s* 0* ($Hex_Regex) \s* $/ox)
next unless exists $shortpc->{$pc};
my $long_pc = $shortpc->{$pc};
script_die
"Parse error in log file: Bad pc $entry->[0] ".
"(expected $long_pc)!\n" unless $long_pc eq $entry->[0];
if(not defined $last_inst or $last_inst ne 'retry') {
chat
"PC=$long_pc, time=$time\n";
push @
{$pchash->{$long_pc}}, $time;
# Keep track of which instruction was the last one
elsif(/^ \d
+ \
:sas\
> \s
+ \d
+ \
: \s
+ \
[swvp
.*\
] \s
+
\
<v\
: $Hex_Regex \
> \s
+ \
<p\
: $Hex_Regex \
> \s
+ (\S
+)/ox
###############################################################################
###############################################################################
###############################################################################
package AnalyzeDiag
::Logfile
::Mom
;
use base
qw(AnalyzeDiag::Logfile);
###############################################################################
$this = fields
::new
($this);
###############################################################################
###############################################################################
sub search_file_for_pcs
{
if(/^ \@
(\d
+): \s
+ \d
+ \
.pc \
= ($Hex_Regex) \s
+ \
[ .* \s
+ latency
=\d
+ \s
+
my ($time, $pc, $this_inst) = ($1, $2, $3);
next unless exists $shortpc->{$pc};
my $long_pc = $shortpc->{$pc};
chat
" Last inst = $last_inst\n" if defined $last_inst;
if(not defined $last_inst or $last_inst ne 'retry') {
chat
"PC=$long_pc, time=$time\n";
push @
{$pchash->{$long_pc}}, $time;
###############################################################################
###############################################################################