Internals: Rework implicit handling to make room for ParseRef vs. VarRef
This commit is contained in:
parent
8d5e37a413
commit
f175db74a5
|
|
@ -74,10 +74,13 @@ private:
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::multimap<string,VSymEnt*> NameScopeMap;
|
typedef std::multimap<string,VSymEnt*> NameScopeMap;
|
||||||
|
typedef set <pair<AstNodeModule*,string> > ImplicitNameSet;
|
||||||
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
VSymGraph m_syms; // Symbol table
|
VSymGraph m_syms; // Symbol table
|
||||||
VSymEnt* m_dunitEntp; // $unit entry
|
VSymEnt* m_dunitEntp; // $unit entry
|
||||||
NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name
|
NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name
|
||||||
|
ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it
|
||||||
bool m_forPrimary; // First link
|
bool m_forPrimary; // First link
|
||||||
bool m_forPrearray; // Compress cell__[array] refs
|
bool m_forPrearray; // Compress cell__[array] refs
|
||||||
bool m_forScopeCreation; // Remove VarXRefs for V3Scope
|
bool m_forScopeCreation; // Remove VarXRefs for V3Scope
|
||||||
|
|
@ -271,6 +274,20 @@ public:
|
||||||
}
|
}
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
void implicitOkAdd(AstNodeModule* nodep, const string& varname) {
|
||||||
|
// Mark the given variable name as being allowed to be implicitly declared
|
||||||
|
if (nodep) {
|
||||||
|
ImplicitNameSet::iterator iter = m_implicitNameSet.find(make_pair(nodep,varname));
|
||||||
|
if (iter == m_implicitNameSet.end()) {
|
||||||
|
m_implicitNameSet.insert(make_pair(nodep,varname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool implicitOk(AstNodeModule* nodep, const string& varname) {
|
||||||
|
return nodep
|
||||||
|
&& (m_implicitNameSet.find(make_pair(nodep,varname)) != m_implicitNameSet.end());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VSymEnt* findWithAltFallback(VSymEnt* symp, const string& name, const string& altname) {
|
VSymEnt* findWithAltFallback(VSymEnt* symp, const string& name, const string& altname) {
|
||||||
VSymEnt* findp = symp->findIdFallback(name);
|
VSymEnt* findp = symp->findIdFallback(name);
|
||||||
|
|
@ -370,46 +387,6 @@ public:
|
||||||
if (!foundp) baddot = dotname;
|
if (!foundp) baddot = dotname;
|
||||||
return foundp;
|
return foundp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// METHODS - Variables
|
|
||||||
bool linkVarName (VSymEnt* lookupSymp, AstVarRef* nodep) {
|
|
||||||
// Return true if changed, and caller should end processing
|
|
||||||
if (!nodep->varp()) {
|
|
||||||
UINFO(9," linkVarName se"<<(void*)lookupSymp<<" n="<<nodep<<endl);
|
|
||||||
if (!lookupSymp) nodep->v3fatalSrc("NULL lookup symbol table");
|
|
||||||
VSymEnt* foundp = lookupSymp->findIdFallback(nodep->name());
|
|
||||||
if (AstVar* varp = foundp->nodep()->castVar()) {
|
|
||||||
nodep->varp(varp);
|
|
||||||
nodep->packagep(foundp->packagep());
|
|
||||||
}
|
|
||||||
else if (AstEnumItem* valuep = foundp->nodep()->castEnumItem()) {
|
|
||||||
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep());
|
|
||||||
nodep->replaceWith(newp);
|
|
||||||
nodep->deleteTree(); nodep=NULL;
|
|
||||||
return true; // Edited
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void createImplicitVar (VSymEnt* lookupSymp, AstVarRef* nodep, AstNodeModule* modp, VSymEnt* moduleSymp, bool noWarn) {
|
|
||||||
// Create implicit after warning
|
|
||||||
if (linkVarName(lookupSymp, nodep)) { nodep=NULL; return; }
|
|
||||||
if (!nodep->varp()) {
|
|
||||||
if (!noWarn) {
|
|
||||||
if (nodep->fileline()->warnIsOff(V3ErrorCode::I_DEF_NETTYPE_WIRE)) {
|
|
||||||
nodep->v3error("Signal definition not found, and implicit disabled with `default_nettype: "<<nodep->prettyName());
|
|
||||||
} else {
|
|
||||||
nodep->v3warn(IMPLICIT,"Signal definition not found, creating implicitly: "<<nodep->prettyName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AstVar* newp = new AstVar (nodep->fileline(), AstVarType::WIRE,
|
|
||||||
nodep->name(), VFlagLogicPacked(), 1);
|
|
||||||
newp->trace(modp->modTrace());
|
|
||||||
modp->addStmtp(newp);
|
|
||||||
// Link it to signal list, must add the variable under the module; current scope might be lower now
|
|
||||||
insertSym(moduleSymp, newp->name(), newp, NULL/*packagep*/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
|
|
@ -812,13 +789,11 @@ private:
|
||||||
void pinImplicitExprRecurse(AstNode* nodep) {
|
void pinImplicitExprRecurse(AstNode* nodep) {
|
||||||
// Under a pin, Check interconnect expression for a pin reference or a concat.
|
// Under a pin, Check interconnect expression for a pin reference or a concat.
|
||||||
// Create implicit variable as needed
|
// Create implicit variable as needed
|
||||||
if (AstVarRef* varrefp = nodep->castVarRef()) {
|
if (nodep->castVarRef()) {
|
||||||
// To prevent user errors, we should only do single bit
|
// To prevent user errors, we should only do single bit
|
||||||
// implicit vars, however some netlists (MIPS) expect single
|
// implicit vars, however some netlists (MIPS) expect single
|
||||||
// bit implicit wires to get created with range 0:0 etc.
|
// bit implicit wires to get created with range 0:0 etc.
|
||||||
//if (!nodep->modVarp()->rangep()) ...
|
m_statep->implicitOkAdd(m_modp, nodep->name());
|
||||||
// Note FindVisitor::visit AstVarRef stashes user1p specifically for this getNodeSym
|
|
||||||
m_statep->createImplicitVar(m_statep->getNodeSym(nodep), varrefp, m_modp, m_statep->getNodeSym(m_modp), false);
|
|
||||||
}
|
}
|
||||||
// These are perhaps a little too generous, as a SELect of siga[sigb]
|
// These are perhaps a little too generous, as a SELect of siga[sigb]
|
||||||
// perhaps shouldn't create an implicit variable. But, we've warned...
|
// perhaps shouldn't create an implicit variable. But, we've warned...
|
||||||
|
|
@ -1028,6 +1003,47 @@ private:
|
||||||
|
|
||||||
int debug() { return LinkDotState::debug(); }
|
int debug() { return LinkDotState::debug(); }
|
||||||
|
|
||||||
|
// METHODS - Variables
|
||||||
|
bool linkVarName (VSymEnt* lookupSymp, AstVarRef* nodep) {
|
||||||
|
// Return true if changed, and caller should end processing
|
||||||
|
if (!nodep->varp()) {
|
||||||
|
UINFO(9," linkVarName se"<<(void*)lookupSymp<<" n="<<nodep<<endl);
|
||||||
|
if (!lookupSymp) nodep->v3fatalSrc("NULL lookup symbol table");
|
||||||
|
VSymEnt* foundp = lookupSymp->findIdFallback(nodep->name());
|
||||||
|
if (AstVar* varp = foundp->nodep()->castVar()) {
|
||||||
|
nodep->varp(varp);
|
||||||
|
nodep->packagep(foundp->packagep());
|
||||||
|
}
|
||||||
|
else if (AstEnumItem* valuep = foundp->nodep()->castEnumItem()) {
|
||||||
|
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep());
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
return true; // Edited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void createImplicitVar (VSymEnt* lookupSymp, AstVarRef* nodep, AstNodeModule* modp, VSymEnt* moduleSymp, bool noWarn) {
|
||||||
|
// Create implicit after warning
|
||||||
|
if (linkVarName(lookupSymp, nodep)) { nodep=NULL; return; }
|
||||||
|
if (!nodep->varp()) {
|
||||||
|
if (!noWarn) {
|
||||||
|
if (nodep->fileline()->warnIsOff(V3ErrorCode::I_DEF_NETTYPE_WIRE)) {
|
||||||
|
nodep->v3error("Signal definition not found, and implicit disabled with `default_nettype: "<<nodep->prettyName());
|
||||||
|
} else {
|
||||||
|
nodep->v3warn(IMPLICIT,"Signal definition not found, creating implicitly: "<<nodep->prettyName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AstVar* newp = new AstVar (nodep->fileline(), AstVarType::WIRE,
|
||||||
|
nodep->name(), VFlagLogicPacked(), 1);
|
||||||
|
newp->trace(modp->modTrace());
|
||||||
|
nodep->varp(newp);
|
||||||
|
modp->addStmtp(newp);
|
||||||
|
// Link it to signal list, must add the variable under the module; current scope might be lower now
|
||||||
|
m_statep->insertSym(moduleSymp, newp->name(), newp, NULL/*packagep*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITs
|
||||||
virtual void visit(AstNetlist* nodep, AstNUser* vup) {
|
virtual void visit(AstNetlist* nodep, AstNUser* vup) {
|
||||||
// Recurse..., backward as must do packages before using packages
|
// Recurse..., backward as must do packages before using packages
|
||||||
|
|
@ -1116,11 +1132,16 @@ private:
|
||||||
// VarRef: Resolve its reference
|
// VarRef: Resolve its reference
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (!nodep->varp()) {
|
if (!nodep->varp()) {
|
||||||
if (m_statep->linkVarName(m_curSymp, nodep)) { nodep=NULL; return; }
|
if (linkVarName(m_curSymp, nodep)) { nodep=NULL; return; }
|
||||||
if (!nodep->varp()) {
|
if (!nodep->varp()) {
|
||||||
|
bool err = (m_statep->forPrimary()
|
||||||
|
&& !m_statep->implicitOk(m_modp, nodep->name()));
|
||||||
|
if (err) {
|
||||||
m_statep->preErrorDump();
|
m_statep->preErrorDump();
|
||||||
nodep->v3error("Can't find definition of signal: "<<nodep->prettyName());
|
nodep->v3error("Can't find definition of signal: "<<nodep->prettyName());
|
||||||
m_statep->createImplicitVar (m_curSymp, nodep, m_modp, m_modSymp, true); // So only complain once
|
}
|
||||||
|
// Create even if error, so only complain once
|
||||||
|
createImplicitVar (m_curSymp, nodep, m_modp, m_modSymp, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue