Fix inline constraints creating class random generator (#5280)

This commit is contained in:
Krzysztof Bieganski
2024-07-19 13:03:48 -04:00
committed by GitHub
parent 298faa84ee
commit 2bd2b9324f
5 changed files with 87 additions and 40 deletions
+41 -26
View File
@@ -552,15 +552,22 @@ class RandomizeVisitor final : public VNVisitor {
std::map<std::string, AstCDType*> m_randcDtypes; // RandC data type deduplication
// METHODS
AstVar* getCreateRandomGenerator(AstClass* classp) {
if (classp->user3p()) return VN_AS(classp->user3p(), Var);
if (classp->extendsp()) return getCreateRandomGenerator(classp->extendsp()->classp());
void createRandomGenerator(AstClass* const classp) {
if (classp->user3p()) return;
if (classp->extendsp()) {
createRandomGenerator(classp->extendsp()->classp());
return;
}
AstVar* const genp = new AstVar{classp->fileline(), VVarType::MEMBER, "constraint",
classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)};
genp->user2p(classp);
classp->addMembersp(genp);
classp->user3p(genp);
return genp;
}
AstVar* getRandomGenerator(AstClass* const classp) {
if (classp->user3p()) return VN_AS(classp->user3p(), Var);
if (classp->extendsp()) return getRandomGenerator(classp->extendsp()->classp());
return nullptr;
}
AstTask* getCreateConstraintSetupFunc(AstClass* classp) {
if (classp->user2p()) return VN_AS(classp->user2p(), Task);
@@ -572,6 +579,14 @@ class RandomizeVisitor final : public VNVisitor {
classp->user2p(setupAllTaskp);
return setupAllTaskp;
}
void createRandomizeClassVars(AstNetlist* const netlistp) {
netlistp->foreach([&](AstClass* const classp) {
if (classp->existsMember(
[&](const AstClass*, const AstConstraint*) { return true; })) {
createRandomGenerator(classp);
}
});
}
AstVar* enumValueTabp(AstEnumDType* const nodep) {
if (nodep->user2p()) return VN_AS(nodep->user2p(), Var);
UINFO(9, "Construct Venumvaltab " << nodep << endl);
@@ -756,27 +771,26 @@ class RandomizeVisitor final : public VNVisitor {
FileLine* fl = nodep->fileline();
AstNodeExpr* beginValp = nullptr;
AstVar* genp = nullptr;
nodep->foreachMember([&](AstClass* classp, AstConstraint* constrp) {
AstTask* taskp = VN_AS(constrp->user2p(), Task);
if (!taskp) {
taskp = newSetupConstraintTask(classp, constrp->name());
constrp->user2p(taskp);
}
AstTaskRef* const setupTaskRefp
= new AstTaskRef{constrp->fileline(), taskp->name(), nullptr};
setupTaskRefp->taskp(taskp);
setupTaskRefp->classOrPackagep(classp);
genp = getCreateRandomGenerator(nodep);
AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep);
setupAllTaskp->addStmtsp(setupTaskRefp->makeStmt());
ConstraintExprVisitor{m_memberMap, constrp->itemsp(), nullptr, genp};
if (constrp->itemsp()) taskp->addStmtsp(constrp->itemsp()->unlinkFrBackWithNext());
});
AstVar* genp = getRandomGenerator(nodep);
if (genp) {
nodep->foreachMember([&](AstClass* const classp, AstConstraint* const constrp) {
AstTask* taskp = VN_AS(constrp->user2p(), Task);
if (!taskp) {
taskp = newSetupConstraintTask(classp, constrp->name());
constrp->user2p(taskp);
}
AstTaskRef* const setupTaskRefp
= new AstTaskRef{constrp->fileline(), taskp->name(), nullptr};
setupTaskRefp->taskp(taskp);
setupTaskRefp->classOrPackagep(classp);
AstTask* const setupAllTaskp = getCreateConstraintSetupFunc(nodep);
setupAllTaskp->addStmtsp(setupTaskRefp->makeStmt());
ConstraintExprVisitor{m_memberMap, constrp->itemsp(), nullptr, genp};
if (constrp->itemsp()) taskp->addStmtsp(constrp->itemsp()->unlinkFrBackWithNext());
});
randomizep->addStmtsp(implementConstraintsClear(fl, genp));
AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep);
AstTaskRef* const setupTaskRefp = new AstTaskRef{fl, setupAllTaskp->name(), nullptr};
@@ -926,13 +940,13 @@ class RandomizeVisitor final : public VNVisitor {
UASSERT_OBJ(classp, m_modp, "Module not class, should have failed in V3Width");
}
if (classp->user1()) {
// We need to first ensure that the class randomizer is instantiated if needed
// We need to first ensure that the class constraints are transformed
// NOTE: This is safe only because AstClass visit function overwrites all
// nesting-dependent state variables
iterate(classp);
}
AstVar* const classGenp = getCreateRandomGenerator(classp);
AstVar* const classGenp = getRandomGenerator(classp);
AstVar* const localGenp
= new AstVar{nodep->fileline(), VVarType::BLOCKTEMP, "randomizer",
classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)};
@@ -1007,6 +1021,7 @@ public:
// CONSTRUCTORS
explicit RandomizeVisitor(AstNetlist* nodep)
: m_inlineUniqueNames("__Vrandwith") {
createRandomizeClassVars(nodep);
iterate(nodep);
nodep->foreach([&](AstConstraint* constrp) {
VL_DO_DANGLING(pushDeletep(constrp->unlinkFrBack()), constrp);