diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 59216ff2a..2d7b74596 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -799,19 +799,24 @@ public: VTimescale timeunit() const { return m_timeunit; } }; class AstClassExtends final : public AstNode { + // class extends class name, or class implements class name // Children: List of AstParseRef for packages/classes // during early parse, then moves to dtype // @astgen op1 := childDTypep : Optional[AstNodeDType] // @astgen op2 := classOrPkgsp : Optional[AstNode] + const bool m_isImplements = false; // class implements public: - AstClassExtends(FileLine* fl, AstNode* classOrPkgsp) - : ASTGEN_SUPER_ClassExtends(fl) { + AstClassExtends(FileLine* fl, AstNode* classOrPkgsp, bool isImplements) + : ASTGEN_SUPER_ClassExtends(fl) + , m_isImplements{isImplements} { this->classOrPkgsp(classOrPkgsp); // Only for parser } ASTGEN_MEMBERS_AstClassExtends; + void dump(std::ostream& str) const override; bool hasDType() const override { return true; } - string verilogKwd() const override { return "extends"; } + string verilogKwd() const override { return isImplements() ? "implements" : "extends"; } AstClass* classp() const; // Class being extended (after link) + bool isImplements() const { return m_isImplements; } }; class AstClocking final : public AstNode { // Parents: MODULE @@ -2094,14 +2099,15 @@ public: // === AstNodeModule === class AstClass final : public AstNodeModule { - // @astgen op4 := extendsp : Optional[AstClassExtends] + // @astgen op4 := extendsp : List[AstClassExtends] // TYPES using MemberNameMap = std::map; // MEMBERS MemberNameMap m_members; // Members or method children AstClassPackage* m_classOrPackagep = nullptr; // Class package this is under - bool m_virtual = false; // Virtual class bool m_extended = false; // Is extension or extended by other classes + bool m_interfaceClass = false; // Interface class + bool m_virtual = false; // Virtual class void insertCache(AstNode* nodep); public: @@ -2129,6 +2135,8 @@ public: } bool isExtended() const { return m_extended; } void isExtended(bool flag) { m_extended = flag; } + bool isInterfaceClass() const { return m_interfaceClass; } + void isInterfaceClass(bool flag) { m_interfaceClass = flag; } bool isVirtual() const { return m_virtual; } void isVirtual(bool flag) { m_virtual = flag; } // Return true if this class is an extension of base class (SLOW) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 8cfc76cb7..cf76a1687 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1458,6 +1458,7 @@ bool AstClass::isClassExtendedFrom(const AstClass* refClassp, const AstClass* ba void AstClass::dump(std::ostream& str) const { this->AstNodeModule::dump(str); if (isExtended()) str << " [EXT]"; + if (isInterfaceClass()) str << " [IFCCLS]"; if (isVirtual()) str << " [VIRT]"; } const char* AstClass::broken() const { @@ -1471,6 +1472,10 @@ void AstClass::cloneRelink() { m_classOrPackagep = m_classOrPackagep->clonep(); } } +void AstClassExtends::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (isImplements()) str << " [IMPLEMENTS]"; +} AstClass* AstClassExtends::classp() const { const AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType); if (VL_UNLIKELY(!refp)) { // LinkDot uses this for 'super.' diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index eb0522b63..f290817d0 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -748,6 +748,7 @@ class LinkDotFindVisitor final : public VNVisitor { string m_scope; // Scope text const AstNodeBlock* m_blockp = nullptr; // Current Begin/end block const AstNodeFTask* m_ftaskp = nullptr; // Current function/task + bool m_inInterfaceClass = false; // Inside a class interface bool m_inRecursion = false; // Inside a recursive module int m_paramNum = 0; // Parameter number, for position based connection bool m_explicitNew = false; // Hit a "new" function @@ -916,6 +917,9 @@ 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); + if (nodep->isInterfaceClass()) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: interface classes"); + } // Remove classes that have void params, as they were only used for the parameterization // step and will not be instantiated if (m_statep->removeVoidParamedClasses()) { @@ -930,6 +934,7 @@ class LinkDotFindVisitor final : public VNVisitor { } VL_RESTORER(m_scope); VL_RESTORER(m_classOrPackagep); + VL_RESTORER(m_inInterfaceClass); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); VL_RESTORER(m_paramNum); @@ -940,6 +945,7 @@ class LinkDotFindVisitor final : public VNVisitor { VSymEnt* const upperSymp = m_curSymp; m_scope = m_scope + "." + nodep->name(); m_classOrPackagep = nodep; + m_inInterfaceClass = nodep->isInterfaceClass(); m_curSymp = m_modSymp = m_statep->insertBlock(upperSymp, nodep->name(), nodep, m_classOrPackagep); m_statep->insertMap(m_curSymp, m_scope); @@ -1068,6 +1074,10 @@ class LinkDotFindVisitor final : public VNVisitor { VL_RESTORER(m_curSymp); VSymEnt* upSymp = m_curSymp; { + if (m_inInterfaceClass && !nodep->pureVirtual()) { + nodep->v3error("Interface class functions must be pure virtual" + << " (IEEE 1800-2017 8.26)"); + } // Change to appropriate package if extern declaration (vs definition) if (nodep->classOrPackagep()) { AstClassOrPackageRef* const cpackagerefp @@ -1190,6 +1200,11 @@ class LinkDotFindVisitor final : public VNVisitor { // Var: Remember its name for later resolution UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?"); iterateChildren(nodep); + if (m_inInterfaceClass && !nodep->isParam() && !nodep->isFuncLocal() + && !nodep->isFuncReturn()) { + nodep->v3error("Interface class cannot contain non-parameter members" + << " (IEEE 1800-2017 8.26)"); + } if (!m_statep->forScopeCreation()) { // Find under either a task or the module's vars const VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); @@ -3226,6 +3241,16 @@ private: if (classp == nodep) { cextp->v3error("Attempting to extend class " << nodep->prettyNameQ() << " from itself"); + } else if (cextp->isImplements() && !classp->isInterfaceClass()) { + cextp->v3error( + "Attempting to implement from non-interface class " + << classp->prettyNameQ() << '\n' + << "... Suggest use 'extends'"); + } else if (!cextp->isImplements() && !nodep->isInterfaceClass() + && classp->isInterfaceClass()) { + cextp->v3error("Attempting to extend from interface class " + << classp->prettyNameQ() << '\n' + << "... Suggest use 'implements'"); } else { cextp->childDTypep(classRefDtypep); classp->isExtended(true); @@ -3240,8 +3265,9 @@ private: const string suggest = m_statep->suggestSymFallback( m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{}); cpackagerefp->v3error( - "Class to extend not found: " - << cpackagerefp->prettyNameQ() << '\n' + "Class for '" + << cextp->verilogKwd() // extends/implements + << "' not found: " << cpackagerefp->prettyNameQ() << '\n' << (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest)); } } diff --git a/src/verilog.y b/src/verilog.y index f544e31cf..1520945b6 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -94,6 +94,7 @@ public: bool m_varDeclTyped = false; // Var got reg/wire for dedup check bool m_pinAnsi = false; // In ANSI port list bool m_tracingParse = true; // Tracing disable for parser + bool m_inImplements = false; // Is inside class implements list bool m_insideProperty = false; // Is inside property declaration bool m_typedPropertyPort = false; // True if typed property port occurred on port lists bool m_modportImpExpActive @@ -6466,8 +6467,8 @@ class_declaration: // ==IEEE: part of class_declaration } /*cont*/ class_itemListE yENDCLASS endLabelE { $$ = $1; $1->addMembersp($2); - $1->extendsp($3); - $1->addMembersp($4); + $1->addExtendsp($3); + $1->addExtendsp($4); $1->addMembersp($7); SYMP->popScope($$); GRAMMARP->endLabel($7, $1, $9); } @@ -6483,9 +6484,10 @@ classFront: // IEEE: part of class_declaration // // IEEE: part of interface_class_declaration | yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/ { $$ = new AstClass{$2, *$4}; + $$->isInterfaceClass(true); $$->lifetime($3); SYMP->pushNew($$); - BBUNSUP($2, "Unsupported: interface classes"); } + v3Global.setHasClasses(); } ; classVirtualE: @@ -6510,25 +6512,30 @@ classExtendsList: // IEEE: part of class_declaration classExtendsOne: // IEEE: part of class_declaration class_typeExtImpList - { $$ = new AstClassExtends{$1->fileline(), $1}; + { $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; $$ = $1; } // | class_typeExtImpList '(' list_of_argumentsE ')' - { $$ = new AstClassExtends{$1->fileline(), $1}; + { $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; $$ = $1; if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); } ; -classImplementsE: // IEEE: part of class_declaration +classImplementsE: // IEEE: part of class_declaration // // All 1800-2012 - /* empty */ { $$ = nullptr; } - | yIMPLEMENTS classImplementsList { $$ = $2; } + /* empty */ { $$ = nullptr; $$ = nullptr; } + | yIMPLEMENTS + /*mid*/ { GRAMMARP->m_inImplements = true; $$ = nullptr; } + /*cont*/ classImplementsList + { $$ = $3; $$ = $3; + GRAMMARP->m_inImplements = false; } ; -classImplementsList: // IEEE: part of class_declaration +classImplementsList: // IEEE: part of class_declaration // // All 1800-2012 - class_typeExtImpList { $$ = nullptr; BBUNSUP($1, "Unsupported: implements class"); } - | classImplementsList ',' class_typeExtImpList { $$ = addNextNull($1, $3); } + classExtendsOne { $$ = $1; $$ = $1; } + | classImplementsList ',' classExtendsOne + { $$ = addNextNull($1, $3); $$ = $3; } ; class_typeExtImpList: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]" diff --git a/test_regress/t/t_class_extends_nf_bad.out b/test_regress/t/t_class_extends_nf_bad.out index 62fc4e306..d01cc3eea 100644 --- a/test_regress/t/t_class_extends_nf_bad.out +++ b/test_regress/t/t_class_extends_nf_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_class_extends_nf_bad.v:10:19: Class to extend not found: 'IsNotFound' +%Error: t/t_class_extends_nf_bad.v:10:19: Class for 'extends' not found: 'IsNotFound' : ... Suggested alternative: 'IsFound' 10 | class Cls extends IsNotFound; | ^~~~~~~~~~ diff --git a/test_regress/t/t_implements.out b/test_regress/t/t_implements.out new file mode 100644 index 000000000..ee4b56b13 --- /dev/null +++ b/test_regress/t/t_implements.out @@ -0,0 +1,14 @@ +%Error-UNSUPPORTED: t/t_implements.v:7:11: Unsupported: interface classes + 7 | interface class Icempty; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_implements.v:10:11: Unsupported: interface classes + 10 | interface class Icls1; + | ^~~~~ +%Error-UNSUPPORTED: t/t_implements.v:17:11: Unsupported: interface classes + 17 | interface class Iext1 extends Icls1; + | ^~~~~ +%Error-UNSUPPORTED: t/t_implements.v:21:11: Unsupported: interface classes + 21 | interface class Icls2; + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_implements.pl b/test_regress/t/t_implements.pl new file mode 100755 index 000000000..40f69d41d --- /dev/null +++ b/test_regress/t/t_implements.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. 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(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +execute( + check_finished => 1, + ) if !$Self->{vlt_all}; + +ok(1); +1; diff --git a/test_regress/t/t_implements.v b/test_regress/t/t_implements.v new file mode 100644 index 000000000..11e2080a7 --- /dev/null +++ b/test_regress/t/t_implements.v @@ -0,0 +1,70 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icempty; +endclass : Icempty + +interface class Icls1; + localparam LP1 = 1; + pure virtual function int icf1; + pure virtual function int icfboth; + pure virtual function int icfpartial; +endclass + +interface class Iext1 extends Icls1; + pure virtual function int icf101; +endclass + +interface class Icls2; + pure virtual function int icf2; + pure virtual function int icfboth; +endclass + + virtual class Base implements Iext1, Icls2; + virtual function int icf1; + return 1; + endfunction + virtual function int icf101; + return 101; + endfunction + virtual function int icf2; + return 2; + endfunction + virtual function int icfboth; + return 3; + endfunction + pure virtual function int icfpartial; + endclass + +class Cls extends Base; + virtual function int icfpartial; + return 62; + endfunction +endclass + +module t(/*AUTOARG*/); + + Cls c; + Iext1 i1; + + initial begin + if (Icls1::LP1 != 1) $stop; + + c = new; + if (c.icf1() != 1) $stop; + if (c.icf101() != 101) $stop; + if (c.icf2() != 2) $stop; + if (c.icfpartial() != 62) $stop; + + i1 = c; + if (i1.icf1() != 1) $stop; + if (i1.icf101() != 101) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_implements_collision.out b/test_regress/t/t_implements_collision.out new file mode 100644 index 000000000..2f499d637 --- /dev/null +++ b/test_regress/t/t_implements_collision.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_collision.v:15:41: Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), and unsupported for interface classes. + 15 | interface class IclsBoth extends Icls1, Icls2; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_collision.pl b/test_regress/t/t_implements_collision.pl new file mode 100755 index 000000000..40f69d41d --- /dev/null +++ b/test_regress/t/t_implements_collision.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. 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(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +execute( + check_finished => 1, + ) if !$Self->{vlt_all}; + +ok(1); +1; diff --git a/test_regress/t/t_implements_collision.v b/test_regress/t/t_implements_collision.v new file mode 100644 index 000000000..12ce71a8f --- /dev/null +++ b/test_regress/t/t_implements_collision.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls1; + pure virtual function int icfboth; +endclass + +interface class Icls2; + pure virtual function int icfboth; +endclass + +interface class IclsBoth extends Icls1, Icls2; + pure virtual function int icfboth; +endclass + +class Cls implements IclsBoth; + virtual function int icfboth; + return 3; + endfunction +endclass + +module t(/*AUTOARG*/); + + Cls c; + + initial begin + c = new; + if (c.ifcboth() != 3) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_implements_collision_bad.out b/test_regress/t/t_implements_collision_bad.out new file mode 100644 index 000000000..96cfc7cec --- /dev/null +++ b/test_regress/t/t_implements_collision_bad.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_collision_bad.v:15:41: Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), and unsupported for interface classes. + 15 | interface class IclsBoth extends Icls1, Icls2; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_collision_bad.pl b/test_regress/t/t_implements_collision_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_collision_bad.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 2020 by Wilson Snyder. 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_implements_collision_bad.v b/test_regress/t/t_implements_collision_bad.v new file mode 100644 index 000000000..d457be661 --- /dev/null +++ b/test_regress/t/t_implements_collision_bad.v @@ -0,0 +1,24 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls1; + pure virtual function int icfboth; +endclass + +interface class Icls2; + pure virtual function int icfboth; +endclass + +interface class IclsBoth extends Icls1, Icls2; + // Bad collision on icfboth +endclass + +class Cls implements IclsBoth; +endclass + +module t (/*AUTOARG*/); + Cls c; +endmodule diff --git a/test_regress/t/t_implements_contents_bad.out b/test_regress/t/t_implements_contents_bad.out new file mode 100644 index 000000000..be41f2343 --- /dev/null +++ b/test_regress/t/t_implements_contents_bad.out @@ -0,0 +1,11 @@ +%Error-UNSUPPORTED: t/t_implements_contents_bad.v:7:11: Unsupported: interface classes + 7 | interface class Icls; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: t/t_implements_contents_bad.v:8:8: Interface class cannot contain non-parameter members (IEEE 1800-2017 8.26) + 8 | int badi; + | ^~~~ +%Error: t/t_implements_contents_bad.v:9:9: Interface class functions must be pure virtual (IEEE 1800-2017 8.26) + 9 | task badtask; + | ^~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_implements_contents_bad.pl b/test_regress/t/t_implements_contents_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_contents_bad.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 2020 by Wilson Snyder. 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_implements_contents_bad.v b/test_regress/t/t_implements_contents_bad.v new file mode 100644 index 000000000..4106c7ed4 --- /dev/null +++ b/test_regress/t/t_implements_contents_bad.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, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls; + int badi; + task badtask; + endtask +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_implements_missing_bad.out b/test_regress/t/t_implements_missing_bad.out new file mode 100644 index 000000000..6c57b4956 --- /dev/null +++ b/test_regress/t/t_implements_missing_bad.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_missing_bad.v:7:11: Unsupported: interface classes + 7 | interface class Icls1; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_missing_bad.pl b/test_regress/t/t_implements_missing_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_missing_bad.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 2020 by Wilson Snyder. 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_implements_missing_bad.v b/test_regress/t/t_implements_missing_bad.v new file mode 100644 index 000000000..f84eb6ae3 --- /dev/null +++ b/test_regress/t/t_implements_missing_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls1; + pure virtual function int icf1; + pure virtual function int icf2; +endclass + +class Cls implements Icls1; + virtual function int icf1; + return 1; + endfunction + // Bad missing icf2 +endclass + +module t (/*AUTOARG*/); + Cls c; +endmodule diff --git a/test_regress/t/t_implements_nested_bad.out b/test_regress/t/t_implements_nested_bad.out new file mode 100644 index 000000000..1121c001f --- /dev/null +++ b/test_regress/t/t_implements_nested_bad.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_nested_bad.v:8:14: Unsupported: class within class + 8 | interface class bad_cannot_nest; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_nested_bad.pl b/test_regress/t/t_implements_nested_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_nested_bad.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 2020 by Wilson Snyder. 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_implements_nested_bad.v b/test_regress/t/t_implements_nested_bad.v new file mode 100644 index 000000000..119033fa3 --- /dev/null +++ b/test_regress/t/t_implements_nested_bad.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, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + interface class bad_cannot_nest; + endclass +endclass + +module t (/*AUTOARG*/); + Cls c; +endmodule diff --git a/test_regress/t/t_implements_new_bad.out b/test_regress/t/t_implements_new_bad.out new file mode 100644 index 000000000..2cd806fe6 --- /dev/null +++ b/test_regress/t/t_implements_new_bad.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_new_bad.v:7:11: Unsupported: interface classes + 7 | interface class Icls; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_new_bad.pl b/test_regress/t/t_implements_new_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_new_bad.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 2020 by Wilson Snyder. 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_implements_new_bad.v b/test_regress/t/t_implements_new_bad.v new file mode 100644 index 000000000..950039100 --- /dev/null +++ b/test_regress/t/t_implements_new_bad.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls; +endclass + +module t (/*AUTOARG*/); + Icls c; + initial begin + c = new; // Bad + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_implements_noinherit_bad.out b/test_regress/t/t_implements_noinherit_bad.out new file mode 100644 index 000000000..813639b52 --- /dev/null +++ b/test_regress/t/t_implements_noinherit_bad.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_implements_noinherit_bad.v:7:11: Unsupported: interface classes + 7 | interface class Icls; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_implements_noinherit_bad.pl b/test_regress/t/t_implements_noinherit_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_noinherit_bad.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 2020 by Wilson Snyder. 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_implements_noinherit_bad.v b/test_regress/t/t_implements_noinherit_bad.v new file mode 100644 index 000000000..8726e86fc --- /dev/null +++ b/test_regress/t/t_implements_noinherit_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface class Icls; + localparam IP = 1; + typedef int i_t; +endclass + +class Cls implements Icls; + function void f; + $display(IP); // Bad + endfunction +endclass + +module t (/*AUTOARG*/); + Cls c; +endmodule diff --git a/test_regress/t/t_implements_noninterface_bad.out b/test_regress/t/t_implements_noninterface_bad.out new file mode 100644 index 000000000..5bf1d237d --- /dev/null +++ b/test_regress/t/t_implements_noninterface_bad.out @@ -0,0 +1,13 @@ +%Error-UNSUPPORTED: t/t_implements_noninterface_bad.v:13:11: Unsupported: interface classes + 13 | interface class Icls; + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: t/t_implements_noninterface_bad.v:10:26: Attempting to implement from non-interface class 'NotIcls' +... Suggest use 'extends' + 10 | class ClsBad1 implements NotIcls; + | ^~~~~~~ +%Error: t/t_implements_noninterface_bad.v:16:23: Attempting to extend from interface class 'Icls' +... Suggest use 'implements' + 16 | class ClsBad2 extends Icls; + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_implements_noninterface_bad.pl b/test_regress/t/t_implements_noninterface_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_noninterface_bad.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 2020 by Wilson Snyder. 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_implements_noninterface_bad.v b/test_regress/t/t_implements_noninterface_bad.v new file mode 100644 index 000000000..95ff76301 --- /dev/null +++ b/test_regress/t/t_implements_noninterface_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class NotIcls; +endclass + +class ClsBad1 implements NotIcls; +endclass + +interface class Icls; +endclass + +class ClsBad2 extends Icls; +endclass + +module t (/*AUTOARG*/); + Cls c; +endmodule diff --git a/test_regress/t/t_implements_notfound_bad.out b/test_regress/t/t_implements_notfound_bad.out new file mode 100644 index 000000000..19bc6b6d0 --- /dev/null +++ b/test_regress/t/t_implements_notfound_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_implements_notfound_bad.v:7:23: Class for 'implements' not found: 'Inotfound' + 7 | class ClsI implements Inotfound; + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_implements_notfound_bad.pl b/test_regress/t/t_implements_notfound_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_implements_notfound_bad.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 2020 by Wilson Snyder. 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_implements_notfound_bad.v b/test_regress/t/t_implements_notfound_bad.v new file mode 100644 index 000000000..66a3bef0f --- /dev/null +++ b/test_regress/t/t_implements_notfound_bad.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class ClsI implements Inotfound; +endclass + +module t (/*AUTOARG*/); + ClsI ci; +endmodule