Support this.randomize() with constraints (#6634)

This commit is contained in:
Artur Bieniek 2025-11-04 14:28:42 +01:00 committed by GitHub
parent ea75163567
commit 8eed4e32ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 1 deletions

View File

@ -914,7 +914,22 @@ class ConstraintExprVisitor final : public VNVisitor {
if (nodep->user1()) {
nodep->v3warn(CONSTRAINTIGN, "Global constraints ignored (unsupported)");
}
editFormat(nodep);
// Handle MemberSel references created by captureRefByThis()
if (VN_IS(nodep->fromp(), VarRef)
&& nodep->fromp()->user1() // Depending on a randomized variable
&& nodep->user2p() // Pointer to containing module
&& VN_AS(nodep->user2p(), NodeModule) == nodep->varp()->user2p()) {
// Convert to VarRef
AstVarRef* const varRefp
= new AstVarRef{nodep->fileline(), nodep->varp(), VAccess::READ};
varRefp->user1(nodep->varp()->rand().isRandomizable());
varRefp->classOrPackagep(VN_AS(nodep->user2p(), NodeModule));
nodep->replaceWith(varRefp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
visit(varRefp);
} else {
editFormat(nodep);
}
}
void visit(AstSFormatF* nodep) override {}
void visit(AstStmtExpr* nodep) override {}

View File

@ -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
if not test.have_solver:
test.skip("No constraint solver installed")
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,28 @@
// 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
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
class Cls;
rand int v_rand;
int v_norand;
task body;
int x;
v_norand = 42;
x = this.randomize() with {v_rand==0;};
`checkd(v_rand, 0);
`checkd(v_norand, 42);
endtask
endclass
module t;
initial begin
Cls c = new;
c.body();
$finish;
end
endmodule