Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
I have some simple code to process a Value Change Dump file and writes out data in the time ranges into one hash and writes out the last time a signal changed into another hash, besides other things.
All of these are further processed to split all the value changes into two groups: (1) signals that are changing in the time regions (time regions are specified using the syntax #time in the value change dump and (2) last change of any signal found in the Value Change Dump
and saved my input file as junk.vcd and then executed min.pl ./junk.vcd from my Linux command prompt):#!/usr/bin/perl use strict; use warnings; use diagnostics; use diagnostics -verbose; use Getopt::Long; use File::Path; use File::Copy; use Cwd; my $currentDir = getcwd; use Cwd 'abs_path'; my $vcdFile = $ARGV[0]; my $vcdObj = ClassVcd->new(); my $dataGenObj = ClassDataGen->new(); my ($inTimeRangeSignalsHRef, $sigsNotInTimeRangeHRef, $timeRngRef, $hi +erScopeRef) = $vcdObj->getSignalsWithValsInTimeWindow($vcdFile); foreach my $vcdFile (keys %{$inTimeRangeSignalsHRef}) { foreach my $s +igNm (keys %{$inTimeRangeSignalsHRef->{$vcdFile}}) { foreach my $sigId (keys %{$inTimeRangeSignalsHRef->{$vcdFile}->{$sig +Nm}}) { if (exists $inTimeRangeSignalsHRef->{$vcdFile}->{$sigNm}->{$sigId}- +>{$$timeRngRef}) { if (exists $inTimeRangeSignalsHRef->{$vcdFile}->{$sigNm}->{$sigId} +->{$$timeRngRef}->{$$hierScopeRef}) { print "Line 23 ::Dbg:: $vcdFile $sigNm $$timeRngRef\n"; } } } } $dataGenObj->matcher($inTimeRangeSignalsHRef, $sigsNotInTimeRangeHRef +, $timeRngRef, $hierScopeRef); } package ClassDataGen; sub new { my $class = shift; my $self = {}; bless($self, $class); return $self; } sub matcher { my $self = shift; my $inTimeRangeSignalsHRef = shift; my $sigsNotInTimeRangeHRef = shift; my $timeRangeRef = shift; my $hierScopeRef = shift; my %failedChecksH = (); my %matchingWhenRiRoCondsH = (); my %sigNmsVcdH = (); foreach my $vcdFile (keys %{$inTimeRangeSignalsHRef}) { foreach my $signalNm (keys %{$inTimeRangeSignalsHRef->{$vcdFile}}) { print "Line 67 ::Dbg:: $signalNm inTimeRangeSignalsHash\n"; } } } package ClassVcd; sub new { my $class = shift; my $self = {}; bless($self, $class); return $self; } sub getSignalsWithValsInTimeWindow { my $self = shift; my $vcdFileOrig = shift; my %vcdSigValsScopeH = (); my %inTimeRangeSignalsH = (); my %sigsNotInTimeRangeH = (); my $timeRng = ""; my $hierScope = ""; my $vcdObj = ClassVcd->new(); my ($lastKnownSigValHRef, $scopesHierHRef, $scopesHRef, $timeRangeHRe +f, $timeIntervalBasedActivityHRef, $vcdFile, $timeUnits) = $vcdObj->p +arseVcd($vcdFileOrig); if(exists $timeRangeHRef->{$vcdFile}) { $timeRng = $timeRangeHRef->{$vcdFile}->{'TIMERANGES'}->[-1]; if(exists $timeIntervalBasedActivityHRef->{$vcdFile}) { if(exists $timeIntervalBasedActivityHRef->{$vcdFile}->{$timeRng}) { foreach my $sigId (keys %{$timeIntervalBasedActivityHRef->{$vcdFil +e}->{$timeRng}}) { foreach my $sigName (keys %{$timeIntervalBasedActivityHRef->{$vcd +File}->{$timeRng}->{$sigId}}) { foreach my $scopeNm (keys %{$timeIntervalBasedActivityHRef->{$vc +dFile}->{$timeRng}->{$sigId}->{$sigName}}) { if ( ($scopeNm =~ /_TB/) && (exists $timeIntervalBasedActivityH +Ref->{$vcdFile}->{$timeRng}->{$sigId}->{$sigName}->{$scopeNm}->{'EXPA +NDEDVAL'}) ) { $hierScope = $scopeNm; my $sigValue = $timeIntervalBasedActivityHRef->{$vcdFile}->{$ +timeRng}->{$sigId}->{$sigName}->{$scopeNm}->{'EXPANDEDVAL'}->[-1]; $inTimeRangeSignalsH{$vcdFile}{$sigName}{$sigId}{$timeRng}{$sc +opeNm} = $sigValue; } } } } } } } if(exists $lastKnownSigValHRef->{$vcdFile}) { foreach my $signalId (keys %{$lastKnownSigValHRef->{$vcdFile}}) { foreach my $signalNm (keys %{$lastKnownSigValHRef->{$vcdFile}->{$si +gnalId}}) { if(!exists $inTimeRangeSignalsH{$vcdFile}{$signalNm}{$signalId}) { $sigsNotInTimeRangeH{$vcdFile}{$signalNm}{$signalId} = $lastKnown +SigValHRef->{$vcdFile}->{$signalId}->{$signalNm}->{$hierScope}->[0]; } } } } return(\%inTimeRangeSignalsH, \%sigsNotInTimeRangeH, \$timeRng, \$hie +rScope); } sub parseVcd { my $self = shift; my $vcdFile = shift; my @scopesA = (); my @timeValsA = (); my %scopesHierH = (); my %timedSigChangesH = (); my %totalSigActivityH = (); my %signalNotFoundInAnyScope = (); my %timeRangeH = (); my %timeValsH = (); my %dumpVarsH = (); my %scopesH = (); my %lastKnownSigValH = (); my $timescaleFlg = 0; my $scopeFlg = 0; my $scopeCnt = 0; my $upscopeCnt = 0; my $dumpvarsFlg = 0; my $inTimeFlg = 0; my $timeCnt = 0; my $timeScale = ""; my $timeUnits = ""; my $timeMultiplier = ""; my $scopeName = ""; my $timeValue = ""; my $foundSignalInSomeScope = 0; open(VCD,"<", $vcdFile) or die "Cannot open $vcdFile:$!"; while(<VCD>) { chomp; if(/^\s*\$timescale\s*$/) { $timescaleFlg = 1; } if($timescaleFlg == 1) { if(/^\s*\$end\s*$/) { $timescaleFlg = 0; }else{ if(/^\s*([0-9]+)\s+(\S+)\s*$/) { $timeMultiplier = $1; $timeUnits = $2; } } } if(/^\s*\$scope\s+module\s+(\S+)\s+\$end/) { $scopeFlg = 1; $scopeName = $1; $scopeCnt++; push(@{$scopesHierH{$vcdFile}{'SCOPES'}}, $scopeName); } if($scopeFlg == 1) { if(/^\s*\$upscope\s+\$end/) { $upscopeCnt++; if($upscopeCnt == $scopeCnt) { $scopeFlg = 0; } }else{ my $varLine = ""; if(/^\s*\$var\s+.*\$end\s*$/) { $varLine = $_; $varLine =~ s/\s+\[(.*)\]\s+\$end/\[$1\] \$end/g; } if($varLine =~ /^\s*\$var\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+\$end\ +s*$/) { my $sigName = $4; my $sigId = $3; my $sigSize = $2; my $sigType = $1; if($sigName =~ /\[\S+\]/) { } if( (defined $scopeName) && ($scopeName ne "")) { if((defined $sigId) && ($sigId ne "")) { if((defined $sigName) && ($sigName ne "")) { if((defined $sigSize) && ($sigSize ne "")) { if((defined $sigType) && ($sigType ne "")) { $scopesH{$vcdFile}{$sigId}{$sigName}{$scopeName} = [$sigType +, $sigSize]; } } } } } } } } if( (/^\s*\$dumpvars\s*$/) && ($inTimeFlg == 0) ) { $dumpvarsFlg = 1; } if( ($dumpvarsFlg == 1) && ($inTimeFlg == 0) ) { if(/^\s*\$end\s*$/) { $dumpvarsFlg = 0; }else{ if(/^\s*(b.*)\s+(\S+)\s*$/) { my $sigId = $2; my $sigVal = $1; if(exists $scopesH{$vcdFile}{$sigId}) { foreach my $sigNm (sort keys %{$scopesH{$vcdFile}{$sigId}}) { foreach my $scopeNm (sort keys %{$scopesH{$vcdFile}{$sigId}{$s +igNm}}) { $lastKnownSigValH{$vcdFile}{$sigId}{$sigNm}{$scopeNm} = [$sigV +al, 'dumpvars']; } } } }elsif( (/^\s*(\S)(\S+)\s*$/) && !(/^\s*(b.*)\s+(\S+)\s*$/) ) { my $sigId = $2; my $sigVal = $1; if(exists $scopesH{$vcdFile}{$sigId}) { foreach my $sigNm (sort keys %{$scopesH{$vcdFile}{$sigId}}) { foreach my $scopeNm (sort keys %{$scopesH{$vcdFile}{$sigId}{$s +igNm}}) { $lastKnownSigValH{$vcdFile}{$sigId}{$sigNm}{$scopeNm} = [$sigV +al, 'dumpvars']; } } } } } } if(/^\s*(#\S+)\s*$/) { $inTimeFlg = 1; my $timePoint = $1; } if($inTimeFlg == 1) { if(/^\s*#(\S+)\s*$/) { my $time = $1; $time *= $timeMultiplier; $timeValue = '#'.$time; push(@timeValsA, $timeValue); }elsif( (/^\s*(\S)(\S+)\s*$/) || (/^\s*(b.*)\s+(\S+)\s*$/) ) { my $signalVal = $1; my $signalId = $2; if(!exists $totalSigActivityH{$vcdFile}{$signalId}) { $totalSigActivityH{$vcdFile}{$signalId}{'CNT'} = 0; }else{ $totalSigActivityH{$vcdFile}{$signalId}{'CNT'}++; } if(exists $scopesH{$vcdFile}{$signalId}) { foreach my $sigNm (sort keys %{$scopesH{$vcdFile}{$signalId}}) { foreach my $scopeNm (sort keys %{$scopesH{$vcdFile}{$signalId}{ +$sigNm}}) { $lastKnownSigValH{$vcdFile}{$signalId}{$sigNm}{$scopeNm} = [$si +gnalVal, $timeValue]; if(exists $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$s +igNm}{$scopeNm}) { if( (exists $timedSigChangesH{$vcdFile}{$timeValue}{$signalId} +{$sigNm}{$scopeNm}{'VAL'}) && ($timedSigChangesH{$vcdFile}{$timeValue +}{$signalId}{$sigNm}{$scopeNm}{'VAL'} ne "") ) { if($timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm} +{$scopeNm}{'VAL'} ne $signalVal) { if(exists $timedSigChangesH{$vcdFile}{$timeValue}{$signalId} +{$sigNm}{$scopeNm}{'CNT'}) { $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{ +$scopeNm}{'CNT'}++; }else{ $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{ +$scopeNm}{'CNT'} = 0; } $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{$ +scopeNm}{'VAL'} = $signalVal; my $expandedVal = $signalVal; push(@{$timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$s +igNm}{$scopeNm}{'EXPANDEDVAL'}}, $expandedVal); }elsif($timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$si +gNm}{$scopeNm}{'VAL'} eq $signalVal) { my $expandedVal = $signalVal; push(@{$timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$s +igNm}{$scopeNm}{'EXPANDEDVAL'}}, $expandedVal); if (!exists $timedSigChangesH{$vcdFile}{$timeValue}{$signalI +d}{$sigNm}{$scopeNm}{'CNT'}) { $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{ +$scopeNm}{'CNT'} = 0; } } }elsif(!exists $timedSigChangesH{$vcdFile}{$timeValue}{$signal +Id}{$sigNm}{$scopeNm}{'VAL'}) { $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{$s +copeNm}{'VAL'} = $signalVal; $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{$s +copeNm}{'CNT'} = 0; my $expandedVal = $signalVal; push(@{$timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$si +gNm}{$scopeNm}{'EXPANDEDVAL'}}, $expandedVal); $signalNotFoundInAnyScope{$vcdFile}{$signalId}++;; } }elsif(!exists $timedSigChangesH{$vcdFile}{$timeValue}{$signalI +d}{$sigNm}{$scopeNm}) { $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{$sc +opeNm}{'VAL'} = $signalVal; $timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sigNm}{$sc +opeNm}{'CNT'} = 0; my $expandedVal = $signalVal; push(@{$timedSigChangesH{$vcdFile}{$timeValue}{$signalId}{$sig +Nm}{$scopeNm}{'EXPANDEDVAL'}}, $expandedVal); } } } } } } } close VCD; my %timeIntervalBasedActivityH = (); my @timeRangeA = (); push(@timeValsA, 'END'); my $limit = scalar (@timeValsA) - 1; for(my $i = 0; $i <= $limit; $i++) { if(exists $timedSigChangesH{$vcdFile}{$timeValsA[$i]}) { my $lBound = $timeValsA[$i]; my $hBound = $timeValsA[$i+1]; my $timeRange = $lBound." ".$hBound; push(@{$timeRangeH{$vcdFile}{'TIMERANGES'}}, $timeRange); foreach my $sigId (keys %{$timedSigChangesH{$vcdFile}{$lBound}}) { foreach my $sigName (keys %{$timedSigChangesH{$vcdFile}{$lBound}{$ +sigId}}) { foreach my $scopeNm (keys %{$timedSigChangesH{$vcdFile}{$lBound}{ +$sigId}{$sigName}}) { if(exists $timedSigChangesH{$vcdFile}{$lBound}{$sigId}{$sigName} +{$scopeNm}{'CNT'}) { $timeIntervalBasedActivityH{$vcdFile}{$timeRange}{$sigId}{$sigN +ame}{$scopeNm}{'CNT'} = $timedSigChangesH{$vcdFile}{$lBound}{$sigId}{ +$sigName}{$scopeNm}{'CNT'}; } if(exists $timedSigChangesH{$vcdFile}{$lBound}{$sigId}{$sigName} +{$scopeNm}{'EXPANDEDVAL'}) { foreach my $expandedVal (@{$timedSigChangesH{$vcdFile}{$lBound} +{$sigId}{$sigName}{$scopeNm}{'EXPANDEDVAL'}}) { push(@{$timeIntervalBasedActivityH{$vcdFile}{$timeRange}{$sigI +d}{$sigName}{$scopeNm}{'EXPANDEDVAL'}}, $expandedVal); } } } } } } } return(\%lastKnownSigValH, \%scopesHierH, \%scopesH, \%timeRangeH, \% +timeIntervalBasedActivityH, $vcdFile, $timeUnits); } <code> Here is a sample input file, I used to run the above code (saved the a +bove file into a file called <code>min.pl
Here is the output I got:$date Dec 02, 2012 04:51:31 $end $version TOOL: ncsim(64) 10.20-s027 $end $timescale 1 ps $end $scope module JUNKCELL_TB $end $var wire 1 ! I0 $end $var wire 1 " I1 $end $var wire 1 # I2 $end $var wire 1 $ RIGHT $end $var wire 1 % SERIAL $end $var wire 1 & ZEN $end $scope module DUTJNKCELL $end $var wire 1 ! I0 $end $var wire 1 " I1 $end $var wire 1 # I2 $end $var wire 1 & ZEN $end $var wire 1 $ RIGHT $end $var wire 1 % SERIAL $end $var wire 1 ' lnx0_out $end $var wire 1 ( lnx1_out $end $var wire 1 ) lnx2_out $end $var wire 1 * lnx3_out $end $var wire 1 + lnx4_out $end $var wire 1 , lnx5_out $end $upscope $end $upscope $end $enddefinitions $end $dumpvars 0! 0" 0# 1$ 1% 1& 0' 0( 1) 0* 1+ 0, $end #10 1! 1' 1( 0) 0$ 0& #20
Produces the output below:[jeff@lnx02_sfo]$ ./min.pl ./junkCell.vcd
Please see the lines "Line 67 ::Dbg::...". These are printed by calling $dataGenObj->matcher($inTimeRangeSignalsHRef, $sigsNotInTimeRangeHRef, $timeRngRef, $hierScopeRef); Why does calling $dataGenObj->matcher($inTimeRangeSignalsHRef, $sigsNotInTimeRangeHRef, $timeRngRef, $hierScopeRef); print all these extra signals as part of $inTimeRangeSignalsHRef? I was expecting that the Hash %inTimeRangeSignalsH contains only three signals as shown below:Line 23 ::Dbg:: ./junkCell.vcd I0 #10 #20 Line 23 ::Dbg:: ./junkCell.vcd ZEN #10 #20 Line 23 ::Dbg:: ./junkCell.vcd RIGHT #10 #20 Line 67 ::Dbg:: lnx4_out inTimeRangeSignalsHash Line 67 ::Dbg:: I0 inTimeRangeSignalsHash Line 67 ::Dbg:: lnx1_out inTimeRangeSignalsHash Line 67 ::Dbg:: ZEN inTimeRangeSignalsHash Line 67 ::Dbg:: lnx3_out inTimeRangeSignalsHash Line 67 ::Dbg:: RIGHT inTimeRangeSignalsHash Line 67 ::Dbg:: lnx2_out inTimeRangeSignalsHash Line 67 ::Dbg:: lnx5_out inTimeRangeSignalsHash Line 67 ::Dbg:: lnx0_out inTimeRangeSignalsHash Line 67 ::Dbg:: SSERIAL inTimeRangeSignalsHash Line 67 ::Dbg:: I2 inTimeRangeSignalsHash Line 67 ::Dbg:: SERIAL inTimeRangeSignalsHash Line 67 ::Dbg:: I1 inTimeRangeSignalsHash
Line 23 ::Dbg:: ./junkCell.vcd I0 #10 #20 Line 23 ::Dbg:: ./junkCell.vcd ZEN #10 #20 Line 23 ::Dbg:: ./junkCell.vcd RIGHT #10 #20
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Hashes not working as expected
by Anonymous Monk on Feb 27, 2016 at 07:02 UTC | |
by stevieb (Canon) on Feb 27, 2016 at 13:14 UTC | |
by poj (Abbot) on Feb 27, 2016 at 18:38 UTC |