diff --git a/Changes b/Changes index 4a02cc3e0..d6a5b1ba3 100644 --- a/Changes +++ b/Changes @@ -27,6 +27,7 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix array slicing of non-const indexes, bug1006. [Johan Bjork] +**** Fix dotted generated array error, bug1005. [Jeff Bush, Johan Bjork] * Verilator 3.878 2015-11-01 diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 2609dbb7a..7dd0034f5 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1905,7 +1905,9 @@ private: m_ds.m_dotp = NULL; } else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) { if (m_ds.m_unresolved && m_ds.m_unlinkedScope) { - AstNode* newp = new AstUnlinkedRef(nodep->fileline(), nodep->cloneTree(false), nodep->name(), m_ds.m_unlinkedScope->unlinkFrBack()); + AstNodeFTaskRef *newftaskp = nodep->cloneTree(false); + newftaskp->dotted(m_ds.m_dotText); + AstNode* newp = new AstUnlinkedRef(nodep->fileline(), newftaskp, nodep->name(), m_ds.m_unlinkedScope->unlinkFrBack()); m_ds.m_unlinkedScope = NULL; m_ds.m_unresolved = false; nodep->replaceWith(newp); diff --git a/src/V3Param.cpp b/src/V3Param.cpp index bc7ae336b..bb02cf483 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -256,16 +256,22 @@ private: } virtual void visit(AstUnlinkedRef* nodep, AstNUser*) { - m_unlinkedTxt.clear(); - nodep->cellrefp()->iterate(*this); AstVarXRef* varxrefp = nodep->op1p()->castVarXRef(); - AstNodeFTaskRef* taskref = nodep->op1p()->castNodeFTaskRef(); + AstNodeFTaskRef* taskrefp = nodep->op1p()->castNodeFTaskRef(); if (varxrefp) { - varxrefp->dotted(m_unlinkedTxt); - } else if (taskref) { - taskref->dotted(m_unlinkedTxt); + m_unlinkedTxt = varxrefp->dotted(); + } else if (taskrefp) { + m_unlinkedTxt = taskrefp->dotted(); } else { nodep->v3fatalSrc("Unexpected AstUnlinkedRef node"); + return; + } + nodep->cellrefp()->iterate(*this); + + if (varxrefp) { + varxrefp->dotted(m_unlinkedTxt); + } else { + taskrefp->dotted(m_unlinkedTxt); } nodep->replaceWith(nodep->op1p()->unlinkFrBack()); pushDeletep(nodep); VL_DANGLING(nodep); @@ -274,30 +280,18 @@ private: V3Const::constifyParamsEdit(nodep->selp()); if (AstConst* constp = nodep->selp()->castConst()) { string index = AstNode::encodeNumber(constp->toSInt()); - m_unlinkedTxt += nodep->name() + "__BRA__"+index+"__KET__"; + string replacestr = nodep->name() + "__BRA__??__KET__"; + size_t pos = m_unlinkedTxt.find(replacestr); + if (pos == string::npos) { + nodep->v3error("Could not find array index in unlinked text: '" << m_unlinkedTxt << "' for node: " << nodep); + return; + } + m_unlinkedTxt.replace(pos, replacestr.length(), nodep->name() + "__BRA__"+index+"__KET__"); } else { nodep->v3error("Could not expand constant selection inside dotted reference: "<selp()->prettyName()); return; } } - virtual void visit(AstCellRef* nodep, AstNUser*) { - // Children must be CellArrayRef, CellRef or ParseRef - if (nodep->cellp()->castCellArrayRef() || nodep->cellp()->castCellRef()) { - nodep->cellp()->iterate(*this); - } else if (nodep->cellp()->castParseRef()) { - m_unlinkedTxt += nodep->cellp()->name(); - } else { - nodep->v3error("Could not elaborate dotted reference (LHS): "<cellp()->prettyName()); - } - m_unlinkedTxt += "."; - if (nodep->exprp()->castCellArrayRef() || nodep->exprp()->castCellRef()) { - nodep->exprp()->iterate(*this); - } else if (nodep->exprp()->castParseRef()) { - m_unlinkedTxt += nodep->exprp()->name(); - } else { - nodep->v3error("Could not elaborate dotted reference (RHS): "<exprp()->prettyName()); - } - } // Generate Statements virtual void visit(AstGenerate* nodep, AstNUser*) { diff --git a/test_regress/t/t_interface_array_bad.pl b/test_regress/t/t_interface_array_bad.pl index 6cd6a6d0d..1e9145239 100755 --- a/test_regress/t/t_interface_array_bad.pl +++ b/test_regress/t/t_interface_array_bad.pl @@ -12,8 +12,6 @@ compile ( expect=> '%Error: t/t_interface_array_bad.v:\d+: Expecting expression to be constant, but variable isn\'t const: bar %Error: t/t_interface_array_bad.v:\d+: Could not expand constant selection inside dotted reference: bar -%Error: t/t_interface_array_bad.v:\d+: Can\'t find definition of \'a\' in dotted signal: .a -%Error: Known scopes under \'a\':.* %Error: Exiting due to.*', ); diff --git a/test_regress/t/t_interface_gen12.pl b/test_regress/t/t_interface_gen12.pl new file mode 100755 index 000000000..1118f2e0e --- /dev/null +++ b/test_regress/t/t_interface_gen12.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_interface_gen12.v b/test_regress/t/t_interface_gen12.v new file mode 100644 index 000000000..d93315bf7 --- /dev/null +++ b/test_regress/t/t_interface_gen12.v @@ -0,0 +1,29 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty. + +// bug1005 + +module foo_module; + generate + for (genvar i = 0; i < 2; i = i + 1) begin : my_gen_block + logic baz; + end + endgenerate +endmodule + +module bar_module; + foo_module foo(); +endmodule + +module t; + bar_module bar(); + initial begin + bar.foo.my_gen_block[0].baz = 1; + if (bar.foo.my_gen_block[0].baz) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule