forked from github/verilator
Fix reporting not found modules if generate-off, bug403.
This commit is contained in:
parent
1a15d41523
commit
fb9ca54c95
2
Changes
2
Changes
@ -8,6 +8,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
*** Add sc_bv attribute to force bit vectors, bug402. [by Stefan Wallentowitz]
|
||||
|
||||
**** Fix reporting not found modules if generate-off, bug403. [Jeremy Bennett]
|
||||
|
||||
|
||||
* Verilator 3.824 2011/10/25
|
||||
|
||||
|
@ -973,6 +973,14 @@ struct AstModule : public AstNodeModule {
|
||||
virtual string verilogKwd() const { return "module"; }
|
||||
};
|
||||
|
||||
struct AstNotFoundModule : public AstNodeModule {
|
||||
// A missing module declaration
|
||||
AstNotFoundModule(FileLine* fl, const string& name)
|
||||
: AstNodeModule (fl,name) {}
|
||||
ASTNODE_NODE_FUNCS(NotFoundModule, NOTFOUNDMODULE)
|
||||
virtual string verilogKwd() const { return "/*not-found-*/ module"; }
|
||||
};
|
||||
|
||||
struct AstPackage : public AstNodeModule {
|
||||
// A package declaration
|
||||
AstPackage(FileLine* fl, const string& name)
|
||||
|
@ -563,8 +563,13 @@ private:
|
||||
nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out
|
||||
}
|
||||
else {
|
||||
if (nodep->modp()->castNotFoundModule()) {
|
||||
// Prevent warnings about missing pin connects
|
||||
if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
}
|
||||
// Need to pass the module info to this cell, so we can link up the pin names
|
||||
if (m_idState==ID_RESOLVE) {
|
||||
else if (m_idState==ID_RESOLVE) {
|
||||
m_cellVarsp = nodep->modp()->user4p()->castSymTable();
|
||||
UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
|
||||
//if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
|
||||
|
@ -176,8 +176,10 @@ private:
|
||||
AstNodeModule* modp = m_mods.findIdUpward(nodep->modName())->castNodeModule();
|
||||
if (!modp) {
|
||||
// Read-subfile
|
||||
// If file not found, make AstNotFoundModule, rather than error out.
|
||||
// We'll throw the error when we know the module will really be needed.
|
||||
V3Parse parser (v3Global.rootp(), m_filterp);
|
||||
parser.parseFile(nodep->fileline(), nodep->modName(), false);
|
||||
parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
|
||||
V3Error::abortIfErrors();
|
||||
// We've read new modules, grab new pointers to their names
|
||||
readModNames();
|
||||
|
@ -288,7 +288,8 @@ string V3Options::fileExists (const string& filename) {
|
||||
return filenameOut;
|
||||
}
|
||||
|
||||
string V3Options::filePath (FileLine* fl, const string& modname, const string& errmsg) {
|
||||
string V3Options::filePath (FileLine* fl, const string& modname,
|
||||
const string& errmsg) { // Error prefix or "" to suppress error
|
||||
// Find a filename to read the specified module name,
|
||||
// using the incdir and libext's.
|
||||
// Return "" if not found.
|
||||
@ -305,7 +306,14 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
|
||||
}
|
||||
|
||||
// Warn and return not found
|
||||
fl->v3error(errmsg+modname);
|
||||
if (errmsg != "") {
|
||||
fl->v3error(errmsg+modname);
|
||||
filePathLookedMsg(fl, modname);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
static bool shown_notfound_msg = false;
|
||||
if (!shown_notfound_msg) {
|
||||
shown_notfound_msg = true;
|
||||
@ -321,7 +329,6 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
|
||||
|
@ -345,6 +345,7 @@ class V3Options {
|
||||
// METHODS (file utilities using these options)
|
||||
string fileExists (const string& filename);
|
||||
string filePath (FileLine* fl, const string& modname, const string& errmsg);
|
||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
||||
static bool fileStatDir (const string& filename);
|
||||
static bool fileStatNormal (const string& filename);
|
||||
|
||||
|
@ -45,7 +45,8 @@ public:
|
||||
|
||||
// METHODS
|
||||
// Preprocess and read the Verilog file specified into the netlist database
|
||||
void parseFile(FileLine* fileline, const string& modname, bool inLibrary);
|
||||
void parseFile(FileLine* fileline, const string& modname, bool inLibrary,
|
||||
const string& errmsg);
|
||||
|
||||
// Push preprocessed text to the lexer
|
||||
static void ppPushText(V3ParseImp* impp, const string& text);
|
||||
|
@ -89,7 +89,8 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
|
||||
return got;
|
||||
}
|
||||
|
||||
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
|
||||
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
||||
const string& errmsg) { // "" for no error, make fake node
|
||||
string modname = V3Options::filenameNonExt(modfilename);
|
||||
|
||||
UINFO(2,__FUNCTION__<<": "<<modname<<(inLibrary?" [LIB]":"")<<endl);
|
||||
@ -104,7 +105,14 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
}
|
||||
|
||||
// Preprocess into m_ppBuffer
|
||||
V3PreShell::preproc(fileline, modfilename, m_filterp, this);
|
||||
bool ok = V3PreShell::preproc(fileline, modfilename, m_filterp, this, errmsg);
|
||||
if (!ok) {
|
||||
if (errmsg != "") return; // Threw error already
|
||||
// Create fake node for later error reporting
|
||||
AstNodeModule* nodep = new AstNotFoundModule(fileline, modname);
|
||||
v3Global.rootp()->addModulep(nodep);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
|
||||
// Create output file with all the preprocessor output we buffered up
|
||||
@ -157,8 +165,9 @@ V3Parse::V3Parse(AstNetlist* rootp, V3InFilter* filterp) {
|
||||
V3Parse::~V3Parse() {
|
||||
delete m_impp; m_impp = NULL;
|
||||
}
|
||||
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary) {
|
||||
m_impp->parseFile(fileline, modname, inLibrary);
|
||||
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary,
|
||||
const string& errmsg) {
|
||||
m_impp->parseFile(fileline, modname, inLibrary, errmsg);
|
||||
}
|
||||
void V3Parse::ppPushText(V3ParseImp* impp, const string& text) {
|
||||
impp->ppPushText(text);
|
||||
|
@ -333,7 +333,8 @@ public:
|
||||
// Preprocess and read the Verilog file specified into the netlist database
|
||||
int lexToBison(); // Pass token to bison
|
||||
|
||||
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary);
|
||||
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
|
||||
const string& errmsg);
|
||||
|
||||
private:
|
||||
void lexFile(const string& modname);
|
||||
|
@ -74,7 +74,8 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void preproc (FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep) {
|
||||
bool preproc (FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep,
|
||||
const string& errmsg) { // "" for no error
|
||||
debug(true); // Recheck if debug on - first check was before command line passed
|
||||
|
||||
// Preprocess the given module, putting output in vppFilename
|
||||
@ -82,11 +83,14 @@ protected:
|
||||
|
||||
// Preprocess
|
||||
s_filterp = filterp;
|
||||
preprocOpen(fl, s_filterp, modname, "Cannot find file containing module: ");
|
||||
bool ok = preprocOpen(fl, s_filterp, modname, errmsg);
|
||||
if (!ok) return false;
|
||||
|
||||
while (!s_preprocp->isEof()) {
|
||||
string line = s_preprocp->getline();
|
||||
V3Parse::ppPushText(parsep, line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void preprocInclude (FileLine* fl, const string& modname) {
|
||||
@ -96,17 +100,20 @@ protected:
|
||||
preprocOpen(fl, s_filterp, modname, "Cannot find include file: ");
|
||||
}
|
||||
|
||||
void preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname, const string& errmsg) {
|
||||
bool preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname,
|
||||
const string& errmsg) { // Error message or "" to suppress
|
||||
// Returns true if successful
|
||||
// Allow user to put `defined names on the command line instead of filenames,
|
||||
// then convert them properly.
|
||||
string ppmodname = s_preprocp->removeDefines (modname);
|
||||
|
||||
// Open include or master file
|
||||
string filename = v3Global.opt.filePath (fl, ppmodname, errmsg);
|
||||
if (filename=="") return; // Not found
|
||||
if (filename=="") return false; // Not found
|
||||
|
||||
UINFO(2," Reading "<<filename<<endl);
|
||||
s_preprocp->openFile(fl, filterp, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
// CONSTRUCTORS
|
||||
@ -124,8 +131,9 @@ V3InFilter* V3PreShellImp::s_filterp = NULL;
|
||||
void V3PreShell::boot(char** env) {
|
||||
V3PreShellImp::s_preImp.boot(env);
|
||||
}
|
||||
void V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep) {
|
||||
V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep);
|
||||
bool V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg) {
|
||||
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
|
||||
}
|
||||
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
|
||||
V3PreShellImp::s_preImp.preprocInclude(fl, modname);
|
||||
|
@ -36,7 +36,8 @@ class V3PreShell {
|
||||
// Static class for calling preprocessor
|
||||
public:
|
||||
static void boot(char** env);
|
||||
static void preproc(FileLine* fileline, const string& module, V3InFilter* filterp, V3ParseImp* parsep);
|
||||
static bool preproc(FileLine* fileline, const string& module, V3InFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg);
|
||||
static void preprocInclude(FileLine* fileline, const string& module);
|
||||
static string dependFiles() { return ""; } // Perl only
|
||||
static void defineCmdLine(const string& name, const string& value);
|
||||
|
@ -1137,6 +1137,13 @@ private:
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
if (!m_paramsOnly) {
|
||||
if (nodep->modp()->castNotFoundModule()) {
|
||||
// We've resolved parameters and hit a module that we couldn't resolve. It's
|
||||
// finally time to report it.
|
||||
// Note only here in V3Width as this is first visitor after V3Dead.
|
||||
nodep->v3error("Cannot find file containing module: "<<nodep->modName());
|
||||
v3Global.opt.filePathLookedMsg(nodep->fileline(), nodep->modName());
|
||||
}
|
||||
if (nodep->rangep()) {
|
||||
m_cellRangep = nodep->rangep();
|
||||
nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
|
@ -106,7 +106,8 @@ void V3Global::readFiles() {
|
||||
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
||||
it != v3Global.opt.vFiles().end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false);
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false,
|
||||
"Cannot find file containing module: ");
|
||||
}
|
||||
|
||||
// Read libraries
|
||||
@ -115,7 +116,8 @@ void V3Global::readFiles() {
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin();
|
||||
it != v3Global.opt.libraryFiles().end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true);
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true,
|
||||
"Cannot find file containing library module: ");
|
||||
}
|
||||
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));
|
||||
V3Error::abortIfErrors();
|
||||
|
19
test_regress/t/t_gen_missing.pl
Executable file
19
test_regress/t/t_gen_missing.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+T_GEN_MISSING'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
58
test_regress/t/t_gen_missing.v
Normal file
58
test_regress/t/t_gen_missing.v
Normal file
@ -0,0 +1,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2011 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
`ifdef T_GEN_MISSING_BAD
|
||||
foobar #(.FOO_TYPE(1)) foobar; // This means we should instatiate missing module
|
||||
`elsif T_GEN_MISSING
|
||||
foobar #(.FOO_TYPE(0)) foobar; // This means we should instatiate foo0
|
||||
`else
|
||||
`error "Bad Test"
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
|
||||
module foobar
|
||||
#( parameter
|
||||
FOO_START = 0,
|
||||
FOO_NUM = 2,
|
||||
FOO_TYPE = 1
|
||||
)
|
||||
(
|
||||
input wire[FOO_NUM-1:0] foo,
|
||||
output wire[FOO_NUM-1:0] bar);
|
||||
|
||||
|
||||
generate
|
||||
begin: g
|
||||
genvar j;
|
||||
for (j = FOO_START; j < FOO_NUM+FOO_START; j = j + 1)
|
||||
begin: foo_inst;
|
||||
if (FOO_TYPE == 0)
|
||||
begin: foo_0
|
||||
// instatiate foo0
|
||||
foo0 i_foo(.x(foo[j]), .y(bar[j]));
|
||||
end
|
||||
if (FOO_TYPE == 1)
|
||||
begin: foo_1
|
||||
// instatiate foo1
|
||||
foo_not_needed i_foo(.x(foo[j]), .y(bar[j]));
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
module foo0(input wire x, output wire y);
|
||||
|
||||
assign y = ~x;
|
||||
|
||||
initial begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
26
test_regress/t/t_gen_missing_bad.pl
Executable file
26
test_regress/t/t_gen_missing_bad.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
top_filename("t/t_gen_missing.v");
|
||||
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
compile (
|
||||
v_flags2 => ['+define+T_GEN_MISSING_BAD'],
|
||||
fails => 1,
|
||||
expect=>
|
||||
'%Error: t/t_gen_missing.v:\d+: Cannot find file containing module: foo_not_needed
|
||||
%Error: t/t_gen_missing.v:\d+: Looked in:
|
||||
%Error: t/t_gen_missing.v:\d+: foo_not_needed
|
||||
%Error: t/t_gen_missing.v:\d+: foo_not_needed.v
|
||||
%Error: t/t_gen_missing.v:\d+: foo_not_needed.sv
|
||||
.*%Error: Exiting due to.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
Loading…
Reference in New Issue
Block a user