mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
@@ -1927,6 +1927,7 @@ public:
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSFormatF;
|
||||
string name() const override VL_MT_STABLE { return m_text; }
|
||||
void name(const string& name) override { m_text = name; }
|
||||
int instrCount() const override { return INSTR_COUNT_PLI; }
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
return text() == VN_DBG_AS(samep, SFormatF)->text();
|
||||
|
||||
+16
-10
@@ -287,6 +287,7 @@ class EmitCHeader final : public EmitCConstInit {
|
||||
putns(itemp, itemp->dtypep()->cType(itemp->nameProtect(), false, false));
|
||||
puts(";\n");
|
||||
}
|
||||
|
||||
// Three helper functions for struct constrained randomization:
|
||||
// - memberNames: Get member names
|
||||
// - getMembers: Access member references
|
||||
@@ -294,13 +295,15 @@ class EmitCHeader final : public EmitCConstInit {
|
||||
// - memberWidth: Retrieve member width
|
||||
// - memberDimension: Retrieve member dimension
|
||||
if (sdtypep->isConstrainedRand()) {
|
||||
bool needComma = false;
|
||||
putns(sdtypep, "\nstd::vector<std::string> memberNames(void) const {\n");
|
||||
puts("return {");
|
||||
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
if (itemp->isConstrainedRand()) putns(itemp, "\"" + itemp->shortName() + "\"");
|
||||
if (itemp->nextp() && VN_AS(itemp->nextp(), MemberDType)->isConstrainedRand())
|
||||
puts(",\n");
|
||||
if (!itemp->isConstrainedRand()) continue;
|
||||
if (needComma) puts(",\n");
|
||||
putns(itemp, "\"" + itemp->shortName() + "\"");
|
||||
needComma = true;
|
||||
}
|
||||
puts("};\n}\n");
|
||||
|
||||
@@ -310,25 +313,28 @@ class EmitCHeader final : public EmitCConstInit {
|
||||
putns(sdtypep, "\nstd::vector<int> memberDimension(void) const {\n");
|
||||
emitMemberVector<AttributeType::Dimension>(sdtypep);
|
||||
|
||||
needComma = false;
|
||||
putns(sdtypep, "\nauto memberIndices(void) const {\n");
|
||||
puts("return std::index_sequence_for<");
|
||||
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
if (itemp->isConstrainedRand())
|
||||
putns(itemp, itemp->dtypep()->cType("", false, false));
|
||||
if (itemp->nextp() && VN_AS(itemp->nextp(), MemberDType)->isConstrainedRand())
|
||||
puts(",\n");
|
||||
if (!itemp->isConstrainedRand()) continue;
|
||||
if (needComma) puts(",\n");
|
||||
putns(itemp, itemp->dtypep()->cType("", false, false));
|
||||
needComma = true;
|
||||
}
|
||||
puts(">{};\n}\n");
|
||||
|
||||
needComma = false;
|
||||
putns(sdtypep, "\ntemplate <typename T>");
|
||||
putns(sdtypep, "\nauto getMembers(T& obj) {\n");
|
||||
puts("return std::tie(");
|
||||
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
if (itemp->isConstrainedRand()) putns(itemp, "obj." + itemp->nameProtect());
|
||||
if (itemp->nextp() && VN_AS(itemp->nextp(), MemberDType)->isConstrainedRand())
|
||||
puts(", ");
|
||||
if (!itemp->isConstrainedRand()) continue;
|
||||
if (needComma) puts(",\n");
|
||||
putns(itemp, "obj." + itemp->nameProtect());
|
||||
needComma = true;
|
||||
}
|
||||
puts(");\n}\n");
|
||||
}
|
||||
|
||||
+40
-5
@@ -481,6 +481,8 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
AstVar* m_randModeVarp; // Relevant randmode state variable
|
||||
bool m_wantSingle = false; // Whether to merge constraint expressions with LOGAND
|
||||
VMemberMap& m_memberMap; // Member names cached for fast lookup
|
||||
bool m_structSel = false; // Marks when inside structSel
|
||||
// (used to format "%@.%@" for struct arrays)
|
||||
|
||||
AstSFormatF* getConstFormat(AstNodeExpr* nodep) {
|
||||
return new AstSFormatF{nodep->fileline(), (nodep->width() & 3) ? "#b%b" : "#x%x", false,
|
||||
@@ -537,6 +539,10 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
UASSERT_OBJ(!rhsp, nodep, "Missing emitSMT %r for " << rhsp);
|
||||
UASSERT_OBJ(!thsp, nodep, "Missing emitSMT %t for " << thsp);
|
||||
AstSFormatF* const newp = new AstSFormatF{nodep->fileline(), smtExpr, false, argsp};
|
||||
if (m_structSel && newp->name() == "(select %@ %@)") {
|
||||
newp->name("%@.%@");
|
||||
newp->exprsp()->nextp()->name("%x");
|
||||
}
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
@@ -712,6 +718,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
editSMT(nodep, nodep->fromp(), lsbp, msbp);
|
||||
}
|
||||
void visit(AstStructSel* nodep) override {
|
||||
m_structSel = true;
|
||||
if (VN_IS(nodep->fromp()->dtypep()->skipRefp(), StructDType)) {
|
||||
AstNodeExpr* const fromp = nodep->fromp();
|
||||
if (VN_IS(fromp, StructSel)) {
|
||||
@@ -726,11 +733,34 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
memberp = VN_CAST(memberp->nextp(), MemberDType);
|
||||
}
|
||||
}
|
||||
// Mark Random for structArray
|
||||
if (VN_IS(nodep->fromp(), ArraySel)) {
|
||||
AstNodeExpr* const fromp = VN_AS(nodep->fromp(), ArraySel)->fromp();
|
||||
AstStructDType* const dtypep
|
||||
= VN_AS(fromp->dtypep()->skipRefp()->subDTypep()->skipRefp(), StructDType);
|
||||
dtypep->markConstrainedRand(true);
|
||||
AstMemberDType* memberp = dtypep->membersp();
|
||||
while (memberp) {
|
||||
if (memberp->name() == nodep->name()) {
|
||||
memberp->markConstrainedRand(true);
|
||||
break;
|
||||
} else
|
||||
memberp = VN_CAST(memberp->nextp(), MemberDType);
|
||||
}
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
if (editFormat(nodep)) return;
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstSFormatF* const newp
|
||||
= new AstSFormatF{fl, nodep->fromp()->name() + "." + nodep->name(), false, nullptr};
|
||||
AstSFormatF* newp = nullptr;
|
||||
if (VN_AS(nodep->fromp(), SFormatF)->name() == "%@.%@") {
|
||||
newp = new AstSFormatF{fl, "%@.%@." + nodep->name(), false,
|
||||
VN_AS(nodep->fromp(), SFormatF)->exprsp()->cloneTreePure(true)};
|
||||
newp->exprsp()->nextp()->name("%x");
|
||||
} else {
|
||||
newp = new AstSFormatF{fl, nodep->fromp()->name() + "." + nodep->name(), false,
|
||||
nullptr};
|
||||
}
|
||||
m_structSel = false;
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
@@ -885,9 +915,14 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||
|
||||
if (nodep->name() == "at" && nodep->fromp()->user1()) {
|
||||
iterateChildren(nodep);
|
||||
AstNodeExpr* const argsp
|
||||
= AstNode::addNext(nodep->fromp()->unlinkFrBack(), nodep->pinsp()->unlinkFrBack());
|
||||
AstSFormatF* const newp = new AstSFormatF{fl, "(select %@ %@)", false, argsp};
|
||||
AstNodeExpr* pinp = nodep->pinsp()->unlinkFrBack();
|
||||
if (VN_IS(pinp, SFormatF) && m_structSel) VN_AS(pinp, SFormatF)->name("%x");
|
||||
AstNodeExpr* const argsp = AstNode::addNext(nodep->fromp()->unlinkFrBack(), pinp);
|
||||
AstSFormatF* newp = nullptr;
|
||||
if (m_structSel)
|
||||
newp = new AstSFormatF{fl, "%@.%@", false, argsp};
|
||||
else
|
||||
newp = new AstSFormatF{fl, "(select %@ %@)", false, argsp};
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user