Fix VCD files showing internal flattened hierarchy, broke in 3.714.

This commit is contained in:
Wilson Snyder 2009-09-26 09:31:50 -04:00
parent 66d000f4ba
commit db5674cb08
10 changed files with 334 additions and 21 deletions

View File

@ -3,6 +3,10 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.71****
**** Fix VCD files showing internal flattened hierarchy, broke in 3.714.
* Verilator 3.714 2009/09/18
** Add --bbox-sys option to blackbox $system calls.

View File

@ -139,6 +139,21 @@ string AstNode::dedotName(const string& namein) {
return pretty;
}
string AstNode::vcdName(const string& namein) {
// VCD tracing expects space to separate hiearchy
// Dots are reserved for dots the user put in the name
string pretty = namein;
string::size_type pos;
while ((pos=pretty.find("__DOT__")) != string::npos) {
pretty.replace(pos, 7, " ");
}
while ((pos=pretty.find(".")) != string::npos) {
pretty.replace(pos, 1, " ");
}
// Now convert escaped special characters, etc
return prettyName(pretty);
}
string AstNode::prettyName(const string& namein) {
string pretty;
pretty = "";

View File

@ -676,6 +676,7 @@ public:
static string prettyName(const string& namein); // Name for printing out to the user
static string encodeName(const string& namein); // Encode user name into internal C representation
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
static string vcdName(const string& namein); // Name for printing out to vcd files
string prettyName() const { return prettyName(name()); }
string prettyTypeName() const; // "VARREF name" for error messages
FileLine* fileline() const { return m_fileline; }

View File

@ -125,8 +125,10 @@ private:
AstVar* varp = nodep->varp();
AstScope* scopep = nodep->scopep();
// Compute show name
string showname = scopep->prettyName() + "." + varp->prettyName();
if (showname.substr(0,4) == "TOP.") showname.replace(0,4,"");
// This code assumes SPTRACEVCDC_VERSION >= 1330;
// it uses spaces to separate hierarchy components.
string showname = AstNode::vcdName(scopep->name() + " " + varp->name());
if (showname.substr(0,4) == "TOP ") showname.replace(0,4,"");
if (!m_initSubFuncp) nodep->v3fatalSrc("NULL");
if (varIgnoreTrace(varp)) {
m_statIgnSigs++;

View File

@ -13,7 +13,7 @@ BEGIN {
use Getopt::Long;
use IO::File;
use Pod::Usage;
use Data::Dumper;
use Data::Dumper; $Data::Dumper::Sortkeys=1;
use strict;
use vars qw ($Debug %Vars $Driver $Fork);
use POSIX qw(strftime);
@ -903,17 +903,59 @@ sub vcd_identical {
my $fn2 = shift;
if (!-r $fn1) { $self->error("File does not exist $fn1\n"); return 0; }
if (!-r $fn2) { $self->error("File does not exist $fn2\n"); return 0; }
my $out = `vcddiff --help`;
if ($out !~ /Usage:/) { $self->skip("No vcddiff installed\n"); return 0; }
$out = `vcddiff "$fn1" "$fn2"`;
if ($out ne '') {
print $out;
$self->error("VCD miscompare $fn1 $fn2\n");
return 0;
{
# vcddiff to check transitions, if installed
my $out = `vcddiff --help`;
if ($out !~ /Usage:/) { $self->skip("No vcddiff installed\n"); return 0; }
my $cmd = qq{vcddiff "$fn1" "$fn2"};
print "\t$cmd\n" if $::Debug;
$out = `$cmd`;
if ($out ne '') {
print $out;
$self->error("VCD miscompare $fn1 $fn2\n");
return 0;
}
}
{
# vcddiff doesn't check module and variable scope, so check that
# Also provides backup if vcddiff not installed
my $h1 = $self->_vcd_read($fn1);
my $h2 = $self->_vcd_read($fn2);
$Data::Dumper::Sortkeys=1;
my $a = Dumper($h1);
my $b = Dumper($h2);
if ($a ne $b) {
print "$a\n$b\n" if $::Debug;
$self->error("VCD hier mismatch $fn1 $fn2\n");
return 0;
}
}
return 1;
}
sub _vcd_read {
my $self = (ref $_[0]? shift : $Self);
my $filename = shift;
my $data = {};
my $fh = IO::File->new ("<$filename");
if (!$fh) { warn "%Error: $! $filename\n"; return $data; }
my @hier = ($data);
while (defined(my $line = $fh->getline)) {
if ($line =~ /\$scope module\s+(\S+)/) {
$hier[$#hier]->{$1} ||= {};
push @hier, $hier[$#hier]->{$1};
} elsif ($line =~ /(\$var \S+\s+\d+\s+)\S+\s+(\S+)/) {
$hier[$#hier]->{$1.$2} ||= 1;
} elsif ($line =~ /\$enddefinitions/) {
last;
}
while ($line =~ s/\$upscope//) {
pop @hier;
}
}
return $data;
}
sub file_grep_not {
my $self = (ref $_[0]? shift : $Self);
my $filename = shift;

View File

@ -20,10 +20,9 @@ if ($Self->{v3}) {
check_finished=>1,
);
ok(vcd_identical ("$Self->{obj_dir}/simx.vcd",
"t/$Self->{name}.out"));
}
else {
ok(1);
vcd_identical ("$Self->{obj_dir}/simx.vcd",
"t/$Self->{name}.out");
}
ok(1);
1;

View File

@ -20,10 +20,10 @@ if ($Self->{v3}) {
check_finished=>1,
);
ok(vcd_identical ("$Self->{obj_dir}/simx.vcd",
"t/$Self->{name}.out"));
}
else {
ok(1);
vcd_identical ("$Self->{obj_dir}/simx.vcd",
"t/$Self->{name}.out");
# vcd_identical doesn't detect "$var a.b;" vs "$scope module a; $var b;"
file_grep ("$Self->{obj_dir}/simx.vcd", qr/module glbl/i);
}
ok(1);
1;

View File

@ -0,0 +1,244 @@
$version Generated by SpTraceVcd $end
$date Sat Sep 26 08:06:30 2009
$end
$timescale 1ns $end
$scope module TOP $end
$var wire 1 * 9num $end
$var wire 1 + bra[ket]slash/dash-colon:9backslash\done $end
$var wire 1 ' clk $end
$var wire 1 ) double__underscore $end
$var wire 1 ( escaped_normal $end
$scope module v $end
$var wire 1 * 9num $end
$var wire 32 & a0.cyc [31:0] $end
$var wire 1 + bra[ket]slash/dash-colon:9backslash\done $end
$var wire 1 $ check:alias $end
$var wire 1 % check;alias $end
$var wire 1 $ check_alias $end
$var wire 1 ' clk $end
$var wire 32 # cyc [31:0] $end
$var wire 1 ) double__underscore $end
$var wire 1 ( escaped_normal $end
$var wire 32 & other.cyc [31:0] $end
$var wire 1 $ wire $end
$scope module a0 $end
$var wire 32 # cyc [31:0] $end
$upscope $end
$scope module mod.with_dot $end
$var wire 32 # cyc [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#1
1$
0%
b11111111111111111111111111111110 &
b00000000000000000000000000000001 #
1'
1(
1)
1*
1+
#2
#3
#4
#5
0'
#6
#7
#8
#9
#10
0$
1%
b11111111111111111111111111111101 &
b00000000000000000000000000000010 #
1'
0(
0)
0*
0+
#11
#12
#13
#14
#15
0'
#16
#17
#18
#19
#20
1$
0%
b11111111111111111111111111111100 &
b00000000000000000000000000000011 #
1'
1(
1)
1*
1+
#21
#22
#23
#24
#25
0'
#26
#27
#28
#29
#30
0$
1%
b11111111111111111111111111111011 &
b00000000000000000000000000000100 #
1'
0(
0)
0*
0+
#31
#32
#33
#34
#35
0'
#36
#37
#38
#39
#40
1$
0%
b11111111111111111111111111111010 &
b00000000000000000000000000000101 #
1'
1(
1)
1*
1+
#41
#42
#43
#44
#45
0'
#46
#47
#48
#49
#50
0$
1%
b11111111111111111111111111111001 &
b00000000000000000000000000000110 #
1'
0(
0)
0*
0+
#51
#52
#53
#54
#55
0'
#56
#57
#58
#59
#60
1$
0%
b11111111111111111111111111111000 &
b00000000000000000000000000000111 #
1'
1(
1)
1*
1+
#61
#62
#63
#64
#65
0'
#66
#67
#68
#69
#70
0$
1%
b11111111111111111111111111110111 &
b00000000000000000000000000001000 #
1'
0(
0)
0*
0+
#71
#72
#73
#74
#75
0'
#76
#77
#78
#79
#80
1$
0%
b11111111111111111111111111110110 &
b00000000000000000000000000001001 #
1'
1(
1)
1*
1+
#81
#82
#83
#84
#85
0'
#86
#87
#88
#89
#90
0$
1%
b11111111111111111111111111110101 &
b00000000000000000000000000001010 #
1'
0(
0)
0*
0+
#91
#92
#93
#94
#95
0'
#96
#97
#98
#99
#100
1$
0%
b11111111111111111111111111110100 &
b00000000000000000000000000001011 #
1'
1(
1)
1*
1+

View File

@ -19,7 +19,11 @@ execute (
if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
my $sig = quotemeta("bra[ket]slash/dash-colon:9");
file_grep ("$Self->{obj_dir}/simx.vcd", qr/$sig/);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/ $sig/);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/ other\.cyc /);
file_grep ("$Self->{obj_dir}/simx.vcd", qr/ module mod\.with_dot /);
vcd_identical ("$Self->{obj_dir}/simx.vcd",
"t/$Self->{name}.out");
}
ok(1);

View File

@ -38,6 +38,8 @@ module t (/*AUTOARG*/
sub a0 (.cyc(cyc));
sub \mod.with_dot (.cyc(cyc));
always @ (posedge clk) begin
cyc <= cyc + 1;
if (escaped_normal != cyc[0]) $stop;