#!/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,2013 # # 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 otherwise # divested of its trade secrets, irrespective of what has been # deposited with the U.S. Copyright Office. # # Origin: 30 # # IBM_PROLOG_END_TAG # # Purpose: This perl script implements isteps on AWAN. # # How to run this program: # 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 (spless ). # Then it will boot HostBoot until it is ready to recieve commands. # 2) hb_istep [--]command # Submit a istep/substep command for hostboot to run. # Periodically call RunClocks() to step through HostBoot. # Checks for status from previous Isteps, and reports status. # # Author: Mark Wenning # ################################################################################## # # # Version 1.1 05-09-2012 Start version history # VPO performance improvement changes # Version 1.2 06-11-2012 Change "-c3" to "-cft" (first avail core) # # Version 1.3 11-27-2012 Modified for Multichip run # ################################################################################## #------------------------------------------------------------------------------ # Specify perl modules to use #------------------------------------------------------------------------------ use strict; use warnings; use POSIX; use Getopt::Long; use File::Basename; use lib dirname (__FILE__); ## 64-bit input use bigint; no warnings 'portable'; # read/write cachelines to L3 use VBU_Cacheline; #------------------------------------------------------------------------------ # Forward Declaration #------------------------------------------------------------------------------ sub main; sub printUsage; sub get_istep_list; sub print_istep_list; sub find_in_inlist; sub parse_command; sub setMode; sub resume_istep; sub continue_istep; sub isShutDown; sub getSymbol; sub dumpEnvVar; sub isTraceFull; #------------------------------------------------------------------------------ # Constants #------------------------------------------------------------------------------ my $CORE = "-cft"; ## @todo extract these from splesscommon.H use constant SPLESS_MODE_SIGNATURE => "0x4057b0074057b007"; use constant RUN_ALL_MODE_SIGNATURE => "0xBADC0FFEE0DDF00D"; use constant SPLESS_SINGLE_ISTEP_CMD => 0x00; use constant SPLESS_RESUME_ISTEP_CMD => 0x01; use constant SPLESS_CLEAR_TRACE_CMD => 0x02; use constant SPLESS_SHUTDOWN_CMD => 0x03; use constant MAX_ISTEPS => 25; use constant MAX_SUBSTEPS => 25; ## shutdown exit codes use constant EXIT_SHUTDOWN => 1; #------------------------------------------------------------------------------ # Globals #------------------------------------------------------------------------------ my $opt_debug = 0; my $opt_help = 0; my $opt_istepmode = 0; my $opt_splessmode = 0; my $opt_fspmode = 0; my $opt_command = ""; my $opt_list = 0; my $opt_resume = 0; ## resume istep from break point my $opt_clock = 0; ## continue istep my $opt_clear_trace = 0; ## submit command 02 my $opt_cmdfile = 0; ## batchmode, later my $opt_setup = ""; ## run Jim's script to start up the model # Start all threads by default, only thread 0 for initial startup my $threads_active = "RUNNING"; ## initialize inList to "undefined" my @inList; $inList[MAX_ISTEPS][MAX_SUBSTEPS] = (); for( my $i = 0; $i < MAX_ISTEPS; $i++) { for(my $j = 0; $j < MAX_SUBSTEPS; $j++) { undef( $inList[$i][$j] ); } } ## initialize the sequence number - 6 bit field, { 0 - 63 } my $g_SeqNum = int(rand(64)); #============================================================================== # MAIN #============================================================================== ## Assume that all the tools, files, etc are in the same directory that ## we are in. ## -------------------------------------------------------------------------- ## get any environment variables ## -------------------------------------------------------------------------- my $pgmDir = `dirname $0`; chomp( $pgmDir ); my $hbToolsDir = $ENV{'HB_TOOLS'}; if ( ! defined( $hbToolsDir) || ( $hbToolsDir eq "" ) ) { $hbToolsDir = $pgmDir; ## Set to tool directory } my $hbDir = $ENV{'HB_IMGDIR'}; if ( ! defined( $hbDir) || ( $hbDir eq "" ) ) { $hbDir = $pgmDir; ## Set to tool directory } my $vbuToolsDir = $ENV{'HB_VBUTOOLS'}; if (defined ($vbuToolsDir)) { unless ($vbuToolsDir ne "") { $vbuToolsDir = "/gsa/ausgsa/projects/h/hostboot/vbutools/latest"; } } my $hbCount = $ENV{'HB_COUNT'}; if ( !defined( $hbCount ) || ( $hbCount eq "" ) ) { ## set default $hbCount = 0xffffffff; ## effectively infinite ... } my $hbCommand = $ENV{'HB_COMMAND'}; if ( !defined( $hbCommand ) ) { $hbCommand = ""; } ## disable continuous trace check my $disableContTrace = $ENV{'HB_DISABLE_CONT_TRACE'}; my $CSVfile = "$hbDir/isteplist.csv"; my $hbSymsFile = "$hbDir/hbicore.syms"; #Use hbicore.syms if ( ! -e "$hbSymsFile" ) { die "Can't find symbols file $hbSymsFile\n"; } if ( ! -e "$CSVfile" ) { die "Can't find isteplist file $hbSymsFile\n"; } print STDOUT "Welcome to hb-istep 3.05 .\n"; ## exit if no args if ( $#ARGV < 0 ) { printUsage(); exit 0 ; } #------------------------------------------------------------------------------ # Parse optional input arguments #------------------------------------------------------------------------------ ## GetOptions( "help|?" => \$opt_help, ## "istepmode" => \$opt_istepmode, ## "normalmode" => \$opt_normalmode, ## "list" => \$opt_list, ## "command=s" => \$opt_command, ## "resume" => \$opt_resume, ## "clear-trace" => \$opt_clear_trace, ## "cmdfile" => \$opt_cmdfile, ## "setup=s" => \$opt_setup, ## ## "debug" => \$opt_debug, ## ); ##-------------------------------------------------------------------------- ## Start processing options ## process the "flag" standard options, then use a loop to go through ## the rest ##-------------------------------------------------------------------------- ## Get all the command line options in an array my @Options = @ARGV; if ( !(@Options) ) { printUsage(); exit; } ## ## find all the standard options, set their flag, and remove them from ## the options list. ## vpo and simics used to use different command-line styles, ## simics wanted you to say "hb-istep debug s4", and ## vpo wanted you to say "hb-istep --debug --command s4" . ## With this change, vpo should accept both styles. ## for ( my $i=0; $i <= $#Options; $i++ ) { $_ = $Options[$i]; if ( m/^\-{0,2}help$/ ) { $opt_help = 1; $Options[$i] = ""; } if ( m/^\-{0,2}debug$/ ) { $opt_debug = 1; $Options[$i] = ""; } if ( m/^\-{0,2}list$/ ) { $opt_list = 1; $Options[$i] = ""; } if ( m/^\-{0,2}istepmode$/ ) { $opt_istepmode = 1; $Options[$i] = ""; } if ( m/^\-{0,2}splessmode$/ ) { $opt_splessmode = 1; $Options[$i] = ""; } if ( m/^\-{0,2}fspmode$/ ) { $opt_fspmode = 1; $Options[$i] = ""; } if ( m/^\-{0,2}command$/ ) { ## does nothing except eat the "[--]command" option $opt_command = 1; $Options[$i] = ""; } if ( m/^\-{0,2}resume$/ ) { $opt_resume = 1; $Options[$i] = ""; } if ( m/^\-{0,2}clock$/ ) { $opt_clock = 1; $Options[$i] = ""; } if ( m/^\-{0,2}clear-trace$/ ) { $opt_clear_trace = 1; $Options[$i] = ""; } } ## endfor ## if there's anything left after this, assume it is a command my $command = join( "", @Options ); chomp $command; ## --------------------------------------------------------------------------- ## Fetch the symbols we need from syms file ## --------------------------------------------------------------------------- my $CommandReg = getSymbol( "SPLESS::g_SPLess_Command_Reg" ); my $StatusReg = getSymbol( "SPLESS::g_SPLess_Status_Reg" ); my $ShutDownFlag = getSymbol( "CpuManager::cv_shutdown_requested" ); my $ShutDownSts = getSymbol( "CpuManager::cv_shutdown_status" ); if ( $opt_debug ) { print STDERR "\n----- DEBUG: ----------------------------------- \n"; print STDERR "help = $opt_help\n"; print STDERR "debug = $opt_debug\n"; print STDERR "list = $opt_list\n"; print STDERR "istepmode = $opt_istepmode\n"; print STDERR "splessmode = $opt_splessmode\n"; print STDERR "fspmode = $opt_fspmode\n"; print STDERR "resume = $opt_resume\n"; print STDERR "clock = $opt_clock\n"; print STDERR "clear-trace = $opt_clear_trace\n"; print STDERR "command flag = $opt_command\n"; print STDERR "command = \"$command\"\n"; print STDERR "pgmDir = $pgmDir\n"; print STDERR "hbDir = $hbDir\n"; print STDERR "hbCount = $hbCount\n"; print STDERR "hbCommand = $hbCommand\n"; print STDERR "hbSymsFile = $hbSymsFile \n" ; print STDERR "CommandReg = $CommandReg \n" ; print STDERR "StatusReg = $StatusReg \n" ; print STDERR "ShutDownFlag = $ShutDownFlag \n" ; print STDERR "ShutDownSts = $ShutDownSts \n" ; ## turn on the debug flag in VBU_Cacheline.pm VBU_Cacheline::SetFlags( 1, 0 ); } if ( $opt_help ) { printUsage(); exit; } ## --------------------------------------------------------------------------- ## run the main loop. ## --------------------------------------------------------------------------- main(); #============================================================================== # SUBROUTINES #============================================================================== sub main() { print STDOUT "\n"; ## fetch the ISTEP csv list get_istep_list(); if ( $opt_list ) { print_istep_list(); exit; } if ( $opt_istepmode ) { print STDOUT "istepmode no longer used - use splessmode\n"; exit; } if ( $opt_fspmode == 1 ) { print STDOUT "fspmode no longer used - use splessmode \n"; exit; } if ( isShutDown() ) { print STDOUT "HostBoot has shut down." ; exit EXIT_SHUTDOWN; } ## Stop instruction to read L3 VBU_Cacheline::P8_Ins_Stop(); VBU_Cacheline::P8_Flush_L2(); ## ## process --Istep Mode command ## if ( $opt_splessmode == 1 ) { print STDOUT "Enable splessmode...\n"; setMode( "spless" ); exit; } if ( $opt_clear_trace ) { print STDOUT "Clear Trace Buffers\n"; clear_trace(); exit; } ## ## Process clock ## if ( $opt_clock ) { clock_istep(); ## exit; ?? } ## ## Process resume ## if ( $opt_resume ) { resume_istep(); ## exit; ?? } ## ## Process other commands ## if ( $command ne "" ) { if ( $opt_debug ) { print STDERR "=== process istep command: \"$opt_command\" \n"; } parse_command( $command ); exit; } } ## end main #------------------------------------------------------------------------------ # Print command line help #------------------------------------------------------------------------------ sub printUsage() { print STDOUT "\nUsage: hb-istep [--help]\n"; print STDOUT " [--splessmode] (enable spless mode)\n" ; print STDOUT " [--command sN] (run istep N)\n" ; print STDOUT " [--command sN..M] (run isteps N through M)\n" ; print STDOUT " [--command ] (run named istep \"foo\")\n" ; print STDOUT " [--command ..] (run named isteps \"foo\" through \"bar\")\n" ; print STDOUT " [--resume] (resume an istep that is at a break point)\n" ; print STDOUT " [--clock] (spless mode -- poll for istep ))\n" ; print STDOUT " [--clear-trace] (clear trace buffers before starting)\n"; print STDOUT "\n" ; } ## ## Increment the sequence number, rolling over at 64 ## sub bumpSeqNum() { $g_SeqNum++; $g_SeqNum %= 64; $g_SeqNum += ($g_SeqNum == 0) ? 1 : 0; return $g_SeqNum; } sub dumpEnvVar( $ ) { my $envvar = shift; if ( defined( $ENV{$envvar} ) ) { ## $$::userDisplay "$envvar = $ENV{$envvar}\n"; print STDOUT "$envvar = $ENV{$envvar}\n"; } } ## ## Get symbol address from hbotSymsFile ## sub getSymbol( $ ) { my $symbol = shift; my $hexstr = ""; my $symAddr = 0; $hexstr = `grep "$symbol" $hbSymsFile | awk -F"," '{print \$2}'`; chomp $hexstr; ## print STDERR __LINE__, ": $hexstr\n"; $symAddr = hex "0x$hexstr"; return $symAddr; } ## ## read in file with csv istep list and store in inList ## sub get_istep_list() { my $istep, my $substep, my $name ; open( FH, "< $CSVfile") or die "can't open $CSVfile : $!"; while( ) { chomp; ( $istep, $substep, $name) = split( ",", $_ ); chomp $name; ## print STDERR "$_, $istep, $substep, $name\n" ; if ( defined($name) && ( $name ne "" ) ) { $inList[$istep][$substep] = $name; } } close( FH ); } ## ## print the istep list to the screen. ## sub print_istep_list( ) { my $hdrflag = 1; print STDOUT " IStep Name\n"; print STDOUT "---------------------------------------------------\n"; for(my $i = 0; $i < MAX_ISTEPS; $i++) { for(my $j = 0; $j < MAX_SUBSTEPS; $j++) { ## print "==$i.$j $inList[$i][$j] \n"; if ( defined( $inList[$i][$j] ) ) { if ( $hdrflag ) { printf STDOUT " -- IStep $i -- \n"; $hdrflag = 0; } printf STDOUT " %s\n", $inList[$i][$j] ; } } ## end for $j $hdrflag=1; } ## end for $i } ## ## Find istep name in inList array. ## ## @param[in] - name ## ## @return - istep #, substep #, found flag = true for success ## fount flag = false for not found ## sub find_in_inList( $ ) { my ( $substepname ) = @_; for(my $i = 0; $i < MAX_ISTEPS; $i++) { for(my $j = 0; $j < MAX_SUBSTEPS; $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 ( MAX_ISTEPS, MAX_SUBSTEPS, 0 ) } ## ## Read memory locations to check if HostBoot has already run and shutdown. ## return nonzero if it has, 0 otherwise ## sub isShutDown() { my $flag = VBU_Cacheline::CLread( sprintf( "%x", $ShutDownFlag ) ); my $status = VBU_Cacheline::CLread( sprintf( "%x", $ShutDownSts ) ); if ( $opt_debug ) { print STDERR "Shutdown Flag = $flag\n"; print STDERR "Shutdown Status = ", sprintf( "0x%x", $status), "\n"; } if ( $flag ) { print STDOUT "HostBoot has shut down with status ", sprintf( "0x%x", $status), "\n"; return 1; } return 0; } ## ## run clocks using calls to VBU_Cacheline ## ## This will also start instructions if necessary ## sub runClocks() { VBU_Cacheline::RunClocks(); } ## ## send command using the command register ## ## sub sendCommand( $ ) { my ( $data ) = @_; my $cmd = ""; ##$$ VBU_Cacheline::CLwrite( $commandreg, $cmd ); ## Use Putscom to avoid hostboot race condition $data =~ s/0x//; $cmd = "putscom pu 05003b -p0 -quiet " . $data; if ( $opt_debug ) { print STDERR __LINE__, "-- run $cmd ...\n"; } ( system( $cmd ) == 0 ) or die "$cmd failed, $? : $! \n"; } ## ## get status using the status register. ## sub getStatus() { my $result = 0; my $resultHi = 0; my $resultLo = 0; my $cmd = ""; my $hexresult = 0; ## $$ mem $$ $result = VBU_Cacheline::CLread( $statusreg ); ## Use GetFac here for Hi status - GMB2E8 is mailbox scratchpad 2 $cmd = "simGETFAC B0.C0.S0.P0.E8.TPC.FSI.FSI_MAILBOX.FSXCOMP." . "FSXLOG.LBUS_MAILBOX.Q_GMB2E8.NLC.L2 32"; if ( $opt_debug ) { print STDERR __LINE__, "-- run $cmd ...\n"; } $resultHi = `$cmd` ; ## print STDERR __LINE__, "=== raw resultHi=$resultHi ...\n"; $resultHi =~ s/.*\n0xr(.*)\n.*/$1/g; $resultHi =~ s/\n//g; ## Use GetFac here for Lo status - GMB2E4 is mailbox scratchpad 1 $cmd = "simGETFAC B0.C0.S0.P0.E8.TPC.FSI.FSI_MAILBOX.FSXCOMP." . "FSXLOG.LBUS_MAILBOX.Q_GMB2E4.NLC.L2 32"; if ( $opt_debug ) { print STDERR __LINE__, "-- run $cmd ...\n"; } $resultLo = `$cmd` ; ## print STDERR __LINE__, "=== raw resultLo=$resultLo ...\n"; $resultLo =~ s/.*\n0xr(.*)\n.*/$1/g; $resultLo =~ s/\n//g; $result = sprintf( "0x%8.8x%8.8x", (hex "0x$resultHi"), (hex "0x$resultLo") ); $hexresult = hex $result; if ( $opt_debug ) { printf STDERR "=== result=0x%lx ...\n", $hexresult; } return $hexresult; } ## ## keep trying to get status until seqnum syncs up ## sub getSyncStatus( ) { # set # of retries ## @todo revisit my $count = $hbCount; my $result = 0; my $seqnum = 0; my $running = 0; # Start instructions before going into loop if ( "$threads_active" eq "RUNNING_T0" ) { VBU_Cacheline::P8_Ins_Start_T0(); } else { VBU_Cacheline::P8_Ins_Start(); } ## 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. # Progress bar print STDOUT "."; # Feed simclocks runClocks(); # Check if trace buffer is full, if it is, call ContTrace to # dump traces out from L3 # Note: This is called here in order to avoid repeated # system calls of ContTrace in every loop, when the # trace buffer is not yet full. if ( isTraceFull() ) { # Print Trace Full message just for reference when running. print STDOUT "T/F"; # Save current thread active state if ( "$threads_active" eq "RUNNING_T0" ) { $threads_active = VBU_Cacheline::P8_Ins_Query(); } system ("$hbToolsDir/hb-ContTrace --no-save-states --mute > /dev/null" ); system ("cat hb-ContTrace.output >> tracMERG"); # Need to start instructions after trace has been dumped out. if ( "$threads_active" eq "RUNNING_T0" ) { VBU_Cacheline::P8_Ins_Start_T0(); } else { VBU_Cacheline::P8_Ins_Start(); } } ## Fetch status reg(s) $result = getStatus( ); $seqnum = ( ( $result & 0x3f00000000000000 ) >> 56 ); $running = ( ( $result & 0x8000000000000000 ) >> 63 ); ## @todo great place to add some debug, check running bit BEFORE ## starting the clock (should be off), then run 100-200 clocks till ## the bit turns on. If it doesn't go on, command was never received. ## Then come here to wait for it to go back off again. ## if ( ( $running == 0 ) ## && ( $seqnum == $g_SeqNum ) if ( $seqnum == $g_SeqNum ) { # Done progress bar print STDOUT "\n"; return $result; } if ($opt_debug) { printf STDERR "=== getSyncStatus: count=%d, result=0x%lx\n", $count, $result ; } if ( $count <= 0 ) { if ( defined( $hbCommand ) && ( $hbCommand ne "" ) ) { if (system("$hbCommand") == 0) { $count = $hbCount; } } } if ( $count <= 0 ) { # Done progress bar print STDOUT "\n"; print STDOUT "TIMEOUT waiting for seqnum=$g_SeqNum\n"; return -1; } $count--; } ## endwhile } ## ## Run an istep ## sub runIStep( $$ ) { my ( $istep, $substep) = @_; my $byte0, my $command; my $cmd; my $result; ## bump the seqnum bumpSeqNum(); printf STDOUT "run %d.%d %s:\n", $istep, $substep, $inList[$istep][$substep]; $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum $command = SPLESS_SINGLE_ISTEP_CMD; $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, $istep, $substep ); ## $$VBU_Cacheline::CLwrite( $commandreg, $cmd ); sendCommand( $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 ) { if ( $taskStatus == 11 ) { printf STDOUT "At breakpoint 0x%x\n", $istepStatus; } else { printf STDOUT "Istep %d.%d %s FAILED to launch, task status is %d\n", $stsIStep, $stsSubstep, $inList[$istep][$substep], $taskStatus ; } } else { printf STDOUT "Istep %d.%d %s returned Status: %d\n", $stsIStep, $stsSubstep, $inList[$istep][$substep], $istepStatus ; if ( $istepStatus == 0xa ) { printf STDOUT ": not implemented yet.\n"; } } print STDOUT "------------------------------------------------------- SeqNum: $g_SeqNum\n"; } } ## ## run command = "sN" ## sub sCommand( $ ) { my ( $scommand ) = @_; my $i = $scommand; my $j = 0; # execute all the substeps in the IStep for( $j=0; $j, or .. @ss_list = split( /\.\./, $command ); if ($opt_debug) { print STDERR __LINE__, "=== 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"; if ( defined( $inList[$x][$y] ) ) { runIStep( $x, $y ); } } } } } ## ## write IStepModeReg in memory to set istep or check return status ## This does not write to a scom reg, I don't have one to write to. ## sub setMode( $ ) { my ( $cmd ) = @_; my $count = $hbCount; my $expected = 0; my $readybit = 0; my $result = 0; my $resultRaw = 0; my $clearcmd = 0; if ( $cmd eq "spless" ) { ## Clear status reg(s) before we start. If the status reg is initialized ## to garbage, there is a chance that it will mistaken for the readybit $clearcmd = "putscom pu 050039 0000000000000000 -quiet" ; ## lo reg if ( $opt_debug ) { print STDERR __LINE__, "-- run $clearcmd ...\n"; } ( system( $clearcmd ) == 0 ) or die "$clearcmd failed, $? : $! \n"; $clearcmd = "putscom pu 05003a 0000000000000000 -quiet" ; ## hi reg if ( $opt_debug ) { print STDERR __LINE__, "-- run $clearcmd ...\n"; } ( system( $clearcmd ) == 0 ) or die "$clearcmd failed, $? : $! \n"; ## clear command reg as well. $clearcmd = "putscom pu 05003b 0000000000000000 -quiet" ; ## cmd reg if ( $opt_debug ) { print STDERR __LINE__, "-- run $clearcmd ...\n"; } ( system( $clearcmd ) == 0 ) or die "$clearcmd failed, $? : $! \n"; print "Use attributes to control SPLess mode" $expected = 1; } else { print "invalid setMode command: %s\n", $cmd ; return -1; } # Start instruction only for master thread 0 VBU_Cacheline::P8_Ins_Start_T0(); ## Loop, advancing clock, and wait for readybit ## @todo revisit while(1) { # Progress bar print STDOUT "."; # Check if trace buffer is full, if it is, call ContTrace to # dump traces out from L3 # Note: This is called here in order to avoid repeated # system calls of ContTrace in every loop, when the # trace buffer is not yet full. if ( isTraceFull() ) { # Print Trace Full message just for reference when running. print STDOUT "T/F"; system ("$hbToolsDir/hb-ContTrace --no-save-states --mute > /dev/null" ); system ("cat hb-ContTrace.output >> tracMERG"); } ## check for system crash if ( isShutDown( ) ) { # Stop progress bar print STDOUT "\n"; print STDOUT "HostBoot has shut down."; return -1; } VBU_Cacheline::P8_Ins_Start_T0(); ## advance HostBoot code by a certain # of cycles, then check the ## sequence number to see if it has changed. rinse and repeat. runClocks( ); if ( $cmd eq "spless" ) { $result = getStatus( ); $readybit = ( ( $result & 0x4000000000000000 ) >> 62 ); } if ($opt_debug) { printf STDERR "=== setMode: count=%d, result=0x%lx, readybit=0x%x\n", $count, $result, $readybit ; } if ( $readybit == $expected ) { # Stop progress bar print STDOUT "\n"; print STDOUT "Set $cmd Mode success.\n" ; return 0; } if ( $count <= 0 ) { if ( defined( $hbCommand ) && ( $hbCommand ne "" ) ) { if (system("$hbCommand") == 0) { $count = $hbCount; } } } if ( $count <= 0 ) { printf STDOUT "TIMEOUT waiting for readybit, status=0x%x\n", $result ; return -1; } $count--; } } sub resume_istep() { my $byte0; my $command; my $cmd; my $result; bumpSeqNum(); ## bump print STDOUT "resume from breakpoint\n"; $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum $command = SPLESS_RESUME_ISTEP_CMD; $cmd = sprintf( "0x%2.2x%2.2x000000000000", $byte0, $command ); ## $$ VBU_Cacheline::CLwrite( $commandreg, $cmd ); sendCommand( $cmd ); ## dgxx while(1) { $result = getSyncStatus(); ## if result is -1 we have a timeout last if ( $result == -1 ); my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 ); my $stsIStep = ( ( $result & 0x0000ff0000000000 ) >> 40 ); my $stsSubstep = ( ( $result & 0x000000ff00000000 ) >> 32 ); my $istepStatus = ( ( $result & 0x00000000ffffffff ) ); my $running = ( ( $result & 0x8000000000000000 ) >> 63 ); print STDOUT "-----------------------------------------------------------------\n"; ## At this point the status is: ## 1) hostboot code was not at a breakpoint - resume ignored (result == 12) ## 2) hostboot resumed from breakpoint, but has not reached the end of ## the istep. (running flag on, result is 0) ## 3) hostboot resumed, but is at a new breakpoint ## 4) hostboot resumed and is at the end of the istep ## (running flag off, result is rc from istep if ( $taskStatus != 0 ) { if ( $taskStatus == 11 ) # HB at new break point { printf STDOUT "At breakpoint 0x%x\n", $istepStatus; last; } elsif ( $taskStatus == 12 ) # HB not at a break point { printf STDOUT "resume istep ignored, task status is %d\n", $taskStatus ; last; } else { printf STDOUT "Istep %d.%d returned Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ; last; } } else { if( $running == 0 ) { printf STDOUT "Istep %d.%d returned Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ; last; } ## continue to wait for istep to complete } } print STDOUT "-----------------------------------------------------------------\n"; } sub clock_istep() { my $byte0; my $command; my $cmd; my $result; bumpSeqNum(); ## bump print STDOUT "Clock istep\n"; # Startup requires using only thread 0 -- allow an environment setting to tell us it is ok for all threads my $HB_START_TALL = $ENV{'HB_START_TALL'}; if ( ! defined ( $HB_START_TALL ) || "$HB_START_TALL" ne "YES" ) { $threads_active = "RUNNING_T0"; } $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 ) { if ( $taskStatus == 11 ) { printf STDOUT "At breakpoint 0x%x\n", $istepStatus; } else { printf STDOUT "Istep %d.%d %s task status is %d\n", $stsIStep, $stsSubstep, $inList[$stsIStep][$stsSubstep], $taskStatus ; } } else { printf STDOUT "Istep %d.%d %s returned Status: 0x%x\n", $stsIStep, $stsSubstep, $inList[$stsIStep][$stsSubstep], $istepStatus ; if ( $istepStatus == 0xa ) { printf STDOUT ": not implemented yet.\n"; } } print STDOUT "------------------------------------------------------- SeqNum: $g_SeqNum\n"; } } sub clear_trace( ) { my $byte0, my $command; my $cmd; my $result; ## bump the seqnum bumpSeqNum(); $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum $command = SPLESS_CLEAR_TRACE_CMD; $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, 0, 0 ); ## $$ VBU_Cacheline::CLwrite( $commandreg, $cmd ); sendCommand( $cmd ); $result = getSyncStatus(); ## if result is -1 we have a timeout if ( $result == -1 ) { print "-----------------------------------------------------------------\n"; } else { print STDOUT "---------------------------------------------------------------\n"; print STDOUT "Trace Buffers Cleared.\n" ; } print STDOUT "---------------------------------------------------------------\n"; } ## ## Read the scratch register to see if trace full condition is notified. ## The purpose of this routine is to avoid making system calls to ## ContTrace, which introduces overheads to VPO performance. ## sub isTraceFull() { if ( $disableContTrace ) { return 0; } my $traceIsFull = 1; my $trigger = "simGETFAC B0.C0.S0.P0.E8.TPC.FSI.FSI_MAILBOX.FSXCOMP." . "FSXLOG.LBUS_MAILBOX.Q_GMB2E0.NLC.L2 32"; $trigger = `$trigger`; $trigger =~ s/.*\n0xr(.*)\n.*/$1/g; $trigger =~ s/\n//g; if ($trigger !~ /[1-9a-fA-F]+/) { $traceIsFull = 0; } return $traceIsFull; } __END__