Fix of inline constraints with member selects (#6321)
This commit is contained in:
parent
b95a974ff1
commit
f506aa878b
|
|
@ -2058,7 +2058,7 @@ AstMemberSel::AstMemberSel(FileLine* fl, AstNodeExpr* fromp, AstVar* varp)
|
||||||
bool AstMemberSel::sameNode(const AstNode* samep) const {
|
bool AstMemberSel::sameNode(const AstNode* samep) const {
|
||||||
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
||||||
return sp && access() == sp->access() && fromp()->isSame(sp->fromp()) && name() == sp->name()
|
return sp && access() == sp->access() && fromp()->isSame(sp->fromp()) && name() == sp->name()
|
||||||
&& (varp() && sp->varp() && varp()->sameNode(sp->varp()));
|
&& (varp() == sp->varp() || (varp() && sp->varp() && varp()->sameNode(sp->varp())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstMemberSel::dump(std::ostream& str) const {
|
void AstMemberSel::dump(std::ostream& str) const {
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ class LinkResolveVisitor final : public VNVisitor {
|
||||||
int m_senitemCvtNum = 0; // Temporary signal counter
|
int m_senitemCvtNum = 0; // Temporary signal counter
|
||||||
std::deque<AstGenFor*> m_underGenFors; // Stack of GenFor underneath
|
std::deque<AstGenFor*> m_underGenFors; // Stack of GenFor underneath
|
||||||
bool m_underGenerate = false; // Under GenFor/GenIf
|
bool m_underGenerate = false; // Under GenFor/GenIf
|
||||||
|
AstNodeExpr* m_currentRandomizeSelectp = nullptr; // fromp() of current `randomize()` call
|
||||||
|
bool m_inRandomizeWith = false; // If in randomize() with (and no other with afterwards)
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
// TODO: Most of these visitors are here for historical reasons.
|
// TODO: Most of these visitors are here for historical reasons.
|
||||||
|
|
@ -185,6 +187,18 @@ class LinkResolveVisitor final : public VNVisitor {
|
||||||
if (nodep->dpiExport()) nodep->scopeNamep(new AstScopeName{nodep->fileline(), false});
|
if (nodep->dpiExport()) nodep->scopeNamep(new AstScopeName{nodep->fileline(), false});
|
||||||
}
|
}
|
||||||
void visit(AstNodeFTaskRef* nodep) override {
|
void visit(AstNodeFTaskRef* nodep) override {
|
||||||
|
VL_RESTORER(m_currentRandomizeSelectp);
|
||||||
|
|
||||||
|
if (nodep->name() == "randomize") {
|
||||||
|
if (const AstMethodCall* const methodcallp = VN_CAST(nodep, MethodCall)) {
|
||||||
|
if (m_inRandomizeWith) {
|
||||||
|
nodep->v3warn(
|
||||||
|
E_UNSUPPORTED,
|
||||||
|
"Unsupported: randomize() nested in inline randomize() constraints");
|
||||||
|
}
|
||||||
|
m_currentRandomizeSelectp = methodcallp->fromp();
|
||||||
|
}
|
||||||
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (AstLet* letp = VN_CAST(nodep->taskp(), Let)) {
|
if (AstLet* letp = VN_CAST(nodep->taskp(), Let)) {
|
||||||
UINFO(7, "letSubstitute() " << nodep << " <- " << letp);
|
UINFO(7, "letSubstitute() " << nodep << " <- " << letp);
|
||||||
|
|
@ -525,6 +539,30 @@ class LinkResolveVisitor final : public VNVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visit(AstMemberSel* nodep) override {
|
||||||
|
if (m_inRandomizeWith && nodep->fromp()->isSame(m_currentRandomizeSelectp)) {
|
||||||
|
// Replace member selects to the element
|
||||||
|
// on which the randomize() is called with LambdaArgRef
|
||||||
|
// This allows V3Randomize to work properly when
|
||||||
|
// constrained variables are referred using that object
|
||||||
|
AstNodeExpr* const prevFromp = nodep->fromp();
|
||||||
|
prevFromp->replaceWith(
|
||||||
|
new AstLambdaArgRef{prevFromp->fileline(), prevFromp->name(), false});
|
||||||
|
pushDeletep(prevFromp);
|
||||||
|
}
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstWith* nodep) override {
|
||||||
|
VL_RESTORER(m_inRandomizeWith);
|
||||||
|
if (const AstMethodCall* const methodCallp = VN_CAST(nodep->backp(), MethodCall)) {
|
||||||
|
m_inRandomizeWith = methodCallp->name() == "randomize";
|
||||||
|
} else {
|
||||||
|
m_inRandomizeWith = false;
|
||||||
|
}
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2025 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
if not test.have_solver:
|
||||||
|
test.skip("No constraint solver installed")
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class B;
|
||||||
|
rand int insideB;
|
||||||
|
constraint i {
|
||||||
|
insideB inside {[0:10]};
|
||||||
|
};
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class A;
|
||||||
|
rand logic[31:0] rdata;
|
||||||
|
rand int delay;
|
||||||
|
int i = 97;
|
||||||
|
rand B b;
|
||||||
|
function new();
|
||||||
|
b = new;
|
||||||
|
endfunction
|
||||||
|
constraint delay_bounds {
|
||||||
|
delay inside {[0:2]};
|
||||||
|
}
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t;
|
||||||
|
A a;
|
||||||
|
int i;
|
||||||
|
int delay;
|
||||||
|
logic[31:0] rdata;
|
||||||
|
int b;
|
||||||
|
initial begin
|
||||||
|
a = new;
|
||||||
|
i = 7;
|
||||||
|
repeat (120) begin
|
||||||
|
a.b.insideB = 3;
|
||||||
|
a.delay = 1;
|
||||||
|
a.rdata = 3;
|
||||||
|
if (a.randomize() with {if (a.delay == 1) a.rdata == i;} == 0) $stop;
|
||||||
|
if (a.b.randomize() with {a.b.insideB < 3;} == 0) $stop;
|
||||||
|
if (a.delay == 1 && a.rdata != 97) $stop;
|
||||||
|
if (a.b.insideB >= 3) $stop;
|
||||||
|
if (a.randomize() with {if (a.delay == 1) a.rdata == local::i;} == 0) $stop;
|
||||||
|
if (a.delay == 1 && a.rdata != 7) $stop;
|
||||||
|
end
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
%Error-UNSUPPORTED: t/t_randomize_neasted_unsup.v:17:41: Unsupported: randomize() nested in inline randomize() constraints
|
||||||
|
17 | if (a.randomize() with {rdata == aa.randomize();} == 0) $stop;
|
||||||
|
| ^~~~~~~~~
|
||||||
|
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2025 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class A;
|
||||||
|
rand logic[31:0] rdata;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t;
|
||||||
|
A a;
|
||||||
|
A aa;
|
||||||
|
initial begin
|
||||||
|
a = new;
|
||||||
|
aa = new;
|
||||||
|
if (a.randomize() with {rdata == aa.randomize();} == 0) $stop;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue