diff options
| author | Dean Sanner <dsanner@us.ibm.com> | 2016-06-28 10:25:22 -0500 |
|---|---|---|
| committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-09-12 09:29:12 -0400 |
| commit | d72ca329056cf523fcfe5c0857fcda30aede1b68 (patch) | |
| tree | 2d2d363ea03a4128098081068be0beb538743aab /src/build/debug | |
| parent | 1073b2b23651fc2683d91add819213eab8b5b21e (diff) | |
| download | blackbird-hostboot-d72ca329056cf523fcfe5c0857fcda30aede1b68.tar.gz blackbird-hostboot-d72ca329056cf523fcfe5c0857fcda30aede1b68.zip | |
Debug framework support of dump of FAPI ATTR
Added a perl module to Dump all FAPI ATTR. It is
used in conjunction with the Istep.pm infrastructre to
send commands/data to a running Hostboot instance in
Simics, VBU, HW
Change-Id: I765e904f9549bcaec2ac9b8b2e6283167c5480f5
RTC: 127348
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26349
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Prachi Gupta <pragupta@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/build/debug')
| -rwxr-xr-x | src/build/debug/Hostboot/FapiAttr.pm | 588 | ||||
| -rwxr-xr-x | src/build/debug/Hostboot/Istep.pm | 135 |
2 files changed, 694 insertions, 29 deletions
diff --git a/src/build/debug/Hostboot/FapiAttr.pm b/src/build/debug/Hostboot/FapiAttr.pm new file mode 100755 index 000000000..924f7f8de --- /dev/null +++ b/src/build/debug/Hostboot/FapiAttr.pm @@ -0,0 +1,588 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/build/debug/Hostboot/FapiAttr.pm $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +# +# This perl module is used in conjunction with the Istep.pm +# infrastructre to dump all FAPI attributes. It requires +# a live and running Hostboot instance in Simics, VBU, HW +# + +use strict; +package Hostboot::FapiAttr; +use Hostboot::_DebugFrameworkVMM; +use Exporter; +our @EXPORT_OK = ('main'); + +use POSIX; +use File::Basename; +use Data::Dumper; +$Data::Dumper::Sortkeys = 1; + + +#------------------------------------------------------------------------------ +# Constants +#------------------------------------------------------------------------------ + +use constant PAGESIZE => 4096; # 4KB + +## each ATTR sync record is formated as follows: +# uint32_t iv_attrId; // Attribute ID +# uint32_t iv_targetType; // Target Type attribute is for +# uint16_t iv_pos; // For chips/dimms the position +# // For chiplets the parent chip position +# uint8_t iv_unitPos; // For chiplets the position +# uint8_t iv_flags : 4; // AttributeFlags enum value(s) +# uint8_t iv_node : 4; // Target Node number +# uint32_t iv_valSize; // Size of the attribute value in bytes + +use constant ATTRID_SIZE => 4; +use constant TARGETTYPE_SIZE => 4; +use constant POS_SIZE => 2; +use constant UNIT_POS_SIZE => 1; +use constant FLAG_NODE_SIZE => 1; +use constant DATA_SIZE => 4; + + +#------------------------------------------------------------------------------ +# Globals +#------------------------------------------------------------------------------ + +my $attrListRef = {}; +my $OUTFILE; +my $no_userDisplay = 0x0; + + + +#------------------------------------------------------------------------------ +# Forward Declarations +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Main +#------------------------------------------------------------------------------ +sub main +{ + my ($packName,$args) = @_; + + #-------------------------------------------------------------------------- + # Process input arguments + #-------------------------------------------------------------------------- + my $debug = 0; + if (defined $args->{"debug"}) + { + $debug = $args->{"debug"}; + + my $debugFileName = ::getImgPath() . "FapiAttr.debug"; + open(DEBUG_FILE, "> $debugFileName") + or die "Cannot open file $debugFileName"; + + ::userDisplay "write debug info to $debugFileName\n"; + } + + ## Normally this will not need to be specified, this is the default. + my $attrListFile = "attrInfo.csv"; + + ## read --attrfile in case the user wants to override + if (defined $args->{"attrfile"}) + { + $attrListFile = $args->{"attrfile"}; + } + else + { + $attrListFile = ::getImgPath() . $attrListFile; + } + + unless (-e $attrListFile) + { + ::userDisplay "Cannot find attribute list file \"$attrListFile\".\n"; + die; + } + + ::userDisplay "Using attribute list file \"$attrListFile\"\n"; + + my $BINFILE; + + ## Must have bin dump file + if (defined $args->{"attrbin"}) + { + my $attrBinFile = $args->{"attrbin"}; + ::userDisplay "Using bin data file \"$attrBinFile\"\n"; + open($BINFILE, "<:raw", $attrBinFile) or die "Cannot open $attrBinFile"; + } + else + { + ::userDisplay "No bin data to process \n"; + die; + } + + ## If user specified an output file, route output there, otherwise console + if (defined $args->{"attr_output"}) + { + my $attrOutFile = $args->{"attr_output"}; + ::userDisplay "Outputting data to \"$attrOutFile\"\n"; + open($OUTFILE, ">", $attrOutFile) or die "Cannot open $attrOutFile"; + $no_userDisplay = 0x1; + } + + #-------------------------------------------------------------------------- + # Process the attribute list file. Save data to a hash. + # + # Format of file is: + # <FAPI-ATTR-ID-STR>,<LAYER-ATTR-ID-STR>,<ATTR-ID-VAL>,<ATTR-TYPE> + # We are not interested in the LAYER-ATTR-ID-STR, parse the rest of + # the csv fields. + #-------------------------------------------------------------------------- + open(FILE, "< $attrListFile") or die "Cannot open file $attrListFile"; + + my @lines = <FILE>; + my $attrIdHex = 0; + + # Get the attribute data and index by ID + foreach my $line (@lines) + { + chomp($line); + my ( $fapi_attr_id_str, + $layer_attr_id_str, + $attr_id_val, + $attr_type ) = split( ',', $line ); + + ## convert to scalar for a clean index + $attrIdHex = hex( $attr_id_val ); + + $attrListRef->{$attrIdHex}->{'str'} = $fapi_attr_id_str ; + $attrListRef->{$attrIdHex}->{'type'} = $attr_type ; + } + close(FILE) or die "Cannot close $attrListFile"; + + ## $$ debug + ## ::userDisplay Dumper( $attrListRef ); + + + ## Walk the binFile of attributes + my $hexHeader; + my $hexData; + my $prevTType = ""; + my $prevPos = ""; + my $prevUnitPos = ""; + + seek ($BINFILE, 0, SEEK_SET); + + while(( my $bytes = read( $BINFILE, $hexHeader, 16)) == 16) + { + + my($attrId, $targetType, $pos, $unitPos, $flag_node, $data_size) = + unpack( 'H8H8H4H2H2H8', $hexHeader); + read( $BINFILE, $hexData, (hex $data_size)); + + ## If this is a new target, emit the target type str + if(($targetType ne $prevTType) || ($pos ne $prevPos) || + ($unitPos ne $prevUnitPos)) + { + $prevTType = $targetType; + $prevPos = $pos; + $prevUnitPos = $unitPos; + outputData( "\n", (cronusTargetStr( $targetType, $pos, + $unitPos, $flag_node))); + } + + #Attempt to display + #find ATTR and type from lookup + my $attrName = $attrListRef->{(hex $attrId)}->{'str'} ; + my $attrType = $attrListRef->{(hex $attrId)}->{'type'}; + + + ## parseType will return a size for simple types, for arrays + ## etc it will fill in @parseDesc . + my @parseDesc = (); + my $readSize = parseType( $attrType, \@parseDesc); + + if ( scalar( @parseDesc ) == 0 ) + { + ## print attr and type + my $upsz = $data_size*2; + my $value = unpack("H$upsz", $hexData ); + outputData($attrName, " ", $attrType, " ", $value, "\n"); + } + else + { + ## array. + userDisplayArray( $attrName, $attrType, $hexData, @parseDesc); + } + } + + + if ( $debug ) + { + close DEBUG_FILE; + } + +} ## end main + + +sub outputData +{ + if(1 == $no_userDisplay) + { + foreach my $value (@_) + { + print $OUTFILE $value; + } + } + else + { + ::userDisplay @_; + } +} + +sub userDisplayArray +{ + my ( $attrName, $attrType, $rawAttrValue, @attrDesc ) = @_; + + ## assume max dimension of 3 deep, and always a good 1st dimension + ## attr Desc is a flat array where every three elements (a tuple) + ## indicate the parameters for the next set of array [] + ## laid out like i_type, i_index, i_enum, j_type, j_index, j_enum, + ## k_type, k_index, k_enum where: + ## type is (u8, u16, etc) + ## index is the array index size (aka the 5 in [5]) + ## enum is not used here (for enumerated ATTR types) + my $i = 0; + my $j_index = -1; + my $k_index = -1; + my $size = $attrDesc[$i]; $i++; + my $i_index = $attrDesc[$i]; $i++; + my $enum = $attrDesc[$i]; $i++; + if ( $attrDesc[$i] ) + { + $i++; ## Move past j_type + $j_index = $attrDesc[$i]; $i++; ## Capture j_index, move past + $i++; ## Move past j_enum + if ( $attrDesc[$i] ) + { + $i++; ## Move past k_type + $k_index = $attrDesc[$i]; ## Capture k_index, move + $i++; ## Move past k_index + if ( $attrDesc[$i] ) + { + die "array dimensions > 3 are not supported."; + } + } + } + + + if ( $k_index > 0 ) + { + userDisplay3dArray( $attrName, + $attrType, + $size, + $i_index, + $j_index, + $k_index, + $rawAttrValue ); + } + elsif ($j_index > 0 ) + { + userDisplay2dArray( $attrName, + $attrType, + $size, + $i_index, + $j_index, + $rawAttrValue ); + } + else + { + ## single array + my $upsz = $size*2; + my @values = unpack("(H$upsz)*", $rawAttrValue ); + ## $$ debug + ## ::userDisplay scalar(@values), ": ", join( ", ", @values), "\n" ; + my $valindex = 0; + for ( my $i=0; $i<$i_index; $i++ ) + { + ##$$debug ::userDisplay (sprintf("%02x ", $valindex) ); + outputData $attrName ; + outputData "[$i]" ; + outputData " $attrType "; + outputData $values[$valindex] ; $valindex++; + outputData "\n"; + } ## endfor i + } ## end else +} + + +sub userDisplay2dArray +{ + my ($attr, + $attrType, + $size, + $i_index, + $j_index, + $rawAttrValue ) = @_; + + my $upsz = $size*2; + my @values = unpack("(H$upsz)*", $rawAttrValue ); + ## $$ debug + ## ::userDisplay scalar(@values), ": ", join( ", ", @values), "\n" ; + my $valindex = 0; + for ( my $i=0; $i<$i_index; $i++ ) + { + for ( my $j=0; $j<$j_index; $j++ ) + { + ##$$debug ::userDisplay (sprintf("%02x", $valindex) ); + outputData $attr ; + outputData "[$i][$j]" ; + outputData " $attrType "; + outputData $values[$valindex] ; $valindex++; + outputData "\n"; + } ## endfor j + } ## endfor i + +} + + +sub userDisplay3dArray +{ + my ($attr, + $attrType, + $size, + $i_index, + $j_index, + $k_index, + $rawAttrValue) = @_; + + my $upsz = $size*2; + my @values = unpack("(H$upsz)*", $rawAttrValue ); + ## $$ debug + ## ::userDisplay scalar(@values), ": ", join( ", ", @values), "\n" ; + my $valindex = 0; + for ( my $i=0; $i<$i_index; $i++ ) + { + for ( my $j=0; $j<$j_index; $j++ ) + { + for ( my $k=0; $k<$k_index; $k++ ) + { + ##$$debug ::userDisplay (sprintf("%02x ", $valindex) ); + outputData $attr ; + outputData "[$i][$j][$k]" ; + outputData " $attrType "; + outputData $values[$valindex] ; $valindex++; + outputData "\n"; + } ## endfor k + } ## endfor j + } ## endfor i +} + + + +sub cronusTargetStr() +{ + my ( $targetType_hexstr, $pos, $unitPos, $flag_node, ) = @_; + + ## This array matches what is in fapi2/include/target_types.H + my %types = ( + "00000000" => "none", + "00000001" => "sys", + "00000002" => "dimm", + "00000004" => "p9n", + "00000008" => "memb", + "00000010" => "p9n.ex", + "00000020" => "cen.mba", + "00000040" => "p9n.mcs", + "00000080" => "p9n.xbus", + "00000100" => "p9n.abus", + "00000200" => "cen.l4", + "00000400" => "p9n.c", + "00000800" => "p9n.eq", + "00001000" => "p9n.mca", + "00002000" => "p9n.mcbist", + "00004000" => "p9n.mi", + "00008000" => "p9n.capp", + "00010000" => "p9n.dmi", + "00020000" => "p9n.obus", + "00040000" => "p9n.nv", + "00080000" => "p9n.sbe", + "00100000" => "p9n.ppe", + "00200000" => "p9n.perv", + "00400000" => "p9n.pec", + "00800000" => "p9n.phb" + ); + + my $cro_type = $types{$targetType_hexstr}; + my $cronusTargetStr; + + # System, dimm, p9 and memb have different string + if($cro_type eq "sys") + { + $cronusTargetStr = "target = k0\n"; + } + elsif(-1 == index($cro_type, ".")) + { + $cronusTargetStr = (sprintf("target = %s:k0:n0:s0:p%02d\n", + $cro_type, (hex $pos))); + } + else + { + $cronusTargetStr = (sprintf("target = %s:k0:n0:s0:p%02d:c%02d\n", + $cro_type, (hex $pos), (hex $unitPos))); + } + + return $cronusTargetStr; +} + + +## +## translate cronus-type type strings to: +## Integer size in bytes +## Number of integers to read +## Enumerated type flag +## Fills in list(s) of these 3 values that describes each field, +## for example: +## u64[5][6][1] +## ( size=8,num=5,enum=0 ), ## dimension 1 +## ( size=8,num=6,enum=0 ), ## dimension 2 +## ( size=8,num=1,enum=0 ), ## dimension 3 +## ( size=0,num=0,enum=0 ), ## endit +## +## if the attr type is a single simpleType, returns the size in bytes. +## If the attr type is more complicated, return the total size in bytes +## and fill in the passed-in parse Description struct. +## +sub parseType +{ + my ( $type, $parseDescRef ) = @_; + + my $size = 8; ## default + my $num = 1; ## default + my $enum = 0; ## default + my $totalSize = 1; + + $_ = $type; + if ( m/u8/ ) { $size = 1; } + if ( m/u16/ ) { $size = 2; } + if ( m/u32/ ) { $size = 4; } + if ( m/u64/ ) { $size = 8; } + if ( m/s8/ ) { $size = 1; } + if ( m/s16/ ) { $size = 2; } + if ( m/s32/ ) { $size = 4; } + if ( m/s64/ ) { $size = 8; } + + ## @TODO RTC 68517 Add code to display non-simple non-integer types + + $totalSize = $size; + + ## remove size spec + s/[us][0-9]*[e]*//; + + ## find any arrays + my @arrayDims = split /\[([^\]]*)\]/g ; + + if ( scalar( @arrayDims ) > 0 ) + { + ## Array. Build the description struct and calculate the right size + my $i = 0; + foreach ( @arrayDims ) + { + ## skip empty array entries + next if ( ! m/[0-9]+/ ) ; + + @{$parseDescRef}[$i] = $size; $i++; ## size in bytes + @{$parseDescRef}[$i] = $_; $i++; ## number of vars + @{$parseDescRef}[$i] = $enum; $i++; ## enum flag + + $totalSize *= $_ ; + } + + ## add a terminating record + @{$parseDescRef}[$i] = 0; $i++; + @{$parseDescRef}[$i] = 0; $i++; + @{$parseDescRef}[$i] = 0; $i++; + + } + + return $totalSize; +} + + + + + +## +## read raw binary string and convert it to a hex scalar +## +sub binToHex() +{ + my ( $rawData ) = @_; + + my $result = hex(unpack("H*",$rawData)); + + return $result; +} + +# Utility to display a block of data +sub userDisplayHex +{ + my $data = shift; + my $count = 0; + + # Make it easier to read by displaying as two bytes chunks + my @twobytes = unpack("(H4)*", $data); + outputData "\n "; + foreach (@twobytes) + { + outputData "$_ "; + $count++; + if (!($count % 8)) + { + outputData "\n "; + } + } + outputData "\n"; +} + +sub helpInfo +{ + my %info = ( + name => "Attr", + intro => ["Dump the specified target attribute(s)."], + options => { + "huid=<HUID>" => ["HUID of the target as a hex number.", + "If not specified, will output attribute(s) of all ". + "targets."], + "attrname=<attribute name>" => ["Attribute to dump.", + "If not specified, will output all attributes for the ". + "specified target."], + "attrfile" => ["specify an alternate attribute " . + "information file. Normally this will not be needed."], + "debug" => ["More debug output."], + }, + ); +} + + +## modules must return a 1 at the end +1; +__END__ + diff --git a/src/build/debug/Hostboot/Istep.pm b/src/build/debug/Hostboot/Istep.pm index f33998000..5157a6bd8 100755 --- a/src/build/debug/Hostboot/Istep.pm +++ b/src/build/debug/Hostboot/Istep.pm @@ -65,6 +65,7 @@ package Hostboot::Istep; use Exporter; our @EXPORT_OK = ('main'); use File::Temp ('tempfile'); +use Data::Dumper; #------------------------------------------------------------------------------ # Constants @@ -104,6 +105,10 @@ my @inList; my $THREAD = "0"; +my $g_attr_fname = ""; +my $g_attr_fh; + + ## -------------------------------------------------------------------------- ## get any environment variables @@ -118,7 +123,7 @@ my $hbCount = $ENV{'HB_COUNT'}; if ( !defined( $hbCount ) || ( $hbCount eq "" ) ) { ## set default - $hbCount = 0xffffffff; ## effectively infinite ... + $hbCount = 0xff; ## default that should work for all env } ## init global variables @@ -127,6 +132,7 @@ my $ShutDownSts = ""; + ######################################################################## ## MAIN ROUTINE, called from debug framework ######################################################################## @@ -363,48 +369,119 @@ sub showHelp } ## --------------------------------------------------------------------------- -## Check to see if there are trace buffers avail -## if so, extract and write them out +## Check to see if there are debug bufs avail avail +## if so, extract type and call correct subroutine to handle ## --------------------------------------------------------------------------- -sub checkContTrace +sub checkDebugBuf { my $SCRATCH_MBOX1 = 0x00050038; my $SCRATCH_MBOX2 = 0x00050039; - my $contTrace = ""; - my $ctName = "tracMERG.cont"; - - $contTrace = ::readScom( $SCRATCH_MBOX1, 8 ); - if ( $contTrace != 0 ) + my $MSG_TYPE_MASK = 0xFF00000000000000; + my $MSG_TYPE_TRACE = 0x0000000000000000; + my $MSG_TYPE_ATTR = 0x0100000000000000; + my $dbgAddr = ""; + my $dbgSize = ""; + + $dbgAddr = ::readScom( $SCRATCH_MBOX1, 8 ); + if ( $dbgAddr != 0 ) { - my $fh; - my $fname; - my $contFile; - ($fh,$fname) = tempfile(); - open ($contFile, '>>', $ctName) or die "Can't open '$ctName' $!"; - binmode($fh); + #There is something to do. Get the dbgSize to determine the type + $dbgSize = ::readScom( $SCRATCH_MBOX2, 8 ); #contTrace has the buffer, address MBOX_SCRATCH2 has size #MBOX Scratch regs are only valid from 0:31, shift to give a num - my $buffAddr = $contTrace >> 32; - my $buffSize = ::readScom($SCRATCH_MBOX2, 8) >> 32; + my $buffAddr = $dbgAddr >> 32; + my $buffSize = ($dbgSize & (~$MSG_TYPE_MASK)) >> 32; + my $msgType = $dbgSize & $MSG_TYPE_MASK; + + #::userDisplay "."; + #::userDisplay "DebugBuf addr[", sprintf("0x%x", $buffAddr), + # "] type[", sprintf("0x%x", $msgType), + # "] size[" , sprintf("0x%x",$buffSize), "]\n"; - print $fh (::readData($buffAddr, $buffSize)); + if ($msgType == $MSG_TYPE_TRACE) + { + handleContTrace($buffAddr, $buffSize); + } + elsif ($msgType == $MSG_TYPE_ATTR) + { + handleAttrDump($buffAddr, $buffSize); + } #Write 0 to let HB know we extracted buf and it can continue ::writeScom($SCRATCH_MBOX1, 8, 0x0); + } +} - open TRACE, ("fsp-trace -s ".::getImgPath(). - "hbotStringFile $fname |") || die; - while (my $line = <TRACE>) - { - ::userDisplay $line; - print $contFile $line; - } +## --------------------------------------------------------------------------- +## Check to see if there are trace buffers avail +## if so, extract and write them out +## --------------------------------------------------------------------------- +sub handleContTrace +{ + my $buffAddr = shift; + my $buffSize = shift; + my $ctName = "tracMERG.cont"; - unlink $fname; + my $fh; + my $fname; + my $contFile; + ($fh,$fname) = tempfile(); + open ($contFile, '>>', $ctName) or die "Can't open '$ctName' $!"; + binmode($fh); + + print $fh (::readData($buffAddr, $buffSize)); + + open TRACE, ("fsp-trace -s ".::getImgPath(). + "hbotStringFile $fname |") || die; + while (my $line = <TRACE>) + { + ::userDisplay $line; + print $contFile $line; + } + + unlink $fname; +} + + +## --------------------------------------------------------------------------- +## Extract an ATTR dump bin, when complete, call tool to parse. +## --------------------------------------------------------------------------- +sub handleAttrDump +{ + my $buffAddr = shift; + my $buffSize = shift; + my $txtName = "hbAttrDump.txt"; + + #If there is an empty filename, need to create one, otherwise just append + if ($g_attr_fname eq "") + { + ($g_attr_fh,$g_attr_fname) = tempfile(); + binmode($g_attr_fh); + } + + # Check to see if magic "done" address has been sent, + # if so call tool to parse + if ($buffAddr == 0xFFFFCAFE) + { + #::userDisplay "Got done, processing bin file[$g_attr_fname]\n"; + close $g_attr_fh ; + + ##Call the FapiAttr tool module + $Hostboot::_DebugFramework::toolOpts{'attrbin'} = $g_attr_fname; + ::callToolModule("FapiAttr"); + + unlink $g_attr_fname; + $g_attr_fname = ""; + + } + else # Write data to bin temp file + { + print $g_attr_fh (::readData($buffAddr, $buffSize)); } } + ## --------------------------------------------------------------------------- ## Dump environment variable specified. ## --------------------------------------------------------------------------- @@ -677,7 +754,7 @@ sub getSyncStatus( ) ## check to see if we need to dump trace - no-op in simics - checkContTrace(); + checkDebugBuf(); $result = getStatus(); $running = ( ( $result & 0x2000000000000000 ) >> 61 ); @@ -940,9 +1017,9 @@ sub setMode( $ ) ## sequence number to see if it has changed. rinse and repeat. ::executeInstrCycles( $hbDefaultCycles, NOSHOW ); - if ( $opt_debug ) { ::userDisplay "=== checkContTrace\n"; } + if ( $opt_debug ) { ::userDisplay "=== checkDebugBuf\n"; } ## check to see if it's time to dump trace - no-op in simics - checkContTrace(); + checkDebugBuf(); if ( $opt_debug ) { ::userDisplay "=== isShutDown\n"; } ## check for system crash |

