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 {
|
||||
const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel);
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ class LinkResolveVisitor final : public VNVisitor {
|
|||
int m_senitemCvtNum = 0; // Temporary signal counter
|
||||
std::deque<AstGenFor*> m_underGenFors; // Stack of GenFor underneath
|
||||
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
|
||||
// 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});
|
||||
}
|
||||
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);
|
||||
if (AstLet* letp = VN_CAST(nodep->taskp(), Let)) {
|
||||
UINFO(7, "letSubstitute() " << nodep << " <- " << letp);
|
||||
|
|
@ -525,6 +539,30 @@ class LinkResolveVisitor final : public VNVisitor {
|
|||
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); }
|
||||
|
||||
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