This commit is contained in:
Yilou Wang 2025-09-19 16:11:58 +02:00
parent 358c5a7d72
commit 77f6b85d1f
2 changed files with 45 additions and 13 deletions

View File

@ -2115,7 +2115,7 @@ public:
void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; } void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; }
bool dfgMultidriven() const { return m_dfgMultidriven; } bool dfgMultidriven() const { return m_dfgMultidriven; }
void setDfgMultidriven() { m_dfgMultidriven = true; } void setDfgMultidriven() { m_dfgMultidriven = true; }
void isGlobalConstrained(bool flag) { m_globalCons = true; } void setGlobalConstrained(bool flag) { m_globalCons = flag; }
// METHODS // METHODS
void name(const string& name) override { m_name = name; } void name(const string& name) override { m_name = name; }
void tag(const string& text) override { m_tag = text; } void tag(const string& text) override { m_tag = text; }

View File

@ -143,6 +143,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
bool m_globalConsProcessed = false; bool m_globalConsProcessed = false;
AstWith* m_astWithp = nullptr; AstWith* m_astWithp = nullptr;
std::vector<AstConstraint*> m_clonedConstraints; std::vector<AstConstraint*> m_clonedConstraints;
std::unordered_set<const AstClass*> m_processedClasses;
// Constants for global constraint processing // Constants for global constraint processing
static constexpr const char* GLOBAL_CONSTRAINT_SEPARATOR = "__DT__"; static constexpr const char* GLOBAL_CONSTRAINT_SEPARATOR = "__DT__";
@ -207,11 +208,24 @@ class RandomizeMarkVisitor final : public VNVisitor {
} }
} }
void nameManipulation(AstVarRef* fromp, AstConstraint* cloneCons) { void nameManipulation(AstVarRef* fromp, AstConstraint* cloneCons) {
if (!fromp || !cloneCons) {
UINFO(9, "Invalid parameters in nameManipulation\n");
return;
}
// Iterate through all variable references and replace them with member selections. // Iterate through all variable references and replace them with member selections.
cloneCons->name(fromp->name() + GLOBAL_CONSTRAINT_SEPARATOR + cloneCons->name()); cloneCons->name(fromp->name() + GLOBAL_CONSTRAINT_SEPARATOR + cloneCons->name());
cloneCons->foreach([&](AstVarRef* varRefp) { cloneCons->foreach([&](AstVarRef* varRefp) {
if (!varRefp || !varRefp->varp()) {
UINFO(9, "Invalid variable reference in constraint\n");
return;
}
AstVarRef* clonedFromp = fromp->cloneTree(false);
if (!clonedFromp) {
UINFO(9, "Failed to clone variable reference in nameManipulation\n");
return;
}
AstMemberSel* varMemberp = new AstMemberSel{cloneCons->fileline(), AstMemberSel* varMemberp = new AstMemberSel{cloneCons->fileline(),
fromp->cloneTree(false), varRefp->varp()}; clonedFromp, varRefp->varp()};
varMemberp->user2p(m_classp); varMemberp->user2p(m_classp);
varRefp->replaceWith(varMemberp); varRefp->replaceWith(varMemberp);
VL_DO_DANGLING(varRefp->deleteTree(), varRefp); VL_DO_DANGLING(varRefp->deleteTree(), varRefp);
@ -223,6 +237,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
VL_RESTORER(m_modp); VL_RESTORER(m_modp);
m_modp = m_classp = nodep; m_modp = m_classp = nodep;
m_globalConsProcessed = false; m_globalConsProcessed = false;
// Clear processed classes for each new class context
m_processedClasses.clear();
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
for (int i = 0; i < m_clonedConstraints.size(); i++) { for (int i = 0; i < m_clonedConstraints.size(); i++) {
m_classp->addStmtsp(m_clonedConstraints[i]); m_classp->addStmtsp(m_clonedConstraints[i]);
@ -507,7 +523,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
m_classp->user1(IS_RANDOMIZED_WITH_GLOBAL_CONSTRAINTS); m_classp->user1(IS_RANDOMIZED_WITH_GLOBAL_CONSTRAINTS);
else if (m_classp->user1() == IS_RANDOMIZED_INLINE) else if (m_classp->user1() == IS_RANDOMIZED_INLINE)
m_classp->user1(IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS); m_classp->user1(IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS);
VN_AS(nodep->fromp(), VarRef)->varp()->isGlobalConstrained(true); // not needed // Mark the object variable as participating in global constraints
VN_AS(nodep->fromp(), VarRef)->varp()->setGlobalConstrained(true);
// Global constraint processing algorithm: // Global constraint processing algorithm:
// 1. Detect globally constrained object variables in randomized classes // 1. Detect globally constrained object variables in randomized classes
@ -516,25 +533,40 @@ class RandomizeMarkVisitor final : public VNVisitor {
// 4. Insert cloned constraints into current class for solver processing // 4. Insert cloned constraints into current class for solver processing
// 5. Use basic randomization for non-constrained variables to avoid recursion // 5. Use basic randomization for non-constrained variables to avoid recursion
if (!m_globalConsProcessed) { // Only process once per object's global constraints // Extract and validate components early to avoid repeated type checks
// TODO: Should be a vector to check if each class is AstVarRef* const varRefp = VN_CAST(nodep->fromp(), VarRef);
// processed if (!varRefp || !varRefp->varp()) return;
if (nodep->user1() && VN_IS(nodep->fromp()->dtypep()->skipRefp(), ClassRefDType)
&& VN_AS(nodep->fromp(), VarRef)->varp()->isGlobalConstrained()) { const AstClassRefDType* const classRefp =
AstClass* gConsClass VN_CAST(varRefp->dtypep()->skipRefp(), ClassRefDType);
= VN_AS(nodep->fromp()->dtypep()->skipRefp(), ClassRefDType)->classp(); if (!classRefp || !classRefp->classp()) return;
if (nodep->user1() && varRefp->varp()->isGlobalConstrained()) {
AstClass* gConsClass = classRefp->classp();
// Use class-specific processing to allow multiple object processing
if (m_processedClasses.find(gConsClass) == m_processedClasses.end()) {
gConsClass->foreachMember( gConsClass->foreachMember(
[&](AstClass* const classp, AstConstraint* const constrp) { [&](AstClass* const classp, AstConstraint* const constrp) {
if (!constrp) {
UINFO(9, "Null constraint found in class " << classp->name() << "\n");
return;
}
AstConstraint* cloneConstrp = constrp->cloneTree(false); AstConstraint* cloneConstrp = constrp->cloneTree(false);
if (!cloneConstrp) {
UINFO(9, "Failed to clone constraint " << constrp->name() << "\n");
return;
}
// Name manipulation // Name manipulation
nameManipulation(VN_AS(nodep->fromp(), VarRef), cloneConstrp); nameManipulation(varRefp, cloneConstrp);
m_clonedConstraints.push_back(cloneConstrp); m_clonedConstraints.push_back(cloneConstrp);
}); });
// Mark this class as processed
m_processedClasses.insert(gConsClass);
} }
} }
m_globalConsProcessed = true;
} }
} }
void visit(AstNodeModule* nodep) override { void visit(AstNodeModule* nodep) override {