From 5d32fc56ac70b925e5cd2c0f4b142e7357e104ca Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 28 Jun 2025 20:32:19 -0400 Subject: [PATCH] Support 'config' parsing, but not functionally --- src/V3AstNodeOther.h | 74 ++++++++- src/V3AstNodes.cpp | 16 ++ src/V3LinkCells.cpp | 21 ++- src/V3SymTable.h | 5 +- src/verilog.l | 14 +- src/verilog.y | 141 +++++++++++++++++- test_regress/t/t_config_libmap.out | 3 - test_regress/t/t_config_param.out | 20 +++ test_regress/t/t_config_param.py | 21 +++ test_regress/t/t_config_param.v | 30 ++++ test_regress/t/t_config_unsup.out | 77 ++++++++++ test_regress/t/t_config_unsup.py | 16 ++ test_regress/t/t_config_unsup.v | 49 ++++++ test_regress/t/t_lint_rsvd_bad.out | 36 ----- test_regress/t/t_lint_rsvd_bad.v | 19 --- test_regress/t/t_mod_dot.py | 25 ++++ test_regress/t/t_mod_dot.v | 12 ++ test_regress/t/t_mod_dup_bad_lib.out | 19 +++ ..._lint_rsvd_bad.py => t_mod_dup_bad_lib.py} | 6 +- test_regress/t/t_mod_dup_bad_lib.v | 18 +++ 20 files changed, 548 insertions(+), 74 deletions(-) create mode 100644 test_regress/t/t_config_param.out create mode 100755 test_regress/t/t_config_param.py create mode 100644 test_regress/t/t_config_param.v create mode 100644 test_regress/t/t_config_unsup.out create mode 100755 test_regress/t/t_config_unsup.py create mode 100644 test_regress/t/t_config_unsup.v delete mode 100644 test_regress/t/t_lint_rsvd_bad.out delete mode 100644 test_regress/t/t_lint_rsvd_bad.v create mode 100755 test_regress/t/t_mod_dot.py create mode 100644 test_regress/t/t_mod_dot.v create mode 100644 test_regress/t/t_mod_dup_bad_lib.out rename test_regress/t/{t_lint_rsvd_bad.py => t_mod_dup_bad_lib.py} (73%) create mode 100644 test_regress/t/t_mod_dup_bad_lib.v diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index d72ebcd9b..d55606b57 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -953,9 +953,9 @@ public: AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp, AstClockingItem* itemsp, bool isDefault, bool isGlobal) : ASTGEN_SUPER_Clocking(fl) + , m_name{name} , m_isDefault{isDefault} , m_isGlobal{isGlobal} { - m_name = name; this->sensesp(sensesp); addItemsp(itemsp); } @@ -994,6 +994,78 @@ public: void outputp(AstClockingItem* outputp) { m_outputp = outputp; } bool maybePointedTo() const override VL_MT_SAFE { return true; } }; +class AstConfig final : public AstNode { + // Parents: NETLIST + // @astgen op1 := designp : List[AstConfigCell] + // @astgen op2 := itemsp : List[AstNode] + std::string m_name; // Config block name + +public: + AstConfig(FileLine* fl, const std::string& name, AstNode* itemsp) + : ASTGEN_SUPER_Config(fl) + , m_name{name} { + addItemsp(itemsp); + } + ASTGEN_MEMBERS_AstConfig; + std::string name() const override VL_MT_STABLE { return m_name; } +}; +class AstConfigCell final : public AstNode { + // Parents: CONFIGRULE + std::string m_libname; // Cell library, or "" + std::string m_cellname; // Cell name within library + +public: + AstConfigCell(FileLine* fl, const std::string& libname, const std::string& cellname) + : ASTGEN_SUPER_ConfigCell(fl) + , m_libname{libname} + , m_cellname{cellname} {} + ASTGEN_MEMBERS_AstConfigCell; + std::string name() const override VL_MT_STABLE { return m_libname + "." + m_cellname; } + std::string libname() const VL_MT_STABLE { return m_libname; } + std::string cellname() const VL_MT_STABLE { return m_cellname; } +}; +class AstConfigRule final : public AstNode { + // Parents: CONFIG + // @astgen op1 := cellp : Optional[AstNode] // Cells to apply to, or nullptr=default + // @astgen op2 := usep : List[AstNode] // Use or design to apply + const bool m_isCell; // Declared as "cell" versus "instance" + +public: + AstConfigRule(FileLine* fl, AstNode* cellp, AstNode* usep, bool isCell) + : ASTGEN_SUPER_ConfigRule(fl) + , m_isCell{isCell} { + this->cellp(cellp); + addUsep(usep); + } + ASTGEN_MEMBERS_AstConfigRule; + bool isCell() const VL_MT_STABLE { return m_isCell; } + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; +}; +class AstConfigUse final : public AstNode { + // Parents: CONFIGRULE + // @astgen op1 := paramsp : List[AstPin] + std::string m_libname; // Use library, or "" + std::string m_cellname; // Use name within library + const bool m_isConfig; // ":config"; Config, not module/primitive name + +public: + AstConfigUse(FileLine* fl, const std::string& libname, const std::string& cellname, + AstPin* paramsp, bool isConfig) + : ASTGEN_SUPER_ConfigUse(fl) + , m_libname{libname} + , m_cellname{cellname} + , m_isConfig{isConfig} { + addParamsp(paramsp); + } + ASTGEN_MEMBERS_AstConfigUse; + std::string name() const override VL_MT_STABLE { return m_libname + "." + m_cellname; } + std::string libname() const VL_MT_STABLE { return m_libname; } + std::string cellname() const VL_MT_STABLE { return m_cellname; } + bool isConfig() const VL_MT_STABLE { return m_isConfig; } + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; +}; class AstConstPool final : public AstNode { // Container for const static data // @astgen op1 := modulep : AstModule // m_modp below TODO: fix this mess diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index c94976487..aabf0d51f 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1806,6 +1806,22 @@ void AstClocking::dumpJson(std::ostream& str) const { dumpJsonBoolFunc(str, isGlobal); dumpJsonGen(str); } +void AstConfigRule::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (isCell()) str << " [CELL]"; +} +void AstConfigRule::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, isCell); + dumpJsonGen(str); +} +void AstConfigUse::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (isConfig()) str << " [CONFIG]"; +} +void AstConfigUse::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, isConfig); + dumpJsonGen(str); +} void AstDisplay::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); str << " [" << displayType().ascii() << "]"; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 30c87c470..1c464b8d1 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -562,6 +562,23 @@ class LinkCellsVisitor final : public VNVisitor { iterateAndNextNull(nodep->attrsp()); } + void visit(AstConfig* nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config"); + iterateChildren(nodep); + } + void visit(AstConfigCell* nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config cell"); + iterateChildren(nodep); + } + void visit(AstConfigRule* nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config rule"); + iterateChildren(nodep); + } + void visit(AstConfigUse* nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: config use"); + iterateChildren(nodep); + } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // METHODS @@ -623,7 +640,9 @@ public: } iterate(nodep); } - ~LinkCellsVisitor() override = default; + ~LinkCellsVisitor() override { + if (debug() >= 5 || dumpGraphLevel() >= 5) { m_mods.dumpFilePrefixed("linkcells"); } + } }; //###################################################################### diff --git a/src/V3SymTable.h b/src/V3SymTable.h index a65b55b58..09d2460ce 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -117,7 +117,7 @@ public: void exported(bool flag) { m_exported = flag; } bool imported() const { return m_imported; } void imported(bool flag) { m_imported = flag; } - void insert(const string& name, VSymEnt* entp) { + VSymEnt* insert(const string& name, VSymEnt* entp) { UINFO(9, " SymInsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp) << " " << entp->nodep()); if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) { @@ -130,6 +130,7 @@ public: } else { m_idNameMap.emplace(name, entp); } + return entp; } void reinsert(const string& name, VSymEnt* entp) { const auto it = m_idNameMap.find(name); @@ -150,7 +151,7 @@ public: << (it == m_idNameMap.end() ? "NONE" : "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep()))); - if (it != m_idNameMap.end()) return (it->second); + if (it != m_idNameMap.end()) return it->second; return nullptr; } VSymEnt* findIdFallback(const string& name) const { diff --git a/src/verilog.l b/src/verilog.l index 69ecd8d7a..c22bf9987 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -441,19 +441,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} /* Verilog 2001 Config */ { /* Generic unsupported keywords */ - "cell" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } - "config" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } - "design" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } - "endconfig" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } + "cell" { FL; return yCELL; } + "config" { FL; return yCONFIG; } + "design" { FL; return yDESIGN; } + "endconfig" { FL; return yENDCONFIG; } "incdir" { FL; ERROR_RSVD_WORD("Verilog 2001-config lib.map"); } "include" { FL; yylval.fl->v3warn(E_UNSUPPORTED, "Unsupported: Verilog 2001-config lib.map reserved word not implemented: 'include'\n" << yylval.fl->warnMore() << "... Suggest unless in a lib.map file," " want `include instead"); FL_BRK; } - "instance" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } - "liblist" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } + "instance" { FL; return yINSTANCE; } + "liblist" { FL; return yLIBLIST; } "library" { FL; ERROR_RSVD_WORD("Verilog 2001-config lib.map"); } - "use" { FL; ERROR_RSVD_WORD("Verilog 2001-config"); } + "use" { FL; return yUSE; } } /* Verilog 2005 */ diff --git a/src/verilog.y b/src/verilog.y index ccbb6c084..d627010ca 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -575,11 +575,13 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yCASE "case" %token yCASEX "casex" %token yCASEZ "casez" +%token yCELL "cell" %token yCHANDLE "chandle" %token yCHECKER "checker" %token yCLASS "class" %token yCLOCKING "clocking" %token yCMOS "cmos" +%token yCONFIG "config" %token yCONSTRAINT "constraint" %token yCONST__ETC "const" %token yCONST__LEX "const-in-lex" @@ -593,6 +595,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yDEASSIGN "deassign" %token yDEFAULT "default" %token yDEFPARAM "defparam" +%token yDESIGN "design" %token yDISABLE "disable" %token yDIST "dist" %token yDO "do" @@ -603,6 +606,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yENDCHECKER "endchecker" %token yENDCLASS "endclass" %token yENDCLOCKING "endclocking" +%token yENDCONFIG "endconfig" %token yENDFUNCTION "endfunction" %token yENDGENERATE "endgenerate" %token yENDGROUP "endgroup" @@ -650,6 +654,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yINOUT "inout" %token yINPUT "input" %token yINSIDE "inside" +%token yINSTANCE "instance" %token yINT "int" %token yINTEGER "integer" %token yINTERCONNECT "interconnect" @@ -659,6 +664,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yJOIN_ANY "join_any" %token yJOIN_NONE "join_none" %token yLET "let" +%token yLIBLIST "liblist" %token yLOCALPARAM "localparam" %token yLOCAL__COLONCOLON "local-then-::" %token yLOCAL__ETC "local" @@ -774,6 +780,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yUNTIL "until" %token yUNTIL_WITH "until_with" %token yUNTYPED "untyped" +%token yUSE "use" %token yVAR "var" %token yVECTORED "vectored" %token yVIRTUAL__CLASS "virtual-then-class" @@ -1212,7 +1219,7 @@ description: // ==IEEE: description | package_declaration { } | package_itemTop { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); } | bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); } - //UNSUP config_declaration { } + | config_declaration { } // // Verilator only | yaT_RESETALL { } // Else, under design, and illegal based on IEEE 22.3 | yaT_NOUNCONNECTED { PARSEP->unconnectedDrive(VOptionBool::OPT_DEFAULT_FALSE); } @@ -7720,8 +7727,140 @@ colon: // Generic colon that isn't making a label (e.g. //********************************************************************** // Config - config...endconfig +config_declaration: // == IEEE: config_declaration + yCONFIG idAny/*config_identifier*/ ';' + /*cont*/ configParameterListE design_statement config_rule_statementListE + /*cont*/ yENDCONFIG endLabelE + { AstConfig* const newp = new AstConfig{$1, *$2, $4}; + newp->addItemsp($5); + newp->addItemsp($6); + GRAMMARP->endLabel($7, *$2, $8); + PARSEP->rootp()->addMiscsp(newp); } + ; + +configParameterListE: // IEEE: { local_parameter_declaration ';' } + /* empty */ { $$ = nullptr; } + | configParameterList { $$ = $1; } + ; + +configParameterList: // IEEE: part of config_declaration + configParameter { $$ = nullptr; } + | configParameterList configParameter { $$ = addNextNull($1, $2); } + ; + +configParameter: // IEEE: part of config_declaration + parameter_declaration ';' + { $$ = nullptr; BBUNSUP($1, "Unsupported: config localparam declaration"); } + ; + +design_statement: // == IEEE: design_statement + yDESIGN configCellList ';' { $$ = $2; } + ; + +configCellList: // IEEE: part of design_statement + configCell { $$ = $1; } + | configCellList configCell { $$ = addNextNull($1, $2); } + ; + +configCell: // IEEE: part of design_statement, part of cell_clause + idAny/*cell_identifier*/ + { $$ = new AstConfigCell{$1, "", *$1}; } + | idAny/*library_identifier*/ '.' idAny/*cell_identifier*/ + { $$ = new AstConfigCell{$1, *$1, *$3}; } + ; + +config_rule_statementListE: // IEEE: { config_rule } + /* empty */ { $$ = nullptr; } + | config_rule_statementList { $$ = $1; } + ; + +config_rule_statementList: // IEEE: { config_rule } + config_rule_statement { $$ = $1; } + | config_rule_statementList config_rule_statement { $$ = addNextNull($1, $2); } + ; + +config_rule_statement: // == IEEE: config_rule_statement + // // IEEE: default_clause + yDEFAULT liblist_clause ';' + { $$ = new AstConfigRule{$1, nullptr, $2, false}; } + // // IEEE: inst_clause + | yINSTANCE inst_name liblist_clause ';' + { $$ = new AstConfigRule{$1, $2, $3, false}; } + | yINSTANCE inst_name use_clause ';' + { $$ = new AstConfigRule{$1, $2, $3, false}; } + // // IEEE: cell_clause + | yCELL configCell liblist_clause ';' + { $$ = new AstConfigRule{$1, $2, $3, true}; } + | yCELL configCell use_clause ';' + { $$ = new AstConfigRule{$1, $2, $3, true}; } + | error ';' + { $$ = nullptr; } + ; + +inst_name: // == IEEE: inst_name + idAnyAsParseRef/*topmodule_identifier*/ + { $$ = $1; } + | idAnyAsParseRef/*topmodule_identifier*/ inst_nameInstanceList + { $$ = new AstDot{$1, false, $1, $2}; } + ; + +inst_nameInstanceList: // IEEE: part of inst_name + '.' idAnyAsParseRef/*instance_identifier*/ + { $$ = $2; } + | inst_nameInstanceList '.' idAnyAsParseRef/*instance_identifier*/ + { $$ = new AstDot{$2, false, $1, $3}; } + ; + +liblist_clause: // == IEEE: liblist_clause + yLIBLIST { $$ = nullptr; } + | yLIBLIST liblistLibraryList { $$ = $2; } + ; + +liblistLibraryList: // IEEE: part of liblist_clause + idAnyAsParseRef/*library_identifier*/ + { $$ = $1; } + | liblistLibraryList idAnyAsParseRef/*library_identifier*/ + { $$ = addNextNull($1, $2); } + ; + +use_clause: // == IEEE: use_clause + yUSE idAny/*cell_identifier*/ useAssignmentListE colonConfigE + { $$ = new AstConfigUse{$1, "", *$2, $3, $4}; } + | yUSE idAny/*library_identifier*/ '.' idAny/*cell_identifier*/ useAssignmentListE colonConfigE + { $$ = new AstConfigUse{$1, *$2, *$4, $5, $6}; } + | yUSE useAssignmentListE colonConfigE + { $$ = new AstConfigUse{$1, "", "", $2, $3}; } + ; + +useAssignmentListE: // IEEE: part of use clause + /* empty */ { $$ = nullptr; } + // // IEEE is missing the '#' '(', but examples need it + | '#' '(' ')' { $$ = nullptr; } + | '#' '(' useAssignmentList ')' { $$ = $3; } + ; + +useAssignmentList: // IEEE: part of use_clause + useAssignment { $$ = $1; } + | useAssignmentList ',' useAssignment { $$ = addNextNull($1, $3); } + ; + +useAssignment: // IEEE: part of use_clause + // // IEEE: named_parameter_assignment + '.' idAny/*parameter_identifier*/ '(' ')' + { $$ = nullptr; BBUNSUP($1, "Unsupported: 'config use' parameter assignment"); } + | '.' idAny/*parameter_identifier*/ '(' exprOrDataType ')' + { $$ = nullptr; BBUNSUP($1, "Unsupported: 'config use' parameter assignment"); } + ; + +colonConfigE: // IEEE: [ ':' yCONFIG] + /* empty */ { $$ = false; } + | ':' yCONFIG { $$ = true; } + ; + //********************************************************************** // Config - lib.map +// +// TODO when implement this support, add -libmap option which takes multiple files. //UNSUP library_text: // == IEEE: library_text (note is top-level entry point) //UNSUP library_description { } diff --git a/test_regress/t/t_config_libmap.out b/test_regress/t/t_config_libmap.out index 0415f7ac2..56ad3db45 100644 --- a/test_regress/t/t_config_libmap.out +++ b/test_regress/t/t_config_libmap.out @@ -26,7 +26,4 @@ %Error-UNSUPPORTED: t/t_config_libmap.map:17:1: Unsupported: Verilog 2001-config lib.map reserved word not implemented: 'library' 17 | library gatelib . | ^~~~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_config_libmap.map:20:1: Unsupported: Verilog 2001-config reserved word not implemented: 'config' -%Error-UNSUPPORTED: t/t_config_libmap.map:21:4: Unsupported: Verilog 2001-config reserved word not implemented: 'design' -%Error-UNSUPPORTED: t/t_config_libmap.map:22:1: Unsupported: Verilog 2001-config reserved word not implemented: 'endconfig' %Error: Exiting due to diff --git a/test_regress/t/t_config_param.out b/test_regress/t/t_config_param.out new file mode 100644 index 000000000..8c756c7aa --- /dev/null +++ b/test_regress/t/t_config_param.out @@ -0,0 +1,20 @@ +%Error-UNSUPPORTED: t/t_config_param.v:24:4: Unsupported: config localparam declaration + 24 | localparam P1 = "cfg.p1"; + | ^~~~~~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_config_param.v:25:4: Unsupported: config localparam declaration + 25 | localparam P2 = "cfg.p2"; + | ^~~~~~~~~~ +%Error-UNSUPPORTED: t/t_config_param.v:27:26: Unsupported: 'config use' parameter assignment + 27 | instance t.u_1a use #(.P1(), .P2("override.u_a.p2")); + | ^ +%Error-UNSUPPORTED: t/t_config_param.v:27:33: Unsupported: 'config use' parameter assignment + 27 | instance t.u_1a use #(.P1(), .P2("override.u_a.p2")); + | ^ +%Error-UNSUPPORTED: t/t_config_param.v:29:26: Unsupported: 'config use' parameter assignment + 29 | instance t.u_1c use #(.P1(P1), .P2(P2)); + | ^ +%Error-UNSUPPORTED: t/t_config_param.v:29:35: Unsupported: 'config use' parameter assignment + 29 | instance t.u_1c use #(.P1(P1), .P2(P2)); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_config_param.py b/test_regress/t/t_config_param.py new file mode 100755 index 000000000..60b7d73ba --- /dev/null +++ b/test_regress/t/t_config_param.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(verilator_flags2=["--lint-only"], + fails=test.vlt_all, + expect_filename=test.golden_filename) + +# Sort so that 'initial' scheduling order is not relevant +# test.files_identical_sorted(test.run_log_filename, test.golden_filename, is_logfile=True) + +test.passes() diff --git a/test_regress/t/t_config_param.v b/test_regress/t/t_config_param.v new file mode 100644 index 000000000..c0dc43af9 --- /dev/null +++ b/test_regress/t/t_config_param.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module m1; + parameter string P1 = "p1.unchanged"; + parameter string P2 = "p2.unchanged"; + initial $display("m1 %%m=%m %%l=%l P1=%s P2=%s", P1, P2); +endmodule + +module t; + + m1 u_1a(); + m1 u_1b(); + m1 u_1c(); + + final $write("*-* All Finished *-*\n"); + +endmodule + +config cfg1; + localparam P1 = "cfg.p1"; + localparam P2 = "cfg.p2"; + design t; + instance t.u_1a use #(.P1(), .P2("override.u_a.p2")); + instance t.u_1b use #(); // All parameters back to default + instance t.u_1c use #(.P1(P1), .P2(P2)); +endconfig diff --git a/test_regress/t/t_config_unsup.out b/test_regress/t/t_config_unsup.out new file mode 100644 index 000000000..988eca8a9 --- /dev/null +++ b/test_regress/t/t_config_unsup.out @@ -0,0 +1,77 @@ +%Error-UNSUPPORTED: t/t_config_unsup.v:24:1: Unsupported: config + 24 | config cfg; + | ^~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_config_unsup.v:25:11: Unsupported: config cell + 25 | design t; + | ^ +%Error-UNSUPPORTED: t/t_config_unsup.v:28:4: Unsupported: config rule + 28 | default liblist; + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:29:4: Unsupported: config rule + 29 | default liblist liba libb; + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:32:4: Unsupported: config rule + 32 | instance t.m20 liblist; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:33:4: Unsupported: config rule + 33 | instance t.m21 liblist libc; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:34:4: Unsupported: config rule + 34 | instance t.m22 liblist libc libd; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:35:4: Unsupported: config rule + 35 | instance t.m23 liblist libc libd; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:36:4: Unsupported: config rule + 36 | instance t.m24 liblist libc libd; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:39:4: Unsupported: config rule + 39 | instance t.m30 use cell_identifier; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:39:19: Unsupported: config use + 39 | instance t.m30 use cell_identifier; + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:40:4: Unsupported: config rule + 40 | instance t.m31 use lib_id.cell_id; + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:40:19: Unsupported: config use + 40 | instance t.m31 use lib_id.cell_id; + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:41:4: Unsupported: config rule + 41 | instance t.m32 use #(); + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:41:19: Unsupported: config use + 41 | instance t.m32 use #(); + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:44:4: Unsupported: config rule + 44 | cell m40 liblist libc libd; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:44:9: Unsupported: config cell + 44 | cell m40 liblist libc libd; + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:45:4: Unsupported: config rule + 45 | cell work.m41 liblist libc libd; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:45:9: Unsupported: config cell + 45 | cell work.m41 liblist libc libd; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:46:4: Unsupported: config rule + 46 | cell m42 use m42alt; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:46:9: Unsupported: config cell + 46 | cell m42 use m42alt; + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:46:13: Unsupported: config use + 46 | cell m42 use m42alt; + | ^~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:47:4: Unsupported: config rule + 47 | cell work.m43 use work.m43alt; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:47:9: Unsupported: config cell + 47 | cell work.m43 use work.m43alt; + | ^~~~ +%Error-UNSUPPORTED: t/t_config_unsup.v:47:18: Unsupported: config use + 47 | cell work.m43 use work.m43alt; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_config_unsup.py b/test_regress/t/t_config_unsup.py new file mode 100755 index 000000000..e30916148 --- /dev/null +++ b/test_regress/t/t_config_unsup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_config_unsup.v b/test_regress/t/t_config_unsup.v new file mode 100644 index 000000000..3e047e50a --- /dev/null +++ b/test_regress/t/t_config_unsup.v @@ -0,0 +1,49 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + m10 u_10(); + m20 u_20(); + m21 u_21(); + m22 u_22(); + m23 u_23(); + m24 u_24(); + m30 u_30(); + m31 u_31(); + m32 u_32(); + m40 u_40(); + m41 u_41(); + m42 u_42(); + m43 u_43(); + final $write("*-* All Finished *-*\n"); +endmodule + +config cfg; + design t; + + // Test uses m10 + default liblist; // Ignored + default liblist liba libb; + + // Test uses m20-29 + instance t.m20 liblist; // Use parent's cell library + instance t.m21 liblist libc; + instance t.m22 liblist libc libd; // m22 in libc + instance t.m23 liblist libc libd; // m23 in libd + instance t.m24 liblist libc libd; // m24 in default (libb) + + // Test uses m30-39 + instance t.m30 use cell_identifier; + instance t.m31 use lib_id.cell_id; + instance t.m32 use #(); + + // Test uses m40-49 + cell m40 liblist libc libd; + cell work.m41 liblist libc libd; + cell m42 use m42alt; + cell work.m43 use work.m43alt; + +endconfig diff --git a/test_regress/t/t_lint_rsvd_bad.out b/test_regress/t/t_lint_rsvd_bad.out deleted file mode 100644 index c98cecae5..000000000 --- a/test_regress/t/t_lint_rsvd_bad.out +++ /dev/null @@ -1,36 +0,0 @@ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:7:1: Unsupported: Verilog 2001-config reserved word not implemented: 'config' - 7 | config cfgBad; - | ^~~~~~~~~~~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error: t/t_lint_rsvd_bad.v:7:14: syntax error, unexpected IDENTIFIER - ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:8:4: Unsupported: Verilog 2001-config reserved word not implemented: 'design' - 8 | design rtlLib.top; - | ^~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:9:12: Unsupported: Verilog 2001-config reserved word not implemented: 'liblist' - 9 | default liblist rtlLib; - | ^~~~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:10:4: Unsupported: Verilog 2001-config reserved word not implemented: 'instance' - 10 | instance top.a2 liblist gateLib; - | ^~~~~~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:10:28: Unsupported: Verilog 2001-config reserved word not implemented: 'liblist' -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:11:4: Unsupported: Verilog 2001-config lib.map reserved word not implemented: 'include' - : ... Suggest unless in a lib.map file, want `include instead - 11 | include none; - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:12:4: Unsupported: Verilog 2001-config lib.map reserved word not implemented: 'library' - 12 | library rtlLib *.v; - | ^~~~~~~~~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:13:4: Unsupported: Verilog 2001-config lib.map reserved word not implemented: 'include' - : ... Suggest unless in a lib.map file, want `include instead - 13 | include aa; - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:14:4: Unsupported: Verilog 2001-config reserved word not implemented: 'use' - 14 | use gateLib; - | ^~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:15:4: Unsupported: Verilog 2001-config reserved word not implemented: 'cell' - 15 | cell rtlLib.cell; - | ^~~~~~~~ -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:15:20: Unsupported: Verilog 2001-config reserved word not implemented: 'cell' -%Error-UNSUPPORTED: t/t_lint_rsvd_bad.v:16:1: Unsupported: Verilog 2001-config reserved word not implemented: 'endconfig' -%Error: Exiting due to diff --git a/test_regress/t/t_lint_rsvd_bad.v b/test_regress/t/t_lint_rsvd_bad.v deleted file mode 100644 index aaef81658..000000000 --- a/test_regress/t/t_lint_rsvd_bad.v +++ /dev/null @@ -1,19 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2019 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 - -config cfgBad; - design rtlLib.top; - default liblist rtlLib; - instance top.a2 liblist gateLib; - include none; - library rtlLib *.v; - include aa; - use gateLib; - cell rtlLib.cell; -endconfig - -module t; -endmodule diff --git a/test_regress/t/t_mod_dot.py b/test_regress/t/t_mod_dot.py new file mode 100755 index 000000000..463f66f1f --- /dev/null +++ b/test_regress/t/t_mod_dot.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('vlt') + +# This doesn't use the general compile rule as we want to make sure we form +# prefix properly using post-escaped identifiers +test.run(cmd=[ + os.environ["VERILATOR_ROOT"] + "/bin/verilator", + "--cc", + "--Mdir " + test.obj_dir + "/t_mod_dot", + "--exe --build --main", + 't/t_mod_dot.v', +], + verilator_run=True) + +test.passes() diff --git a/test_regress/t/t_mod_dot.v b/test_regress/t/t_mod_dot.v new file mode 100644 index 000000000..c86095ba0 --- /dev/null +++ b/test_regress/t/t_mod_dot.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, 2020 by engr248. +// SPDX-License-Identifier: CC0-1.0 + +module \foo.bar (/*AUTOARG*/); + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_mod_dup_bad_lib.out b/test_regress/t/t_mod_dup_bad_lib.out new file mode 100644 index 000000000..cc0bdb504 --- /dev/null +++ b/test_regress/t/t_mod_dup_bad_lib.out @@ -0,0 +1,19 @@ +%Warning-MODDUP: t/t_mod_dup_bad_lib.v:14:8: Duplicate declaration of module: 'a' + 14 | module a(); + | ^ + t/t_mod_dup_bad_lib.v:7:8: ... Location of original declaration + 7 | module a(); + | ^ + ... For warning description see https://verilator.org/warn/MODDUP?v=latest + ... Use "/* verilator lint_off MODDUP */" and lint_on around source to disable this message. +%Warning-MULTITOP: t/t_mod_dup_bad_lib.v:17:8: Multiple top level modules + : ... Suggest see manual; fix the duplicates, or use --top-module to select top. + ... For warning description see https://verilator.org/warn/MULTITOP?v=latest + ... Use "/* verilator lint_off MULTITOP */" and lint_on around source to disable this message. + : ... Top module 'test' + 10 | module test(); + | ^~~~ + : ... Top module 'b' + 17 | module b(); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_lint_rsvd_bad.py b/test_regress/t/t_mod_dup_bad_lib.py similarity index 73% rename from test_regress/t/t_lint_rsvd_bad.py rename to test_regress/t/t_mod_dup_bad_lib.py index acbdae169..a19988f61 100755 --- a/test_regress/t/t_lint_rsvd_bad.py +++ b/test_regress/t/t_mod_dup_bad_lib.py @@ -9,10 +9,8 @@ import vltest_bootstrap -test.scenarios('linter') +test.scenarios('vlt') -test.lint(verilator_flags2=["--lint-only -Wwarn-REALCVT"], - fails=True, - expect_filename=test.golden_filename) +test.lint(verilator_flag2=["--work liba"], fails=True, expect_filename=test.golden_filename) test.passes() diff --git a/test_regress/t/t_mod_dup_bad_lib.v b/test_regress/t/t_mod_dup_bad_lib.v new file mode 100644 index 000000000..ad2b678af --- /dev/null +++ b/test_regress/t/t_mod_dup_bad_lib.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2008 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module a(); +endmodule + +module test(); + a a(); +endmodule + +module a(); +endmodule + +module b(); +endmodule