naming adjustment and leak-error fixing

This commit is contained in:
Yilou Wang 2025-10-19 11:55:59 +02:00
parent 2679c8a235
commit 7c8d5a7468
2 changed files with 43 additions and 33 deletions

View File

@ -1897,7 +1897,7 @@ class AstVar final : public AstNode {
bool m_ignorePostWrite : 1; // Ignore writes in 'Post' blocks during ordering
bool m_ignoreSchedWrite : 1; // Ignore writes in scheduling (for special optimizations)
bool m_dfgMultidriven : 1; // Singal is multidriven, used by DFG to avoid repeat processing
bool m_globalCons : 1;
bool m_globalConstrained : 1; // Global constraint per IEEE 1800-2023 18.5.8
void init() {
m_ansi = false;
m_declTyped = false;
@ -1948,7 +1948,7 @@ class AstVar final : public AstNode {
m_ignoreSchedWrite = false;
m_dfgMultidriven = false;
m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
m_globalCons = false;
m_globalConstrained = false;
}
public:
@ -2115,7 +2115,7 @@ public:
void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; }
bool dfgMultidriven() const { return m_dfgMultidriven; }
void setDfgMultidriven() { m_dfgMultidriven = true; }
void setGlobalConstrained(bool flag) { m_globalCons = flag; }
void setGlobalConstrained(bool flag) { m_globalConstrained = flag; }
// METHODS
void name(const string& name) override { m_name = name; }
void tag(const string& text) override { m_tag = text; }
@ -2180,7 +2180,7 @@ public:
bool isTrace() const { return m_trace; }
bool isRand() const { return m_rand.isRand(); }
bool isRandC() const { return m_rand.isRandC(); }
bool isGlobalConstrained() const { return m_globalCons; }
bool isGlobalConstrained() const { return m_globalConstrained; }
bool isConst() const VL_MT_SAFE { return m_isConst; }
bool isStatic() const VL_MT_SAFE { return m_isStatic; }
bool isLatched() const { return m_isLatched; }

View File

@ -52,12 +52,12 @@ VL_DEFINE_DEBUG_FUNCTIONS;
// Determines if a class is used with randomization
enum ClassRandom : uint8_t {
NONE, // randomize() is not called
IS_RANDOMIZED, // randomize() is called
IS_RANDOMIZED_WITH_GLOBAL_CONSTRAINTS, // randomize() is called with global constraints
IS_RANDOMIZED_INLINE, // randomize() with args is called
IS_STD_RANDOMIZED, // std::randomize() is called
IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS, // randomize() with args and global constraints
NONE, // randomize() is not called
IS_RANDOMIZED, // randomize() is called
IS_RANDOMIZED_INLINE, // randomize() with args is called
IS_STD_RANDOMIZED, // std::randomize() is called
IS_RANDOMIZED_GLOBAL, // randomize() is called with global constraints
IS_RANDOMIZED_INLINE_GLOBAL, // randomize() with args and global constraints
};
// ######################################################################
@ -146,9 +146,9 @@ class RandomizeMarkVisitor final : public VNVisitor {
AstNodeModule* m_modp; // Current module
AstNodeStmt* m_stmtp = nullptr; // Current statement
std::set<AstNodeVarRef*> m_staticRefs; // References to static variables under `with` clauses
bool m_globalConsProcessed = false;
AstWith* m_astWithp = nullptr;
std::vector<AstConstraint*> m_clonedConstraints;
bool m_globalConsProcessed = false; // Flag to track if global constraints have been processed
AstWith* m_withp = nullptr; // Current 'with' constraint node
std::vector<AstConstraint*> m_clonedConstraints; // List of cloned global constraints
std::unordered_set<const AstVar*> m_processedVars; // Track by variable instance, not class
// METHODS
@ -177,7 +177,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
}
// If the class is randomized inline, all members use rand mode
if ((nodep->user1() == IS_RANDOMIZED_INLINE)
|| (nodep->user1() == IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS)) {
|| (nodep->user1() == IS_RANDOMIZED_INLINE_GLOBAL)) {
RandomizeMode randMode = {};
randMode.usesMode = true;
varp->user1(randMode.asInt);
@ -214,10 +214,16 @@ class RandomizeMarkVisitor final : public VNVisitor {
if (!nodep) return;
if (VN_IS(nodep, VarRef)) {
VN_AS(nodep, VarRef)->varp()->setGlobalConstrained(true);
AstVar* const varp = VN_AS(nodep, VarRef)->varp();
if (varp->isGlobalConstrained()) return;
varp->setGlobalConstrained(true);
} else if (VN_IS(nodep, MemberSel)) {
AstMemberSel* memberSelp = VN_AS(nodep, MemberSel);
if (memberSelp->varp()) memberSelp->varp()->setGlobalConstrained(true);
AstMemberSel* const memberSelp = VN_AS(nodep, MemberSel);
if (memberSelp->varp()) {
AstVar* const varp = memberSelp->varp();
if (varp->isGlobalConstrained()) return;
varp->setGlobalConstrained(true);
}
markNestedGlobalConstrained(memberSelp->fromp());
}
}
@ -235,7 +241,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
}
// Clone constraints from nested rand class members
void cloneNestedConstraintsRecursive(AstVarRef* rootVarRefp, AstClass* classp,
void cloneNestedConstraintsRecurse(AstVarRef* rootVarRefp, AstClass* classp,
const std::vector<AstVar*>& pathToClass) {
if (!classp) return;
for (AstNode* memberNodep = classp->membersp(); memberNodep;
@ -264,7 +270,6 @@ class RandomizeMarkVisitor final : public VNVisitor {
cloneConstrp->name(pathPrefix + GLOBAL_CONSTRAINT_SEPARATOR
+ cloneConstrp->name());
cloneConstrp->foreach([&](AstVarRef* varRefp) {
if (!varRefp || !varRefp->varp()) return;
@ -279,7 +284,7 @@ class RandomizeMarkVisitor final : public VNVisitor {
m_clonedConstraints.push_back(cloneConstrp);
});
cloneNestedConstraintsRecursive(rootVarRefp, nestedClassp, newPath);
cloneNestedConstraintsRecurse(rootVarRefp, nestedClassp, newPath);
}
}
}
@ -288,12 +293,11 @@ class RandomizeMarkVisitor final : public VNVisitor {
void cloneNestedConstraints(AstVarRef* rootVarRefp, AstClass* rootClass) {
std::vector<AstVar*> emptyPath;
cloneNestedConstraintsRecursive(rootVarRefp, rootClass, emptyPath);
cloneNestedConstraintsRecurse(rootVarRefp, rootClass, emptyPath);
}
void nameManipulation(AstVarRef* fromp, AstConstraint* cloneCons) {
if (!fromp || !cloneCons) return;
// Iterate through all variable references and replace them with member selections.
cloneCons->name(fromp->name() + GLOBAL_CONSTRAINT_SEPARATOR + cloneCons->name());
cloneCons->foreach([&](AstVarRef* varRefp) {
if (!varRefp || !varRefp->varp()) return;
@ -578,8 +582,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
const bool randObject = nodep->fromp()->user1() || VN_IS(nodep->fromp(), LambdaArgRef);
nodep->user1(randObject && nodep->varp()->rand().isRandomizable());
if (m_astWithp) {
AstNode* backp = m_astWithp;
if (m_withp) {
AstNode* backp = m_withp;
while (backp->backp()) {
if (VN_IS(backp, MethodCall)) {
AstClassRefDType* classdtype = VN_CAST(
@ -594,9 +598,9 @@ class RandomizeMarkVisitor final : public VNVisitor {
if (randObject && nodep->varp()
&& nodep->varp()->rand().isRandomizable()) { // Process global constraints
if (m_classp && m_classp->user1() == IS_RANDOMIZED)
m_classp->user1(IS_RANDOMIZED_WITH_GLOBAL_CONSTRAINTS);
m_classp->user1(IS_RANDOMIZED_GLOBAL);
else if (m_classp && m_classp->user1() == IS_RANDOMIZED_INLINE)
m_classp->user1(IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS);
m_classp->user1(IS_RANDOMIZED_INLINE_GLOBAL);
// Mark the entire nested chain as participating in global constraints
// For foo.in.val, this marks: foo, foo.in, and foo.in.val
if (VN_IS(nodep->fromp(), VarRef) || VN_IS(nodep->fromp(), MemberSel)) {
@ -660,9 +664,9 @@ class RandomizeMarkVisitor final : public VNVisitor {
iterateChildrenConst(nodep);
}
void visit(AstWith* nodep) override {
m_astWithp = nodep;
m_withp = nodep;
iterateChildrenConst(nodep);
m_astWithp = nullptr;
m_withp = nullptr;
}
void visit(AstNodeExpr* nodep) override {
@ -920,7 +924,13 @@ class ConstraintExprVisitor final : public VNVisitor {
AstVarRef* const varRefp
= new AstVarRef{varp->fileline(), classp, varp, VAccess::WRITE};
varRefp->classOrPackagep(classOrPackagep);
membersel ? methodp->addPinsp(membersel) : methodp->addPinsp(varRefp);
if (membersel) {
methodp->addPinsp(membersel);
// Delete the unused varRefp to avoid memory leak
VL_DO_DANGLING(varRefp->deleteTree(), varRefp);
} else {
methodp->addPinsp(varRefp);
}
AstNodeDType* tmpDtypep = varp->dtypep();
while (VN_IS(tmpDtypep, UnpackArrayDType) || VN_IS(tmpDtypep, DynArrayDType)
|| VN_IS(tmpDtypep, QueueDType) || VN_IS(tmpDtypep, AssocArrayDType))
@ -2357,8 +2367,8 @@ class RandomizeVisitor final : public VNVisitor {
UINFO(9, "Define randomize() for " << nodep);
nodep->baseMostClassp()->needRNG(true);
bool globalcons = nodep->user1() == IS_RANDOMIZED_INLINE_WITH_GLOBAL_CONSTRAINTS
|| nodep->user1() == IS_RANDOMIZED_WITH_GLOBAL_CONSTRAINTS;
bool globalConstrained = nodep->user1() == IS_RANDOMIZED_INLINE_GLOBAL
|| nodep->user1() == IS_RANDOMIZED_GLOBAL;
AstFunc* const randomizep = V3Randomize::newRandomizeFunc(m_memberMap, nodep);
AstVar* const fvarp = VN_AS(randomizep->fvarp(), Var);
addPrePostCall(nodep, randomizep, "pre_randomize");
@ -2424,7 +2434,7 @@ class RandomizeVisitor final : public VNVisitor {
AstVarRef* const fvarRefp = new AstVarRef{fl, fvarp, VAccess::WRITE};
// For global constraints: call basic randomize first (without global constraints)
if (globalcons) {
if (globalConstrained) {
AstFunc* const basicRandomizep
= V3Randomize::newRandomizeFunc(m_memberMap, nodep, BASIC_RANDOMIZE_FUNC_NAME);
addBasicRandomizeBody(basicRandomizep, nodep, randModeVarp);
@ -2446,7 +2456,7 @@ class RandomizeVisitor final : public VNVisitor {
// For global constraints: combine with solver result (beginValp)
// For normal classes: call basic randomize after resize
if (globalcons) {
if (globalConstrained) {
randomizep->addStmtsp(new AstAssign{fl, fvarRefp->cloneTree(false),
new AstAnd{fl, fvarRefReadp, beginValp}});
} else {