diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 1f4757e89..6c3885ff1 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -161,6 +161,7 @@ private: bool m_forPrimary; // First link bool m_forPrearray; // Compress cell__[array] refs bool m_forScopeCreation; // Remove VarXRefs for V3Scope + bool m_removeVoidParamedClasses; // Remove classes with void params public: // METHODS @@ -207,6 +208,7 @@ public: m_forPrimary = (step == LDS_PRIMARY); m_forPrearray = (step == LDS_PARAMED || step == LDS_PRIMARY); m_forScopeCreation = (step == LDS_SCOPED); + m_removeVoidParamedClasses = (step == LDS_PARAMED); s_errorThisp = this; V3Error::errorExitCb(preErrorDumpHandler); // If get error, dump self } @@ -220,6 +222,7 @@ public: bool forPrimary() const { return m_forPrimary; } bool forPrearray() const { return m_forPrearray; } bool forScopeCreation() const { return m_forScopeCreation; } + bool removeVoidParamedClasses() const { return m_removeVoidParamedClasses; } // METHODS static string nodeTextType(AstNode* nodep) { @@ -902,6 +905,18 @@ class LinkDotFindVisitor final : public VNVisitor { void visit(AstClass* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit"); UINFO(8, " " << nodep << endl); + // Remove classes that have void params, as they were only used for the parametrization + // step and will not be instantiated + if (m_statep->removeVoidParamedClasses()) { + for (auto* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (auto* dtypep = VN_CAST(stmtp, ParamTypeDType)) { + if (VN_IS(dtypep->subDTypep(), VoidDType)) { + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; + } + } + } + } VL_RESTORER(m_scope); VL_RESTORER(m_classOrPackagep); VL_RESTORER(m_modSymp); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 32e656dc4..7dd81fb2a 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -209,18 +209,16 @@ private: } if (VN_IS(nodep->subDTypep(), ParseTypeDType)) { // It's a parameter type. Use a different node type for this. - AstNodeDType* const dtypep = VN_CAST(nodep->valuep(), NodeDType); - if (!dtypep) { - nodep->v3error( - "Parameter type's initial value isn't a type: " << nodep->prettyNameQ()); - nodep->unlinkFrBack(); - } else { + AstNodeDType* dtypep = VN_CAST(nodep->valuep(), NodeDType); + if (dtypep) { dtypep->unlinkFrBack(); - AstNode* const newp = new AstParamTypeDType( - nodep->fileline(), nodep->varType(), nodep->name(), VFlagChildDType(), dtypep); - nodep->replaceWith(newp); - VL_DO_DANGLING(nodep->deleteTree(), nodep); + } else { + dtypep = new AstVoidDType{nodep->fileline()}; } + AstNode* const newp = new AstParamTypeDType{nodep->fileline(), nodep->varType(), + nodep->name(), VFlagChildDType{}, dtypep}; + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); return; } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3ff5e8b56..baef76ddf 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -801,6 +801,15 @@ class ParamProcessor final { srcModpr = modInfop->m_modp; } + for (auto* stmtp = srcModpr->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (auto* dtypep = VN_CAST(stmtp, ParamTypeDType)) { + if (VN_IS(dtypep->subDTypep(), VoidDType)) { + nodep->v3error("Missing type parameter: " << dtypep->prettyNameQ()); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + } + } + } + // Delete the parameters from the cell; they're not relevant any longer. if (paramsp) paramsp->unlinkFrBackWithNext()->deleteTree(); return any_overrides; @@ -822,8 +831,11 @@ class ParamProcessor final { } void classRefDeparam(AstClassRefDType* nodep, AstNodeModule*& srcModpr) { - if (nodeDeparamCommon(nodep, srcModpr, nodep->paramsp(), nullptr, false)) - nodep->classp(VN_AS(srcModpr, Class)); + if (nodeDeparamCommon(nodep, srcModpr, nodep->paramsp(), nullptr, false)) { + AstClass* const classp = VN_AS(srcModpr, Class); + nodep->classp(classp); + nodep->classOrPackagep(classp); + } } public: diff --git a/src/verilog.y b/src/verilog.y index 86f8edc58..f366c5b61 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2882,7 +2882,9 @@ list_of_param_assignments: // ==IEEE: list_of_param_assignments type_assignment: // ==IEEE: type_assignment // // note exptOrDataType being a data_type is only for yPARAMETER yTYPE - idAny/*new-parameter*/ sigAttrListE '=' data_type + idAny/*new-parameter*/ sigAttrListE + { $$ = VARDONEA($1, *$1, nullptr, $2); } + | idAny/*new-parameter*/ sigAttrListE '=' data_type { $$ = VARDONEA($1, *$1, nullptr, $2); $$->valuep($4); } ; diff --git a/test_regress/t/t_class_param_bad.out b/test_regress/t/t_class_param_bad.out deleted file mode 100644 index ef96bc2f3..000000000 --- a/test_regress/t/t_class_param_bad.out +++ /dev/null @@ -1,9 +0,0 @@ -%Error-PINNOTFOUND: t/t_class_param_bad.v:12:11: Parameter pin not found: 'PARAMBAD' - : ... Suggested alternative: 'PARAMB' - 12 | Cls #(.PARAMBAD(1)) c; - | ^~~~~~~~ - ... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest -%Error-PINNOTFOUND: t/t_class_param_bad.v:13:14: Parameter pin not found: '__paramNumber2' - 13 | Cls #(13, 1) cd; - | ^ -%Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad1.out b/test_regress/t/t_class_param_bad1.out new file mode 100644 index 000000000..756f6e838 --- /dev/null +++ b/test_regress/t/t_class_param_bad1.out @@ -0,0 +1,9 @@ +%Error-PINNOTFOUND: t/t_class_param_bad1.v:12:11: Parameter pin not found: 'PARAMBAD' + : ... Suggested alternative: 'PARAMB' + 12 | Cls #(.PARAMBAD(1)) c; + | ^~~~~~~~ + ... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest +%Error-PINNOTFOUND: t/t_class_param_bad1.v:13:14: Parameter pin not found: '__paramNumber2' + 13 | Cls #(13, 1) cd; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad.pl b/test_regress/t/t_class_param_bad1.pl similarity index 100% rename from test_regress/t/t_class_param_bad.pl rename to test_regress/t/t_class_param_bad1.pl diff --git a/test_regress/t/t_class_param_bad.v b/test_regress/t/t_class_param_bad1.v similarity index 100% rename from test_regress/t/t_class_param_bad.v rename to test_regress/t/t_class_param_bad1.v diff --git a/test_regress/t/t_class_param_bad2.out b/test_regress/t/t_class_param_bad2.out new file mode 100644 index 000000000..35b901184 --- /dev/null +++ b/test_regress/t/t_class_param_bad2.out @@ -0,0 +1,5 @@ +%Error: t/t_class_param_bad2.v:12:4: Missing type parameter: 'PARAMB' + : ... In instance t + 12 | Cls c; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_param_bad2.pl b/test_regress/t/t_class_param_bad2.pl new file mode 100755 index 000000000..19ba90d40 --- /dev/null +++ b/test_regress/t/t_class_param_bad2.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_param_bad2.v b/test_regress/t/t_class_param_bad2.v new file mode 100644 index 000000000..9332fdde8 --- /dev/null +++ b/test_regress/t/t_class_param_bad2.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +class Cls #(type PARAMB); +endclass + +module t (/*AUTOARG*/); + + Cls c; // Missing type param + +endmodule diff --git a/test_regress/t/t_class_vparam.v b/test_regress/t/t_class_vparam.v index 660dbb5fa..6d927d6ac 100644 --- a/test_regress/t/t_class_vparam.v +++ b/test_regress/t/t_class_vparam.v @@ -14,7 +14,7 @@ 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, int I = 0); +class paramed_class_t #(type TYPE, int I = 0); TYPE memb; endclass