Fix ugly interface-to-non-interface errors, bug1112.

This commit is contained in:
Wilson Snyder 2017-03-17 18:35:53 -04:00
parent fa9208ccdd
commit 473d555dc1
4 changed files with 43 additions and 27 deletions

View File

@ -1759,26 +1759,29 @@ private:
// Upper AstDot visitor will handle it from here
}
else if (foundp->nodep()->castCell()
&& allowVar && m_cellp
&& foundp->nodep()->castCell()->modp()->castIface()) {
// Interfaces can be referenced like a variable for interconnect
&& allowVar && m_cellp) {
AstCell* cellp = foundp->nodep()->castCell();
VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin
string findName = nodep->name()+"__Viftop";
VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName);
AstVar* ifaceRefVarp = ifaceSymp ? ifaceSymp->nodep()->castVar() : NULL;
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
//
ok = true;
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotSymp = foundp;
m_ds.m_dotPos = DP_SCOPE;
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
}
if (cellp->modp()->castIface()) {
// Interfaces can be referenced like a variable for interconnect
VSymEnt* cellEntp = m_statep->getNodeSym(cellp); if (!cellEntp) nodep->v3fatalSrc("No interface sym entry");
VSymEnt* parentEntp = cellEntp->parentp(); // Container of the var; probably a module or generate begin
string findName = nodep->name()+"__Viftop";
VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName);
AstVar* ifaceRefVarp = ifaceSymp ? ifaceSymp->nodep()->castVar() : NULL;
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
//
ok = true;
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
m_ds.m_dotText += nodep->name();
m_ds.m_dotSymp = foundp;
m_ds.m_dotPos = DP_SCOPE;
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
} else if (cellp->modp()->castNotFoundModule()) {
cellp->v3error("Cannot find file containing interface: " << AstNode::prettyName(cellp->modp()->name()));
}
}
}
else if (AstVar* varp = foundp->nodep()->castVar()) {
AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(varp->subDTypep());
@ -1858,7 +1861,9 @@ private:
}
//
if (!ok) {
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="");
//Cells/interfaces can't be implicit
bool isCell = foundp ? foundp->nodep()->castCell() != NULL : false;
bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell);
bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name()));
if (err) {
if (foundp) {

View File

@ -541,7 +541,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
AstVar* modvarp = pinp->modVarp();
if (modvarp->isIfaceRef()) {
AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
if (!portIrefp) {
if (!portIrefp && modvarp->subDTypep()->castUnpackArrayDType()) {
portIrefp = modvarp->subDTypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
}
@ -574,7 +574,7 @@ void ParamVisitor::visitCell(AstCell* nodep) {
UINFO(9," portIfaceRef "<<portIrefp<<endl);
if (!portIrefp) {
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not an interface" << modvarp);
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not an interface " << modvarp);
} else if (!pinIrefp) {
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not connected to interface/modport pin expression");
} else {

View File

@ -2157,15 +2157,25 @@ private:
// otherwise would need some mess to force both sides to proper size
}
}
// Check if an interface is connected to a non-interface and vice versa
AstNodeDType* modDTypep = nodep->modVarp()->dtypep();
AstNodeDType* exprDTypep = nodep->exprp()->dtypep();
if ((modDTypep->castIfaceRefDType() && !exprDTypep->castIfaceRefDType()) ||
(exprDTypep->castIfaceRefDType() && !modDTypep->castIfaceRefDType())) {
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
<<" mismatch between port which is"<<(modDTypep->castIfaceRefDType()?"":" not")<<" an interface,"
<<" and expression which is"<<(exprDTypep->castIfaceRefDType()?"":" not")<<" an interface.");
}
// TODO Simple dtype checking, should be a more general check
bool hiArray = nodep->exprp()->dtypep()->skipRefp()->castUnpackArrayDType();
bool loArray = nodep->modVarp()->dtypep()->skipRefp()->castUnpackArrayDType();
bool hiArray = exprDTypep->skipRefp()->castUnpackArrayDType();
bool loArray = modDTypep->skipRefp()->castUnpackArrayDType();
if (loArray != hiArray && pinwidth != conwidth) {
nodep->v3error("Illegal "<<nodep->prettyOperatorName()<<","
<<" mismatch between port which is"<<(hiArray?"":" not")<<" an array,"
<<" and expression which is"<<(loArray?"":" not")<<" an array.");
UINFO(1," Related lo: "<<nodep->exprp()->dtypep()->skipRefp()<<endl);
UINFO(1," Related hi: "<<nodep->modVarp()->dtypep()->skipRefp()<<endl);
UINFO(1," Related lo: "<<exprDTypep->skipRefp()<<endl);
UINFO(1," Related hi: "<<modDTypep->skipRefp()<<endl);
}
iterateCheckAssign(nodep,"pin connection",nodep->exprp(),FINAL,subDTypep);
}

View File

@ -17,7 +17,8 @@ compile (
# However we no longer gate optimize this
expect=>
q{%Error: t/t_interface_typo_bad.v:\d+: Parent cell's interface is not found: foo_intf
%Warning-IMPLICIT: t/t_interface_typo_bad.v:\d+: Signal definition not found, creating implicitly: the_foo
%Error: t/t_interface_typo_bad.v:\d+: Cannot find file containing interface: fo_intf
%Error: t/t_interface_typo_bad.v:\d+: Found definition of 'the_foo' as a CELL but expected a variable
.*},
);