From 292c2e289e2161f570c577e467ec83c12bba4543 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Fri, 25 Oct 2024 18:00:43 +0200 Subject: [PATCH] Support `rand` dynamic arrays of objects (#5557) (#5564) --- src/V3Randomize.cpp | 43 +++++++++++++++++++++--------- test_regress/t/t_randomize_array.v | 14 ++++++++++ 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index daf457b88..49ef24aff 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -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}); } }); diff --git a/test_regress/t/t_randomize_array.v b/test_regress/t/t_randomize_array.v index fd6b5f853..63747653c 100755 --- a/test_regress/t/t_randomize_array.v +++ b/test_regress/t/t_randomize_array.v @@ -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