Fix std::randomize treated as this.randomize in parameterized-derived class (#7409) (#7416)

Fixes #7409.
This commit is contained in:
Yilou Wang 2026-04-13 17:34:17 +02:00 committed by GitHub
parent 14e2f834e9
commit 83b2061a35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 129 additions and 2 deletions

View File

@ -5148,8 +5148,10 @@ class LinkDotResolveVisitor final : public VNVisitor {
return;
}
}
if (first && nodep->name() == "randomize" && VN_IS(m_modp, Class)) {
if (first && nodep->name() == "randomize" && VN_IS(m_modp, Class)
&& !VN_IS(nodep->classOrPackagep(), Package)) {
// need special handling to avoid falling back to std::randomize
// Skip if classOrPackagep is a Package (i.e. std::randomize resolved earlier)
VMemberMap memberMap;
AstFunc* const randFuncp = V3Randomize::newRandomizeFunc(
memberMap, VN_AS(m_modp, Class), nodep->name(), true, true);
@ -5231,7 +5233,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|| nodep->name() == "get_randstate" || nodep->name() == "set_randstate"
|| nodep->name() == "rand_mode" || nodep->name() == "constraint_mode") {
if (AstClass* const classp = VN_CAST(m_modp, Class)) {
nodep->classOrPackagep(classp);
// Don't overwrite if already resolved to a package (e.g. std::randomize)
if (!VN_IS(nodep->classOrPackagep(), Package))
nodep->classOrPackagep(classp);
} else if (nodep->name() == "randomize") {
// A std::randomize resolved in V3Width
nodep->classOrPackagep(v3Global.rootp()->stdPackagep());

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# 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()

View File

@ -0,0 +1,102 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`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);
// verilog_format: on
// Test std::randomize() inside classes extending parameterized base classes.
// Derived from issue #7409 (wsnyder's minimized reproduction).
package my_pkg;
class uvm_sequence_item;
endclass
class uvm_sequence #(
parameter type T = int
);
endclass
// std::randomize in class extending parameterized base (the bug)
class foo_t extends uvm_sequence #(uvm_sequence_item);
task test_std_rand();
int unsigned my_var;
int ok;
ok = std::randomize(my_var);
`checkd(ok, 1);
endtask
endclass
// std::randomize with 'with' clause
class bar_t extends uvm_sequence #(uvm_sequence_item);
task test_std_rand_with();
int unsigned v;
int ok;
ok = std::randomize(v) with { v inside {[1:100]}; };
`checkd(ok, 1);
if (v < 1 || v > 100) begin
$write("%%Error: constraint violated: v=%0d\n", v);
`stop;
end
endtask
endclass
// this.randomize() regression for parameterized-derived class
class rand_t extends uvm_sequence #(uvm_sequence_item);
rand int unsigned x;
constraint c_x { x inside {[1:50]}; }
endclass
endpackage
// std::randomize outside package, multi-level parameterized inheritance
class base_c #(type T = int);
T item;
endclass
class mid_c extends base_c #(int);
endclass
class leaf_c extends mid_c;
task test_std_rand();
int unsigned v;
int ok;
ok = std::randomize(v);
`checkd(ok, 1);
endtask
endclass
module t;
initial begin
automatic my_pkg::foo_t foo = new;
automatic my_pkg::bar_t bar = new;
automatic my_pkg::rand_t rt = new;
automatic leaf_c lc = new;
int ok;
// Issue #7409 exact scenario: std::randomize in package class
foo.test_std_rand();
// std::randomize with 'with' clause
bar.test_std_rand_with();
// this.randomize() regression
ok = rt.randomize();
`checkd(ok, 1);
if (rt.x < 1 || rt.x > 50) begin
$write("%%Error: constraint violated: x=%0d\n", rt.x);
`stop;
end
// Multi-level parameterized inheritance outside package
lc.test_std_rand();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule