Fix escaped identifiers with '.' causing conflicts, bug83.

This commit is contained in:
Wilson Snyder 2009-05-08 13:16:19 -04:00
parent 4569278c53
commit a3e463030d
11 changed files with 91 additions and 47 deletions

View File

@ -7,6 +7,11 @@ indicates the contributor was also the author of the fix; Thanks!
** Verilator is now licensed under LGPL v3 and/or Artistic v2.0. ** Verilator is now licensed under LGPL v3 and/or Artistic v2.0.
**** The front end parser has been re-factored to enable more SV parsing.
Code should parse the same, but minor parsing bugs may pop up now.
**** Fix escaped identifiers with '.' causing conflicts, bug83. [J Baxter]
* Verilator 3.703 2009/05/02 * Verilator 3.703 2009/05/02
*** Fix $clog2 calculation error with powers-of-2, bug81. [Patricio Kaplan] *** Fix $clog2 calculation error with powers-of-2, bug81. [Patricio Kaplan]

View File

@ -86,9 +86,9 @@ void AstNode::init() {
} }
string AstNode::encodeName(const string& namein) { string AstNode::encodeName(const string& namein) {
string name2 = namein; // Encode signal name raw from parser, then not called again on same signal
const char* start = namein.c_str();
string out; string out;
const char* start = name2.c_str();
for (const char* pos = start; *pos; pos++) { for (const char* pos = start; *pos; pos++) {
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
: isalnum(pos[0])) { : isalnum(pos[0])) {
@ -100,17 +100,13 @@ string AstNode::encodeName(const string& namein) {
} else { } else {
out += pos[0]; out += pos[0];
} }
} else if (pos[0]=='.') {
out += "__DOT__";
} else if (pos[0]=='[') {
out += "__BRA__";
} else if (pos[0]==']') {
out += "__KET__";
} else { } else {
// Need the leading 0 so this will never collide with // Need the leading 0 so this will never collide with
// a user identifier nor a temp we create in Verilator. // a user identifier nor a temp we create in Verilator.
char hex[10]; sprintf(hex,"%02X",pos[0]); // We also do *NOT* use __DOT__ etc, as we search for those
out += "__0"; out += hex; // in some replacements, and don't want to mangle the user's names.
char hex[10]; sprintf(hex,"__0%02X",pos[0]);
out += hex;
} }
} }
return out; return out;
@ -145,9 +141,8 @@ string AstNode::dedotName(const string& namein) {
string AstNode::prettyName(const string& namein) { string AstNode::prettyName(const string& namein) {
string pretty; string pretty;
string name2 = namein;
pretty = ""; pretty = "";
for (const char* pos = name2.c_str(); *pos; ) { for (const char* pos = namein.c_str(); *pos; ) {
if (0==strncmp(pos,"__BRA__",7)) { if (0==strncmp(pos,"__BRA__",7)) {
pretty += "["; pretty += "[";
pos += 7; pos += 7;

View File

@ -207,12 +207,12 @@ public:
// hiearchies itself, and if SystemPerl also did it, you'd end up // hiearchies itself, and if SystemPerl also did it, you'd end up
// with (number-of-instant) times too many counts in this bin. // with (number-of-instant) times too many counts in this bin.
puts(", first"); // Enable, passed from __Vconfigure parameter puts(", first"); // Enable, passed from __Vconfigure parameter
puts(", \""); puts(nodep->fileline()->filename()); puts("\""); puts(", "); putsQuoted(nodep->fileline()->filename());
puts(", "); puts(cvtToStr(nodep->fileline()->lineno())); puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
puts(", "); puts(cvtToStr(nodep->column())); puts(", "); puts(cvtToStr(nodep->column()));
puts(", \""); puts((nodep->hier()!=""?".":"")+nodep->hier()); puts("\""); puts(", "); putsQuoted((nodep->hier()!=""?".":"")+nodep->hier());
puts(", \""); puts(nodep->page()); puts("\""); puts(", "); putsQuoted(nodep->page());
puts(", \""); puts(nodep->comment()); puts("\""); puts(", "); putsQuoted(nodep->comment());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstCoverInc* nodep, AstNUser*) { virtual void visit(AstCoverInc* nodep, AstNUser*) {
@ -339,16 +339,16 @@ public:
puts("}\n"); puts("}\n");
} }
virtual void visit(AstStop* nodep, AstNUser*) { virtual void visit(AstStop* nodep, AstNUser*) {
puts("vl_stop(\""); puts("vl_stop(");
puts(nodep->fileline()->filename()); putsQuoted(nodep->fileline()->filename());
puts("\","); puts(",");
puts(cvtToStr(nodep->fileline()->lineno())); puts(cvtToStr(nodep->fileline()->lineno()));
puts(",\"\");\n"); puts(",\"\");\n");
} }
virtual void visit(AstFinish* nodep, AstNUser*) { virtual void visit(AstFinish* nodep, AstNUser*) {
puts("vl_finish(\""); puts("vl_finish(");
puts(nodep->fileline()->filename()); putsQuoted(nodep->fileline()->filename());
puts("\","); puts(",");
puts(cvtToStr(nodep->fileline()->lineno())); puts(cvtToStr(nodep->fileline()->lineno()));
puts(",\"\");\n"); puts(",\"\");\n");
} }
@ -830,8 +830,8 @@ void EmitCStmts::emitVarCtors() {
} }
else puts(", "); else puts(", ");
if (ofp()->exceededWidth()) puts("\n "); if (ofp()->exceededWidth()) puts("\n ");
puts((*it)->name()); puts("(\""); puts((*it)->name());
puts((*it)->name()); puts("\")"); puts("("); putsQuoted((*it)->name()); puts(")");
} }
if (!first) puts ("\n#endif\n"); if (!first) puts ("\n#endif\n");
ofp()->indentDec(); ofp()->indentDec();
@ -995,7 +995,7 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
nodep->v3fatalSrc("Unknown displayEmit node type"); nodep->v3fatalSrc("Unknown displayEmit node type");
} }
puts("\""); puts("\"");
ofp()->putsNoTracking(emitDispState.m_format); ofp()->putsNoTracking(emitDispState.m_format); // Not putsQuoted - already contains \s
puts("\""); puts("\"");
// Arguments // Arguments
for (unsigned i=0; i < emitDispState.m_argsp.size(); i++) { for (unsigned i=0; i < emitDispState.m_argsp.size(); i++) {
@ -1299,7 +1299,9 @@ void EmitCImp::emitTextSection(AstType type) {
puts("\n//*** Below code from `systemc in Verilog file\n"); puts("\n//*** Below code from `systemc in Verilog file\n");
} }
ofp()->putsNoTracking("//#line "+cvtToStr(nodep->fileline()->lineno()) ofp()->putsNoTracking("//#line "+cvtToStr(nodep->fileline()->lineno())
+" \""+nodep->fileline()->filename()+"\"\n"); +" ");
ofp()->putsQuoted(nodep->fileline()->filename());
ofp()->putsNoTracking("\n");
last_line = nodep->fileline()->lineno(); last_line = nodep->fileline()->lineno();
} }
ofp()->putsNoTracking(textp->text()); ofp()->putsNoTracking(textp->text());
@ -1838,7 +1840,8 @@ class EmitCTrace : EmitCStmts {
} }
puts("(c+"+cvtToStr(nodep->code())); puts("(c+"+cvtToStr(nodep->code()));
if (nodep->arrayWidth()) puts("+i*"+cvtToStr(nodep->widthWords())); if (nodep->arrayWidth()) puts("+i*"+cvtToStr(nodep->widthWords()));
puts(",\""+nodep->showname()+"\""); puts(",");
putsQuoted(nodep->showname());
if (nodep->arrayWidth()) { if (nodep->arrayWidth()) {
puts(",(i+"+cvtToStr(nodep->arrayLsb())+")"); puts(",(i+"+cvtToStr(nodep->arrayLsb())+")");
} else { } else {

View File

@ -107,6 +107,7 @@ public:
V3OutCFile* ofp() const { return m_ofp; }; V3OutCFile* ofp() const { return m_ofp; };
void puts(const string& str) { ofp()->puts(str); } void puts(const string& str) { ofp()->puts(str); }
void putbs(const string& str) { ofp()->putbs(str); } void putbs(const string& str) { ofp()->putbs(str); }
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
bool optSystemC() { return v3Global.opt.systemC(); } bool optSystemC() { return v3Global.opt.systemC(); }
bool optSystemPerl() { return v3Global.opt.systemPerl(); } bool optSystemPerl() { return v3Global.opt.systemPerl(); }
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; } static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }

View File

@ -209,9 +209,9 @@ void EmitCSyms::emitImp() {
if (modp->isTop()) { if (modp->isTop()) {
} else { } else {
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str()); ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
puts("(Verilated::catName(topp->name(),\""); puts("(Verilated::catName(topp->name(),");
puts("."+scopep->prettyName()); putsQuoted("."+scopep->prettyName());
puts("\"))\n"); puts("))\n");
comma=','; comma=',';
} }
} }

View File

@ -177,7 +177,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putbs(" ("); putbs(" (");
if (filep) { filep->iterateAndNext(*this); putbs(","); } if (filep) { filep->iterateAndNext(*this); putbs(","); }
puts("\""); puts("\"");
putsNoTracking(text); putsNoTracking(text); // Not putsQuoted, as display text contains \ already
puts("\""); puts("\"");
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) { for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
puts(","); puts(",");

View File

@ -431,6 +431,23 @@ void V3OutFile::putBreak () {
} }
} }
void V3OutFile::putsQuoted(const char* strg) {
// Quote \ and " for use inside C programs
// Don't use to quote a filename for #include - #include doesn't \ escape.
putcNoTracking('"');
for (const char* cp=strg; *cp; cp++) {
if (*cp == '\\') {
putcNoTracking('\\');
putcNoTracking('\\');
} else if (*cp == '"') {
putcNoTracking('\\');
putcNoTracking('"');
} else {
putcNoTracking (*cp);
}
}
putcNoTracking('"');
}
void V3OutFile::putsNoTracking (const char *strg) { void V3OutFile::putsNoTracking (const char *strg) {
// Don't track {}'s, probably because it's a $display format string // Don't track {}'s, probably because it's a $display format string
for (const char* cp=strg; *cp; cp++) { for (const char* cp=strg; *cp; cp++) {

View File

@ -113,6 +113,8 @@ public:
void puts(const string& strg) { puts(strg.c_str()); } void puts(const string& strg) { puts(strg.c_str()); }
void putsNoTracking(const char* strg); void putsNoTracking(const char* strg);
void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); } void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); }
void putsQuoted(const char* strg);
void putsQuoted(const string& strg) { putsQuoted(strg.c_str()); }
void putBreak(); // Print linebreak if line is too wide void putBreak(); // Print linebreak if line is too wide
void putBreakExpr(); // Print linebreak in expression if line is too wide void putBreakExpr(); // Print linebreak in expression if line is too wide
void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment

View File

@ -278,7 +278,7 @@ private:
} }
// Autoflush // Autoflush
virtual void visit(AstDisplay* nodep, AstNUser* vup) { virtual void visit(AstDisplay* nodep, AstNUser*) {
startStatement(nodep); startStatement(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_stmtp = NULL; m_stmtp = NULL;

View File

@ -44,6 +44,7 @@ my $opt_vcs;
my $opt_v3; my $opt_v3;
my $opt_stop; my $opt_stop;
my $opt_optimize; my $opt_optimize;
my $opt_trace;
my $opt_gdb; my $opt_gdb;
my $opt_jobs = 1; my $opt_jobs = 1;
my $opt_verbose; my $opt_verbose;
@ -63,6 +64,7 @@ if (! GetOptions (
"gdb!" => \$opt_gdb, "gdb!" => \$opt_gdb,
"optimize:s" => \$opt_optimize, "optimize:s" => \$opt_optimize,
"stop!" => \$opt_stop, "stop!" => \$opt_stop,
"trace!" => \$opt_trace,
"verbose!" => \$opt_verbose, "verbose!" => \$opt_verbose,
"<>" => \&parameter, "<>" => \&parameter,
)) { )) {
@ -122,7 +124,7 @@ sub one_test {
} else { } else {
$test->oprint("FAILED: ","*"x60,"\n"); $test->oprint("FAILED: ","*"x60,"\n");
push @fails, "\t#".$test->soprint("%Error: $test->{errors}\n"); push @fails, "\t#".$test->soprint("%Error: $test->{errors}\n");
my $j = ($opt_jobs>1?" -j 2":""); my $j = ($opt_jobs>1?" -j $opt_jobs":"");
push @fails, "\t\tmake$j && test_regress/" push @fails, "\t\tmake$j && test_regress/"
.$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n"; .$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n";
$failcnt++; $failcnt++;
@ -234,6 +236,7 @@ sub new {
v_flags => [split(/\s+/,(" -f input.vc --debug-check" v_flags => [split(/\s+/,(" -f input.vc --debug-check"
.($opt_verbose ? " +define+TEST_VERBOSE=1":"") .($opt_verbose ? " +define+TEST_VERBOSE=1":"")
.($opt_benchmark ? " +define+TEST_BENCHMARK=$opt_benchmark":"") .($opt_benchmark ? " +define+TEST_BENCHMARK=$opt_benchmark":"")
.($opt_trace ? " +define+WAVES=1":"")
))], ))],
v_flags2 => [], # Overridden in some sim files v_flags2 => [], # Overridden in some sim files
v_other_filenames => [], # After the filename so we can spec multiple files v_other_filenames => [], # After the filename so we can spec multiple files
@ -265,6 +268,7 @@ sub new {
$self->{status_filename} ||= "$self->{obj_dir}/V".$self->{name}.".status"; $self->{status_filename} ||= "$self->{obj_dir}/V".$self->{name}.".status";
$self->{run_log_filename} ||= "$self->{obj_dir}/vl_sim.log"; $self->{run_log_filename} ||= "$self->{obj_dir}/vl_sim.log";
$self->{coverage_filename} ||= "$self->{obj_dir}/vl_coverage.pl"; $self->{coverage_filename} ||= "$self->{obj_dir}/vl_coverage.pl";
$self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd";
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/; ($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/;
if (!$self->{make_top_shell}) { if (!$self->{make_top_shell}) {
$self->{top_shell_filename} = $self->{top_filename}; $self->{top_shell_filename} = $self->{top_filename};
@ -349,7 +353,7 @@ sub compile {
@{$param{verilator_flags2}}); @{$param{verilator_flags2}});
$self->{sc} = 1 if ($checkflags =~ /-sc\b/); $self->{sc} = 1 if ($checkflags =~ /-sc\b/);
$self->{sp} = 1 if ($checkflags =~ /-sp\b/); $self->{sp} = 1 if ($checkflags =~ /-sp\b/);
$self->{trace} = 1 if ($checkflags =~ /-trace\b/); $self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/);
$self->{coverage} = 1 if ($checkflags =~ /-coverage\b/); $self->{coverage} = 1 if ($checkflags =~ /-coverage\b/);
if ($param{vcs}) { if ($param{vcs}) {
@ -386,7 +390,7 @@ sub compile {
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb; unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags; unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
# unshift @verilator_flags, "--trace"; unshift @verilator_flags, "--trace" if $opt_trace;
if (defined $opt_optimize) { if (defined $opt_optimize) {
my $letters = ""; my $letters = "";
if ($opt_optimize =~ /[a-zA-Z]/) { if ($opt_optimize =~ /[a-zA-Z]/) {
@ -786,7 +790,18 @@ sub _make_top {
} }
print $fh " );\n"; print $fh " );\n";
# Waves
print $fh "\n";
print $fh "`ifdef WAVES\n";
print $fh " initial begin\n";
print $fh " \$display(\"-Tracing Waves to Dumpfile: $self->{vcd_filename}\");\n";
print $fh " \$dumpfile(\"$self->{vcd_filename}\");\n";
print $fh " \$dumpvars(12, t);\n";
print $fh " end\n";
print $fh "`endif\n";
# Test # Test
print $fh "\n";
print $fh " initial begin\n"; print $fh " initial begin\n";
print $fh " fastclk=1;\n" if $self->{inputs}{fastclk}; print $fh " fastclk=1;\n" if $self->{inputs}{fastclk};
print $fh " clk=1;\n" if $self->{inputs}{clk}; print $fh " clk=1;\n" if $self->{inputs}{clk};

View File

@ -5,7 +5,7 @@
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Outputs // Outputs
\escaped_normal , double__underscore, \9num , \bra[ket]slash/dash-colon:9 , \escaped_normal , double__underscore, \9num , \bra[ket]slash/dash-colon:9backslash\done ,
// Inputs // Inputs
clk clk
); );
@ -24,20 +24,19 @@ module t (/*AUTOARG*/
output \9num ; output \9num ;
wire \9num = cyc[0]; wire \9num = cyc[0];
output \bra[ket]slash/dash-colon:9 ; output \bra[ket]slash/dash-colon:9backslash\done ;
wire \bra[ket]slash/dash-colon:9 = cyc[0]; wire \bra[ket]slash/dash-colon:9backslash\done = cyc[0];
wire \wire = cyc[0];
wire \check_alias = cyc[0]; wire \check_alias = cyc[0];
wire \check:alias = cyc[0]; wire \check:alias = cyc[0];
wire \check;alias = !cyc[0]; wire \check;alias = !cyc[0];
`ifndef verilator // These are *different entities*, bug83
initial begin wire [31:0] \a0.cyc = ~a0.cyc;
$dumpfile("obj_dir/t_var_escape/t_var_escape_dump.vcd"); wire [31:0] \other.cyc = ~a0.cyc;
$dumpvars( 0, t );
$dumpon; sub a0 (.cyc(cyc));
end
`endif
always @ (posedge clk) begin always @ (posedge clk) begin
cyc <= cyc + 1; cyc <= cyc + 1;
@ -45,11 +44,13 @@ module t (/*AUTOARG*/
if (\escaped_normal != cyc[0]) $stop; if (\escaped_normal != cyc[0]) $stop;
if (double__underscore != cyc[0]) $stop; if (double__underscore != cyc[0]) $stop;
if (\9num != cyc[0]) $stop; if (\9num != cyc[0]) $stop;
if (\bra[ket]slash/dash-colon:9 != cyc[0]) $stop; if (\bra[ket]slash/dash-colon:9backslash\done != cyc[0]) $stop;
if (\wire != cyc[0]) $stop;
if (\check_alias != cyc[0]) $stop; if (\check_alias != cyc[0]) $stop;
if (\check:alias != cyc[0]) $stop; if (\check:alias != cyc[0]) $stop;
if (\check;alias != !cyc[0]) $stop; if (\check;alias != !cyc[0]) $stop;
if (\a0.cyc != ~cyc) $stop;
if (\other.cyc != ~cyc) $stop;
if (cyc==10) begin if (cyc==10) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
@ -57,3 +58,8 @@ module t (/*AUTOARG*/
end end
endmodule endmodule
module sub (
input [31:0] cyc
);
endmodule