From 67d5b1a11a3a05b0bd3796a1b4cc15f776f0a430 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 8 Nov 2020 19:15:53 -0500 Subject: [PATCH] Internals: Preserve arrays of modports. Part of #2614. --- src/V3LinkDot.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 2356c30a5..f7dc86027 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1866,14 +1866,16 @@ private: } } 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 string varName = cellp->name() + "__Vmp__" + modportp->name() + "__Viftop" + cvtToStr(++m_modportNum); AstIfaceRefDType* idtypep = new AstIfaceRefDType(fl, modportp->fileline(), cellp->name(), ifacep->name(), modportp->name()); 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); m_modp->addStmtp(varp); return varp; @@ -2277,8 +2279,25 @@ private: m_ds.m_dotSymp = m_statep->getNodeSym(modportp); m_ds.m_dotPos = DP_SCOPE; ok = true; - AstVar* varp = makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp); - AstVarRef* refp = new AstVarRef(varp->fileline(), varp, VAccess::READ); + auto* cellarrayrefp = VN_CAST(m_ds.m_unlinkedScopep, CellArrayRef); + 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); VL_DO_DANGLING(pushDeletep(nodep), nodep); }