From 97d5844f2ea62bead1b2b7bc0db157e0919d1e86 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Thu, 8 Jan 2026 15:02:28 +0100 Subject: [PATCH] Support dynamic array elements in std::randomize (#6896) --- src/V3Randomize.cpp | 5 +++++ src/V3Width.cpp | 12 +++++++++--- test_regress/t/t_randomize_arraysel_membersel.v | 9 +++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index bc6e8d20a..313fba115 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -184,6 +184,8 @@ class RandomizeMarkVisitor final : public VNVisitor { exprp = arrselp->fromp(); } else if (const AstStructSel* const strselp = VN_CAST(exprp, StructSel)) { exprp = strselp->fromp(); + } else if (const AstCMethodHard* const methodp = VN_CAST(exprp, CMethodHard)) { + exprp = methodp->fromp(); } else { break; } @@ -359,6 +361,9 @@ class RandomizeMarkVisitor final : public VNVisitor { } else if (AstStructSel* const structSelp = VN_CAST(exprp, StructSel)) { exprp = structSelp->fromp(); continue; // Skip StructSel, continue traversing + } else if (AstCMethodHard* const methodp = VN_CAST(exprp, CMethodHard)) { + exprp = methodp->fromp(); + continue; } else if (AstVarRef* const varrefp = VN_CAST(exprp, VarRef)) { randVarp = varrefp->varp(); varrefp->user1(true); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 888c4bea7..24d6a3bda 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6781,12 +6781,18 @@ class WidthVisitor final : public VNVisitor { // IEEE 1800-2023 (18.12) limits args to current scope variables. // Verilator accepts this for compatibility with other simulators. continue; - } else if (VN_IS(exprp, VarRef) || VN_IS(exprp, ArraySel) || VN_IS(exprp, StructSel)) { + } + if (VN_IS(exprp, VarRef) || VN_IS(exprp, ArraySel) || VN_IS(exprp, StructSel)) { // Valid usage continue; - } else { - argp->v3error("Non-variable arguments for 'std::randomize()'."); } + if (const AstCMethodHard* const methodp = VN_CAST(exprp, CMethodHard)) { + if (methodp->method() == VCMethod::ARRAY_AT + || methodp->method() == VCMethod::ARRAY_AT_WRITE) { + continue; + } + } + argp->v3error("Non-variable arguments for 'std::randomize()'."); } if (nullp) nullp->v3error("'std::randomize()' does not accept 'null' as arguments."); } diff --git a/test_regress/t/t_randomize_arraysel_membersel.v b/test_regress/t/t_randomize_arraysel_membersel.v index 9ad7fa351..a7c1dd65a 100644 --- a/test_regress/t/t_randomize_arraysel_membersel.v +++ b/test_regress/t/t_randomize_arraysel_membersel.v @@ -9,6 +9,7 @@ typedef struct {int x;} struct_t; class inner_class; logic [3:0] c; logic [3:0] d[2]; + logic [3:0] dyn[]; struct_t s; endclass @@ -20,9 +21,11 @@ endclass module t; initial begin + int x = 2; test_class example; example = new; example.b = new; + example.b.dyn = new[3]; // Simple array element access repeat (5) begin @@ -83,6 +86,12 @@ module t; if (example.b.d[1] < 2 || example.b.d[1] > 6) $stop; end + // Nested object with dynamic array: obj.b.dyn[x] + repeat (5) begin + if (std::randomize(example.b.dyn[x]) with {example.b.dyn[x] inside {[1 : 3]};} == 0) $stop; + if (example.b.dyn[x] < 1 || example.b.dyn[x] > 3) $stop; + end + // Nested object with struct: obj.b.s.x repeat (5) begin if (std::randomize(example.b.s.x) with {example.b.s.x inside {[7 : 9]};} == 0) $stop;