$SIG{__WARN__} = sub {die $_[0]};
# Initialize and defines all kinds of variables
#----------------------------------------------
my(@gl); # global register level per thread
my(@tl); # trap level per thread
my(@cwp); # current window pointer per thread
my($logfile); # what file to read
# global, FP, integer, asi registers
my(@gregs, @fpregs, @regs, @asi_reg);
my($pc, $inst); # program counter, instructions
my(%diag_code, %label); # disassembled diag code and labels
my($time, $spc, $thr, $proc, $reg, $val, $win, $instr, $tmp);
my(@instr_list); # instruction list
my($PROG) = ($0=~ m%([^/]+)$%); # regreport real name
my(%miss); # additional info - less important
my(%notintlb); # additional info - less important
print "===============================================\n";
print "=== OpenSPARC T1 Vlog Version $version ===\n";
print "===============================================\n";
my @Options = qw( debug sas mom h help ccx l2 dram cycles sort! perf);
GetOptions(\%opt, @Options) or die "Error in arguments!\n";
my($debug) = $opt{debug};
my($cycles) = $opt{cycles};
print "===============================================\n";
print "=== Version $PROG ===\n";
print "Usage: vlog [logfilename|path_to_sim.log] [-debug -h -ccx -l2 -dram -cycles -[no]sort] [-perf] \n";
print "-ccx prints ccx related messages\n";
print "-l2 prints l2 related messages\n";
print "-dram prints dram related messages\n";
print "-h prints out this screen\n";
print "-debug is for script debug\n";
print " It will probably be obsoleted in the future \n";
print "-cycles prints the cycles and not the time \n";
print "-sort will sort sim.log according to time stamps first [default is on]\n";
print "-perf will print all kinds of performance data - I, D miss e.t.c.\n";
print "-mom Special mom sas.log file processing\n";
print "===============================================\n";
print "vlog -ccx -l2 -dram >! vlog.log\n";
print "vlog >! vlog.log\n";
print "vlog <my_path>/sim.log >! vlog.log\n";
print "===============================================\n";
if($debug) { print "Debug mode on\n"; }
if($sas) { print "sas mode\n"; }
if($mom) { print "mom mode\n"; }
if($sorti) { print "sort mode\n"; }
if($perf) { print "perf mode\n"; }
#==========================================
# initialize register hashes.
#==========================================
for ($i = 0; $i < 32; $i++){
for ($k = 0; $k < 32; $k++){
for ($k = 0; $k < 64; $k++){
for ($k = 0; $k < 256; $k++){
#==========================================
# figure out logfile to read
#==========================================
my $logfilename = $mom ? "sas.log" : "sim.log";
my @pathname = split '/' , $ARGV[0];
if($pathname[$#pathname] =~ /$logfilename/){
chdir join '/', @pathname or die "cannot change dir\n";
$logfile= (-f $logfilename) ? $logfilename :
(-f "$logfilename.gz") ? "$logfilename.gz" :
&error("Logfile $logfilename or $logfilename.gz not found");
print "\n===== Opening $logfile ======\n";
#-------------------------------------
# log file in N1 is unsorted mess.
# sort it unless soritng is disabled.
# sort by forking a sorting process.
#-------------------------------------
my $pid = open(VCS, "-|");
unless (defined $pid){die "cannot fork $!\n"}
if($logfile =~ /\.gz$/) {
open(VCS, "gunzip -c $logfile |") || die "cannot open gunzip -c $logfile";
open(VCS, "< $logfile") || die "cannot open $logfile";
#============================================================
# get the labels inside the diag.s
if((! -f "symbol.tbl") &&(-f "symbol.tbl.gz")){
system("gunzip symbol.tbl.gz");
if(! -f "symbol.tbl") {print "no symbol.tbl\n"; exit 0;}
open(SYM , "symbol.tbl") || die " BAD BAD symbol.tbl opening";
my @symline = split /\s+/;
if($#symline != 3){die "something is wrong with symbol.tbl\n";}
my $pc = truncate_len($symline[1]);
if(exists $label{$pc} and $label{$pc} eq 'main'){
$label{$pc} = $symline[0];
print "label $label{$pc}, $pc\n" if($debug);
my(@diag_exe_files) = `ls diag*.exe*`;
print "Warning: No diag.\*exe files!!!\n";
my($exe_file, $exe_file_gz);
foreach $exe_file (@diag_exe_files){
$exe_file_gz = $exe_file . ".gz";
if(!(-e $exe_file) && (-e $exe_file_gz)){ system("gunzip $exe_file_gz"); }
print "Will extract instruction info from: $exe_file \n";
open(DIS, "g_objdump -m sparc:v9B -d $exe_file | ") || die "BAD objdump";
if(/^([a-f\d]+):\s+.. .. .. ..\s+(.*)$/) {
if($inst =~ /\((\d+)\)/){ # convert from decimal to hex.
my $inst_left = $` . '(0x';
my $inst_cent = sprintf("%lx",$1);
my $inst_right = ')' . $';
my $asi_str = asi_mnem($inst_cent);
$inst = $inst_left . $inst_cent . ' ' . $asi_str . $inst_right;
#============================================================
if(/MISMATCH/) { print ;print "\n"; next;}
elsif(/timeout/i) { print ;print "\n"; next;}
elsif(/error/i) { print ;print "\n"; next;}
elsif(/fail/i) { print ;print "\n"; next;}
elsif(/wrong/i) { print ;print "\n"; next;}
elsif(/good trap/i) { print ;print "\n"; next;}
# some messing around needed to calculate the clock period.
#----------------------------------------------------------
elsif(/cmp_clk period\s*=\s*(\d+)/){
print "cycle time is $ctime\n";
die "Found clock period of 0!\n" unless $ctime;
elsif(!$found_ctime && /cmp_clk divider\s*=\s*(\d+)/){
print "cmp_clk_divider is $cmp_clk_divider\n";
elsif(!$found_ctime && /pll_clk frequency\s*=\s*(\d+)/i){
print "pll_freq time is $pll_freq\n";
elsif(!$found_ctime && /Selected Core Clock Frequency\s(\d+)\s*MHz/){
if($pll_freq && $cmp_clk_divider){
my %pll_periods = ( # HACK! These are periods hardcoded from cmp_clk.v.
2000 => 250, # Hopefully, we're using a version of hte model that has the
2200 => 227, # "cmp_period" defined, so we don't have to use this.
$pll_period = exists $pll_periods{$pll_freq} ? $pll_periods{$pll_freq} : $pll_periods{default};
$ctime = $pll_period * 2 * $cmp_clk_divider;
print "Computed cycle_period from PLL ($pll_freq) and div ". "($cmp_clk_divider): $ctime\n";
# Couldn't find anything but the frequency message. Use that.
#------------------------------------------------------------
$ctime = int(1 / $freq * 1000000);
print "Guessed at cycle_period from frequency ($freq): $ctime\n";
#=============================
#567: [th02] <v:0x0000000000134000> < not in tlb >
# this is not very important`. It was nice to the perofrmace
#=============================
elsif(/th([\dabcdef]+)\]\s+\<v:0x(\w+)>.*not in tlb/i){
$notintlb{$spc}{$thr}{$val} = 1;
print "switch on tlb message $_\n" if($debug);
# this is VERY IMPORTANT - the register updates:
elsif(/^(\d+):.*reg.updated\s*->\s*spc.(\d).\s*thread.(\d)/){
$time = format_time($1, $ctime, $cycles);
if(/float_reg.updated.*reg#\((\w+)\).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tFPREG UPDATE <%s = %s>\n", $time, $spc, $thr, $reg, $val;
my @chars = split //, $val;
if($reg =~ /%[df](\d+)/){
die " $time: something is wrong with FP updates\n";
elsif(/window.(\w+).*reg#\((\w+)\).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tREG UPDATE <%s = %s> in window %s\n", $time, $spc, $thr, $reg, $val, $win;
elsif(/asi_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tASI REG UPDATE <ASI = $2> in window %s\n", $time, $spc, $thr, $1;
elsif(/canrestore_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tCANRESTORE REG UPDATE <CANRESTORE = $2> in window %s\n", $time, $spc, $thr, $1;
elsif(/cansave_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tCANSAVE REG UPDATE <CANSAVE = $2> in window %s\n", $time, $spc, $thr, $1;
elsif(/ccr_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tCCR REG UPDATE <CCR = $2> in window %s\n", $time, $spc, $thr, $1;
elsif(/cleanwin_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tCLEANWIN REG UPDATE <CLEANWIN = $2> in window %s\n", $time, $spc, $thr, $1;
elsif(/cwp_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tCWP REG UPDATE <CWP = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/hpstate_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tHPSTATE REG UPDATE <HPSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/htba_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tHTBA REG UPDATE <HTBA = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/hstate2_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tHSTATE2 REG UPDATE <HSTATE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/hstate3_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tHSTATE3 REG UPDATE <HSTATE3 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/otherwin_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tOTHERWIN REG UPDATE <OTHERWIN = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/pil_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tPIL REG UPDATE <PIL = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/pstate_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tPSTATE REG UPDATE <PSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/tba_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTBA REG UPDATE <TBA = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/tl_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTL REG UPDATE <TL = %d>\n", $time, $spc, $thr, $tl[$proc];
elsif(/gl_reg.updated.*window.(\w+).*val = 0*(\w+)/){
printf "%-10s: C%dT%d\t\tGL REG UPDATE <GL = $2>\n", $time, $spc, $thr;
elsif(/tstate1_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTSTATE1 REG UPDATE <TSTATE1 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/tstate2_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTSTATE2 REG UPDATE <TSTATE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/ttype1_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTTYPE1 REG UPDATE <TTYPE1 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/ttype2_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTTYPE2 REG UPDATE <TTYPE2 = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/wstate_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tWSTATE REG UPDATE <WSTATE = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/hstick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tHSTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/stick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tSTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/tick_cmpr_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tTICK_CMPR REG UPDATE <TICK_CMPR = %s> in window %s\n", $time, $spc, $thr, $2, $1;
elsif(/y_reg.updated.*window.(\w+).*val = (\w+)/){
printf "%-10s: C%dT%d\t\tY REG UPDATE <Y = %s> in window %s\n", $time, $spc, $thr, $2, $1;
print "$_ - an undetected register\n" if ($debug);
#================================
# VERY IMPORTANT - PC extraction
# the notintlb and miss info
# everything else is crucial.
#================================
elsif(!$sas && /info-perm/i){
if(/^.(\d+).info-perm\s+thread.([\dabcdef]+).\s+pc.(\w+)/i){
$time = format_time($1, $ctime, $cycles);
die "See this\n$_\nsomething is wrong with the PC extraction\n";
$instr = $diag_code{$val};
printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr;
printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val};
my($notintlb, $imiss, $dmiss, $short_val);
if((exists $miss{I}{$spc}{$thr}{$short_val}) && ( $miss{I}{$spc}{$thr}{$short_val} == 1) && $perf){
$miss{I}{$spc}{$thr}{$short_val} = 0;
if((exists $miss{D}{$spc}{$thr}{$short_val}) && ( $miss{D}{$spc}{$thr}{$short_val} == 1) && $perf){
$miss{D}{$spc}{$thr}{$short_val} = 0;
if(exists $notintlb{$spc}{$thr}{$val} && $notintlb{$spc}{$thr}{$val} && $perf){
$notintlb = "not in tlb";
$notintlb{$spc}{$thr}{$val} = 0;
print "switch off tlb message $_\n" if($debug);
my $asi_str = asi_mnem($asi_reg[$proc]);
$instr =~ s/%asi/%asi ($asi_reg[$proc] $asi_str)/;
printf "%-10s: C%dT%d v%-12s \t%-30s $notintlb $imiss $dmiss\n", $time, $spc, $thr, $val, $instr;
if($instr =~ /%fp\W|%sp\W|%fp$|%sp$/){
@instr_list = split /\s+/, $instr;
printf "%-10s: C%dT%d v%-12s \tWARNING probably illegal instruction - could not translate\n", $time, $spc, $thr, $val;
#====================================
# also very important - SAS only runs
#====================================
elsif($sas && /^\((\d+)\):sas>\s+\d+:\s+\[th([\dabcdef]+)\]\s+<v:0x(\w+)>\s+<p:0*(\w+)>\s(.*)/){
$time = format_time($1, $ctime, $cycles);
printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr;
printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val};
printf "%-10s: C%dT%d v%-12s \t%-30s \(pa=%-12s\)\n", $time, $spc, $thr, $val, $instr, $pa;
@instr_list = split /\s+/, $instr;
#@1101: 0000.pc=00000000000400ac inst[lstore] in switch stage /wo speculation, latency=0
elsif($mom && /^\@(\d+):\s+(\d+)\.pc=(\w+)\s+inst/){
$time = format_time($1, $ctime, $cycles);
if(exists $diag_code{$val}){
$instr = $diag_code{$val};
$instr = "Instruction not found";
printf "%-10s: C%dT%d ======================================\n", $time, $spc, $thr;
printf "%-10s: C%dT%d LABEL <%s>:\n", $time, $spc, $thr, $label{$val};
printf "%-10s: C%dT%d v%-12s \t%-30s\n", $time, $spc, $thr, $val, $instr;
#=============================
#=============================
elsif($ccx && (/^(\d+):Info cpu.(\d). cpx.*->\s*(\w+)/)) {
$time = format_time($1, $ctime, $cycles);
my($pkt) = process_cpx_pkt($rawpkt);
print "debug cpx: $_\n" if($debug);
printf "%-10s: C${spc}T$pkt\n", $time;
elsif(/^(\d+):Info cpu.(\d). pcx.*->\s*(\w+)/) {
$time = format_time($1, $ctime, $cycles);
my($pkt) = process_pcx_pkt($rawpkt);
print "debug pcx: $_\n" if($debug);
printf "%-10s: C$spc$pkt\n", $time;
if($pkt =~ /^T(\d).*([id])fill_req.*addr\s+\w*(\w{8})\s/i){
$miss{$iord}{$spc}{$thr}{$addr} = 1;
print " setting $iord $spc $thr $addr miss \n" if($debug);
elsif($l2 && /^(\d+):\s+(L2 bank.*)/) {
$time = format_time($1, $ctime, $cycles);
if($rawpkt =~ /core\s+(\d+),\s+thread\s+(\d+)/){
printf "%-10s: C${spc}T${thr}\t$rawpkt\n", $time;
printf "%-10s: \t$rawpkt\n", $time;
elsif($dram && /^(\d+):\s*(DRAM.*)/) {
$time = format_time($1, $ctime, $cycles);
printf "%-10s: $rawpkt\n", $time;
elsif($dram && /^(\d+):\s*(L2_DRAM.*)/) {
$time = format_time($1, $ctime, $cycles);
printf "%-10s: $rawpkt\n", $time;
elsif(/bad/i) { print "$_\n"; }
#==========================
print STDERR "ERR: $msg!\n";
#==========================
# updates the register values
# I am modeling all registers per thread as one big flat
# register file, index by register window number * N + register number
# where N = 8 for globals and 16 for others
#==========================
if($1 < 8){ # global reg.
$gregs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating global $reg to $gregs[$proc][$1] reg num = $reg_num\n" if($debug);
else{ # not a global reg.
$reg_num = $win*16 + 31 - $1;
$regs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num = $reg_num\n" if($debug);
elsif($reg =~ /%g(\d+)/){ # global reg
$reg_num = 8 * $win + $1;
$gregs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $gregs[$proc][$reg_num] reg_num: $reg_num\n" if($debug);
elsif($reg =~ /%i(\d+)/){ # input reg
$regs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug);
elsif($reg =~ /%l(\d+)/){ # local reg
$reg_num = $win*16 + 8 + $1;
$regs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug);
elsif($reg =~ /%o(\d+)/){ # output reg
$reg_num = $win*16 + 16 + $1;
$regs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $regs[$proc][$reg_num] reg_num: $reg_num\n" if($debug);
elsif($reg =~ /%f(\d+)/){ # FP reg.
$fpregs[$proc][$reg_num] = $val;
print "C${spc}T${thr} debug updating $reg to $fpregs[$proc][$reg_num] reg_num: $reg_num\n" if($debug);
elsif($reg =~ /%d(\d+)/){ # should not come here.
print "%d stuff, man, don't know what to do yet.\n";
#-----------------------------------------------------------------
# prints the relevant registers for the instruction/PC which found it.
if($instr =~ /%(r|g|l|i|o|f|d)\d+/){
printf " C%dT%d\t\told reg values: ", $spc, $thr;
foreach $e (@instr_list){
if($rnumh < 8) { $e =~ s/%r/%g/; }
elsif(($rnumh >= 8) && ($rnumh < 16)) { $e =~ s/%r/%o/; }
elsif(($rnumh >= 16) && ($rnumh < 24)) { $e =~ s/%r/%l/; }
elsif(($rnumh >= 24) && ($rnumh < 32)) { $e =~ s/%r/%i/; }
else { die "something is wrong with register number $rnumh\n";}
$reg_num = $gl[$proc] * 8 + $1;
printf "%s= %s ", $e, $gregs[$proc][$reg_num];
$reg_num = $cwp[$proc]*16 + $1;
printf "%s= %s ", $e, $regs[$proc][$reg_num];
$reg_num = $cwp[$proc]*16 + 8 + $1;
printf "%s= %s ", $e, $regs[$proc][$reg_num];
$reg_num = $cwp[$proc]*16 + 16 + $1;
printf "%s= %s ", $e, $regs[$proc][$reg_num];
printf "%s= %s ", $e, $fpregs[$proc][$reg_num];
print "%d stuff, man, don't know what to do yet.\n";
#====================================================================
# makes sense of the PCX packet
#====================================================================
'00100' => 'Stream_loads',
'00101' => 'Stream_store',
my $vld = substr $rawpkt, 0, 1;
my $rawtype = substr $rawpkt, 1, 5;
my $nc = substr $rawpkt, 6, 1;
my $cpuid = substr $rawpkt, 7, 3;
my $thrid = substr $rawpkt, 10, 2;
my $inv = substr $rawpkt, 12, 1;
my $pf = substr $rawpkt, 13, 1;
my $binit = substr $rawpkt, 14, 1;
my $repl = substr $rawpkt, 15, 2;
my $size = substr $rawpkt, 17, 3;
my $rawaddr = substr $rawpkt, 20, 40;
my $rawdata = substr $rawpkt, 60, 64;
my $addr = b2h($rawaddr);
my $data = b2h($rawdata);
$type = $ReqTyps{$rawtype} if (defined $ReqTyps{$rawtype});
if ($thrid eq '00'){ $reqid = 'T0'; }
elsif($thrid eq '01'){ $reqid = 'T1'; }
elsif($thrid eq '10'){ $reqid = 'T2'; }
elsif($thrid eq '11'){ $reqid = 'T3'; }
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";
#====================================================================
# makes sense of the CPX packet
#====================================================================
'0110' => 'Strm_Store_Ack',
my $vld = substr $rawpkt, 0, 1;
my $rawtype = substr $rawpkt, 1, 4;
my $l2miss = substr $rawpkt, 5, 1;
my $err = substr $rawpkt, 6, 2;
my $nc = substr $rawpkt, 8, 1;
my $shared = substr $rawpkt, 9, 7;
my $thrbits = substr $rawpkt, 9, 2;
my $rsvd = substr $rawpkt, 16, 1;
my $rawdata = substr $rawpkt, 17, 128;
$type = $RtnTyps{$rawtype} if (defined $RtnTyps{$rawtype});
my $data = b2h($rawdata);
my $pkt = "$thread\t\tCPX: $type l2miss $l2miss err $err nc $nc shared $shared rsvd $rsvd data $data";
#====================================================================
#====================================================================
my @inlist = split //, $in;
my ($res, $i, $digit, @num, $strres);
$digit = sprintf "%lx", $res;
#====================================================================
#truncate PC length from the MSB zeroes (or FF-s)
#====================================================================
my($length) = length($pc);
$pc =~ /(.{$va_length})$/;
$pc= 'f' x ($va_length-$length) . $pc;
$pc= '0' x ($va_length-$length) . $pc;
print "pc= $pc\n" if($debug);
#====================================================================
#====================================================================
# sorti: sorts the input file in a special way.
# very simple - the RTL messages are ordered and the SAS
# messages are ordered, so all we need is merge sorting.
# disambiguate lines on the same timetick. - register updates,
#====================================================================
if($logfile =~ /\.gz$/) {
open(VCSRAW1, "gunzip -c $logfile | egrep 'sas|MAT|trig' | ") || die "cannot open gunzip -c $logfile";
open(VCSRAW2, "gunzip -c $logfile | egrep -v 'sas|MAT|trig' | ") || die "cannot open gunzip -c $logfile";
open(VCSRAW1, "egrep 'sas|MAT|trig' $logfile | ") || die "cannot open $logfile";
open(VCSRAW2, "egrep -v 'sas|MAT|trig' $logfile | ") || die "cannot open $logfile";
if($s1line =~ /^(\d+)\s*:.*(gl|tl|pstate)_reg-M/) {
}elsif($s1line =~ /^(\d+)\s*:.*reg-M/) {
}elsif($s1line =~ /^(\d+)\s*:/) {
}elsif($s1line =~ /^\((\d+)\)\s*:/) {
if($s2line =~ /^\((\d+)\)Info-p/) {
}elsif($s2line =~ /^(\d+)\s*:/) {
}elsif($s2line =~ /^\((\d+)\)\s*:/) {
if($curtime1 < $curtime2){
#=======================================================
# print ASI mnemonics to make debugging more pleasurable.
#=======================================================
"c", "ASI_NUCLEUS_LITTLE",
"10", "ASI_AS_IF_USER_PRIMARY",
"11", "ASI_AS_IF_USER_SECONDARY",
"16", "ASI_BLOCK_AS_IF_USER_PRIMARY",
"17", "ASI_BLOCK_AS_IF_USER_SECONDARY",
"18", "ASI_AS_IF_USER_PRIMARY_LITTLE",
"19", "ASI_AS_IF_USER_SECONDARY_LITTLE",
"1c", "ASI_REAL_MEM_LITTLE",
"1d", "ASI_REAL_IO_LITTLE",
"1e", "ASI_BLOCK_AS_IF_USER_P_LITTLE",
"1f", "ASI_BLOCK_AS_IF_USER_S_LITTLE",
"22", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_P",
"23", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_S",
"26", "ASI_QUAD_LDD_REAL",
"27", "ASI_NUCLEUS_BLK_INIT_ST_QUAD_LDD",
"2a", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_P_LITTLE",
"2b", "ASI_AS_IF_USER_BLK_INIT_ST_QUAD_LDD_S_LITTLE",
"2c", "ASI_QUAD_LDD_LITTLE",
"2e", "ASI_QUAD_LDD_REAL_LITTLE",
"2f", "ASI_NUCLEUS_BLK_INIT_ST_QUAD_LDD_P_LITTLE",
"31", "ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0",
"32", "ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1",
"33", "ASI_DMMU_CTXT_ZERO_CONFIG",
"35", "ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0",
"36", "ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1",
"37", "ASI_IMMU_CTXT_ZERO_CONFIG",
"38", "ASI_DTSB_TAG_TARGET",
"39", "ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0",
"3a", "ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1",
"3b", "ASI_DMMU_CTXT_NONZERO_CONFIG",
"3d", "ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0",
"3e", "ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1",
"3f", "ASI_IMMU_CTXT_NONZERO_CONFIG",
"42", "ASI_SPARC_BIST_CONTROL_OR_INST_MASK_REG_OR_LSU_DIAG_REG",
"43", "ASI_ERROR_INJECT_REG",
"48", "ASI_INTR_DISPATCH_STATUS_OBSOLETE",
"49", "ASI_INTR_RECEIVE_OBSOLETE",
"4b", "ASI_SPARC_ERROR_EN_REG",
"4c", "ASI_SPARC_ERROR_STAT_REG",
"4d", "ASI_SPARC_ERROR_ADDR_REG",
"4e", "ASI_ECACHE_TAG_DATA",
"4f", "ASI_HYP_SCRATCHPAD",
"51", "ASI_IMMU_TSB_8KB_PTR_REG",
"52", "ASI_IMMU_TSB_64KB_PTR_REG",
"54", "ASI_ITLB_DATA_IN_REG",
"55", "ASI_ITLB_DATA_ACCESS_REG",
"56", "ASI_ITLB_TAG_READ_REG",
"59", "ASI_DMMU_TSB_8KB_PTR_REG",
"5a", "ASI_DMMU_TSB_64KB_PTR_REG",
"5b", "ASI_DMMU_TSB_DIRECT_PTR_REG",
"5c", "ASI_DTLB_DATA_IN_REG",
"5d", "ASI_DTLB_DATA_ACCESS_REG",
"5e", "ASI_DTLB_TAG_READ_REG",
"60", "ASI_TLB_INVALIDATE_ALL",
"66", "ASI_ICACHE_INSTR",
"72", "ASI_SWVR_INTR_RECEIVE",
"73", "ASI_SWVR_UDB_INTR_W",
"74", "ASI_SWVR_UDB_INTR_R",
"82", "ASI_PRIMARY_NO_FAULT",
"83", "ASI_SECONDARY_NO_FAULT",
"88", "ASI_PRIMARY_LITTLE",
"89", "ASI_SECONDARY_LITTLE",
"8a", "ASI_PRIMARY_NOFAULT_LITTLE",
"8b", "ASI_SECONDARY_NOFAULT_LITTLE",
"e2", "ASI_BLK_INIT_ST_QUAD_LDD_P",
"e3", "ASI_BLK_INIT_ST_QUAD_LDD_S",
"ea", "ASI_BLK_INIT_ST_QUAD_LDD_P_LITTLE",
"eb", "ASI_BLK_INIT_ST_QUAD_LDD_S_LITTLE",
"f8", "ASI_BLK_P_LITTLE",
if(exists $asis{$mykey}){
#============================================
# print cycles or timeticks.
#============================================
$time = int ($time /$ctime);
else { die "something is wrong with ctime\n" }
#============================================