From 50c105937449fa4f315014779cfc7b9d559c2933 Mon Sep 17 00:00:00 2001 From: Yilou Wang Date: Mon, 13 Jul 2026 22:35:37 +0200 Subject: [PATCH] address review: brace, exist, dtype and test --- src/V3Randomize.cpp | 26 ++-- .../t/t_constraint_dist_randmode_frozen.v | 115 +++++++++++++++--- 2 files changed, 109 insertions(+), 32 deletions(-) diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 4623dae4e..c7deebfa5 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -4488,10 +4488,8 @@ class RandomizeVisitor final : public VNVisitor { new AstSub{fl, new AstExtend{fl, irp->rhsp()->cloneTreePure(false), 64}, new AstExtend{fl, irp->lhsp()->cloneTreePure(false), 64}}}; - rangeSizep->dtypeSetUInt64(); } weightExprp = new AstMul{fl, weightExprp, rangeSizep}; - weightExprp->dtypeSetUInt64(); } } buckets.push_back({ditemp->rangep(), weightExprp}); @@ -4534,8 +4532,9 @@ class RandomizeVisitor final : public VNVisitor { // Membership test for one bucket: a range comparison or an equality. static AstNodeExpr* newDistMembershipTerm(AstDist* distp, AstNodeExpr* rangep) { - if (const AstInsideRange* const irp = VN_CAST(rangep, InsideRange)) + if (const AstInsideRange* const irp = VN_CAST(rangep, InsideRange)) { return newDistRangeMembership(distp, irp); + } FileLine* const fl = distp->fileline(); AstNodeExpr* const eqExprp = distp->exprp()->cloneTreePure(false); eqExprp->user1(true); @@ -4589,14 +4588,15 @@ class RandomizeVisitor final : public VNVisitor { // Each direct, static, or sub-object member reference carries a mode bit. distp->exprp()->foreach([&](const AstNode* nodep) { const AstNodeVarRef* const refp = VN_CAST(nodep, NodeVarRef); - const AstMemberSel* const mselp = refp ? nullptr : VN_CAST(nodep, MemberSel); + const AstMemberSel* const mselp = VN_CAST(nodep, MemberSel); if (!refp && !mselp) return; AstVar* const varp = refp ? refp->varp() : mselp->varp(); const RandomizeMode rmode = {.asInt = varp->user1()}; if (!rmode.usesMode || !gatedVars.insert(varp).second) return; if (varp->lifetime().isStatic()) { - if (AstNodeExpr* const readp = staticModeRead(varp)) + if (AstNodeExpr* const readp = staticModeRead(varp)) { addModeGate(readp, rmode.index); + } } else if (mselp) { AstVar* const memberModep = getRandModeVarFromClass(VN_AS(varp->user2p(), NodeModule)); @@ -4617,8 +4617,8 @@ class RandomizeVisitor final : public VNVisitor { for (auto& bucket : buckets) { AstNodeExpr* termp = newDistMembershipTerm(distp, bucket.rangep); // A weight that is zero only at runtime excludes the bucket's values too. - bool runtimeWeight = false; - bucket.weightExprp->foreach([&](const AstNodeVarRef*) { runtimeWeight = true; }); + const bool runtimeWeight + = bucket.weightExprp->exists([](const AstNodeVarRef*) { return true; }); if (runtimeWeight) { AstNeq* const nzp = new AstNeq{fl, bucket.weightExprp->cloneTreePure(false), new AstConst{fl, AstConst::Unsized64{}, 0}}; @@ -4654,13 +4654,11 @@ class RandomizeVisitor final : public VNVisitor { new AstExtendS{fl, irp->lhsp()->cloneTreePure(false), 64}) : static_cast( new AstExtend{fl, irp->lhsp()->cloneTreePure(false), 64}); - lo64p->dtypeSetUInt64(); AstNodeExpr* const hi64p = isSigned ? static_cast( new AstExtendS{fl, irp->rhsp()->cloneTreePure(false), 64}) : static_cast( new AstExtend{fl, irp->rhsp()->cloneTreePure(false), 64}); - hi64p->dtypeSetUInt64(); rangeSzp = new AstAdd{fl, new AstConst{fl, AstConst::Unsized64{}, 1ULL}, new AstSub{fl, hi64p, lo64p}}; } @@ -4669,7 +4667,6 @@ class RandomizeVisitor final : public VNVisitor { AstNodeExpr* const offsetp = new AstCCast{fl, new AstModDiv{fl, rand64p, rangeSzp}, distWidth}; AstNodeExpr* const valuep = new AstAdd{fl, irp->lhsp()->cloneTreePure(false), offsetp}; - valuep->dtypeFrom(distp->exprp()); AstNodeExpr* const eqp = new AstEq{fl, distExprCopyp, valuep}; eqp->user1(true); return eqp; @@ -4735,10 +4732,12 @@ class RandomizeVisitor final : public VNVisitor { // dist can appear inside an if/else or foreach constraint. if (AstConstraintIf* const cifp = VN_CAST(itemp, ConstraintIf)) { - if (cifp->thensp()) + if (cifp->thensp()) { lowerDistConstraints(taskp, cifp->thensp(), randModeVarp, foreachp); - if (cifp->elsesp()) + } + if (cifp->elsesp()) { lowerDistConstraints(taskp, cifp->elsesp(), randModeVarp, foreachp); + } continue; } if (AstConstraintForeach* const cfep = VN_CAST(itemp, ConstraintForeach)) { @@ -4940,8 +4939,9 @@ class RandomizeVisitor final : public VNVisitor { } if (constrp->itemsp()) expandUniqueElementList(constrp->itemsp()); - if (constrp->itemsp()) + if (constrp->itemsp()) { lowerDistConstraints(taskp, constrp->itemsp(), randModeVarp); + } std::set& sizeArrays = m_sizeConstrainedArrays[classp]; ConstraintExprVisitor{classp, m_memberMap, constrp->itemsp(), nullptr, genp, randModeVarp, diff --git a/test_regress/t/t_constraint_dist_randmode_frozen.v b/test_regress/t/t_constraint_dist_randmode_frozen.v index 6dc84b138..396327658 100644 --- a/test_regress/t/t_constraint_dist_randmode_frozen.v +++ b/test_regress/t/t_constraint_dist_randmode_frozen.v @@ -15,43 +15,75 @@ typedef int unsigned uint; class Base; rand uint delay; rand uint x; - constraint delay_c {delay inside {[1:100]};} + constraint delay_c {delay inside {[1 : 100]};} function int rd(); return this.randomize(delay); endfunction endclass class SingleVals extends Base; - constraint c {x dist {5 := 99, 1000000 := 1};} + constraint c { + x dist { + 5 := 99, + 1000000 := 1 + }; + } endclass class RangeVals extends Base; - constraint c {x dist {[1:10] := 1, [1000:2000] := 9};} + constraint c { + x dist { + [1 : 10] := 1, + [1000 : 2000] := 9 + }; + } endclass class MixVals extends Base; - constraint c {x dist {0 := 1, [100:200] := 5, 9999 := 3};} + constraint c { + x dist { + 0 := 1, + [100 : 200] := 5, + 9999 := 3 + }; + } endclass class DistInIf extends Base; rand uint sel; constraint c { sel inside {0, 1}; - if (sel == 1) x dist {5 := 9, 70 := 1}; - else x == 4242; + if (sel == 1) + x dist { + 5 := 9, + 70 := 1 + }; + else + x == 4242; } endclass class DistInForeach; rand uint arr[4]; - constraint c {foreach (arr[i]) arr[i] dist {10 := 9, 20 := 1};} + constraint c { + foreach (arr[i]) + arr[i] dist { + 10 := 9, + 20 := 1 + }; + } endclass class StaticVar; rand uint delay; static rand uint sx; - constraint delay_c {delay inside {[1:100]};} - constraint c {sx dist {5 := 9, 70 := 1};} + constraint delay_c {delay inside {[1 : 100]};} + constraint c { + sx dist { + 5 := 9, + 70 := 1 + }; + } function int rd(); return this.randomize(delay); endfunction @@ -60,7 +92,7 @@ endclass class StaticPlain; // non-dist constraint on a frozen static var rand uint d; static rand uint sy; - constraint c {sy inside {[10:20]};} + constraint c {sy inside {[10 : 20]};} endclass class Sub; @@ -70,8 +102,13 @@ endclass class Holder; rand Sub s; rand uint delay; - constraint delay_c {delay inside {[1:100]};} - constraint c {s.x dist {5 := 9, 70 := 1};} + constraint delay_c {delay inside {[1 : 100]};} + constraint c { + s.x dist { + 5 := 9, + 70 := 1 + }; + } function new(); s = new; endfunction @@ -79,17 +116,32 @@ endclass class MultiVar; rand uint x, y; - constraint c {(x + y) dist {10 := 9, 1000 := 1};} + constraint c { + (x + y) dist { + 10 := 9, + 1000 := 1 + }; + } endclass class DupVar; rand uint x; - constraint c {(x + x) dist {10 := 9, 20 := 1};} + constraint c { + (x + x) dist { + 10 := 9, + 20 := 1 + }; + } endclass class DupMember; rand Sub s; - constraint c {(s.x + s.x) dist {10 := 9, 20 := 1};} + constraint c { + (s.x + s.x) dist { + 10 := 9, + 20 := 1 + }; + } function new(); s = new; endfunction @@ -98,7 +150,12 @@ endclass class RtWeight; rand uint x; uint w; - constraint c {x dist {5 := 9, 70 := w};} + constraint c { + x dist { + 5 := 9, + 70 := w + }; + } endclass module t; @@ -124,6 +181,7 @@ module t; ok = sv.rd(); `checkd(ok, 1); `checkd(sv.x, 1000000); + if (sv.delay < 1 || sv.delay > 100) `checkd(sv.delay, 0); end // Frozen in the high-weight bucket -> succeeds. @@ -246,6 +304,25 @@ module t; `checkd(h.s.x, 7); end + // Both the handle and the member frozen. + h = new; + ok = h.randomize(); + `checkd(ok, 1); + h.s.rand_mode(0); + h.s.x.rand_mode(0); + h.s.x = 5; + for (int i = 0; i < 8; ++i) begin + ok = h.randomize(); + `checkd(ok, 1); + `checkd(h.s.x, 5); + end + h.s.x = 7; + for (int i = 0; i < 8; ++i) begin + ok = h.randomize(); + `checkd(ok, 0); + `checkd(h.s.x, 7); + end + // Multi-var dist expression, one var frozen: the active var must still // satisfy membership (sum wraps mod 2**32, so both values stay reachable). m = new; @@ -350,7 +427,8 @@ module t; `checkd(ok, 1); if (di.sel == 1) begin if (di.x != 5 && di.x != 70) `checkd(0, 1); - end else begin + end + else begin `checkd(di.x, 4242); end end @@ -360,8 +438,7 @@ module t; for (int i = 0; i < 16; ++i) begin ok = df.randomize(); `checkd(ok, 1); - foreach (df.arr[j]) - if (df.arr[j] != 10 && df.arr[j] != 20) `checkd(0, 1); + foreach (df.arr[j]) if (df.arr[j] != 10 && df.arr[j] != 20) `checkd(0, 1); end $write("*-* All Finished *-*\n");