Fix randomization of dynamic arrs of objects (#7790)

This commit is contained in:
Ryszard Rozak 2026-06-16 18:19:00 +02:00 committed by GitHub
parent bec45125bd
commit 792008514b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 143 additions and 0 deletions

View File

@ -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};

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: 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()

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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