diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 7c10fb1eb..9687f1f12 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -2169,8 +2169,8 @@ class RandomizeVisitor final : public VNVisitor { } return false; } - // Expand AstConstraintUnique with element-list items into pairwise != constraints. - // Whole-array VarRef unique constraints are left untouched for ConstraintExprVisitor. + // Expand unique{a,b,c} with explicit elements into pairwise != constraints. + // Whole-array unique{arr} is left for ConstraintExprVisitor's rand_unique handling. static void expandUniqueElementList(AstNode* itemsp) { AstNode* itemp = itemsp; while (itemp) { @@ -2181,14 +2181,13 @@ class RandomizeVisitor final : public VNVisitor { continue; } - // Collect non-array-VarRef items std::vector exprItems; bool hasArrayVarRef = false; for (AstNode* rp = uniquep->rangesp(); rp; rp = rp->nextp()) { if (AstVarRef* const vrp = VN_CAST(rp, VarRef)) { if (VN_IS(vrp->varp()->dtypep()->skipRefp(), UnpackArrayDType)) { hasArrayVarRef = true; - continue; // Skip whole-array items + continue; } } exprItems.push_back(VN_AS(rp, NodeExpr)); @@ -2201,17 +2200,15 @@ class RandomizeVisitor final : public VNVisitor { AstNodeExpr* const lhsp = exprItems[i]->cloneTree(false); AstNodeExpr* const rhsp = exprItems[j]->cloneTree(false); AstNeq* const neqp = new AstNeq{fl, lhsp, rhsp}; - neqp->user1(true); // Mark as depending on rand variable + neqp->user1(true); AstConstraintExpr* const cexprp = new AstConstraintExpr{fl, neqp}; uniquep->addNextHere(cexprp); } } if (!hasArrayVarRef) { - // All items expanded — remove the AstConstraintUnique uniquep->unlinkFrBack(); VL_DO_DANGLING(uniquep->deleteTree(), uniquep); } - // If hasArrayVarRef: keep AstConstraintUnique for whole-array handling } itemp = nextp; } diff --git a/test_regress/t/t_randomize_unique_elem.v b/test_regress/t/t_randomize_unique_elem.v index 579995427..34a633c4e 100644 --- a/test_regress/t/t_randomize_unique_elem.v +++ b/test_regress/t/t_randomize_unique_elem.v @@ -9,17 +9,13 @@ `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 -// Test: unique constraint on explicit array element subset -// IEEE 1800-2017 Section 18.5.9 -// -// Uses bit [3:0] (16 possible values) with 5-element unique subsets -// so that without proper constraint enforcement, collisions are -// virtually guaranteed across 20 iterations. +// Test unique constraint on explicit array element subsets (IEEE 18.5.9). +// bit [3:0] keeps the value space small so collisions are near-certain +// without proper constraint enforcement. class UniqueElemSubset; rand bit [3:0] arr[10]; - // Unique applied to a subset of array indices constraint unique_subset_con { unique { arr[2], arr[3], arr[4], arr[5], arr[6] }; } @@ -38,7 +34,6 @@ endclass class UniqueElemFour; rand bit [3:0] data[8]; - // Unique on 4 explicit elements constraint unique_data_con { unique { data[1], data[2], data[3], data[4] }; } @@ -59,14 +54,12 @@ module t; UniqueElemFour uef; initial begin - // Test 1: unique on 5 explicit array elements ues = new(); repeat (20) begin `checkd(ues.randomize(), 1) `checkd(ues.check_unique(), 1) end - // Test 2: unique on 4 explicit array elements uef = new(); repeat (20) begin `checkd(uef.randomize(), 1)