Fix associative array size() constraint generating invalid resize() call (#7103) (#7112)

This commit is contained in:
Yilou Wang 2026-02-20 16:54:02 +01:00 committed by GitHub
parent e0edb49f7a
commit f25a85ea57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 87 additions and 9 deletions

View File

@ -3915,16 +3915,21 @@ class RandomizeVisitor final : public VNVisitor {
queueVarp->user4p(sizeVarp);
AstTask* resizerTaskp = VN_AS(m_constraintp->user3p(), Task);
if (!resizerTaskp) {
resizerTaskp = newResizeConstrainedArrayTask(classp, m_constraintp->name());
m_constraintp->user3p(resizerTaskp);
// Associative arrays have no resize(); only generate resize
// for dynamic arrays and queues
if (!VN_IS(queueVarp->dtypep()->skipRefp(), AssocArrayDType)) {
AstTask* resizerTaskp = VN_AS(m_constraintp->user3p(), Task);
if (!resizerTaskp) {
resizerTaskp
= newResizeConstrainedArrayTask(classp, m_constraintp->name());
m_constraintp->user3p(resizerTaskp);
}
AstCMethodHard* const resizep = new AstCMethodHard{
fl, nodep->fromp()->unlinkFrBack(), VCMethod::DYN_RESIZE,
new AstVarRef{fl, sizeVarp, VAccess::READ}};
resizep->dtypep(nodep->findVoidDType());
resizerTaskp->addStmtsp(new AstStmtExpr{fl, resizep});
}
AstCMethodHard* const resizep
= new AstCMethodHard{fl, nodep->fromp()->unlinkFrBack(), VCMethod::DYN_RESIZE,
new AstVarRef{fl, sizeVarp, VAccess::READ}};
resizep->dtypep(nodep->findVoidDType());
resizerTaskp->addStmtsp(new AstStmtExpr{fl, resizep});
// Since size variable is signed int, we need additional constraint
// to make sure it is always >= 0.

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,52 @@
// 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
module t;
// String-key associative array with size constraint
class StringKeyTest;
rand int data[string];
constraint c_size { data.size() == 3; }
endclass
// Int-key associative array with size constraint
class IntKeyTest;
rand bit [7:0] values[int];
constraint c_size { values.size() == 2; }
endclass
initial begin
automatic StringKeyTest str_obj = new();
automatic IntKeyTest int_obj = new();
automatic int rand_ok;
// String-key: pre-populate 3 entries to match constraint
str_obj.data["x"] = 0;
str_obj.data["y"] = 0;
str_obj.data["z"] = 0;
rand_ok = str_obj.randomize();
`checkd(rand_ok, 1);
`checkd(str_obj.data.size(), 3);
// Int-key: pre-populate 2 entries to match constraint
int_obj.values[10] = 0;
int_obj.values[20] = 0;
rand_ok = int_obj.randomize();
`checkd(rand_ok, 1);
`checkd(int_obj.values.size(), 2);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule