diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index d9d32c101..5edb41a03 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1978,6 +1978,8 @@ private: checkNoDot(nodep); AstNode::user5ClearTree(); UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class"); + UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep, + "class reference parameter not removed by V3Param"); VL_RESTORER(m_pinSymp); { // ClassRef's have pins, so track @@ -2902,8 +2904,6 @@ private: "Unsupported: Multiple '::' package/class reference"); } VL_DO_DANGLING(cpackagep->unlinkFrBack()->deleteTree(), cpackagep); - } else if (nodep->paramsp()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages"); } if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 9d8ba6828..3bbb8243f 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -96,8 +96,6 @@ private: virtual void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_classp && !nodep->isParam()) nodep->varType(AstVarType::MEMBER); - if (m_classp && nodep->isParam()) - nodep->v3warn(E_UNSUPPORTED, "Unsupported: class parameter"); if (m_ftaskp) nodep->funcLocal(true); if (nodep->isSigModPublic()) { nodep->sigModPublic(false); // We're done with this attribute diff --git a/src/V3Param.cpp b/src/V3Param.cpp index df9e60c1e..7a99de07f 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -804,13 +804,29 @@ class ParamVisitor final : public AstNVisitor { virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) { UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot + return; } else if (nodep->recursiveClone()) { // Fake, made for recursive elimination UINFO(4, " MOD-recursive-dead. " << nodep << endl); nodep->dead(true); // So Dead checks won't count references to it - } else if (m_modp) { + return; + } + // + if (!nodep->dead() && VN_IS(nodep, Class)) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { + if (varp->isParam()) { + varp->v3warn(E_UNSUPPORTED, "Unsupported: class parameters"); + } + } + } + } + // + if (m_modp) { UINFO(4, " MOD-under-MOD. " << nodep << endl); + iterateChildren(nodep); } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top + || VN_IS(nodep, Class) // Nor moved classes || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet // Add request to END of modules left to process m_todoModps.insert(make_pair(nodep->level(), nodep)); @@ -830,6 +846,14 @@ class ParamVisitor final : public AstNVisitor { m_cellps.push_back(nodep); } + virtual void visit(AstClassRefDType* nodep) override { + if (nodep->paramsp()) { + nodep->paramsp()->v3warn(E_UNSUPPORTED, "Unsupported: parameterized classes"); + pushDeletep(nodep->paramsp()->unlinkFrBackWithNext()); + } + iterateChildren(nodep); + } + // Make sure all parameters are constantified virtual void visit(AstVar* nodep) override { if (nodep->user5SetOnce()) return; // Process once diff --git a/test_regress/t/t_class_param.out b/test_regress/t/t_class_param.out index 53cdad86a..1a041787c 100644 --- a/test_regress/t/t_class_param.out +++ b/test_regress/t/t_class_param.out @@ -1,7 +1,9 @@ -%Error-UNSUPPORTED: t/t_class_param.v:20:4: Unsupported: parameterized packages - 20 | Cls #(.P(4)) c4; - | ^~~ -%Error-UNSUPPORTED: t/t_class_param.v:9:23: Unsupported: class parameter +%Error-UNSUPPORTED: t/t_class_param.v:9:23: Unsupported: class parameters + : ... In instance t 9 | class Cls #(parameter P = 12); | ^ +%Error-UNSUPPORTED: t/t_class_param.v:20:11: Unsupported: parameterized classes + : ... In instance t + 20 | Cls #(.P(4)) c4; + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad.out b/test_regress/t/t_class_param_bad.out index d7a071bf0..20b89cfa7 100644 --- a/test_regress/t/t_class_param_bad.out +++ b/test_regress/t/t_class_param_bad.out @@ -1,17 +1,8 @@ -%Error-UNSUPPORTED: t/t_class_param_bad.v:12:4: Unsupported: parameterized packages - 12 | Cls #(.PARAMBAD(1)) c; - | ^~~ %Error: t/t_class_param_bad.v:12:11: Parameter pin not found: 'PARAMBAD' : ... Suggested alternative: 'PARAMB' 12 | Cls #(.PARAMBAD(1)) c; | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_class_param_bad.v:13:4: Unsupported: parameterized packages - 13 | Cls #(13, 1) cd; - | ^~~ %Error: t/t_class_param_bad.v:13:14: Parameter pin not found: '__paramNumber2' 13 | Cls #(13, 1) cd; | ^ -%Error-UNSUPPORTED: t/t_class_param_bad.v:7:23: Unsupported: class parameter - 7 | class Cls #(parameter PARAMB = 12); - | ^~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_vparam.out b/test_regress/t/t_class_vparam.out index c5a35f922..798dea2ca 100644 --- a/test_regress/t/t_class_vparam.out +++ b/test_regress/t/t_class_vparam.out @@ -1,4 +1,17 @@ -%Error-UNSUPPORTED: t/t_class_vparam.v:13:40: Unsupported: parameterized packages - 13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); - | ^~~~~~~~~~~~~~~ +%Error-UNSUPPORTED: t/t_class_vparam.v:11:26: Unsupported: parameterized classes + : ... In instance t + 11 | typedef paramed_class_t#(real, 1) paramed_class_double_t; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_vparam.v:13:56: Unsupported: class parameters + : ... In instance t + 13 | virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0); + | ^ +%Error-UNSUPPORTED: t/t_class_vparam.v:14:58: Unsupported: parameterized classes + : ... In instance t + 14 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_class_vparam.v:17:46: Unsupported: class parameters + : ... In instance t + 17 | class paramed_class_t #(type TYPE = int, int I = 0); + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_vparam.v b/test_regress/t/t_class_vparam.v index d19d0988e..9f19c609a 100644 --- a/test_regress/t/t_class_vparam.v +++ b/test_regress/t/t_class_vparam.v @@ -8,12 +8,13 @@ typedef class paramed_class_t; typedef class arg_class_t; +typedef paramed_class_t#(real, 1) paramed_class_double_t; -virtual class vclass #(type CTYPE_t = arg_class_t); +virtual class vclass #(type CTYPE_t = arg_class_t, int I = 0); pure virtual function void funcname(paramed_class_t #(CTYPE_t) v); endclass -class paramed_class_t #(type TYPE=int); +class paramed_class_t #(type TYPE = int, int I = 0); endclass class arg_class_t;