diff options
Diffstat (limited to 'src/build')
-rwxr-xr-x | src/build/simics/hb-simdebug.py | 81 | ||||
-rwxr-xr-x | src/build/tools/cpfiles.pl | 27 | ||||
-rwxr-xr-x | src/build/vpo/VBU_Cacheline.pm | 474 | ||||
-rwxr-xr-x | src/build/vpo/hb-istep | 565 | ||||
-rwxr-xr-x | src/build/vpo/hb-virtdebug.pl | 2 |
5 files changed, 1131 insertions, 18 deletions
diff --git a/src/build/simics/hb-simdebug.py b/src/build/simics/hb-simdebug.py index 0f5774a2e..4e5dbb2ee 100755 --- a/src/build/simics/hb-simdebug.py +++ b/src/build/simics/hb-simdebug.py @@ -59,6 +59,30 @@ def dumpL3(): # Functions to run isteps #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ + +def findAddr( symsFile, symName ): + + + #Find location of the variable from the image's .syms file + for line in open(symsFile): + if symName in line : #if found + #print line + x = line.split(",") + addr = int(x[1],16) + #print "addr = 0x%x"%(addr) + size = int(x[3],16) + #print "size = 0x%x"%(size) + break + + #print line + if symName not in line: #if not found + print "\nCannot find %s in %s"%( symName,symsFile) + return "0" + + ## returns an int + return addr + + def hb_istep_usage(): print "hb-istep usage:" print " istepmode - enable IStep Mode. Must be executed before simics run command" @@ -89,7 +113,7 @@ def bump_g_SeqNum() : ## def runClocks() : - SIM_continue( 100000 ) + SIM_continue( 250000 ) return None ## @@ -103,14 +127,16 @@ def runClocks() : ## 3. hardware def sendCommand( cmd ): global g_IStep_DEBUG - CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd) + ## CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd) + CommandStr = "phys_mem.write 0x%8.8x %s 8"%(g_SPLess_Command_Reg, cmd ) ## send command to Hostboot - ## print CommandStr + if ( g_IStep_DEBUG ) : + print CommandStr (result, out) = quiet_run_command(CommandStr, output_modes.regular ) if ( g_IStep_DEBUG ) : - print "sendCommand( 0x%x ) returns : " + "0x%x"%(cmd, result) + " : " + out + print "sendCommand( \"%s\" ) returns : "%(cmd) + "0x%x"%(result) + " : " + out return result @@ -134,7 +160,9 @@ def printStsHdr( status ): ## def getStatus(): global g_IStep_DEBUG - StatusStr = "cpu0_0_0_2->scratch" + + ## StatusStr = "cpu0_0_0_2->scratch" + StatusStr = "phys_mem.read 0x%8.8x 8"%(g_SPLess_Status_Reg ) ( result, out ) = quiet_run_command( StatusStr, output_modes.regular ) if ( g_IStep_DEBUG ) : @@ -177,14 +205,20 @@ def getSyncStatus( ) : ## write to scratch reg 3 to set istep or normal mode, check return status def setMode( cmd ) : - IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007" - NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504" + global g_IStep_DEBUG + global g_SPLess_IStepMode_Reg + + ##IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007" + ##NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504" + IStepModeStr = "phys_mem.write 0x%8.8x 0x4057b007_4057b007 8"%(g_SPLess_IStepMode_Reg) + NormalModeStr = "phys_mem.write 0x%8.8x 0x700b7504_700b7504 8"%(g_SPLess_IStepMode_Reg) - count = 10 + count = 50 if ( cmd == "istep" ) : (result, out) = quiet_run_command( IStepModeStr ) + # print IStepModeStr # print "set istepmode returned 0x%x"%(result) + " : " + out expected = 1 elif ( cmd == "normal" ) : @@ -201,7 +235,8 @@ def setMode( cmd ) : result = getStatus() readybit = ( ( result & 0x4000000000000000 ) >> 62 ) - print "Setting %s mode, readybit=%d..."%( cmd, readybit ) + if ( g_IStep_DEBUG ) : + print "Setting %s mode, readybit=%d..."%( cmd, readybit ) if ( readybit == expected ) : print "Set %s Mode success."%(cmd) return 0 @@ -229,7 +264,6 @@ def get_istep_list( inList ): return None - def print_istep_list( inList ): print "IStep\tSubStep\tName" print "---------------------------------------------------" @@ -322,17 +356,28 @@ def find_in_inList( inList, substepname) : ## sN..M ## <substepname1>..<substepname2> -## declare GLOBAL g_IStep_DEBUG +## declare GLOBAL g_IStep_DEBUG & SPLess memory mapped regs g_IStep_DEBUG = 0 -def istepHB( str_arg1 ): - +g_SPLess_IStepMode_Reg = "" +g_SPLess_Command_Reg = "" +g_SPLess_Status_Reg = "" +def istepHB( symsFile, str_arg1 ): + global g_IStep_DEBUG + global g_SPLess_IStepMode_Reg + global g_SPLess_Command_Reg + global g_SPLess_Status_Reg + + ## find addresses of the memory-mapped SPLess regs in the image + g_SPLess_IStepMode_Reg = findAddr( symsFile, "SPLESS::g_SPLess_IStepMode_Reg" ) + g_SPLess_Command_Reg = findAddr( symsFile, "SPLESS::g_SPLess_Command_Reg" ) + g_SPLess_Status_Reg = findAddr( symsFile, "SPLESS::g_SPLess_Status_Reg" ) + ## simics cannot be running when we start, or SIM_continue() will not work ## and the Status reg will not be updated. if ( SIM_simics_is_running() ) : print "simics must be halted before issuing an istep command." - return; - - + return; + ## start with empty inList. Put some dummy isteps in istep4 for debug. n = 10 ## size of inlist array inList = [[None]*n for x in xrange(n)] ## init to nothing @@ -503,12 +548,14 @@ Examples: \n # implement isteps #------------------------------------------------ def hb_istep(str_arg1): + + syms = default_syms if ( str_arg1 == None): hb_istep_usage() else: ## print "args=%s" % str(str_arg1) - istepHB( str_arg1 ) + istepHB( syms, str_arg1 ) return None diff --git a/src/build/tools/cpfiles.pl b/src/build/tools/cpfiles.pl index 3c71b55fa..520c6a1c1 100755 --- a/src/build/tools/cpfiles.pl +++ b/src/build/tools/cpfiles.pl @@ -79,6 +79,16 @@ my @files = ("src/build/tools/hb-parsedump.pl", "img/vbu_targeting.bin", "img/isteplist.csv", ); + +# copy vpo files into working dir for AWAN +my @vpofiles = ("src/build/vpo/hb-dump", + "src/build/vpo/hb-errl", + "src/build/vpo/hb-istep", + "src/build/vpo/hb-printk", + "src/build/vpo/hb-trace", + "src/build/vpo/hb-virtdebug.pl", + "src/build/vpo/VBU_Cacheline.pm", + ); #Directories in base git repository my @gitRepoDirs = ("img", @@ -98,8 +108,9 @@ my $numArgs = $#ARGV + 1; my $test = 0; #Flag to overwrite hbicore.<syms|bin|list> with the test versions my $inDir = ""; #User specified directory to copy files to +my $vpo = 0; # copy extra vpo files to inDir -if ($numArgs > 2) +if ($numArgs > 3) { #Print command line help print ("ERROR: Too many arguments entered.\n"); @@ -121,6 +132,11 @@ else #Set flag to copy hbicore_test.<syms|bin> to hbcore_test.<syms|bin> $test = 1; } + elsif ($_ eq "--vpo") + { + #Set flag to copy list of vpo files to $inDir + $vpo = 1; + } else { #Save user specified directory @@ -187,6 +203,14 @@ else } #------------------------------------------------------------------------------ +# If vpo flag is set, add the vpo files to the @files array +#------------------------------------------------------------------------------ +if ( $vpo ) +{ + push( @files, @vpofiles ); +} + +#------------------------------------------------------------------------------ # Get the base dir of the git repository #------------------------------------------------------------------------------ my $cwd = getcwd(); @@ -322,5 +346,6 @@ sub printUsage() print (" if it is defined.\n\n"); print (" --help: prints usage information\n"); print (" --test: Copy hbicore_test.<syms|bin|list> to hbicore.<syms|bin|list>\n"); + print (" --vpo: Copy files in src/build/vpo to support vpo operation\n"); } diff --git a/src/build/vpo/VBU_Cacheline.pm b/src/build/vpo/VBU_Cacheline.pm new file mode 100755 index 000000000..23a1d30da --- /dev/null +++ b/src/build/vpo/VBU_Cacheline.pm @@ -0,0 +1,474 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/vpo/VBU_Cacheline.pm $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2011 - 2012 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or other- +# wise divested of its trade secrets, irrespective of what has +# been deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END +# +# Name: hb-modify-cacheline.pm +# +# Purpose: routines for reading and writing a 64-bit value into L3 in an +# AWAN session. Accepts an address into L3, and 64-bit data hex word +# (write). +# VBU can only read/write to memory in 128-byte cachelines, so if +# we want to write a memory location we must read in the entire +# cacheline, modify the correct byte(s) and then write it back. +# Called from shell script do_p8vbu_script_hbi* +# Written in perl because that is what is being used for the debug +# framework +# +# Author: Mark Wenning +# + +package VBU_Cacheline; +require Exporter; + +our @ISA = qw( Exporter ); +our @EXPORT = qw( CLread CLwrite RunClocks P8_Ins_Start P8_Ins_Stop P8_Ins_Query SetFlags); + + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use strict; +use warnings; +use POSIX; +use Fcntl; + +## 64-bit input +use bigint; +no warnings 'portable'; + +#------------------------------------------------------------------------------ +# Forward declarations +#------------------------------------------------------------------------------ +sub CLread; +sub CLwrite; +sub RunClocks; +sub P8_Ins_Start; +sub P8_Ins_Stop; +sub P8_Ins_Query; +sub P8_Flush_L2; +sub SetFlags; + + +############################################ +## constants +## use constant MAX_NUM_TRACE_BUFFERS => 24; +############################################ +my $CLfile = "./istepmodereg.dma"; +my $CORE = "-c3"; +my $SIM_CLOCKS = "4000000"; + +## later... +my $vbuToolsDir = "/gsa/ausgsa/projects/h/hostboot/vbutools"; + + +my $DUMPCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_dump_l3"; +my $LOADCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_load_l3"; +## my $FLUSHCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_l2_flush.x86 $CORE"; +my $FLUSHCMD = "/afs/awd/projects/eclipz/lab/p8/compiled_procs/procs/p8_l2_flush_wrap.x86 $CORE -quiet"; +my $FLUSHQUERY = "/afs/awd.austin.ibm.com/projects/eclipz/lab/p8/gsiexe/p8_check_l3"; +my $RUNCLKSCMD = "simclock"; + +my $QUERYCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_query"; +my $STOPCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_stop"; +my $STARTCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_start"; +## ## later... +## ## my $QUERYCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -query"; +## ## my $STOPCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -stop"; +## ## my $STARTCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -start"; + +############################################# +## Internal Globals +############################################# +my $CLdebug = 0; +my $CLtest = 0; + +## flushed Flag, if 0, it means the L2 cache has not been flushed. +## It must be flushed once before doing L3 reads +my $L2_Flushed = 0; + + +## +#============================================================================== +# SUBROUTINES +#============================================================================== + + +## +## Read the cacheline at addr from L3 and dump it to a binary file. +## Assumes that the input address is a binary addr on a 128 byte boundary +## +sub readcacheline( $ ) +{ + my ( $addr ) = @_; + my $cmd; + ## my $hexaddr = sprintf( "0x%x", $addr ); + my $hexaddr = sprintf( "%x", $addr ); + + if ( $CLdebug ) { print STDOUT "-- Read cacheline at $hexaddr...\n"; } + + ## Stop simulation so we can read L3 properly + P8_Ins_Stop(); + + ## flush L2 if necessary + P8_Flush_L2(); + + $cmd = "$DUMPCMD $hexaddr 1 -f $CLfile -b $CORE"; + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + ( system( $cmd ) == 0 ) + or die "$cmd failed $? : $! \n"; + + ## Start simulation back up. + ## P8_Ins_Start(); + +} + + +## +## derived from Perl Cookbook, 8.13 +## pack/unpack format is unsigned big endian 32-bit hi, lo +## however, the input data from getopts still assumes that perl is compiled +## for 64-bit #s +## +sub modifycacheline( $$ ) +{ + my ( $offset, $data ) = @_; + + my $typedef = 'N N'; # 2 32-bit network order + my $sizeof = length( pack($typedef,() ) ); + my $filesize = -s $CLfile; + my $buffer; + + open( FH, "+< $CLfile") or die "can't open $CLfile : $!"; + binmode FH; ## not really necessary, but.... + seek( FH, $offset, SEEK_SET) or die "seek $CLfile failed: $!"; + read( FH, $buffer, $sizeof) == $sizeof or die "read failed: $!"; + + ( my $hi, my $lo ) = unpack($typedef, $buffer); + + $hi = ($data >> 32) ; + $lo = ($data & 0x00000000ffffffff); + + $buffer = pack($typedef, $hi, $lo ); + + # back up one record + seek( FH, -$sizeof, SEEK_CUR) or die "seek $CLfile failed: $!"; + + print FH $buffer; + + close( FH ) or die "close $CLfile failed: $!"; +} + +## +## Write modified file back to L3 cacheline. +## This assumes that addr has already been converted to binary addr on a +## 128 byte boundary +## +sub writecacheline( $ ) +{ + my ( $addr ) = @_; + my $cmd; + ## my $hexaddr = sprintf( "0x%x", $addr ); + my $hexaddr = sprintf( "%x", $addr ); + + ## Stop simulation so we can write L3 + P8_Ins_Stop(); + + $cmd = "$LOADCMD -o $hexaddr -f $CLfile -b $CORE"; + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + ( system( $cmd ) == 0 ) + or die "$cmd failed, $? : $! \n"; + + ## Start sim back up + ## P8_Ins_Start(); + +} + + +## +## Query the state of the simulator, "RUNNING" or "STOPPED". +## +sub P8_Ins_Query() +{ + my $cmd = "$QUERYCMD"; + my $retstr = ""; + + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + + ## execute it with backticks so we can get the output. + $retstr = `$cmd`; + if ( $? != 0 ) { die "$cmd failed $? : $! \n"; } + + chomp( $retstr ); + + if ( $CLdebug ) { print STDOUT "-- P8_Ins_Query returned $retstr\n"; } + + if ( ($retstr ne "STOPPED" ) + && ($retstr ne "RUNNING" ) + ) + { + die "invalid string \"$retstr\" from P8_Ins_Query\n"; + } + + return $retstr; +} + + +## +## Stop the simulation. Necessary to read and write L3 . +## +sub P8_Ins_Start() +{ + my $cmd = "$STARTCMD"; + + if ( P8_Ins_Query() eq "STOPPED" ) + { + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + + ( system( $cmd ) == 0 ) + or die "$cmd failed $? : $! \n"; + + + ## reset the flushFlag, need to flush again before a read. + $L2_Flushed = 0; + } + else + { + if ($CLdebug) { print STDOUT "-- P8_Ins_Start: already RUNNING\n"; } + } + +} + + +## +## Stop the simulation. +## +sub P8_Ins_Stop() +{ + my $cmd = "$STOPCMD"; + + if ( P8_Ins_Query() eq "RUNNING" ) + { + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + ( system( $cmd ) == 0 ) + or die "$cmd failed $? : $! \n"; + + } + else + { + if ($CLdebug) { print STDOUT "-- P8_Ins_Stop: already STOPPED\n"; } + } + +} + +## +## Check if cache is flushed. +## $TODO +## p8_check_L3 will scan the L3 directory for unfilled cachelines and +## return a string: +## $ p8_check_l3 100 4 -c3 -f $labhome/foo -x -o +## p8_check_l3 - address (0x100) not found in L3 directory. +## +## $ p8_check_l3 100 4 -c3 -f $labhome/foo -x -o +## p8_check_l3 - all addresses found in L3 directory. +## +sub P8_Check_Flushed +{ + my ( $addr, $lines ) = @_; + my $tmpfile = "./tmpflush"; + my $cmd = "$FLUSHQUERY"; + my $rc = 0; + + ## execute it with backticks so we can get the output. + my $retstr = `$cmd $CORE -f $tmpfile -x -o`; + if ( $? != 0 ) { die "$cmd failed $? : $! \n"; } + + chomp( $retstr ); + + if ( $retstr =~ /^.*.all addresses.*/ ) + { + $rc = 1; + } + + return $rc; +} + +## +## Flush L2 Cache +## This only needs to be done once after the clock is stopped, +## thus the toggle flag +## +sub P8_Flush_L2() +{ + my $cmd = "$FLUSHCMD"; + + if ( !$L2_Flushed ) + { + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + ( system( $cmd ) == 0 ) + or die "$cmd failed $? : $! \n"; + + ## mark the CPU as flushed. + $L2_Flushed = 1; + } + + if ($CLdebug) { print STDOUT "-- P8_FLush_L2 : $L2_Flushed\n"; } +} + + +## +## tell the simulator to run for so many clock cycles. +## If simulator is stopped, then start it up first. +## +sub RunClocks() +{ + my $cmd = 0; + + if ( $CLdebug ) { printf STDOUT "-- RunClocks()\n"; } + + ## Check, and start instructions if necessary + if ( P8_Ins_Query( ) ne "RUNNING" ) + { + + P8_Ins_Start(); + } + + $cmd = "$RUNCLKSCMD $SIM_CLOCKS -quiet"; + if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; } + ( system( $cmd ) == 0 ) + or die "$cmd failed, $? : $! \n"; + +} + + +## +## Read a 64-bit value from L3 at hex addr. +## Input is expected to be a hex ascii string +## +sub CLread( $ ) +{ + my ( $addr ) = @_; + my $cmd; + my $CLbase = ( hex($addr) & 0xffffff80); + my $CLoffset = ( hex($addr) & (~0xffffff80) ); + my $result = 0; ## 64-bit hex + + if ( $CLdebug ) { printf STDOUT "-- CLread( %s ) : CLbase=0x%x, CLoffset=0x%x\n", $addr, $CLbase, $CLoffset } + + readcacheline( $CLbase ); + + ## extract quadword from cacheline file + my $typedef = 'N N'; # QuadWord + my $sizeof = length( pack($typedef,() ) ); + my $filesize = -s $CLfile; + my $buffer; + open( FH, "+< $CLfile") or die "can't open $CLfile : $!"; + binmode FH; ## not really necessary, but.... + seek( FH, $CLoffset, SEEK_SET) or die "seek $CLfile failed: $!"; + read( FH, $buffer, $sizeof) == $sizeof or die "read failed: $!"; + close( FH ) or die "close $CLfile failed: $!"; + + ## unpack and reassemble as big-endian + ( my $hi, my $lo ) = unpack($typedef, $buffer); + $result = ( ( ( $hi << 32 ) & 0xffffffff00000000 ) | $lo ); + + if ( $CLdebug ) + { + printf STDOUT "-- CLread( %s ) = 0x%lx ", $addr, $result; + dumpcacheline(" " ); + } + + return ( $result ); +} + +## +## Write command byte to cacheline +## Inputs are expected to be hex ascii strings +## +sub CLwrite( $$ ) +{ + my ( $addr, $data ) = @_; + my $CLbase = ( hex($addr) & 0xffffff80 ); + my $CLoffset = ( hex($addr) & (~0xffffff80) ); + my $CLdata = hex($data); + my $result = 0; + + if ( $CLdebug ) { printf STDOUT "-- CLwrite( %s, %s ) : CLbase=0x%x, CLoffset=0x%x, CLdata=0x%lx\n", + $addr, $data, $CLbase, $CLoffset, $CLdata; } + + ## clear the cacheline file + system( "rm -f $CLfile" ); + + ## issue the command to dump the cacheline to a file + readcacheline( $CLbase ); + + ## dumpcacheline( "after read", $CLfile ); + + ## modify the cacheline file + modifycacheline( $CLoffset, $data ); + + ## dumpcacheline( "after modify", $CLfile ); + + ## write the cacheline back to L3 + writecacheline( $CLbase ); + + if ( $CLdebug ) + { + ## check, clear the cacheline file and read again + system( "rm -f $CLfile" ); + readcacheline( $CLbase ); + dumpcacheline( "Readback", $CLfile ); + } + +} + + +sub dumpcacheline() +{ + my ( $comment ) = @_; + + if ( $CLdebug ) + { + print STDOUT "-- $comment, dump cache file :\n"; + system( "xxd $CLfile" ); + } + +} + +sub SetFlags( $$ ) +{ + my ( $debug, $test ) = @_; + + $CLdebug = $debug; + $CLtest = $test; + + if ( $CLdebug ) + { + print STDOUT "-- CLdebug=$CLdebug, CLtest=$CLtest\n"; + } +} + + +## required at the end of perl modules +1; + +__END__ diff --git a/src/build/vpo/hb-istep b/src/build/vpo/hb-istep new file mode 100755 index 000000000..2cae8e617 --- /dev/null +++ b/src/build/vpo/hb-istep @@ -0,0 +1,565 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/vpo/hb-istep $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2011 +# +# p1 +# +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code +# +# The source code for this program is not published or other- +# wise divested of its trade secrets, irrespective of what has +# been deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END +# +# Purpose: This perl script works in concert with do_p8vbu_script_hbi_* to +# implement isteps on AWAN. +# +# Description: +# The do.. script will run first to set up the AWAN environment, +# then call hb_istep twice: +# 1) hb_istep --istepmode +# called after loading but before starting HostBoot +# this will check to see if the user has set istep mode, if so +# it will write the Istep_mode signature to L3 memory to put +# HostBoot mode into single-step mode. +# 2) hb_istep --command +# Periodically call RunClocks() to step through HostBoot. +# Checks for status from previous Isteps, and reports status. +# +# Comments: +# +# +# Author: Mark Wenning +# + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use strict; +use warnings; +use POSIX; +use Getopt::Long; + +## 64-bit input +## argh, not compatable with GetOpt!! use bigint; +no warnings 'portable'; + +# read/write cachelines to L3 +use VBU_Cacheline; + +#------------------------------------------------------------------------------ +# Forward Declaration +#------------------------------------------------------------------------------ +sub printUsage; +sub get_istep_list; +sub print_istep_list; +sub find_in_inlist; +sub parse_command; +sub setMode; + +#------------------------------------------------------------------------------ +# Constants +#------------------------------------------------------------------------------ +my $CSVfile = "isteplist.csv"; +my $hbSymsFile = "hbicore.syms"; #Use hbicore.syms +my $CORE = "-c3"; + + +#------------------------------------------------------------------------------ +# Globals +#------------------------------------------------------------------------------ +my $opt_debug = 0; +my $opt_istepmode = 0; +my $opt_normalmode = 0; +my $opt_command = ""; +my $opt_list = 0; +my $opt_help = 0; +my $opt_cmdfile = 0; ## batchmode, later + +my @inList; +$inList[10][10] = (); +## initialize inList to "undefined" +for( my $i = 0; $i <= $#inList; $i++) +{ + for(my $j = 0; $j <= $#inList; $j++) + { + undef( $inList[$i][$j] ); + } +} + +my $g_SeqNum = 0; + + +#============================================================================== +# MAIN +#============================================================================== +## get any environment variables + +my $hbDir = $ENV{'HBDIR'}; +if (defined ($hbDir)) +{ + unless ($hbDir ne "") + { + $hbDir = '.'; #Set to current directory + } +} +else +{ + $hbDir = '.'; #Set to current directory +} + +# print $#ARGV; +if ( ($#ARGV < 0) or ($opt_help) ) +{ + printUsage(); + exit 0 ; +} + + +#------------------------------------------------------------------------------ +# Parse optional input arguments +#------------------------------------------------------------------------------ +GetOptions( "help" => \$opt_help, + "istepmode" => \$opt_istepmode, + "normalmode" => \$opt_normalmode, + "list" => \$opt_list, + "command=s" => \$opt_command, + "cmdfile" => \$opt_cmdfile, + + "debug" => \$opt_debug, + ); + +## +## find the istep mode, command, and status registers in the syms file +## +my $istepmodereg = `grep "SPLESS::g_SPLess_IStepMode_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'`; +chomp $istepmodereg; + +my $commandreg = `grep "SPLESS::g_SPLess_Command_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'`; +chomp $commandreg; + +my $statusreg = `grep "SPLESS::g_SPLess_Status_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'` ; +chomp $statusreg; + +if ( $opt_debug ) +{ + print STDOUT "istepmode = $opt_istepmode\n"; + print STDOUT "normalmode = $opt_normalmode\n"; + print STDOUT "command = $opt_command\n"; + print STDOUT "debug = $opt_debug\n"; + + print STDOUT "hbDir = $hbDir\n"; + print STDOUT "hbSymsFile = $hbSymsFile\n"; + print STDOUT "istepmodereg = $istepmodereg\n"; + print STDOUT "commandreg = $commandreg\n"; + print STDOUT "statusreg = $statusreg\n"; + + VBU_Cacheline::SetFlags( 1, 0 ); + +} + + +## fetch the ISTEP csv list +get_istep_list(); + +if ( $opt_list ) +{ + print_istep_list(); + exit; +} + + ## VPO cannot be running when we start. + my $qstr = VBU_Cacheline::P8_Ins_Query(); + if ( $qstr ne "STOPPED" ) + { + print STDOUT "VPO is \"$qstr\", setting to STOPPED.\n"; + VBU_Cacheline::P8_Ins_Stop(); + } + +## +## process --Istep Mode command +## IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007" +## NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504" +## +if ( $opt_istepmode == 1 ) +{ + print STDOUT "ENable istepmode\n"; + setMode( "istep" ); +} + +if ( $opt_normalmode == 1 ) +{ + print STDOUT "DISable istepmode\n"; + setMode( "normal" ); +} + +## +## Process other commands +## +if ( $opt_command ne "" ) +{ + if ( $opt_debug ) { print STDOUT "== process command \"$opt_command\" \n"; } + parse_command( $opt_command ); +} + + +#============================================================================== +# SUBROUTINES +#============================================================================== + +#------------------------------------------------------------------------------ +# Print command line help +#------------------------------------------------------------------------------ +sub printUsage() +{ + print STDOUT "\nUsage: hb-istep [--help]\n"; + print STDOUT " [--istepmode] (enable istep mode)\n" ; + print STDOUT " [--normalmode] (disable istep mode)\n" ; + print STDOUT " [--command sN] (run istep N)\n" ; + print STDOUT " [--command sN..M] (run isteps N through M)\n" ; + print STDOUT " [--command <foo>] (run named istep \"foo\")\n" ; + print STDOUT " [--command <foo>..<bar>] (run named isteps \"foo\" through \"bar\")\n" ; + + print STDOUT "\n" ; + +} + + +## read in file with csv istep list and store in inList +sub get_istep_list() +{ + my $istep, my $substep, my $name ; + + open( FH, "< $hbDir/$CSVfile") or die "can't open $hbDir/$CSVfile : $!"; + + while( <FH> ) + { + chomp; + + ( $istep, $substep, $name) = split( ",", $_ ); + ## print STDERR "$_, $istep, $substep, $name\n" ; + + $inList[$istep][$substep] = $name; + } + + close( FH ); +} + +sub print_istep_list( ) +{ + my $hdrflag = 1; + + ## print STDOUT "IStep\tSubStep\tName\n"; + print STDOUT " IStep Name\n"; + print STDOUT "---------------------------------------------------\n"; + + for(my $i = 4; $i <= $#inList; $i++) + { + for(my $j = 0; $j <= $#inList; $j++) + { + ## print all substeps + # print "==$inList[$i][$j] \n"; + if ( defined( $inList[$i][$j] ) ) + { + if ( $hdrflag ) + { + printf STDOUT " -- IStep $i -- \n"; + $hdrflag = 0; + } + ## printf STDOUT "%d\t%d\t%s\n", $i, $j, $inList[$i][$j] ; + printf STDOUT " %s\n", $inList[$i][$j] ; + } + } ## end for $j + $hdrflag=1; + } ## end for $i +} + +sub find_in_inList( $ ) +{ + my ( $substepname ) = @_; + + for(my $i = 0; $i <= $#inList; $i++) + { + for(my $j = 0; $j <= $#inList; $j++) + { + ## if ( defined($inList[$i][$j]) ) { print ".$inList[$i][$j]?$substepname. \n"; } + + if ( defined($inList[$i][$j]) && ($inList[$i][$j] eq $substepname ) ) + { + ## print "== $i $j $inList[$i][$j] \n"; + return ($i, $j, 1 ); + } + } + } + + return ( $#inList, $#inList, 0 ) +} + +## +## keep trying to get status until seqnum syncs up + +sub getSyncStatus( ) +{ + # set # of retries + my $count = 100; + my $result = 0; + my $seqnum = 0; + + ## get response. sendCmd() should have bumped g_SeqNum, so we will sit + ## here for a reasonable amount of time waiting for the correct sequence + ## number to come back. + while(1) + { + + ## advance HostBoot code by a certain # of cycles, then check the + ## sequence number to see if it has changed. rinse and repeat. + VBU_Cacheline::RunClocks(); + + ## dump printk similar to the Jim McGuire's script + ## dumpPrintk(); + + $result = CLread( $statusreg ); + $seqnum = ( ( $result & 0x3f00000000000000 ) >> 56 ); + if ( $seqnum == $g_SeqNum ) + { + return $result; + } + + if ( $count <= 0 ) + { + print STDOUT "TIMEOUT waiting for seqnum=$g_SeqNum\n"; + return -1; + } + $count--; + } ## endwhile + +} + +sub runIStep( $$ ) +{ + my ( $istep, $substep) = @_; + my $byte0, my $command; + my $cmd; + my $result; + + + ## bump the seqnum + $g_SeqNum++; + + printf STDOUT "run %d.%d %s:\n", $istep, $substep, $inList[$istep][$substep]; + + $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum + $command = 0x00; + $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, $istep, $substep ); + VBU_Cacheline::CLwrite( $commandreg, $cmd ); + + $result = getSyncStatus(); + + ## if result is -1 we have a timeout + if ( $result == -1 ) + { + print "-----------------------------------------------------------------\n"; + } + else + { + my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 ); + my $stsIStep = ( ( $result & 0x0000ff0000000000 ) >> 40 ); + my $stsSubstep = ( ( $result & 0x000000ff00000000 ) >> 32 ); + my $istepStatus = ( ( $result & 0x00000000ffffffff ) ); + + print STDOUT "-----------------------------------------------------------------\n"; + ## printf STDOUT "Istep %d.%d Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ; + if ( $taskStatus != 0 ) + { + printf STDOUT "Istep %d.%d FAILED to launch, task status is %d\n", $stsIStep, $stsSubstep, $taskStatus ; + } + else + { + printf STDOUT "Istep %d.%d returned Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ; + } + print STDOUT "-----------------------------------------------------------------\n"; + } + +} + + +## run command = "sN" +sub sCommand( $ ) +{ + my ( $scommand ) = @_; + + my $i = $scommand; + my $j = 0; + + # sanity check + if ( !defined($inList[$i][0]) ) + { + printf STDOUT "IStep %d.0 does not exist.\n", $i; + return -1; + } + + # execute all the substeps in the IStep + for( $j=0; $j<$#inList; $j++ ) + { + ## print "-----------------" + ##print STDOUT "run IStep %d %s ...\n", $i, $inList[$i][$j] ); + ##print "-----------------" + if ( defined( $inList[$i][$j] ) ) + { + runIStep( $i, $j ); + } + } +} + + +sub parse_command() +{ + my ( $command ) = @_; + my @execlist; + my $istepM, my $substepM, my $foundit, my $istepN, my $substepN; + my $M, my $N, my $scommand; + my @ss_list; + + ## check to see if we have an 's' command (string starts with 's' and a number) + chomp( $command); + if ( $command =~ m/^s+[0-9].*/ ) + { + ## run "s" command + if ($opt_debug) { print STDOUT "===== s command : ", $command, ":\n"; } + substr( $command, 0, 1, "" ); + + if ( isdigit( $command ) ) + { + # command = "sN" + if ($opt_debug) { print STDOUT "===== single IStep: ", $command, "\n"; } + sCommand( $command ); + } + else + { + # list of substeps = "sM..N" + ( $M, $N ) = split( /\.\./, $command ); + + if ($opt_debug) { print STDOUT "===== multiple ISteps: ", $M, "-", $N, "\n"; } + for ( my $x=$M; $x<$N+1; $x++ ) + { + sCommand( $x ); + } + } + } + else + { + ## <substep name>, or <substep name>..<substep name> + @ss_list = split( /\.\./, $command ); + + if ($opt_debug) { print STDOUT "===== named commands : ", @ss_list, "\n"; } + + ( $istepM, $substepM, $foundit) = find_in_inList( $ss_list[0] ); + $istepN = $istepM; + $substepN = $substepM; + if ( ! $foundit ) + { + print STDOUT "Invalid substep ", $ss_list[0], "\n" ; + return -1; + } + + + if ( $#ss_list > 0 ) + { + ( $istepN, $substepN, $foundit) = find_in_inList( $ss_list[1] ); + if ( ! $foundit ) + { + print STDOUT "Invalid substep %s", $ss_list[1], "\n" ; + return -1; + } + } + + ## print "got it, running isteps:\n"; + for( my $x=$istepM; $x<$istepN+1; $x++ ) + { + for( my $y=$substepM; $y<$substepN+1; $y++ ) + { + ## print STDOUT "run $x $y $inList[$x][$y]\n"; + runIStep( $x, $y ); + } + } + + } +} + +## write to scratch reg 3 to set istep or normal mode, check return status +sub setMode( ) +{ + my ( $cmd ) = @_; + my $count = 0; + my $expected = 0; + my $readybit = 0; + my $result = 0; + + + if ( $cmd eq "istep" ) + { + VBU_Cacheline::CLwrite( $istepmodereg, "0x4057b0074057b007" ); + $expected = 1; + } + elsif ( $cmd eq "normal" ) + { + VBU_Cacheline::CLwrite( $istepmodereg, "0x700b7504700b7504" ); + $expected = 0; + } + else + { + print "invalid setMode command: %s\n", $cmd ; + return -1; + } + + if ( $opt_debug ) + { + ## readback and display + $result = CLread( $istepmodereg ); + printf STDOUT "===== istepmodereg readback: 0x%lx\n", $result ; + } + + + ## Loop, advancing clock, and wait for readybit + $count = 30; + while(1) + { + ## advance HostBoot code by a certain # of cycles, then check the + ## sequence number to see if it has changed. rinse and repeat. + VBU_Cacheline::RunClocks(); + + $result = CLread( $statusreg ); + + $readybit = ( ( $result & 0x4000000000000000 ) >> 62 ); + + if ($opt_debug) + { printf STDOUT "===== setMode: count=%d, result=0x%lx, readybit=0x%x\n", $count, $result, $readybit } + + if ( $readybit == $expected ) + { + print STDOUT "Set $cmd Mode success.\n" ; + return 0; + } + + if ( $count <= 0 ) + { + print STDOUT "TIMEOUT waiting for readybit, status=0x%x\n", $result ; + return -1; + } + + $count--; + } +} + +__END__
\ No newline at end of file diff --git a/src/build/vpo/hb-virtdebug.pl b/src/build/vpo/hb-virtdebug.pl index 74013231c..19dc38d3f 100755 --- a/src/build/vpo/hb-virtdebug.pl +++ b/src/build/vpo/hb-virtdebug.pl @@ -568,6 +568,8 @@ if ($dumpAll) } + + #============================================================================== # SUBROUTINES #============================================================================== |