#!/usr/bin/perl #process_trace: process acid output. # tirath.ramdas@eng.monash.edu.au, 2006. #take input: i.e. input file name. #generate output file names. #print for user awareness. $file=@ARGV[0]; $read_outfile=join("_",">read",$file); $write_outfile=join("_",">write",$file); print "input: ",$file,"\n"; print "output: ",$read_outfile,"\n"; print "output: ",$write_outfile,"\n"; #open files. error checking should probably be put in at some point open(DATA, $file); open(R_OUTPUT, $read_outfile); open(W_OUTPUT, $write_outfile); #max and min addresses to aid plotting or whatever $min_address=4294967294; $max_address=0; #lets count reads and writes on our own... $read_count=0; $write_count=0; #dec holds decimal value (the traces are in hex!) $dec=0; #dots while you wait... $dotcounter=0; #and also need to unbuffer output to allow progress dots to show $|=1; print "\n"; #use a hash to identify WaR and RbW samples %address=('0' => "x:s"); #format: (address,'{r|w|s|x}') #explanation: # the address field is the memory address (duh) # r - read, w - write, s - scratch x - special (e.g. for address 0, # which is reserved here for padding the # individial read/write traces # w - WaR - write after read: identified when last reference to # address (at the end of the trace) was a write. # r - RbW - read before write: identified when address is detected for # the first time and it is read. # s - Scratch space; anything that doesn't meet the above criteria # (i.e. was written first then read). $RbW_count=0; $WaR_count=0; #dig in to the trace file... while($line=){ chomp $line; my @fields = split(" ",$line); if($fields[0]=~ /-------/){ #end of memory address trace reached last; } $dec=hex($fields[2]); #update min and max if($min_address > $dec){ $min_address=$dec; } if($max_address < $dec){ $max_address=$dec; } #output individual read and write traces if($fields[1]=~r){ print W_OUTPUT "0\n"; # print R_OUTPUT $dec,"\n"; if(exists $address{$dec}){ if($address{$dec} eq "w"){ #a previously assumed WaR was NOT, so decrement the count. $WaR_count--; } #if it was previously marked as scratch, then it's still scratch. #if it was previously marked ass RbW, then it's now scratch. $address{$dec}="s"; } else{ $address{$dec}="r"; $RbW_count++; } $read_count++; } if($fields[1]=~w){ print R_OUTPUT "0\n"; # print W_OUTPUT $dec,"\n"; if(exists $address{$dec}){ if(!($address{$dec} eq "w")){ $WaR_count++; } } else{ $WaR_count++; } $address{$dec}='w'; $write_count++; } $dotcounter++; if($dotcounter==20000){ $dotcounter=0; print "."; } } print "*BING!*\n\n"; close(R_OUTPUT); close(W_OUTPUT); print "\nreads: ", $read_count, "\n"; print "writes: ", $write_count, "\n"; print "\nlowest address: ", $min_address, "\n"; print "highest address: ", $max_address, "\n"; print "\nRbW: ", $RbW_count, "\n"; print "WaR: ", $WaR_count, "\n"; #double check WaR (and unique address count too while we're at it): #Note: can't verify RbW like this because some RbW space may have been # reclaimed as scratch, or even WaR space. #This should be disabled when dealing with large traces; ploughing through # a massive hash can't be good. $WaR_verify=0; $UqA_verify=0; while(($dec, $state) = each (%address)){ if($state eq "w"){ $WaR_verify++; } $UqA_verify++; } #need to subtract 1 from UqA_verify (to eliminate the '0' key) $UqA_verify--; print "Number of unique addresses inferred from trace: ", $UqA_verify, "\n"; if($WaR_verify!=$WaR_count){ print "\n***WARNING: Something weird going on... WaR count mismatch! (", $WaR_verify,")\n\n" } #extract some info from acid's output print "\nacid reports the following:\n"; while($line=){ chomp $line; if($line=~ /Total Instruction Count/){ print $line,"\n"; } if($line=~ /Unique Data Addresses Accessed/){ print $line,"\n"; #this should be the last thing in the acid output that # we are interested in... so it should be safe to bail now. last; } } close(DATA);