follow comments and refine
This commit is contained in:
parent
69b485012f
commit
ec027b5fa3
|
|
@ -3534,7 +3534,14 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
buckets.push_back({ditemp->rangep(), weightExprp});
|
||||
}
|
||||
|
||||
if (buckets.empty()) continue;
|
||||
if (buckets.empty()) {
|
||||
// All weights are zero: dist is vacuously true (unconstrained)
|
||||
AstConstraintExpr* const truep
|
||||
= new AstConstraintExpr{fl, new AstConst{fl, AstConst::BitTrue{}}};
|
||||
constrExprp->replaceWith(truep);
|
||||
VL_DO_DANGLING(pushDeletep(constrExprp), constrExprp);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build totalWeight expression: w[0] + w[1] + ... + w[N-1]
|
||||
AstNodeExpr* totalWeightExprp = nullptr;
|
||||
|
|
@ -3556,6 +3563,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
totalVarp->noSubst(true);
|
||||
totalVarp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
totalVarp->funcLocal(true);
|
||||
totalVarp->isInternal(true);
|
||||
taskp->addStmtsp(totalVarp);
|
||||
taskp->addStmtsp(
|
||||
new AstAssign{fl, new AstVarRef{fl, totalVarp, VAccess::WRITE}, totalWeightExprp});
|
||||
|
|
@ -3567,6 +3575,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
bucketVarp->noSubst(true);
|
||||
bucketVarp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
bucketVarp->funcLocal(true);
|
||||
bucketVarp->isInternal(true);
|
||||
taskp->addStmtsp(bucketVarp);
|
||||
|
||||
AstNodeExpr* randp = new AstRand{fl, nullptr, false};
|
||||
|
|
@ -3629,16 +3638,16 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
|
||||
if (chainp) {
|
||||
constrExprp->replaceWith(chainp);
|
||||
VL_DO_DANGLING(constrExprp->deleteTree(), constrExprp);
|
||||
VL_DO_DANGLING(pushDeletep(constrExprp), constrExprp);
|
||||
}
|
||||
|
||||
// Clean up nodes used only as clone templates (never inserted into tree)
|
||||
for (auto& bucket : buckets) {
|
||||
VL_DO_DANGLING(bucket.weightExprp->deleteTree(), bucket.weightExprp);
|
||||
VL_DO_DANGLING(pushDeletep(bucket.weightExprp), bucket.weightExprp);
|
||||
}
|
||||
VL_DO_DANGLING(runningSump->deleteTree(), runningSump);
|
||||
VL_DO_DANGLING(pushDeletep(runningSump), runningSump);
|
||||
// Last cumSum is unused (last bucket is unconditional default)
|
||||
VL_DO_DANGLING(cumSums.back()->deleteTree(), cumSums.back());
|
||||
pushDeletep(cumSums.back());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3658,6 +3667,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
void visit(AstClass* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_randCaseNum);
|
||||
VL_RESTORER(m_distNum);
|
||||
m_modp = nodep;
|
||||
m_randCaseNum = 0;
|
||||
m_distNum = 0;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ class DistZeroWeight;
|
|||
constraint c { x dist { 8'd0 := 0, 8'd1 := 1, 8'd2 := 1 }; }
|
||||
endclass
|
||||
|
||||
class DistAllZeroWeight;
|
||||
rand bit [7:0] x;
|
||||
constraint c { x dist { 8'd0 := 0, 8'd1 := 0, 8'd2 := 0 }; }
|
||||
endclass
|
||||
|
||||
class DistVarWeight;
|
||||
rand bit [7:0] x;
|
||||
int w1, w2;
|
||||
|
|
@ -42,6 +47,7 @@ module t;
|
|||
DistScalar sc;
|
||||
DistRange rg;
|
||||
DistZeroWeight zw;
|
||||
DistAllZeroWeight azw;
|
||||
DistVarWeight vw;
|
||||
DistVarWeightRange vwr;
|
||||
int count_high;
|
||||
|
|
@ -58,7 +64,7 @@ module t;
|
|||
if (sc.x == 8'd255) count_high++;
|
||||
else `checkd(sc.x, 0);
|
||||
end
|
||||
`check_range(count_high, 1200, 1800);
|
||||
`check_range(count_high, total * 60 / 100, total * 90 / 100);
|
||||
|
||||
// :/ range weights: expect ~75% in [10:19]
|
||||
rg = new;
|
||||
|
|
@ -71,7 +77,7 @@ module t;
|
|||
`stop;
|
||||
end
|
||||
end
|
||||
`check_range(count_range_high, 1200, 1800);
|
||||
`check_range(count_range_high, total * 60 / 100, total * 90 / 100);
|
||||
|
||||
// Zero weight: value 0 must never appear
|
||||
zw = new;
|
||||
|
|
@ -84,6 +90,12 @@ module t;
|
|||
`check_range(zw.x, 1, 2);
|
||||
end
|
||||
|
||||
// All-zero weights: dist constraint is effectively unconstrained, randomize succeeds
|
||||
azw = new;
|
||||
repeat (20) begin
|
||||
`checkd(azw.randomize(), 1);
|
||||
end
|
||||
|
||||
// Variable := scalar weights: w1=1, w2=3 => expect ~75% for value 255
|
||||
vw = new;
|
||||
vw.w1 = 1;
|
||||
|
|
@ -94,7 +106,7 @@ module t;
|
|||
if (vw.x == 8'd255) count_high++;
|
||||
else `checkd(vw.x, 0);
|
||||
end
|
||||
`check_range(count_high, 1200, 1800);
|
||||
`check_range(count_high, total * 60 / 100, total * 90 / 100);
|
||||
|
||||
// Variable :/ range weights: w1=1, w2=3 => expect ~75% in [10:19]
|
||||
vwr = new;
|
||||
|
|
@ -109,7 +121,7 @@ module t;
|
|||
`stop;
|
||||
end
|
||||
end
|
||||
`check_range(count_range_high, 1200, 1800);
|
||||
`check_range(count_range_high, total * 60 / 100, total * 90 / 100);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,13 @@
|
|||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.lint()
|
||||
if not test.have_solver:
|
||||
test.skip("No constraint solver installed")
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class Packet;
|
|||
rand bit if_4;
|
||||
rand bit iff_5_6;
|
||||
|
||||
/*rand*/ int array[2]; // 2,4,6 // TODO: add rand when supported
|
||||
rand int array[2]; // 2,4,6
|
||||
|
||||
constraint empty {}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ module t;
|
|||
|
||||
automatic int v;
|
||||
automatic bit if_4 = '0;
|
||||
// TODO not testing constrained values
|
||||
p = new;
|
||||
v = p.randomize();
|
||||
if (v != 1) $stop;
|
||||
v = p.randomize() with {};
|
||||
|
|
|
|||
Loading…
Reference in New Issue