Fix dist inside a foreach nested in a constraint if (#8016)

This commit is contained in:
BRDR LIFE
2026-07-31 23:35:01 -04:00
committed by GitHub
parent 704c5a1c96
commit 6b3aebfa32
3 changed files with 530 additions and 8 deletions
+16 -8
View File
@@ -1176,6 +1176,17 @@ class ConstraintExprVisitor final : public VNVisitor {
nodep->user1(anyChild);
}
// Prepend the bucket preamble stmts stored on user3p by lowerDistConstraints to the
// statements that will become the body of the generated AstForeach, so the per-element
// bucket draw is declared and evaluated in the same scope as its references.
static AstNode* prependDistPreamble(AstConstraintForeach* nodep, AstNode* bodyp) {
AstNode* const preamblep = nodep->user3p();
if (!preamblep) return bodyp;
nodep->user3p(nullptr);
preamblep->addNext(bodyp);
return preamblep;
}
// VISITORS
void visit(AstNodeVarRef* nodep) override {
AstVar* varp = nodep->varp();
@@ -2306,25 +2317,22 @@ class ConstraintExprVisitor final : public VNVisitor {
cstmtp->add("ret += ");
cstmtp->add(itemp);
cstmtp->add(";");
AstNode* const bodyp = prependDistPreamble(nodep, cstmtp);
AstCExpr* const cexprp = new AstCExpr{fl};
cexprp->dtypeSetString();
cexprp->add("([&]{\nstd::string ret;\n");
cexprp->add(new AstBegin{
fl, "", new AstForeach{fl, nodep->headerp()->unlinkFrBack(), cstmtp}, true});
fl, "", new AstForeach{fl, nodep->headerp()->unlinkFrBack(), bodyp}, true});
cexprp->add("return ret.empty() ? \"#b1\" : \"(bvand\" + ret + \")\";\n})()");
nodep->replaceWith(new AstSFormatF{fl, "%s", false, cexprp});
} else {
iterateAndNextNull(nodep->bodyp());
AstNode* bodyp = nodep->bodyp()->unlinkFrBackWithNext();
// Prepend bucket preamble stmts stored by lowerDistConstraints (foreach case)
if (AstNode* const preamblep = nodep->user3p()) {
preamblep->addNext(bodyp);
bodyp = preamblep;
nodep->user3p(nullptr);
}
AstNode* const bodyp
= prependDistPreamble(nodep, nodep->bodyp()->unlinkFrBackWithNext());
nodep->replaceWith(new AstBegin{
fl, "", new AstForeach{fl, nodep->headerp()->unlinkFrBack(), bodyp}, true});
}
UASSERT_OBJ(!nodep->user3p(), nodep, "Dist bucket preamble not injected into foreach");
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void visit(AstConstraintBefore* nodep) override {