Change MULTITOP to warning to help linting, see manual.

This commit is contained in:
Wilson Snyder
2019-06-30 16:46:48 -04:00
parent 5f27c41ee3
commit f7641d2ecc
18 changed files with 329 additions and 84 deletions
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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",
+2 -1
View File
@@ -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();
+9 -7
View File
@@ -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: "<<topmodp<<endl);
}
for (AstNodeModule* modp = nodep->modulesp(); modp && modp->level() <= 2;
modp = VN_CAST(modp->nextp(), NodeModule)) {
UINFO(8,"Top Module: "<<modp<<endl);
m_scope = "TOP";
m_curSymp = m_modSymp = m_statep->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;
+95 -58
View File
@@ -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: "
<<nodep->prettyName()<<" and "<<topp->prettyName()<<endl
nodep->v3warn(MULTITOP, "Multiple top level modules: "
<<nodep->prettyName()<<" and "<<topp->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__<<": "<<endl);
// We do ONLY the top module
AstNodeModule* oldmodp = rootp->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 "<<oldvarp<<endl);
if (oldvarp->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: "
<<varp->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<std::string> 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: "<<oldvarp<<endl);
dupNames.insert(oldvarp->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 "<<oldmodp<<endl);
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 "<<oldvarp<<endl);
if (oldvarp->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: "
<<varp->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);
}
}
}
}
}
+1 -1
View File
@@ -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;