Internals: Preserve arrays of modports. Part of #2614.

This commit is contained in:
Wilson Snyder 2020-11-08 19:15:53 -05:00
parent d78941885b
commit 67d5b1a11a

View File

@ -1866,14 +1866,16 @@ private:
} }
} }
AstVar* makeIfaceModportVar(FileLine* fl, AstCell* cellp, AstIface* ifacep, AstVar* makeIfaceModportVar(FileLine* fl, AstCell* cellp, AstIface* ifacep,
AstModport* modportp) { AstModport* modportp, AstRange* rangep) {
// Create iface variable, using duplicate var when under same module scope // Create iface variable, using duplicate var when under same module scope
string varName string varName
= cellp->name() + "__Vmp__" + modportp->name() + "__Viftop" + cvtToStr(++m_modportNum); = cellp->name() + "__Vmp__" + modportp->name() + "__Viftop" + cvtToStr(++m_modportNum);
AstIfaceRefDType* idtypep = new AstIfaceRefDType(fl, modportp->fileline(), cellp->name(), AstIfaceRefDType* idtypep = new AstIfaceRefDType(fl, modportp->fileline(), cellp->name(),
ifacep->name(), modportp->name()); ifacep->name(), modportp->name());
idtypep->cellp(cellp); idtypep->cellp(cellp);
AstVar* varp = new AstVar(fl, AstVarType::IFACEREF, varName, VFlagChildDType(), idtypep); AstNodeDType* vdtypep = idtypep;
if (rangep) vdtypep = new AstUnpackArrayDType(fl, VFlagChildDType(), vdtypep, rangep);
AstVar* varp = new AstVar(fl, AstVarType::IFACEREF, varName, VFlagChildDType(), vdtypep);
varp->isIfaceParent(true); varp->isIfaceParent(true);
m_modp->addStmtp(varp); m_modp->addStmtp(varp);
return varp; return varp;
@ -2277,8 +2279,25 @@ private:
m_ds.m_dotSymp = m_statep->getNodeSym(modportp); m_ds.m_dotSymp = m_statep->getNodeSym(modportp);
m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotPos = DP_SCOPE;
ok = true; ok = true;
AstVar* varp = makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp); auto* cellarrayrefp = VN_CAST(m_ds.m_unlinkedScopep, CellArrayRef);
AstVarRef* refp = new AstVarRef(varp->fileline(), varp, VAccess::READ); AstRange* rangep = nullptr;
if (cellarrayrefp)
rangep = new AstRange(nodep->fileline(),
cellarrayrefp->selp()->cloneTree(true),
cellarrayrefp->selp()->cloneTree(true));
AstVar* varp
= makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp, rangep);
AstNode* refp = new AstVarRef(varp->fileline(), varp, VAccess::READ);
if (cellarrayrefp) {
// iface[vec].modport became CellArrayRef(iface, lsb)
// Convert back to SelBit(iface, lsb)
UINFO(9, " Array modport to SelBit " << cellarrayrefp << endl);
refp = new AstSelBit(cellarrayrefp->fileline(), refp,
cellarrayrefp->selp()->unlinkFrBack());
refp->user3(true); // Don't process again
VL_DO_DANGLING(cellarrayrefp->unlinkFrBack(), cellarrayrefp);
m_ds.m_unlinkedScopep = nullptr;
}
nodep->replaceWith(refp); nodep->replaceWith(refp);
VL_DO_DANGLING(pushDeletep(nodep), nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }