From f7641d2ecceece8a4c20706fbfb8ffc94e525afc Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 30 Jun 2019 16:46:48 -0400 Subject: [PATCH] Change MULTITOP to warning to help linting, see manual. --- Changes | 2 + bin/verilator | 33 +++-- src/V3CCtors.cpp | 2 +- src/V3Error.h | 6 +- src/V3LinkCells.cpp | 3 +- src/V3LinkDot.cpp | 16 +-- src/V3LinkLevel.cpp | 153 +++++++++++++++--------- src/V3Scope.cpp | 2 +- test_regress/t/t_flag_topmodule_bad.out | 7 +- test_regress/t/t_mod_dup_bad.out | 4 +- test_regress/t/t_multitop1.pl | 25 ++++ test_regress/t/t_multitop1.v | 17 +++ test_regress/t/t_multitop1s.v | 12 ++ test_regress/t/t_multitop_sig.cpp | 44 +++++++ test_regress/t/t_multitop_sig.pl | 30 +++++ test_regress/t/t_multitop_sig.v | 32 +++++ test_regress/t/t_multitop_sig_bad.out | 5 + test_regress/t/t_multitop_sig_bad.pl | 20 ++++ 18 files changed, 329 insertions(+), 84 deletions(-) create mode 100755 test_regress/t/t_multitop1.pl create mode 100644 test_regress/t/t_multitop1.v create mode 100644 test_regress/t/t_multitop1s.v create mode 100644 test_regress/t/t_multitop_sig.cpp create mode 100755 test_regress/t/t_multitop_sig.pl create mode 100644 test_regress/t/t_multitop_sig.v create mode 100644 test_regress/t/t_multitop_sig_bad.out create mode 100755 test_regress/t/t_multitop_sig_bad.pl diff --git a/Changes b/Changes index 943cbebcf..c5547e5ef 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.017 devel +*** Change MULTITOP to warning to help linting, see manual. + **** Show included-from filenames in warnings, bug1439. [Todd Strader] **** Fix not reporting some duplicate signals/ports, bug1462. [Peter Gerst] diff --git a/bin/verilator b/bin/verilator index d829af894..3ec98058d 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1280,7 +1280,7 @@ good value. When the input Verilog contains more than one top level module, specifies the name of the top level Verilog module to become the top, and sets the default for if --prefix is not used. This is not needed with standard -designs with only one top. +designs with only one top. See also the MULTITOP warning section. =item --trace @@ -3718,14 +3718,31 @@ correctly. =item MULTITOP -Error that there are multiple top level modules, that is modules not -instantiated by any other module. Verilator only supports a single top -level, if you need more, create a module that wraps all of the top modules. +Warns that there are multiple top level modules, that is modules not +instantiated by any other module, and both modules were put on the command +line (not in a library). Three likely cases: -Often this error is because some low level cell is being read in, but is -not really needed. The best solution is to insure that each module is in a -unique file by the same name. Otherwise, make sure all library files are -read in as libraries with -v, instead of automatically with -y. +1. A single module is intended to be the top. This warning then occurs +because some low level cell is being read in, but is not really needed as +part of the design. The best solution for this situation is to ensure that +only the top module is put on the command line without any flags, and all +remaining library files are read in as libraries with -v, or are +automatically resolved by having filenames that match the module names. + +2. A single module is intended to be the top, the name of it is known, and +all other modules should be ignored if not part of the design. The best +solution is to use the --top-module option to specify the top module's +name. All other modules that are not part of the design will be for the +most part ignored (they must be clean in syntax and their contents will be +removed as part of the Verilog module elaboration process.) + +3. Multiple modules are intended to be design tops, e.g. when linting a +library file. As multiple modules are desired, disable the MULTITOP +warning. All input/outputs will go uniquely to each module, with any +conflicting and identical signal names being uniquified by adding a prefix +based on the top module name followed by __02E (a Verilator-encoded ASCII +".'). This renaming is done even if the two modules' signals seem +identical, e.g. multiple modules with a "clk" input. =item PINCONNECTEMPTY diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 9cc44741b..e7d795858 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -106,7 +106,7 @@ private: //###################################################################### void V3CCtors::evalAsserts() { - AstNodeModule* modp = v3Global.rootp()->modulesp(); // Top module + AstNodeModule* modp = v3Global.rootp()->modulesp(); // Top module wrapper AstCFunc* funcp = new AstCFunc(modp->fileline(), "_eval_debug_assertions", NULL, "void"); funcp->declPrivate(true); funcp->isStatic(false); diff --git a/src/V3Error.h b/src/V3Error.h index 9d7347671..97a61ae36 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -49,7 +49,6 @@ public: I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE) // Error codes: E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable - E_MULTITOP, // Error: Multiple top level modules E_PORTSHORT, // Error: Output port is connected to a constant, electrical short E_TASKNSVAR, // Error: Task I/O not simple // @@ -89,6 +88,7 @@ public: LITENDIAN, // Little bit endian vector MODDUP, // Duplicate module MULTIDRIVEN, // Driven from multiple blocks + MULTITOP, // Multiple top level modules PINMISSING, // Cell pin not specified PINNOCONNECT, // Cell pin not connected PINCONNECTEMPTY,// Cell pin connected by name with empty reference @@ -131,7 +131,7 @@ public: // Boolean " I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE", // Errors - "DETECTARRAY", "MULTITOP", "PORTSHORT", "TASKNSVAR", + "DETECTARRAY", "PORTSHORT", "TASKNSVAR", // Warnings " EC_FIRST_WARN", "ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN", @@ -144,7 +144,7 @@ public: "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "LITENDIAN", "MODDUP", - "MULTIDRIVEN", + "MULTIDRIVEN", "MULTITOP", "PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE", "REALCVT", "REDEFMACRO", "SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 88574be48..66f073c1b 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -141,7 +141,8 @@ private: // We'll throw the error when we know the module will really be needed. string prettyName = AstNode::prettyName(modName); V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp); - parser.parseFile(nodep->fileline(), prettyName, false, ""); + // true below -> other simulators treat modules in link-found files as library cells + parser.parseFile(nodep->fileline(), prettyName, true, ""); V3Error::abortIfErrors(); // We've read new modules, grab new pointers to their names readModNames(); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 603f3cc5f..e0d9672c3 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -674,18 +674,20 @@ class LinkDotFindVisitor : public AstNVisitor { // packages before using packages iterateChildrenBackwards(nodep); - // The first module in the list is always the top module (sorted before this is called). + // The first modules in the list are always the top modules + // (sorted before this is called). // This may not be the module with isTop() set, as early in the steps, // wrapTop may have not been created yet. - AstNodeModule* topmodp = nodep->modulesp(); - if (!topmodp) { + if (!nodep->modulesp()) { nodep->v3error("No top level module found"); - } else { - UINFO(8,"Top Module: "<modulesp(); modp && modp->level() <= 2; + modp = VN_CAST(modp->nextp(), NodeModule)) { + UINFO(8,"Top Module: "<insertTopCell(topmodp, m_scope); + m_curSymp = m_modSymp = m_statep->insertTopCell(modp, m_scope); { - iterate(topmodp); + iterate(modp); } m_scope = ""; m_curSymp = m_modSymp = NULL; diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 6a5044b4b..b619dab40 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -60,17 +60,18 @@ void V3LinkLevel::modSortByLevel() { if (nodep->level()<=2) { if (topp) { static int warnedOnce = 0; - nodep->v3warn(E_MULTITOP, "Unsupported: Multiple top level modules: " - <prettyName()<<" and "<prettyName()<v3warn(MULTITOP, "Multiple top level modules: " + <prettyName()<<" and "<prettyName() <<(!warnedOnce++ - ? (nodep->warnMore() - +"... Fix, or use --top-module option to select which you want.") + ? ("\n"+nodep->warnMore() + +"... Suggest see manual; fix the duplicates, or use --top-module to select top.") : "")); } topp = nodep; } vec.push_back(nodep); } + // Reorder the netlist's modules to have modules in level sorted order stable_sort(vec.begin(), vec.end(), CmpLevel()); // Sort the vector UINFO(9,"modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666 for (ModVec::iterator it = vec.begin(); it != vec.end(); ++it) { @@ -95,7 +96,10 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<modulesp(); - if (!oldmodp) rootp->v3fatalSrc("No module found to process"); + if (!oldmodp) { // Later V3LinkDot will warn + UINFO(1,"No module found to wrap\n"); + return; + } AstNodeModule* newmodp = new AstModule(oldmodp->fileline(), string("TOP")); // Make the new module first in the list oldmodp->unlinkFrBackWithNext(); @@ -108,62 +112,10 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { // the rest must be done after data type resolution wrapTopCell(rootp); - V3Global::dumpCheckGlobalTree("wraptop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); -} - -void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { - AstNodeModule* newmodp = rootp->modulesp(); - if (!newmodp || !newmodp->isTop()) rootp->v3fatalSrc("No TOP module found to process"); - AstNodeModule* oldmodp = VN_CAST(newmodp->nextp(), NodeModule); - if (!oldmodp) rootp->v3fatalSrc("No module found to process"); - - // Add instance - AstCell* cellp = new AstCell(newmodp->fileline(), - (!v3Global.opt.l2Name().empty() - ? v3Global.opt.l2Name() : oldmodp->name()), - oldmodp->name(), - NULL, NULL, NULL); - cellp->modp(oldmodp); - newmodp->addStmtp(cellp); - - // Add pins - for (AstNode* subnodep=oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { - if (AstVar* oldvarp = VN_CAST(subnodep, Var)) { - UINFO(8,"VARWRAP "<isIO()) { - AstVar* varp = oldvarp->cloneTree(false); - newmodp->addStmtp(varp); - varp->sigPublic(true); // User needs to be able to get to it... - if (oldvarp->isIO()) { - oldvarp->primaryIO(false); - varp->primaryIO(true); - } - if (varp->direction().isRefOrConstRef()) { - varp->v3error("Unsupported: ref/const ref as primary input/output: " - <prettyName()); - } - if (varp->isIO() && v3Global.opt.systemC()) { - varp->sc(true); - // User can see trace one level down from the wrapper - // Avoids packing & unpacking SC signals a second time - varp->trace(false); - } - - AstPin* pinp = new AstPin(oldvarp->fileline(), 0, oldvarp->name(), - new AstVarRef(varp->fileline(), - varp, oldvarp->isWritable())); - // Skip length and width comp; we know it's a direct assignment - pinp->modVarp(oldvarp); - cellp->addPinsp(pinp); - } - } - } - // Instantiate all packages under the top wrapper // This way all later SCOPE based optimizations can ignore packages for (AstNodeModule* modp = rootp->modulesp(); modp; modp=VN_CAST(modp->nextp(), NodeModule)) { - if (VN_IS(modp, Package) - && modp != oldmodp) { // Don't duplicate if didn't find a top module + if (VN_IS(modp, Package)) { AstCell* cellp = new AstCell(modp->fileline(), // Could add __03a__03a="::" to prevent conflict // with module names/"v" @@ -174,4 +126,89 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { newmodp->addStmtp(cellp); } } + + V3Global::dumpCheckGlobalTree("wraptop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); +} + +void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { + AstNodeModule* newmodp = rootp->modulesp(); + if (!newmodp || !newmodp->isTop()) rootp->v3fatalSrc("No TOP module found to insert under"); + + // Find all duplicate signal names (if multitop) + typedef vl_unordered_set NameSet; + NameSet ioNames; + NameSet dupNames; + // For all modulues, skipping over new top + for (AstNodeModule* oldmodp = VN_CAST(rootp->modulesp()->nextp(), NodeModule); + oldmodp && oldmodp->level() <= 2; + oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { + for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { + if (AstVar* oldvarp = VN_CAST(subnodep, Var)) { + if (oldvarp->isIO()) { + if (ioNames.find(oldvarp->name()) != ioNames.end()) { + //UINFO(8, "Multitop dup I/O found: "<name()); + } else { + ioNames.insert(oldvarp->name()); + } + } + } + } + } + + // For all modulues, skipping over new top + for (AstNodeModule* oldmodp = VN_CAST(rootp->modulesp()->nextp(), NodeModule); + oldmodp && oldmodp->level() <= 2; + oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { + if (VN_IS(oldmodp, Package)) continue; + // Add instance + UINFO(5,"LOOP "<fileline(), + (!v3Global.opt.l2Name().empty() + ? v3Global.opt.l2Name() : oldmodp->name()), + oldmodp->name(), + NULL, NULL, NULL); + cellp->modp(oldmodp); + newmodp->addStmtp(cellp); + + // Add pins + for (AstNode* subnodep=oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { + if (AstVar* oldvarp = VN_CAST(subnodep, Var)) { + UINFO(8,"VARWRAP "<isIO()) { + string name = oldvarp->name(); + if (dupNames.find(name) != dupNames.end()) { + // __02E=. while __DOT__ looks nicer but will break V3LinkDot + name = oldmodp->name()+"__02E"+name; + } + + AstVar* varp = oldvarp->cloneTree(false); + varp->name(name); + newmodp->addStmtp(varp); + varp->sigPublic(true); // User needs to be able to get to it... + if (oldvarp->isIO()) { + oldvarp->primaryIO(false); + varp->primaryIO(true); + } + if (varp->direction().isRefOrConstRef()) { + varp->v3error("Unsupported: ref/const ref as primary input/output: " + <prettyName()); + } + if (varp->isIO() && v3Global.opt.systemC()) { + varp->sc(true); + // User can see trace one level down from the wrapper + // Avoids packing & unpacking SC signals a second time + varp->trace(false); + } + + AstPin* pinp = new AstPin(oldvarp->fileline(), 0, varp->name(), + new AstVarRef(varp->fileline(), + varp, oldvarp->isWritable())); + // Skip length and width comp; we know it's a direct assignment + pinp->modVarp(oldvarp); + cellp->addPinsp(pinp); + } + } + } + } } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index d10084f53..568cbf786 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -90,7 +90,7 @@ private: // VISITORS virtual void visit(AstNetlist* nodep) { AstNodeModule* modp = nodep->topModulep(); - if (!modp) { nodep->v3error("No root module specified"); return; } + if (!modp) { nodep->v3error("No top level module found"); return; } // Operate starting at the top of the hierarchy m_aboveCellp = NULL; m_aboveScopep = NULL; diff --git a/test_regress/t/t_flag_topmodule_bad.out b/test_regress/t/t_flag_topmodule_bad.out index 346b43c34..d856bb542 100644 --- a/test_regress/t/t_flag_topmodule_bad.out +++ b/test_regress/t/t_flag_topmodule_bad.out @@ -1,4 +1,5 @@ -%Error-MULTITOP: t/t_flag_topmodule.v:14: Unsupported: Multiple top level modules: a2 and a - t/t_flag_topmodule.v:14: ... Fix, or use --top-module option to select which you want. -%Error-MULTITOP: t/t_flag_topmodule.v:21: Unsupported: Multiple top level modules: b and a2 +%Warning-MULTITOP: t/t_flag_topmodule.v:14: Multiple top level modules: a2 and a + t/t_flag_topmodule.v:14: ... Suggest see manual; fix the duplicates, or use --top-module to select top. + ... Use "/* verilator lint_off MULTITOP */" and lint_on around source to disable this message. +%Warning-MULTITOP: t/t_flag_topmodule.v:21: Multiple top level modules: b and a2 %Error: Exiting due to diff --git a/test_regress/t/t_mod_dup_bad.out b/test_regress/t/t_mod_dup_bad.out index a55c4eec9..7fe323200 100644 --- a/test_regress/t/t_mod_dup_bad.out +++ b/test_regress/t/t_mod_dup_bad.out @@ -1,6 +1,6 @@ %Warning-MODDUP: t/t_mod_dup_bad.v:13: Duplicate declaration of module: a t/t_mod_dup_bad.v:6: ... Location of original declaration ... Use "/* verilator lint_off MODDUP */" and lint_on around source to disable this message. -%Error-MULTITOP: t/t_mod_dup_bad.v:16: Unsupported: Multiple top level modules: b and test - t/t_mod_dup_bad.v:16: ... Fix, or use --top-module option to select which you want. +%Warning-MULTITOP: t/t_mod_dup_bad.v:16: Multiple top level modules: b and test + t/t_mod_dup_bad.v:16: ... Suggest see manual; fix the duplicates, or use --top-module to select top. %Error: Exiting due to diff --git a/test_regress/t/t_multitop1.pl b/test_regress/t/t_multitop1.pl new file mode 100755 index 000000000..ecd47aaf6 --- /dev/null +++ b/test_regress/t/t_multitop1.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +scenarios(vlt_all => 1); + +compile( + ); + +execute( + check_finished => 0, + ); + +# Order of lines is unspecified, so don't use a golden file +file_grep($Self->{run_log_filename}, qr!In 'top.t'!); +file_grep($Self->{run_log_filename}, qr!In 'top.t.s'!); +file_grep_not($Self->{run_log_filename}, qr!in_subfile!); + +ok(1); +1; diff --git a/test_regress/t/t_multitop1.v b/test_regress/t/t_multitop1.v new file mode 100644 index 000000000..1eaaea718 --- /dev/null +++ b/test_regress/t/t_multitop1.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + t_multitop1s s (); + initial $display("In '%m'"); + always @(posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_multitop1s.v b/test_regress/t/t_multitop1s.v new file mode 100644 index 000000000..2fc35f055 --- /dev/null +++ b/test_regress/t/t_multitop1s.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +module t_multitop1s; + initial $display("In '%m'"); +endmodule + +module in_subfile; + initial $display("In '%m'"); +endmodule diff --git a/test_regress/t/t_multitop_sig.cpp b/test_regress/t/t_multitop_sig.cpp new file mode 100644 index 000000000..8f5ed43cf --- /dev/null +++ b/test_regress/t/t_multitop_sig.cpp @@ -0,0 +1,44 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2006 by Wilson Snyder. + +#include +#include +#include "Vt_multitop_sig.h" + + +// Use cout to avoid issues with %d/%lx etc +#define CHECK_RESULT(got, exp) \ + if ((got) != (exp)) { \ + std::cout<a__02Ein = 0; + topp->b__02Ein = 0; + topp->uniq_in = 0; + topp->eval(); + CHECK_RESULT(topp->a__02Eout, 1); + CHECK_RESULT(topp->b__02Eout, 0); + CHECK_RESULT(topp->uniq_out, 1); + topp->a__02Ein = 1; + topp->b__02Ein = 1; + topp->uniq_in = 1; + topp->eval(); + CHECK_RESULT(topp->a__02Eout, 0); + CHECK_RESULT(topp->b__02Eout, 1); + CHECK_RESULT(topp->uniq_out, 0); + } + printf("*-* All Finished *-*\n"); +} diff --git a/test_regress/t/t_multitop_sig.pl b/test_regress/t/t_multitop_sig.pl new file mode 100755 index 000000000..6f98c4cda --- /dev/null +++ b/test_regress/t/t_multitop_sig.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +scenarios(vlt_all => 1); + +compile( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["-Wno-MULTITOP --exe $Self->{t_dir}/$Self->{name}.cpp"], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{run_log_filename}, qr!In 'a'!); +file_grep($Self->{run_log_filename}, qr!In 'a.sub'!); +file_grep($Self->{run_log_filename}, qr!In 'b'!); +file_grep($Self->{run_log_filename}, qr!In 'b.sub'!); +file_grep($Self->{run_log_filename}, qr!In 'c'!); +file_grep($Self->{run_log_filename}, qr!In 'c.sub'!); + +ok(1); +1; diff --git a/test_regress/t/t_multitop_sig.v b/test_regress/t/t_multitop_sig.v new file mode 100644 index 000000000..cc20c3287 --- /dev/null +++ b/test_regress/t/t_multitop_sig.v @@ -0,0 +1,32 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +module a(in, out); + input in; + output out; + assign out = !in; + sub sub (); + initial $display("In '%m'"); +endmodule + +module b(in, out); + input in; + output out; + assign out = in; + sub sub (); + initial $display("In '%m'"); +endmodule + +module c(uniq_in, uniq_out); + input uniq_in; + output uniq_out; + assign uniq_out = !uniq_in; + sub sub (); + initial $display("In '%m'"); +endmodule + +module sub; + initial $display("In '%m'"); +endmodule diff --git a/test_regress/t/t_multitop_sig_bad.out b/test_regress/t/t_multitop_sig_bad.out new file mode 100644 index 000000000..a37b98743 --- /dev/null +++ b/test_regress/t/t_multitop_sig_bad.out @@ -0,0 +1,5 @@ +%Warning-MULTITOP: t/t_multitop_sig.v:14: Multiple top level modules: b and a + t/t_multitop_sig.v:14: ... Suggest see manual; fix the duplicates, or use --top-module to select top. + ... Use "/* verilator lint_off MULTITOP */" and lint_on around source to disable this message. +%Warning-MULTITOP: t/t_multitop_sig.v:22: Multiple top level modules: c and b +%Error: Exiting due to diff --git a/test_regress/t/t_multitop_sig_bad.pl b/test_regress/t/t_multitop_sig_bad.pl new file mode 100755 index 000000000..24556312b --- /dev/null +++ b/test_regress/t/t_multitop_sig_bad.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +scenarios(simulator => 1); + +top_filename("t/t_multitop_sig.v"); + +compile( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1;