Fix reporting not found modules if generate-off, bug403.

This commit is contained in:
Wilson Snyder 2011-10-27 20:56:38 -04:00
parent 1a15d41523
commit fb9ca54c95
16 changed files with 177 additions and 20 deletions

View File

@ -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

View File

@ -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)

View File

@ -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:"); }

View File

@ -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();

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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());

View File

@ -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
View 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;

View 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

View 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;