diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 929bbf115..911660103 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -4569,6 +4569,16 @@ class RandomizeVisitor final : public VNVisitor { } } + static bool isDynArrOfClassTypeRecurse(const AstNodeDType* const dtypep) { + const AstNodeDType* const refp = dtypep->skipRefp(); + if (VN_IS(refp, DynArrayDType) || VN_IS(refp, QueueDType)) { + return isDynArrOfClassTypeRecurse(refp->subDTypep()); + } else if (VN_IS(refp, ClassRefDType)) { + return true; + } + return false; + } + // VISITORS void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); @@ -4801,6 +4811,18 @@ class RandomizeVisitor final : public VNVisitor { // Refresh array element tables after resize for (AstVar* const arrVarp : sizeArraysIt->second) { + // Array elements of class data type are passed to the solver as separate + // variables, so passing the original array variable is redundant, because it + // won't be referenced + if (isDynArrOfClassTypeRecurse(arrVarp->dtypep())) { + const uint32_t unpackedDims = arrVarp->dtypep()->dimensions(false).second; + if (unpackedDims > 1) { + arrVarp->v3warn( + E_UNSUPPORTED, + "Unsupported: Nested array element access in global constraint"); + } + continue; + } AstCMethodHard* const methodp = new AstCMethodHard{ fl, new AstVarRef{fl, genModp, genp, VAccess::READWRITE}, VCMethod::RANDOMIZER_WRITE_VAR}; diff --git a/test_regress/t/t_constraint_global_cls_arr.py b/test_regress/t/t_constraint_global_cls_arr.py new file mode 100755 index 000000000..8862c2c31 --- /dev/null +++ b/test_regress/t/t_constraint_global_cls_arr.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: 2025 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_constraint_global_cls_arr.v b/test_regress/t/t_constraint_global_cls_arr.v new file mode 100644 index 000000000..1f6efdd42 --- /dev/null +++ b/test_regress/t/t_constraint_global_cls_arr.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +class Foo; + rand int abcd; +endclass + +class Bar; + rand Foo foo_arr[]; + + function new(); + foo_arr = new[12]; + foreach(foo_arr[i]) foo_arr[i] = new; + endfunction + + constraint c { + foo_arr.size() == 10; + foreach (foo_arr[i]) foo_arr[i].abcd < 8; + } +endclass + +module t; + Bar bar; + initial begin + bar = new(); + bar.randomize(); + if (bar.foo_arr.size() != 10) $stop; + foreach (bar.foo_arr[i]) begin + if (bar.foo_arr[i] >= 8) $stop; + end + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_global_cls_arr_2d_unsup.out b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.out new file mode 100644 index 000000000..9d049fc2e --- /dev/null +++ b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.out @@ -0,0 +1,6 @@ +%Error-UNSUPPORTED: t/t_constraint_global_cls_arr_2d_unsup.v:13:12: Unsupported: Nested array element access in global constraint + : ... note: In instance 't' + 13 | rand Foo foo_arr[$][]; + | ^~~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_global_cls_arr_2d_unsup.py b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.py new file mode 100755 index 000000000..4cebd5d8e --- /dev/null +++ b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.py @@ -0,0 +1,16 @@ +#!/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: 2025 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_global_cls_arr_2d_unsup.v b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.v new file mode 100644 index 000000000..b83e1362d --- /dev/null +++ b/test_regress/t/t_constraint_global_cls_arr_2d_unsup.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +class Foo; + rand int abcd; + constraint c { abcd >= 2; } +endclass + +class Bar; + rand Foo foo_arr[$][]; + + function new(); + for (int i = 0; i < 3; i++) foo_arr[i] = new[5]; + foreach(foo_arr[i, j]) foo_arr[i][j] = new; + endfunction + + constraint c { + foo_arr.size() == 10; + foreach (foo_arr[i, j]) foo_arr[i][j].abcd < 8; + } +endclass + +module t; + Bar bar; + initial begin + bar = new(); + void'(bar.randomize()); + if (bar.foo_arr.size() != 10) $stop; + foreach (bar.foo_arr[i, j]) begin + if (bar.foo_arr[i][j].abcd < 2 || bar.foo_arr[i][j].abcd >= 8) $stop; + end + for (int i = 3; i < 10; i++) begin + if (bar.foo_arr[i].size() != 0) $stop; + end + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule