Fix inline constraints creating class random generator (#5280)

This commit is contained in:
Krzysztof Bieganski 2024-07-19 19:03:48 +02:00 committed by GitHub
parent 298faa84ee
commit 2bd2b9324f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 87 additions and 40 deletions

View File

@ -2338,17 +2338,40 @@ public:
// root superclass). Note: after V3Scope, several children are moved under an AstScope and will // root superclass). Note: after V3Scope, several children are moved under an AstScope and will
// not be found by this. // not be found by this.
template <typename Callable> template <typename Callable>
void foreachMember(const Callable& visit) { void foreachMember(const Callable& f) {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 1>::type; using T_Node = typename FunctionArgNoPointerNoCV<Callable, 1>::type;
static_assert(
vlstd::is_invocable<Callable, AstClass*, T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
"with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const extendsp = this->extendsp()) { if (AstClassExtends* const extendsp = this->extendsp()) {
extendsp->classp()->foreachMember(visit); extendsp->classp()->foreachMember(f);
} }
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (T_Node* memberp = AstNode::privateCast<T_Node, decltype(stmtp)>(stmtp)) { if (T_Node* memberp = AstNode::privateCast<T_Node, decltype(stmtp)>(stmtp)) {
visit(this, memberp); f(this, memberp);
} }
} }
} }
// Same as above, but stops after first match
template <typename Callable>
bool existsMember(const Callable& p) const {
using T_Node = typename FunctionArgNoPointerNoCV<Callable, 1>::type;
static_assert(vlstd::is_invocable_r<bool, Callable, const AstClass*, const T_Node*>::value
&& std::is_base_of<AstNode, T_Node>::value,
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
if (AstClassExtends* const extendsp = this->extendsp()) {
if (extendsp->classp()->existsMember(p)) return true;
}
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (T_Node* memberp = AstNode::privateCast<T_Node, decltype(stmtp)>(stmtp)) {
if (p(this, memberp)) return true;
}
}
return false;
}
}; };
class AstClassPackage final : public AstNodeModule { class AstClassPackage final : public AstNodeModule {
// The static information portion of a class (treated similarly to a package) // The static information portion of a class (treated similarly to a package)

View File

@ -552,15 +552,22 @@ class RandomizeVisitor final : public VNVisitor {
std::map<std::string, AstCDType*> m_randcDtypes; // RandC data type deduplication std::map<std::string, AstCDType*> m_randcDtypes; // RandC data type deduplication
// METHODS // METHODS
AstVar* getCreateRandomGenerator(AstClass* classp) { void createRandomGenerator(AstClass* const classp) {
if (classp->user3p()) return VN_AS(classp->user3p(), Var); if (classp->user3p()) return;
if (classp->extendsp()) return getCreateRandomGenerator(classp->extendsp()->classp()); if (classp->extendsp()) {
createRandomGenerator(classp->extendsp()->classp());
return;
}
AstVar* const genp = new AstVar{classp->fileline(), VVarType::MEMBER, "constraint", AstVar* const genp = new AstVar{classp->fileline(), VVarType::MEMBER, "constraint",
classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)}; classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)};
genp->user2p(classp); genp->user2p(classp);
classp->addMembersp(genp); classp->addMembersp(genp);
classp->user3p(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) { AstTask* getCreateConstraintSetupFunc(AstClass* classp) {
if (classp->user2p()) return VN_AS(classp->user2p(), Task); if (classp->user2p()) return VN_AS(classp->user2p(), Task);
@ -572,6 +579,14 @@ class RandomizeVisitor final : public VNVisitor {
classp->user2p(setupAllTaskp); classp->user2p(setupAllTaskp);
return 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) { AstVar* enumValueTabp(AstEnumDType* const nodep) {
if (nodep->user2p()) return VN_AS(nodep->user2p(), Var); if (nodep->user2p()) return VN_AS(nodep->user2p(), Var);
UINFO(9, "Construct Venumvaltab " << nodep << endl); UINFO(9, "Construct Venumvaltab " << nodep << endl);
@ -756,8 +771,9 @@ class RandomizeVisitor final : public VNVisitor {
FileLine* fl = nodep->fileline(); FileLine* fl = nodep->fileline();
AstNodeExpr* beginValp = nullptr; AstNodeExpr* beginValp = nullptr;
AstVar* genp = nullptr; AstVar* genp = getRandomGenerator(nodep);
nodep->foreachMember([&](AstClass* classp, AstConstraint* constrp) { if (genp) {
nodep->foreachMember([&](AstClass* const classp, AstConstraint* const constrp) {
AstTask* taskp = VN_AS(constrp->user2p(), Task); AstTask* taskp = VN_AS(constrp->user2p(), Task);
if (!taskp) { if (!taskp) {
taskp = newSetupConstraintTask(classp, constrp->name()); taskp = newSetupConstraintTask(classp, constrp->name());
@ -768,15 +784,13 @@ class RandomizeVisitor final : public VNVisitor {
setupTaskRefp->taskp(taskp); setupTaskRefp->taskp(taskp);
setupTaskRefp->classOrPackagep(classp); setupTaskRefp->classOrPackagep(classp);
genp = getCreateRandomGenerator(nodep); AstTask* const setupAllTaskp = getCreateConstraintSetupFunc(nodep);
AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep);
setupAllTaskp->addStmtsp(setupTaskRefp->makeStmt()); setupAllTaskp->addStmtsp(setupTaskRefp->makeStmt());
ConstraintExprVisitor{m_memberMap, constrp->itemsp(), nullptr, genp}; ConstraintExprVisitor{m_memberMap, constrp->itemsp(), nullptr, genp};
if (constrp->itemsp()) taskp->addStmtsp(constrp->itemsp()->unlinkFrBackWithNext()); if (constrp->itemsp()) taskp->addStmtsp(constrp->itemsp()->unlinkFrBackWithNext());
}); });
if (genp) {
randomizep->addStmtsp(implementConstraintsClear(fl, genp)); randomizep->addStmtsp(implementConstraintsClear(fl, genp));
AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep); AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep);
AstTaskRef* const setupTaskRefp = new AstTaskRef{fl, setupAllTaskp->name(), nullptr}; 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"); UASSERT_OBJ(classp, m_modp, "Module not class, should have failed in V3Width");
} }
if (classp->user1()) { 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 // NOTE: This is safe only because AstClass visit function overwrites all
// nesting-dependent state variables // nesting-dependent state variables
iterate(classp); iterate(classp);
} }
AstVar* const classGenp = getCreateRandomGenerator(classp); AstVar* const classGenp = getRandomGenerator(classp);
AstVar* const localGenp AstVar* const localGenp
= new AstVar{nodep->fileline(), VVarType::BLOCKTEMP, "randomizer", = new AstVar{nodep->fileline(), VVarType::BLOCKTEMP, "randomizer",
classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)}; classp->findBasicDType(VBasicDTypeKwd::RANDOM_GENERATOR)};
@ -1007,6 +1021,7 @@ public:
// CONSTRUCTORS // CONSTRUCTORS
explicit RandomizeVisitor(AstNetlist* nodep) explicit RandomizeVisitor(AstNetlist* nodep)
: m_inlineUniqueNames("__Vrandwith") { : m_inlineUniqueNames("__Vrandwith") {
createRandomizeClassVars(nodep);
iterate(nodep); iterate(nodep);
nodep->foreach([&](AstConstraint* constrp) { nodep->foreach([&](AstConstraint* constrp) {
VL_DO_DANGLING(pushDeletep(constrp->unlinkFrBack()), constrp); VL_DO_DANGLING(pushDeletep(constrp->unlinkFrBack()), constrp);

View File

@ -48,7 +48,8 @@
{"type":"VARREF","name":"strings_equal","addr":"(JB)","loc":"d,62:7,62:13","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} {"type":"VARREF","name":"strings_equal","addr":"(JB)","loc":"d,62:7,62:13","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}
],"timingControlp": []} ],"timingControlp": []}
],"scopeNamep": []}, ],"scopeNamep": []},
{"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []} {"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []},
{"type":"VAR","name":"constraint","addr":"(MB)","loc":"d,7:1,7:6","dtypep":"(NB)","origName":"constraint","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"MEMBER","dtypeName":"VlRandomizer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}
],"activesp": [],"extendsp": []} ],"activesp": [],"extendsp": []}
],"activesp": []} ],"activesp": []}
],"filesp": [], ],"filesp": [],
@ -56,28 +57,29 @@
{"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(LB)", {"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(LB)",
"typesp": [ "typesp": [
{"type":"BASICDTYPE","name":"logic","addr":"(GB)","loc":"d,22:14,22:15","dtypep":"(GB)","keyword":"logic","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(GB)","loc":"d,22:14,22:15","dtypep":"(GB)","keyword":"logic","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(MB)","loc":"d,25:21,25:22","dtypep":"(MB)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(OB)","loc":"d,25:21,25:22","dtypep":"(OB)","keyword":"logic","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"string","addr":"(M)","loc":"d,73:7,73:13","dtypep":"(M)","keyword":"string","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"string","addr":"(M)","loc":"d,73:7,73:13","dtypep":"(M)","keyword":"string","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"int","addr":"(Q)","loc":"d,8:9,8:12","dtypep":"(Q)","keyword":"int","range":"31:0","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"int","addr":"(Q)","loc":"d,8:9,8:12","dtypep":"(Q)","keyword":"int","range":"31:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"bit","addr":"(U)","loc":"d,11:9,11:12","dtypep":"(U)","keyword":"bit","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"bit","addr":"(U)","loc":"d,11:9,11:12","dtypep":"(U)","keyword":"bit","generic":true,"rangep": []},
{"type":"UNPACKARRAYDTYPE","name":"","addr":"(Y)","loc":"d,15:18,15:19","dtypep":"(Y)","isCompound":false,"declRange":"[0:1]","generic":false,"refDTypep":"(Q)","childDTypep": [], {"type":"UNPACKARRAYDTYPE","name":"","addr":"(Y)","loc":"d,15:18,15:19","dtypep":"(Y)","isCompound":false,"declRange":"[0:1]","generic":false,"refDTypep":"(Q)","childDTypep": [],
"rangep": [ "rangep": [
{"type":"RANGE","name":"","addr":"(NB)","loc":"d,15:18,15:19","ascending":true, {"type":"RANGE","name":"","addr":"(PB)","loc":"d,15:18,15:19","ascending":true,
"leftp": [ "leftp": [
{"type":"CONST","name":"32'h0","addr":"(OB)","loc":"d,15:19,15:20","dtypep":"(MB)"} {"type":"CONST","name":"32'h0","addr":"(QB)","loc":"d,15:19,15:20","dtypep":"(OB)"}
], ],
"rightp": [ "rightp": [
{"type":"CONST","name":"32'h1","addr":"(PB)","loc":"d,15:19,15:20","dtypep":"(MB)"} {"type":"CONST","name":"32'h1","addr":"(RB)","loc":"d,15:19,15:20","dtypep":"(OB)"}
]} ]}
]}, ]},
{"type":"VOIDDTYPE","name":"","addr":"(LB)","loc":"d,7:1,7:6","dtypep":"(LB)","generic":false}, {"type":"VOIDDTYPE","name":"","addr":"(LB)","loc":"d,7:1,7:6","dtypep":"(LB)","generic":false},
{"type":"CLASSREFDTYPE","name":"Packet","addr":"(H)","loc":"d,69:4,69:10","dtypep":"(H)","generic":false,"classp":"(O)","classOrPackagep":"(O)","paramsp": []} {"type":"CLASSREFDTYPE","name":"Packet","addr":"(H)","loc":"d,69:4,69:10","dtypep":"(H)","generic":false,"classp":"(O)","classOrPackagep":"(O)","paramsp": []},
{"type":"BASICDTYPE","name":"VlRandomizer","addr":"(NB)","loc":"d,7:1,7:6","dtypep":"(NB)","keyword":"VlRandomizer","generic":true,"rangep": []}
]}, ]},
{"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0", {"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0",
"modulep": [ "modulep": [
{"type":"MODULE","name":"@CONST-POOL@","addr":"(QB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","inlinesp": [], {"type":"MODULE","name":"@CONST-POOL@","addr":"(SB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"NONE","inlinesp": [],
"stmtsp": [ "stmtsp": [
{"type":"SCOPE","name":"@CONST-POOL@","addr":"(RB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(QB)","varsp": [],"blocksp": [],"inlinesp": []} {"type":"SCOPE","name":"@CONST-POOL@","addr":"(TB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(SB)","varsp": [],"blocksp": [],"inlinesp": []}
],"activesp": []} ],"activesp": []}
]} ]}
]} ]}

View File

@ -48,22 +48,24 @@
</assign> </assign>
</func> </func>
<func loc="d,7,1,7,6" name="new" dtype_id="7"/> <func loc="d,7,1,7,6" name="new" dtype_id="7"/>
<var loc="d,7,1,7,6" name="constraint" dtype_id="8" vartype="VlRandomizer" origName="constraint"/>
</class> </class>
</package> </package>
<typetable loc="a,0,0,0,0"> <typetable loc="a,0,0,0,0">
<basicdtype loc="d,22,14,22,15" id="6" name="logic"/> <basicdtype loc="d,22,14,22,15" id="6" name="logic"/>
<basicdtype loc="d,25,21,25,22" id="8" name="logic" left="31" right="0"/> <basicdtype loc="d,25,21,25,22" id="9" name="logic" left="31" right="0"/>
<basicdtype loc="d,73,7,73,13" id="2" name="string"/> <basicdtype loc="d,73,7,73,13" id="2" name="string"/>
<basicdtype loc="d,8,9,8,12" id="3" name="int" left="31" right="0" signed="true"/> <basicdtype loc="d,8,9,8,12" id="3" name="int" left="31" right="0" signed="true"/>
<basicdtype loc="d,11,9,11,12" id="4" name="bit"/> <basicdtype loc="d,11,9,11,12" id="4" name="bit"/>
<unpackarraydtype loc="d,15,18,15,19" id="5" sub_dtype_id="3"> <unpackarraydtype loc="d,15,18,15,19" id="5" sub_dtype_id="3">
<range loc="d,15,18,15,19"> <range loc="d,15,18,15,19">
<const loc="d,15,19,15,20" name="32&apos;h0" dtype_id="8"/> <const loc="d,15,19,15,20" name="32&apos;h0" dtype_id="9"/>
<const loc="d,15,19,15,20" name="32&apos;h1" dtype_id="8"/> <const loc="d,15,19,15,20" name="32&apos;h1" dtype_id="9"/>
</range> </range>
</unpackarraydtype> </unpackarraydtype>
<voiddtype loc="d,7,1,7,6" id="7"/> <voiddtype loc="d,7,1,7,6" id="7"/>
<classrefdtype loc="d,69,4,69,10" id="1" name="Packet"/> <classrefdtype loc="d,69,4,69,10" id="1" name="Packet"/>
<basicdtype loc="d,7,1,7,6" id="8" name="VlRandomizer"/>
</typetable> </typetable>
</netlist> </netlist>
</verilator_xml> </verilator_xml>

View File

@ -23,5 +23,10 @@ if (!$Self->have_solver) {
); );
} }
for my $file (glob_all("$Self->{obj_dir}/$Self->{vm_prefix}*Baz*.cpp")) {
# Check that "Baz" has no constrained random generator
file_grep_not($file, "this->__PVT__constraint");
}
ok(1); ok(1);
1; 1;