Fix dist range bounds over rand variables failing randomization since #7802
This commit is contained in:
parent
119493ee8a
commit
5797913600
|
|
@ -4571,31 +4571,47 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto boundRefsRandVarp = [](const AstNode* boundp) -> bool {
|
||||||
|
bool found = false;
|
||||||
|
boundp->foreach([&](const AstVarRef* vrefp) {
|
||||||
|
if (vrefp->varp()->rand().isRandomizable()) found = true;
|
||||||
|
});
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// (distExpr >= lo) && (distExpr <= hi); signed comparisons for signed vars
|
||||||
|
const auto rangeMembershipp = [&](const AstInsideRange* irp) -> AstNodeExpr* {
|
||||||
|
const bool isSigned = distp->exprp()->isSigned();
|
||||||
|
AstNodeExpr* const distExprGtep = distp->exprp()->cloneTreePure(false);
|
||||||
|
AstNodeExpr* const distExprLtep = distp->exprp()->cloneTreePure(false);
|
||||||
|
distExprGtep->user1(true);
|
||||||
|
distExprLtep->user1(true);
|
||||||
|
AstNodeExpr* const gep
|
||||||
|
= isSigned
|
||||||
|
? static_cast<AstNodeExpr*>(
|
||||||
|
new AstGteS{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)})
|
||||||
|
: static_cast<AstNodeExpr*>(
|
||||||
|
new AstGte{fl, distExprGtep, irp->lhsp()->cloneTreePure(false)});
|
||||||
|
AstNodeExpr* const lep
|
||||||
|
= isSigned
|
||||||
|
? static_cast<AstNodeExpr*>(
|
||||||
|
new AstLteS{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)})
|
||||||
|
: static_cast<AstNodeExpr*>(
|
||||||
|
new AstLte{fl, distExprLtep, irp->rhsp()->cloneTreePure(false)});
|
||||||
|
gep->user1(true);
|
||||||
|
lep->user1(true);
|
||||||
|
AstNodeExpr* const andp = new AstLogAnd{fl, gep, lep};
|
||||||
|
andp->user1(true);
|
||||||
|
return andp;
|
||||||
|
};
|
||||||
|
|
||||||
// IEEE 1800-2023 18.5.3: values not in the distribution must never appear.
|
// IEEE 1800-2023 18.5.3: values not in the distribution must never appear.
|
||||||
// Build the union of all non-zero-weight ranges as a single hard ConstraintExpr
|
// Build the union of all non-zero-weight ranges as a single hard ConstraintExpr
|
||||||
AstNodeExpr* unionExprp = nullptr;
|
AstNodeExpr* unionExprp = nullptr;
|
||||||
for (const auto& bucket : buckets) {
|
for (const auto& bucket : buckets) {
|
||||||
AstNodeExpr* memberp;
|
AstNodeExpr* memberp;
|
||||||
if (const AstInsideRange* const irp = VN_CAST(bucket.rangep, InsideRange)) {
|
if (const AstInsideRange* const irp = VN_CAST(bucket.rangep, InsideRange)) {
|
||||||
// (distExpr >= lo) && (distExpr <= hi); signed comparisons for signed vars
|
memberp = rangeMembershipp(irp);
|
||||||
const bool isSigned = distp->exprp()->isSigned();
|
|
||||||
AstNodeExpr* const distExprGtep = distp->exprp()->cloneTreePure(false);
|
|
||||||
AstNodeExpr* const distExprLtep = distp->exprp()->cloneTreePure(false);
|
|
||||||
distExprGtep->user1(true);
|
|
||||||
distExprLtep->user1(true);
|
|
||||||
AstNodeExpr* const gep
|
|
||||||
= isSigned ? static_cast<AstNodeExpr*>(new AstGteS{
|
|
||||||
fl, distExprGtep, irp->lhsp()->cloneTreePure(false)})
|
|
||||||
: static_cast<AstNodeExpr*>(new AstGte{
|
|
||||||
fl, distExprGtep, irp->lhsp()->cloneTreePure(false)});
|
|
||||||
AstNodeExpr* const lep
|
|
||||||
= isSigned ? static_cast<AstNodeExpr*>(new AstLteS{
|
|
||||||
fl, distExprLtep, irp->rhsp()->cloneTreePure(false)})
|
|
||||||
: static_cast<AstNodeExpr*>(new AstLte{
|
|
||||||
fl, distExprLtep, irp->rhsp()->cloneTreePure(false)});
|
|
||||||
gep->user1(true);
|
|
||||||
lep->user1(true);
|
|
||||||
memberp = new AstLogAnd{fl, gep, lep};
|
|
||||||
} else {
|
} else {
|
||||||
// distExpr == val
|
// distExpr == val
|
||||||
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);
|
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);
|
||||||
|
|
@ -4673,7 +4689,12 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
AstNode* chainp = nullptr;
|
AstNode* chainp = nullptr;
|
||||||
for (int i = static_cast<int>(buckets.size()) - 1; i >= 0; --i) {
|
for (int i = static_cast<int>(buckets.size()) - 1; i >= 0; --i) {
|
||||||
AstNodeExpr* constraintExprp;
|
AstNodeExpr* constraintExprp;
|
||||||
if (const AstInsideRange* const irp = VN_CAST(buckets[i].rangep, InsideRange)) {
|
const AstInsideRange* const irp = VN_CAST(buckets[i].rangep, InsideRange);
|
||||||
|
if (irp && (boundRefsRandVarp(irp->lhsp()) || boundRefsRandVarp(irp->rhsp()))) {
|
||||||
|
// Bounds solved concurrently cannot pin a pre-solve value; softly
|
||||||
|
// prefer the symbolic range so the hard membership stays satisfiable
|
||||||
|
constraintExprp = rangeMembershipp(irp);
|
||||||
|
} else if (irp) {
|
||||||
// Pick distExpr = lo + rand64() % (hi - lo + 1) for a uniform value in range
|
// Pick distExpr = lo + rand64() % (hi - lo + 1) for a uniform value in range
|
||||||
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);
|
AstNodeExpr* const distExprCopyp = distp->exprp()->cloneTreePure(false);
|
||||||
distExprCopyp->user1(true);
|
distExprCopyp->user1(true);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue