diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 2d99a4b2a..f3fa98379 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -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. diff --git a/test_regress/t/t_randomize_assoc_size.py b/test_regress/t/t_randomize_assoc_size.py new file mode 100755 index 000000000..db1adb3f9 --- /dev/null +++ b/test_regress/t/t_randomize_assoc_size.py @@ -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() diff --git a/test_regress/t/t_randomize_assoc_size.v b/test_regress/t/t_randomize_assoc_size.v new file mode 100644 index 000000000..5d7f0003a --- /dev/null +++ b/test_regress/t/t_randomize_assoc_size.v @@ -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