Fix foreach on dotted reference.

This commit is contained in:
Wilson Snyder 2021-12-12 20:43:15 -05:00
parent 0a94ea5386
commit f775feb7f0
6 changed files with 82 additions and 6 deletions

View File

@ -1726,6 +1726,7 @@ public:
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool maybePointedTo() const override { return false; }
AstNode* fromp() const { return op1p(); }
void fromp(AstNode* nodep) { setOp1p(nodep); }
AstNode* elementsp() const { return op2p(); }
};
@ -3137,6 +3138,7 @@ public:
}
virtual void dump(std::ostream& str) const override;
AstNode* lhsp() const { return op1p(); }
void rhsp(AstNode* nodep) { setOp2p(nodep); }
AstNode* rhsp() const { return op2p(); }
bool colon() const { return m_colon; }
};

View File

@ -1280,16 +1280,25 @@ class LinkDotFindVisitor final : public AstNVisitor {
m_curSymp = m_statep->insertBlock(m_curSymp, "__Vforeach" + cvtToStr(m_modWithNum),
nodep, m_classOrPackagep);
m_curSymp->fallbackp(oldCurSymp);
// DOT(x, SELLOOPVARS(var, loops)) -> SELLOOPVARS(DOT(x, var), loops)
if (AstDot* const dotp = VN_CAST(nodep->arrayp(), Dot)) {
if (AstSelLoopVars* const loopvarsp = VN_CAST(dotp->rhsp(), SelLoopVars)) {
AstNode* const fromp = loopvarsp->fromp()->unlinkFrBack();
loopvarsp->unlinkFrBack();
dotp->replaceWith(loopvarsp);
dotp->rhsp(fromp);
loopvarsp->fromp(dotp);
}
}
const auto loopvarsp = VN_CAST(nodep->arrayp(), SelLoopVars);
if (!loopvarsp) {
AstNode* const warnp = nodep->arrayp() ? nodep->arrayp() : nodep;
warnp->v3warn(E_UNSUPPORTED,
"Unsupported (or syntax error): Foreach on this array's construct");
nodep->dumpTree(cout, "-FIXME-us ");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
for (AstNode *nextp, *argp = loopvarsp->elementsp(); argp; argp = nextp) {
nextp = argp->nextp();
AstVar* argrefp = nullptr;
@ -1310,6 +1319,7 @@ class LinkDotFindVisitor final : public AstNVisitor {
argp->v3error("'foreach' loop variable expects simple variable name");
}
}
iterateChildren(nodep);
}
}

View File

@ -444,6 +444,7 @@ private:
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
iterateChildren(nodep);
}
virtual void visit(AstNodeModule* nodep) override {

View File

@ -1,8 +1,4 @@
%Error: t/t_foreach_bad.v:14:7: Syntax error; foreach missing bracketed loop variable (IEEE 1800-2017 12.7.3)
14 | foreach (array);
| ^~~~~~~
%Error-UNSUPPORTED: t/t_foreach_bad.v:16:21: Unsupported (or syntax error): Foreach on this array's construct
16 | foreach (array.array[a]);
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,21 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,46 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2016 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
class Cls;
int q[$];
function new();
q.push_back(1);
q.push_back(2);
q.push_back(3);
endfunction
endclass
module t (/*AUTOARG*/);
int two[5:6];
if (1) begin : named
Cls c;
end
function [63:0] crc(input [63:0] sum, input [31:0] a, input [31:0] b, input [31:0] c, input [31:0] d);
crc = {sum[62:0],sum[63]} ^ {20'b0,a[7:0], 4'h0,b[7:0], 4'h0,c[7:0], 4'h0,d[7:0]};
endfunction
bit [63:0] sum;
initial begin
named.c = new;
sum = 0;
foreach (named.c.q[i]) begin
foreach (two[j]) begin
// $display(i, j);
sum = crc(sum, i, named.c.q[i], j, 0);
end
end
`checkh(sum, 64'h000000a02d0fc000);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule