diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index d5a987152..e3fe9941d 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -64,23 +64,29 @@ struct RandModeTarget final { return RandModeTarget::get(methodHardp->fromp(), modp); } AstVar* receiverp = nullptr; + AstClass* classp = VN_CAST(modp, Class); if (AstVarRef* const varrefp = VN_CAST(fromp, VarRef)) { receiverp = varrefp->varp(); + if (receiverp->isRand()) { + fromp = nullptr; + if (receiverp->lifetime().isStatic()) { + classp = VN_AS(varrefp->classOrPackagep(), Class); + } + } } else if (AstMemberSel* const memberSelp = VN_CAST(fromp, MemberSel)) { receiverp = memberSelp->varp(); + if (receiverp->isRand()) { + fromp = memberSelp->fromp(); + classp = VN_AS(fromp->dtypep()->skipRefp(), ClassRefDType)->classp(); + } } UASSERT_OBJ(receiverp, fromp, "Unknown rand_mode() receiver"); - if (receiverp->isRand()) { - if (AstMemberSel* const memberselp = VN_CAST(fromp, MemberSel)) { - return {receiverp, memberselp->fromp(), - VN_AS(memberselp->fromp()->dtypep()->skipRefp(), ClassRefDType)->classp()}; - } - } else { + if (!receiverp->isRand()) { AstClassRefDType* const classRefDtp = VN_CAST(receiverp->dtypep()->skipRefp(), ClassRefDType); - if (classRefDtp) return {receiverp, fromp, classRefDtp->classp()}; + if (classRefDtp) classp = classRefDtp->classp(); } - return {receiverp, nullptr, VN_AS(modp, Class)}; + return {receiverp, fromp, classp}; } }; @@ -192,6 +198,10 @@ class RandomizeMarkVisitor final : public VNVisitor { nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'rand_mode()' on unpacked array element"); valid = false; + } else if (VN_IS(fromp, StructSel)) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: 'rand_mode()' on unpacked struct element"); + valid = false; } else if (VN_IS(fromp, Sel)) { nodep->v3error("Cannot call 'rand_mode()' on packed array element"); valid = false; @@ -223,6 +233,11 @@ class RandomizeMarkVisitor final : public VNVisitor { } else if (nodep->pinsp() && !VN_IS(nodep->backp(), StmtExpr)) { nodep->v3error("'rand_mode()' with arguments cannot be called as a function"); valid = false; + } else if (randModeTarget.receiverp + && randModeTarget.receiverp->lifetime().isStatic() + && randModeTarget.receiverp->isRand()) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'rand_mode()' on static variable"); + valid = false; } else if (randModeTarget.receiverp && randModeTarget.receiverp->isRand()) { // Called on a rand member variable VarRandMode randMode = {}; @@ -232,6 +247,11 @@ class RandomizeMarkVisitor final : public VNVisitor { // Called on 'this' or a non-rand class instance randModeTarget.classp->foreachMember([&](AstClass*, AstVar* varp) { if (!varp->isRand()) return; + if (varp->lifetime().isStatic()) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: 'rand_mode()' on static variable: " + << varp->prettyNameQ()); + } VarRandMode randMode = {}; randMode.usesRandMode = true; varp->user1(randMode.asInt); diff --git a/test_regress/t/t_randomize_rand_mode_unsup.out b/test_regress/t/t_randomize_rand_mode_unsup.out index c76afbc78..7c5186142 100644 --- a/test_regress/t/t_randomize_rand_mode_unsup.out +++ b/test_regress/t/t_randomize_rand_mode_unsup.out @@ -1,10 +1,26 @@ -%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:15:22: Unsupported: 'rand_mode()' on dynamic array element +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:17:22: Unsupported: 'rand_mode()' on dynamic array element : ... note: In instance 't' - 15 | p.m_dyn_arr[0].rand_mode(0); + 17 | p.m_dyn_arr[0].rand_mode(0); | ^~~~~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:16:22: Unsupported: 'rand_mode()' on unpacked array element +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:18:22: Unsupported: 'rand_mode()' on unpacked array element : ... note: In instance 't' - 16 | p.m_unp_arr[0].rand_mode(0); + 18 | p.m_unp_arr[0].rand_mode(0); | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:19:20: Unsupported: 'rand_mode()' on unpacked struct element + : ... note: In instance 't' + 19 | p.m_struct.y.rand_mode(0); + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:20:18: Unsupported: 'rand_mode()' on static variable + : ... note: In instance 't' + 20 | p.m_static.rand_mode(0); + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:21:57: Unsupported: 'rand_mode()' on static variable + : ... note: In instance 't' + 21 | $display("p.m_static.rand_mode()=%0d", p.m_static.rand_mode()); + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_randomize_rand_mode_unsup.v:22:9: Unsupported: 'rand_mode()' on static variable: 'm_static' + : ... note: In instance 't' + 22 | p.rand_mode(0); + | ^~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_randomize_rand_mode_unsup.v b/test_regress/t/t_randomize_rand_mode_unsup.v index 8b72243f8..4132667fe 100644 --- a/test_regress/t/t_randomize_rand_mode_unsup.v +++ b/test_regress/t/t_randomize_rand_mode_unsup.v @@ -7,6 +7,8 @@ class Packet; rand int m_dyn_arr[]; rand int m_unp_arr[10]; + rand struct { int y; } m_struct; + static rand int m_static; endclass module t; @@ -14,5 +16,9 @@ module t; Packet p = new; p.m_dyn_arr[0].rand_mode(0); p.m_unp_arr[0].rand_mode(0); + p.m_struct.y.rand_mode(0); + p.m_static.rand_mode(0); + $display("p.m_static.rand_mode()=%0d", p.m_static.rand_mode()); + p.rand_mode(0); end endmodule