Support rand dynamic arrays of objects (#5557) (#5564)

This commit is contained in:
Ryszard Rozak 2024-10-25 18:00:43 +02:00 committed by GitHub
parent 87ac61140d
commit 292c2e289e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 13 deletions

View File

@ -145,8 +145,14 @@ class RandomizeMarkVisitor final : public VNVisitor {
if (!varp) continue;
// If member is randomizable and of class type, mark its class
if (varp->rand().isRandomizable()) {
if (const AstClassRefDType* const classRefp
= VN_CAST(varp->dtypep()->skipRefp(), ClassRefDType)) {
const AstNodeDType* const varDtypep = varp->dtypep()->skipRefp();
const AstClassRefDType* classRefp = VN_CAST(varDtypep, ClassRefDType);
if (!classRefp) {
const AstNodeDType* subDTypep = varDtypep->subDTypep();
if (subDTypep) subDTypep = subDTypep->skipRefp();
classRefp = VN_CAST(subDTypep, ClassRefDType);
}
if (classRefp) {
AstClass* const rclassp = classRefp->classp();
if (!rclassp->user1()) {
rclassp->user1(IS_RANDOMIZED);
@ -1374,7 +1380,7 @@ class RandomizeVisitor final : public VNVisitor {
return newp;
}
AstNodeStmt* createArrayForeachLoop(FileLine* const fl, AstNodeDType* const dtypep,
AstNodeExpr* exprp) {
AstNodeExpr* exprp, AstVar* const outputVarp) {
V3UniqueNames* uniqueNamep = new V3UniqueNames{"__Vrandarr"};
AstNodeDType* tempDTypep = dtypep;
AstVar* randLoopIndxp = nullptr;
@ -1393,7 +1399,8 @@ class RandomizeVisitor final : public VNVisitor {
auto createForeachLoop = [&](AstNodeExpr* tempElementp, AstVar* randLoopIndxp) {
AstSelLoopVars* const randLoopVarp
= new AstSelLoopVars{fl, exprp->cloneTree(false), randLoopIndxp};
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
return new AstForeach{fl, randLoopVarp,
newRandStmtsp(fl, tempElementp, nullptr, outputVarp)};
};
AstNodeExpr* tempElementp = nullptr;
while (VN_IS(tempDTypep, DynArrayDType) || VN_IS(tempDTypep, UnpackArrayDType)
@ -1426,7 +1433,8 @@ class RandomizeVisitor final : public VNVisitor {
stmtsp = createForeachLoop(tempElementp, randLoopIndxp);
return stmtsp;
}
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp, int offset = 0,
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp,
AstVar* const outputVarp, int offset = 0,
AstMemberDType* memberp = nullptr) {
AstNodeDType* const memberDtp
= memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp();
@ -1438,13 +1446,13 @@ class RandomizeVisitor final : public VNVisitor {
AstNodeStmt* randp = nullptr;
if (structDtp->packed()) {
randp = newRandStmtsp(fl, stmtsp ? exprp->cloneTree(false) : exprp, nullptr,
offset, smemberp);
outputVarp, offset, smemberp);
} else {
AstStructSel* structSelp
= new AstStructSel{fl, exprp->cloneTree(false), smemberp->name()};
structSelp->dtypep(smemberp->childDTypep());
if (!structSelp->dtypep()) structSelp->dtypep(smemberp->subDTypep());
randp = newRandStmtsp(fl, structSelp, nullptr);
randp = newRandStmtsp(fl, structSelp, nullptr, outputVarp);
}
stmtsp = stmtsp ? stmtsp->addNext(randp) : randp;
}
@ -1456,16 +1464,25 @@ class RandomizeVisitor final : public VNVisitor {
return nullptr;
}
AstMemberDType* const firstMemberp = unionDtp->membersp();
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
return newRandStmtsp(fl, exprp, nullptr, outputVarp, offset, firstMemberp);
} else if (const AstClassRefDType* const classRefDtp = VN_CAST(memberDtp, ClassRefDType)) {
AstFunc* const memberFuncp
= V3Randomize::newRandomizeFunc(m_memberMap, classRefDtp->classp());
AstMethodCall* const callp = new AstMethodCall{fl, exprp, "randomize", nullptr};
callp->taskp(memberFuncp);
callp->dtypeFrom(memberFuncp);
return new AstAssign{
fl, new AstVarRef{fl, outputVarp, VAccess::WRITE},
new AstAnd{fl, new AstVarRef{fl, outputVarp, VAccess::READ}, callp}};
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
return createArrayForeachLoop(fl, dynarrayDtp, exprp, outputVarp);
} else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) {
return createArrayForeachLoop(fl, queueDtp, exprp);
return createArrayForeachLoop(fl, queueDtp, exprp, outputVarp);
} else if (AstUnpackArrayDType* const unpackarrayDtp
= VN_CAST(memberDtp, UnpackArrayDType)) {
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
return createArrayForeachLoop(fl, unpackarrayDtp, exprp, outputVarp);
} else if (AstAssocArrayDType* const assocarrayDtp = VN_CAST(memberDtp, AssocArrayDType)) {
return createArrayForeachLoop(fl, assocarrayDtp, exprp);
return createArrayForeachLoop(fl, assocarrayDtp, exprp, outputVarp);
} else {
AstNodeExpr* valp;
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
@ -1671,7 +1688,7 @@ class RandomizeVisitor final : public VNVisitor {
} else {
AstVar* const randcVarp = newRandcVarsp(memberVarp);
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp, basicFvarp);
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
}
});

View File

@ -63,10 +63,15 @@ class unconstrained_unpacked_array_test;
endclass
class Cls;
rand int x = 1;
endclass
class unconstrained_dynamic_array_test;
rand int dynamic_array_1d[];
rand int dynamic_array_2d[][];
rand Cls class_dynamic_array[];
function new();
// Initialize 1D dynamic array
@ -83,6 +88,12 @@ class unconstrained_dynamic_array_test;
dynamic_array_2d[i][j] = 'h0 + i + j;
end
end
class_dynamic_array = new[5];
foreach(class_dynamic_array[i]) begin
class_dynamic_array[i] = new;
end
endfunction
function void check_randomization();
@ -94,6 +105,9 @@ class unconstrained_dynamic_array_test;
`check_rand(this, dynamic_array_2d[i][j])
end
end
foreach (class_dynamic_array[i]) begin
`check_rand(this, class_dynamic_array[i].x)
end
endfunction
endclass