From 7d3021c34d0f26a88e8b1107c50ceb2d896689b3 Mon Sep 17 00:00:00 2001 From: Kornel Uriasz Date: Thu, 23 Jul 2026 21:56:51 +0200 Subject: [PATCH] Fix varRef scope in unique on dynamic array (#7981) Signed-off-by: Kornel Uriasz --- src/V3Randomize.cpp | 14 ++++---- test_regress/t/t_constraint_unq_arr.v | 47 ++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 259d88ba2..172ace4b7 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -2397,12 +2397,14 @@ class ConstraintExprVisitor final : public VNVisitor { return; } - AstNodeModule* const modp = VN_AS(genVarp->user2p(), NodeModule); - UASSERT_OBJ(modp, nodep, "genVarp has no NodeModule set"); + AstNodeModule* const genModp = VN_AS(genVarp->user2p(), NodeModule); + UASSERT_OBJ(genModp, nodep, "genVarp has no NodeModule set"); for (AstNode* itemp = nodep->rangesp(); itemp; itemp = itemp->nextp()) { if (AstVarRef* const varRefp = VN_CAST(itemp, VarRef)) { AstVar* const varp = varRefp->varp(); + AstNodeModule* const varModp = VN_AS(varp->user2p(), NodeModule); + UASSERT_OBJ(varModp, nodep, "varp has no NodeModule set"); AstNodeDType* const dtypep = varp->dtypep()->skipRefp(); AstConst* dtypeWidthp = nullptr; @@ -2444,9 +2446,9 @@ class ConstraintExprVisitor final : public VNVisitor { fl, AstCExpr::Pure{}, "\"" + varp->name() + "\"", varp->width()}; AstCMethodHard* const writeVarCallp - = new AstCMethodHard{fl, new AstVarRef{fl, modp, genVarp, VAccess::READ}, + = new AstCMethodHard{fl, new AstVarRef{fl, genModp, genVarp, VAccess::READ}, VCMethod::RANDOMIZER_WRITE_VAR}; - writeVarCallp->addPinsp(new AstVarRef{fl, varp, VAccess::READ}); + writeVarCallp->addPinsp(new AstVarRef{fl, varModp, varp, VAccess::READ}); writeVarCallp->addPinsp(dtypeWidthp); writeVarCallp->addPinsp(varnamep); writeVarCallp->addPinsp(new AstConst{fl, 1}); // Dimension @@ -2473,7 +2475,7 @@ class ConstraintExprVisitor final : public VNVisitor { ? VCMethod::ASSOC_SIZE : VCMethod::DYN_SIZE; AstCMethodHard* const dynSizep = new AstCMethodHard{ - fl, new AstVarRef{fl, modp, varp, VAccess::READ}, sizeMethod}; + fl, new AstVarRef{fl, varModp, varp, VAccess::READ}, sizeMethod}; dynSizep->dtypeSetUInt32(); // unable to check dynamic array size during verilation randUniquePinsp->addNext(dynSizep); @@ -2484,7 +2486,7 @@ class ConstraintExprVisitor final : public VNVisitor { } AstCMethodHard* const randUniqueCallp - = new AstCMethodHard{fl, new AstVarRef{fl, modp, genVarp, VAccess::READ}, + = new AstCMethodHard{fl, new AstVarRef{fl, genModp, genVarp, VAccess::READ}, VCMethod::RANDOMIZER_UNIQUE, randUniquePinsp}; randUniqueCallp->dtypep(nodep->findVoidDType()); initTaskp->addStmtsp(new AstStmtExpr{fl, randUniqueCallp}); diff --git a/test_regress/t/t_constraint_unq_arr.v b/test_regress/t/t_constraint_unq_arr.v index fb139674d..01198ad5c 100644 --- a/test_regress/t/t_constraint_unq_arr.v +++ b/test_regress/t/t_constraint_unq_arr.v @@ -8,6 +8,46 @@ // We only check uniqueness for small # of elements on a large range // as Z3 does not actually give unique elements (bug?) as of Jul 2026. +class Subclass; + rand int sub_arr[]; +endclass + +class C extends Subclass; + rand int arr[]; + + function new (); + arr = new[10]; + sub_arr = new[10]; + endfunction + + function bit check_unique(); + // dynamic array inside class + for (int i = 0; i < $size(arr); i++) begin + for (int j = i + 1; j < $size(arr); j++) begin + if (arr[i] == arr[j]) begin + $error("UNIQUENESS VIOLATION: arr[%0d] == arr[%0d] == 0x%h", i, j, arr[i]); + return 0; + end + end + end + // dynamic array inside base class + for (int i = 0; i < $size(sub_arr); i++) begin + for (int j = i + 1; j < $size(sub_arr); j++) begin + if (sub_arr[i] == sub_arr[j]) begin + $error("UNIQUENESS VIOLATION: arr[%0d] == arr[%0d] == 0x%h", i, j, arr[i]); + return 0; + end + end + end + return 1; + endfunction + + constraint c { + unique {arr}; + unique {sub_arr}; + } +endclass + module t; class UniqueMultipleArray; rand bit [15:0] arr[4]; @@ -86,9 +126,14 @@ module t; endclass : UniqueMultipleArray initial begin + automatic C cc = new(); automatic UniqueMultipleArray a = new(); + + cc.randomize(); a.randomize(); - assert (a.check_unique()); + + assert(cc.check_unique()); + assert(a.check_unique()); $write("*-* All Finished *-*\n"); $finish;