Fix VCD files showing internal flattened hierarchy, broke in 3.714.
This commit is contained in:
parent
66d000f4ba
commit
db5674cb08
4
Changes
4
Changes
|
|
@ -3,6 +3,10 @@ Revision history for Verilator
|
||||||
The contributors that suggested a given feature are shown in []. [by ...]
|
The contributors that suggested a given feature are shown in []. [by ...]
|
||||||
indicates the contributor was also the author of the fix; Thanks!
|
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
|
* Verilator 3.714 2009/09/18
|
||||||
|
|
||||||
** Add --bbox-sys option to blackbox $system calls.
|
** Add --bbox-sys option to blackbox $system calls.
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,21 @@ string AstNode::dedotName(const string& namein) {
|
||||||
return pretty;
|
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 AstNode::prettyName(const string& namein) {
|
||||||
string pretty;
|
string pretty;
|
||||||
pretty = "";
|
pretty = "";
|
||||||
|
|
|
||||||
|
|
@ -676,6 +676,7 @@ public:
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
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 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 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 prettyName() const { return prettyName(name()); }
|
||||||
string prettyTypeName() const; // "VARREF name" for error messages
|
string prettyTypeName() const; // "VARREF name" for error messages
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,10 @@ private:
|
||||||
AstVar* varp = nodep->varp();
|
AstVar* varp = nodep->varp();
|
||||||
AstScope* scopep = nodep->scopep();
|
AstScope* scopep = nodep->scopep();
|
||||||
// Compute show name
|
// Compute show name
|
||||||
string showname = scopep->prettyName() + "." + varp->prettyName();
|
// This code assumes SPTRACEVCDC_VERSION >= 1330;
|
||||||
if (showname.substr(0,4) == "TOP.") showname.replace(0,4,"");
|
// 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 (!m_initSubFuncp) nodep->v3fatalSrc("NULL");
|
||||||
if (varIgnoreTrace(varp)) {
|
if (varIgnoreTrace(varp)) {
|
||||||
m_statIgnSigs++;
|
m_statIgnSigs++;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ BEGIN {
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use IO::File;
|
use IO::File;
|
||||||
use Pod::Usage;
|
use Pod::Usage;
|
||||||
use Data::Dumper;
|
use Data::Dumper; $Data::Dumper::Sortkeys=1;
|
||||||
use strict;
|
use strict;
|
||||||
use vars qw ($Debug %Vars $Driver $Fork);
|
use vars qw ($Debug %Vars $Driver $Fork);
|
||||||
use POSIX qw(strftime);
|
use POSIX qw(strftime);
|
||||||
|
|
@ -903,17 +903,59 @@ sub vcd_identical {
|
||||||
my $fn2 = shift;
|
my $fn2 = shift;
|
||||||
if (!-r $fn1) { $self->error("File does not exist $fn1\n"); return 0; }
|
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; }
|
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; }
|
# vcddiff to check transitions, if installed
|
||||||
$out = `vcddiff "$fn1" "$fn2"`;
|
my $out = `vcddiff --help`;
|
||||||
if ($out ne '') {
|
if ($out !~ /Usage:/) { $self->skip("No vcddiff installed\n"); return 0; }
|
||||||
print $out;
|
my $cmd = qq{vcddiff "$fn1" "$fn2"};
|
||||||
$self->error("VCD miscompare $fn1 $fn2\n");
|
print "\t$cmd\n" if $::Debug;
|
||||||
return 0;
|
$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;
|
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 {
|
sub file_grep_not {
|
||||||
my $self = (ref $_[0]? shift : $Self);
|
my $self = (ref $_[0]? shift : $Self);
|
||||||
my $filename = shift;
|
my $filename = shift;
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ if ($Self->{v3}) {
|
||||||
check_finished=>1,
|
check_finished=>1,
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(vcd_identical ("$Self->{obj_dir}/simx.vcd",
|
vcd_identical ("$Self->{obj_dir}/simx.vcd",
|
||||||
"t/$Self->{name}.out"));
|
"t/$Self->{name}.out");
|
||||||
}
|
|
||||||
else {
|
|
||||||
ok(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@ if ($Self->{v3}) {
|
||||||
check_finished=>1,
|
check_finished=>1,
|
||||||
);
|
);
|
||||||
|
|
||||||
ok(vcd_identical ("$Self->{obj_dir}/simx.vcd",
|
vcd_identical ("$Self->{obj_dir}/simx.vcd",
|
||||||
"t/$Self->{name}.out"));
|
"t/$Self->{name}.out");
|
||||||
}
|
# vcd_identical doesn't detect "$var a.b;" vs "$scope module a; $var b;"
|
||||||
else {
|
file_grep ("$Self->{obj_dir}/simx.vcd", qr/module glbl/i);
|
||||||
ok(1);
|
|
||||||
}
|
}
|
||||||
|
ok(1);
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
|
|
@ -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+
|
||||||
|
|
@ -19,7 +19,11 @@ execute (
|
||||||
if ($Self->{v3}) {
|
if ($Self->{v3}) {
|
||||||
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
|
file_grep ("$Self->{obj_dir}/simx.vcd", qr/\$enddefinitions/x);
|
||||||
my $sig = quotemeta("bra[ket]slash/dash-colon:9");
|
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);
|
ok(1);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
sub a0 (.cyc(cyc));
|
sub a0 (.cyc(cyc));
|
||||||
|
|
||||||
|
sub \mod.with_dot (.cyc(cyc));
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
cyc <= cyc + 1;
|
cyc <= cyc + 1;
|
||||||
if (escaped_normal != cyc[0]) $stop;
|
if (escaped_normal != cyc[0]) $stop;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue