diff --git a/Changes b/Changes index 9c4368051..c16077e68 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,9 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.63* +** Support standard NAME[#] for cells created by arraying or generate for. + This replaces the non-standard name__# syntax used in earlier versions. + **** Fix again dotted references into generate cells. [David Hewson] Verilator no longer accepts duplicated variables inside unique generate blocks as this is illegal according to the specification. diff --git a/bin/verilator b/bin/verilator index 3656ca549..5608426b2 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1169,24 +1169,22 @@ always @* to prevent these issues.) Verilator supports dotted references to variables, functions and tasks in different modules. However, references into named blocks and function-local -variables are not supported. References into arrayed and generated -instances work, but still require some work-arounds in the Verilog code: +variables are not supported. The portion before the dot must have a +constant value; for example a[2].b is acceptable, while a[x].b is not. -References into arrayed instances use different names from the Verilog -standard; arrayed instances are named {cellName}__{instanceNumber}. For -example a[2] is instead a__2. Thus you cannot use a parameter or variable -to select the index number; expand it into a case statement manually. - -References into generate statements should match the names from the Verilog -standard; subject to converting generate-for a[#] to a__# as described -above. When a dotted signal cannot be resolved, Verilator will print a -list of known scopes to help debugging. +References into generated and arrayed instances use the instance names +specified in the Verilog standard; arrayed instances are named +{cellName}[{instanceNumber}] in Verilog, which becomes +{cellname}__BRA__{instanceNumber}__KET__ inside the generated C++ code. Verilator creates numbered "genblk" when a begin: name is not specified around a block inside a generate statement. These numbers may differ between other simulators, but the Verilog specification does not allow users to use these names, so it should not matter. +If you are having trouble determining where a dotted path goes wrong, note +that Verilator will print a list of known scopes to help your debugging. + =head2 Latches Verilator is optimized for edge sensitive (flop based) designs. It will @@ -1626,6 +1624,12 @@ create a SpTraceFile object as you would create a normal SystemC trace file. For an example, see the call to SpTraceFile in the test_sp/sc_main.cpp file of the distribution. +=item How do I view waveforms (traces)? + +Verilator makes standard VCD (Value Change Dump) files. They are viewable +with the public domain Dinotrace or GtkWave programs, or any of the many +commercial offerings. + =item Where is the translate_off command? (How do I ignore a construct?) Translate on/off pragmas are generally a bad idea, as it's easy to have diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index d492190e0..5b014dda8 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -92,12 +92,19 @@ string AstNode::shortName() const { return pretty; } -string AstNode::prettyName(const string& namein) { +string AstNode::dedotName(const string& namein) { string pretty = namein; string::size_type pos; while ((pos=pretty.find("__DOT__")) != string::npos) { pretty.replace(pos, 7, "."); } + if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,""); + return pretty; +} + +string AstNode::prettyName(const string& namein) { + string pretty = namein; + string::size_type pos; while ((pos=pretty.find("__BRA__")) != string::npos) { pretty.replace(pos, 7, "["); } @@ -107,8 +114,7 @@ string AstNode::prettyName(const string& namein) { while ((pos=pretty.find("__PVT__")) != string::npos) { pretty.replace(pos, 7, ""); } - if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,""); - return pretty; + return AstNode::dedotName(pretty); } int AstNode::widthPow2() const { diff --git a/src/V3Ast.h b/src/V3Ast.h index 85c76edcb..b72041331 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -523,6 +523,7 @@ public: virtual string name() const { return ""; } virtual string verilogKwd() const { return ""; } string shortName() const; // Name with __PVT__ removed for concatenating scopes + static string dedotName(const string& namein); // Name with dots removed static string prettyName(const string& namein); // Name for printing out to the user string prettyName() const { return prettyName(name()); } FileLine* fileline() const { return m_fileline; } diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 9b3e038c2..4a03ba20e 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -163,8 +163,8 @@ private: // Somewhat illogically, we need to rename the orignal name of the cell too. // as that is the name users expect for dotting // The spec says we add [x], but that won't work in C... - newp->name(newp->name()+"__"+cvtToStr(m_instNum)); - newp->origName(newp->origName()+"__"+cvtToStr(m_instNum)); + newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__"); + newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__"); // Fixup pins newp->pinsp()->iterateAndNext(*this); if (debug()==9) { newp->dumpTree(cout,"newcell: "); cout< NameScopeMap; // MEMBERS LinkDotGraph m_graph; // Graph of hiearchy - NameScopeMap m_nameScopeMap; // Hash of scope referenced by textual name + NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name bool m_forPrearray; // Compress cell__[array] refs bool m_forScopeCreation; // Remove VarXRefs for V3Scope public: @@ -298,7 +298,7 @@ public: string altIdent = ""; if (m_forPrearray) { // Cell foo__[array] before we've expanded arrays is just foo. - if ((pos = ident.find("__")) != string::npos) { + if ((pos = ident.find("__BRA__")) != string::npos) { altIdent = ident.substr(0,pos); } } @@ -415,7 +415,7 @@ private: LinkDotBaseVertex* oldInlineVxp = m_inlineVxp; // Where do we add it? LinkDotBaseVertex* aboveVxp = m_inlineVxp; - string origname = nodep->prettyName(); + string origname = AstNode::dedotName(nodep->name()); string::size_type pos; if ((pos = origname.rfind(".")) != string::npos) { // Flattened, find what CellInline it should live under @@ -616,7 +616,7 @@ private: LinkDotBaseVertex* okVxp; LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope if (nodep->inlinedDots()!="") { // Correct for current scope - string inl = AstNode::prettyName(nodep->inlinedDots()); + string inl = AstNode::dedotName(nodep->inlinedDots()); dotVxp = m_statep->findDotted(dotVxp, inl, baddot, okVxp); if (!dotVxp) nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); } @@ -663,10 +663,13 @@ private: LinkDotBaseVertex* okVxp; LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope if (nodep->inlinedDots()!="") { // Correct for current scope - string inl = AstNode::prettyName(nodep->inlinedDots()); + string inl = AstNode::dedotName(nodep->inlinedDots()); UINFO(8,"\t\tInlined "<findDotted(dotVxp, inl, baddot, okVxp); - if (!dotVxp) nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); + if (!dotVxp) { + okVxp->errorScopes(nodep); + nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); + } } dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot, okVxp); // Maybe NULL diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 663814a9d..0732dff18 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -348,10 +348,7 @@ private: // V3Begin sees these DOTs and makes CellInlines for us. string nname = (string)"genfor"+cvtToStr(m_varValuep->asInt())+"__DOT__"+nodep->name(); // Verilog seems to drop the for loop name and tack on [#] - //nname = nodep->name() + "__BRA__" + cvtToStr(m_varValuep->asInt()) + "__KET__"; - // However we don't parse [#]'s correctly, so just use __ for now. - // (Fixing parsing to allow hardcoded numbers then leads to shift/reduce conflicts.) - nname = nodep->name() + "__" + cvtToStr(m_varValuep->asInt()); + nname = nodep->name() + "__BRA__" + cvtToStr(m_varValuep->asInt()) + "__KET__"; //UINFO(8," Rename begin "<name(nname); } diff --git a/test_regress/t/t_gen_intdot.v b/test_regress/t/t_gen_intdot.v index ef8c88188..7887835b3 100644 --- a/test_regress/t/t_gen_intdot.v +++ b/test_regress/t/t_gen_intdot.v @@ -98,11 +98,7 @@ module Genit (clk, value, result); Test tt (clk, value, result); `endif -`ifdef verilator - wire Result2 = t.g.foo__0.tt.gen.Internal; -`else wire Result2 = t.g.foo[0].tt.gen.Internal; // Works - Do not change! -`endif always @ (posedge clk) begin $write("[%0t] Result2 = %x\n", $time, Result2); end diff --git a/test_regress/t/t_gen_intdot2.v b/test_regress/t/t_gen_intdot2.v index deeaa1b7b..e35ebf420 100644 --- a/test_regress/t/t_gen_intdot2.v +++ b/test_regress/t/t_gen_intdot2.v @@ -51,13 +51,8 @@ module Genit ( // ARRAY One cellarray1[1:0] (); //cellarray[0..1][0..1] -`ifdef verilator - always @ (posedge clk) if (cellarray1__0.one !== 1'b1) $stop; - always @ (posedge clk) if (cellarray1__1.one !== 1'b1) $stop; -`else always @ (posedge clk) if (cellarray1[0].one !== 1'b1) $stop; always @ (posedge clk) if (cellarray1[1].one !== 1'b1) $stop; -`endif // IF generate @@ -122,8 +117,8 @@ module Genit ( One cellfor20 (); // genblk5[0..1].cellfor20 endgenerate `ifdef verilator - always @ (posedge clk) if (genblk4__0.cellfor20.one !== 1'b1) $stop; - always @ (posedge clk) if (genblk4__1.cellfor20.one !== 1'b1) $stop; + always @ (posedge clk) if (genblk4[0].cellfor20.one !== 1'b1) $stop; + always @ (posedge clk) if (genblk4[1].cellfor20.one !== 1'b1) $stop; //`else // NOT SUPPORTED accoring to spec - generic block references `endif @@ -134,13 +129,8 @@ module Genit ( One cellfor21 (); // namedfor21[0..1].cellfor21 end endgenerate -`ifdef verilator - always @ (posedge clk) if (namedfor21__0.cellfor21.one !== 1'b1) $stop; - always @ (posedge clk) if (namedfor21__1.cellfor21.one !== 1'b1) $stop; -`else always @ (posedge clk) if (namedfor21[0].cellfor21.one !== 1'b1) $stop; always @ (posedge clk) if (namedfor21[1].cellfor21.one !== 1'b1) $stop; -`endif generate for (i = 0; i < 2; i = i + 1) @@ -162,15 +152,13 @@ module Genit ( end end endgenerate -`ifdef verilator - always @ (posedge clk) if (namedfor30__0.forb30__0.forif30.cellfor30a.one !== 1'b1) $stop; - always @ (posedge clk) if (namedfor30__0.forb30__1.forif30b.cellfor30b.one !== 1'b1) $stop; - always @ (posedge clk) if (namedfor30__1.forb30__0.forif30.cellfor30a.one !== 1'b1) $stop; - always @ (posedge clk) if (namedfor30__1.forb30__1.forif30b.cellfor30b.one !== 1'b1) $stop; -`else always @ (posedge clk) if (namedfor30[0].forb30[0].forif30.cellfor30a.one !== 1'b1) $stop; - always @ (posedge clk) if (namedfor30[0].forb30[1].forif30.cellfor30b.one !== 1'b1) $stop; always @ (posedge clk) if (namedfor30[1].forb30[0].forif30.cellfor30a.one !== 1'b1) $stop; +`ifdef verilator + always @ (posedge clk) if (namedfor30[0].forb30[1].forif30b.cellfor30b.one !== 1'b1) $stop; + always @ (posedge clk) if (namedfor30[1].forb30[1].forif30b.cellfor30b.one !== 1'b1) $stop; +`else + always @ (posedge clk) if (namedfor30[0].forb30[1].forif30.cellfor30b.one !== 1'b1) $stop; always @ (posedge clk) if (namedfor30[1].forb30[1].forif30.cellfor30b.one !== 1'b1) $stop; `endif diff --git a/test_regress/t/t_inst_array.v b/test_regress/t/t_inst_array.v index cc03e516a..9ff4edf69 100644 --- a/test_regress/t/t_inst_array.v +++ b/test_regress/t/t_inst_array.v @@ -36,12 +36,9 @@ module t (/*AUTOARG*/ end if (cyc==3) begin if (bitout !== 8'h41) $stop; -`ifdef verilator // Hacky array subscripting - if (sub__0.bitout !== 1'b1) $stop; - if (sub__1.bitout !== 1'b0) $stop; -`else if (sub[0].bitout !== 1'b1) $stop; if (sub[1].bitout !== 1'b0) $stop; +`ifndef verilator // Hacky array subscripting if (sub[ONE].bitout !== 1'b0) $stop; `endif $write("*-* All Finished *-*\n");