Fix dotted generated array error, bug1005.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Johan Bjork 2015-12-05 19:58:58 -05:00 committed by Wilson Snyder
parent 178028a70a
commit f920b3945e
6 changed files with 70 additions and 28 deletions

View File

@ -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

View File

@ -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);

View File

@ -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: "<<nodep->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): "<<nodep->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): "<<nodep->exprp()->prettyName());
}
}
// Generate Statements
virtual void visit(AstGenerate* nodep, AstNUser*) {

View File

@ -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.*',
);

View File

@ -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;

View File

@ -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