diff --git a/src/V3WidthCommit.cpp b/src/V3WidthCommit.cpp index 53031bf2c..ccf3d80cd 100644 --- a/src/V3WidthCommit.cpp +++ b/src/V3WidthCommit.cpp @@ -43,6 +43,8 @@ class WidthCommitVisitor final : public VNVisitor { // STATE AstNodeModule* m_modp = nullptr; std::string m_contNba; // In continuous- or non-blocking assignment + bool m_dynsizedelem + = false; // Writing a dynamically-sized array element, not the array itself VMemberMap m_memberMap; // Member names cached for fast lookup bool m_underSel = false; // Whether is currently under AstMemberSel or AstSel @@ -138,7 +140,7 @@ private: else if (varp->isClassMember() && !varp->lifetime().isStatic() && !VN_IS(varDtp, IfaceRefDType)) varType = "Class non-static"; - else if (varDtp->isDynamicallySized()) + else if (varDtp->isDynamicallySized() && m_dynsizedelem) varType = "Dynamically-sized"; if (!varType.empty()) { UINFO(1, " Related var dtype: " << varDtp); @@ -395,6 +397,20 @@ private: // This check could go anywhere after V3Param nodep->v3fatalSrc("Presels should have been removed before this point"); } + void visit(AstCMethodHard* nodep) override { + VL_RESTORER(m_dynsizedelem); + if (nodep->name() == "atWrite" || nodep->name() == "atWriteAppend" + || nodep->name() == "at") + m_dynsizedelem = true; + iterateChildren(nodep); + editDType(nodep); + } + void visit(AstAssocSel* nodep) override { + VL_RESTORER(m_dynsizedelem); + m_dynsizedelem = true; + iterateChildren(nodep); + editDType(nodep); + } void visit(AstSel* nodep) override { { VL_RESTORER(m_underSel); diff --git a/test_regress/t/t_assign_automatic_bad.out b/test_regress/t/t_assign_automatic_bad.out index 6fb3bcec9..45e0790c1 100644 --- a/test_regress/t/t_assign_automatic_bad.out +++ b/test_regress/t/t_assign_automatic_bad.out @@ -1,26 +1,42 @@ -%Error: t/t_assign_automatic_bad.v:31:10: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_auto3' +%Error: t/t_assign_automatic_bad.v:37:10: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_auto3' : ... note: In instance 't' - 31 | assign bad_auto3 = 2; + 37 | assign bad_auto3 = 2; | ^~~~~~~~~ ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. -%Error: t/t_assign_automatic_bad.v:32:10: Dynamically-sized variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_dyn5' +%Error: t/t_assign_automatic_bad.v:38:10: Dynamically-sized variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'bad_dyn5' : ... note: In instance 't' - 32 | assign bad_dyn5 = empty_dyn; + 38 | assign bad_dyn5[0] = empty_dyn; | ^~~~~~~~ -%Error: t/t_assign_automatic_bad.v:33:12: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'm_bad1' +%Error: t/t_assign_automatic_bad.v:40:12: Automatic lifetime variable not allowed in continuous assignment (IEEE 1800-2023 6.21): 'm_bad1' : ... note: In instance 't' - 33 | assign c.m_bad1 = 2; + 40 | assign c.m_bad1 = 2; | ^~~~~~ -%Error: t/t_assign_automatic_bad.v:43:5: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_auto4' +%Error: t/t_assign_automatic_bad.v:50:5: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_auto4' : ... note: In instance 't' - 43 | bad_auto4 <= 2; + 50 | bad_auto4 <= 2; | ^~~~~~~~~ -%Error: t/t_assign_automatic_bad.v:44:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_dyn6' +%Error: t/t_assign_automatic_bad.v:51:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_dyn6' : ... note: In instance 't' - 44 | bad_dyn6 <= empty_dyn; + 51 | bad_dyn6[0] <= 2; | ^~~~~~~~ -%Error: t/t_assign_automatic_bad.v:46:7: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'm_bad2' +%Error: t/t_assign_automatic_bad.v:53:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_queue' : ... note: In instance 't' - 46 | c.m_bad2 <= 2; + 53 | bad_queue[0] <= 2; + | ^~~~~~~~~ +%Error: t/t_assign_automatic_bad.v:55:5: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'bad_assoc' + : ... note: In instance 't' + 55 | bad_assoc[0] <= 2; + | ^~~~~~~~~ +%Error: t/t_assign_automatic_bad.v:58:7: Automatic lifetime variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 'm_bad2' + : ... note: In instance 't' + 58 | c.m_bad2 <= 2; | ^~~~~~ +%Error: t/t_assign_automatic_bad.v:60:10: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 's_dyn' + : ... note: In instance 't' + 60 | Cls::s_dyn[0] <= 2; + | ^~~~~ +%Error: t/t_assign_automatic_bad.v:62:26: Dynamically-sized variable not allowed in nonblocking assignment (IEEE 1800-2023 6.21): 's_dyn' + : ... note: In instance 't' + 62 | clist[bad_dyn6[0]++].s_dyn[0] <= '1; + | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_assign_automatic_bad.v b/test_regress/t/t_assign_automatic_bad.v index 98905ca97..b6e233b5f 100644 --- a/test_regress/t/t_assign_automatic_bad.v +++ b/test_regress/t/t_assign_automatic_bad.v @@ -13,6 +13,7 @@ class Cls; static int s_ok1; static int s_ok2; + static int s_dyn[]; int m_bad1; int m_bad2; endclass @@ -27,9 +28,15 @@ module t(clk); int bad_dyn5[]; int bad_dyn6[]; int empty_dyn[]; + int empty_queue[$]; + int empty_assoc[int]; + int bad_queue[$]; + int bad_assoc[int]; + Cls clist[1]; assign bad_auto3 = 2; // <--- Error: continuous automatic - assign bad_dyn5 = empty_dyn; // <--- Error: continuous dynarray + assign bad_dyn5[0] = empty_dyn; // <--- Error: continuous dynarray element + assign bad_dyn5 = empty_dyn; // <--- OK: continuous dynarray assignment, not to its element assign c.m_bad1 = 2; // <--- Error: continuous class non-static // Only one simulator fails on this, probably not legal // assign Cls::s_ok1 = 2; // OK: continuous class static @@ -41,9 +48,18 @@ module t(clk); always @(posedge clk) begin bad_auto4 <= 2; // <--- Error: nonblocking automatic - bad_dyn6 <= empty_dyn; // <--- Error: nonblocking dynarray + bad_dyn6[0] <= 2; // <--- Error: nonblocking dynarray element + bad_dyn6 <= empty_dyn; // <--- OK: nonblocking dynarray assignment, not to its element + bad_queue[0] <= 2; // Error: nonblocking queue element assignment + bad_queue <= empty_queue; // OK: nonblocking assignment to queue itself, not to its element + bad_assoc[0] <= 2; // Error: nonblocking associative array element assignment + bad_assoc <= empty_assoc; // OK: nonblocking assignment to associative array itself, not to its element Cls::s_ok2 <= 2; // OK: nonblocking class static c.m_bad2 <= 2; // <--- Error: nonblocking class automatic + Cls::s_dyn <= 2; // OK: nonblocking class static dynarray assignment, not to its element + Cls::s_dyn[0] <= 2; // Error: nonblocking class static dynarray element + clist[bad_dyn6[0]++].s_dyn <= '1; // OK: direct nonblocking assignment to dynamically-sized array + clist[bad_dyn6[0]++].s_dyn[0] <= '1; // Error: nonblocking assigment to dynamically-sized array element mt(ok_7); $stop; end