Internals: Refactor huge func in V3Param. No functional change intended.

This commit is contained in:
Wilson Snyder 2020-11-16 22:35:51 -05:00
parent 0e1e380a55
commit 1e7c61b23e
1 changed files with 99 additions and 97 deletions

View File

@ -316,6 +316,25 @@ private:
}
return string("z") + cvtToStr(num);
}
string moduleCalcName(AstNodeModule* srcModp, AstCell* cellp, const string& longname) {
string newname = longname;
if (longname.length() > 30 || srcModp->hierBlock()) {
const auto iter = m_longMap.find(longname);
if (iter != m_longMap.end()) {
newname = iter->second;
} else {
if (srcModp->hierBlock()) {
newname = parametrizedHierBlockName(srcModp, cellp->paramsp());
} else {
newname = srcModp->name();
// We use all upper case above, so lower here can't conflict
newname += "__pi" + cvtToStr(++m_longId);
}
m_longMap.insert(make_pair(longname, newname));
}
}
return newname;
}
AstNodeDType* arraySubDTypep(AstNodeDType* nodep) {
// If an unpacked array, return the subDTypep under it
if (AstUnpackArrayDType* adtypep = VN_CAST(nodep, UnpackArrayDType)) {
@ -436,6 +455,83 @@ private:
hash.insert(V3Os::trueRandom(64));
}
}
AstNodeModule* deepCloneModule(AstNodeModule* srcModp, AstCell* cellp, const string& newname,
const IfaceRefRefs& ifaceRefRefs) {
// Deep clone of new module
// Note all module internal variables will be re-linked to the new modules by clone
// However links outside the module (like on the upper cells) will not.
AstNodeModule* newmodp = srcModp->cloneTree(false);
newmodp->name(newname);
newmodp->user5(false); // We need to re-recurse this module once changed
newmodp->recursive(false);
newmodp->recursiveClone(false);
// Only the first generation of clone holds this property
newmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone());
cellp->recursive(false);
// Recursion may need level cleanups
if (newmodp->level() <= m_modp->level()) newmodp->level(m_modp->level() + 1);
if ((newmodp->level() - srcModp->level()) >= (v3Global.opt.moduleRecursionDepth() - 2)) {
cellp->v3error("Exceeded maximum --module-recursion-depth of "
<< v3Global.opt.moduleRecursionDepth());
}
// Keep tree sorted by level
AstNodeModule* insertp = srcModp;
while (VN_IS(insertp->nextp(), NodeModule)
&& VN_CAST(insertp->nextp(), NodeModule)->level() < newmodp->level()) {
insertp = VN_CAST(insertp->nextp(), NodeModule);
}
insertp->addNextHere(newmodp);
m_modNameMap.insert(make_pair(newmodp->name(), ModInfo(newmodp)));
auto iter = m_modNameMap.find(newname);
CloneMap* clonemapp = &(iter->second.m_cloneMap);
UINFO(4, " De-parameterize to new: " << newmodp << endl);
// Grab all I/O so we can remap our pins later
// Note we allow multiple users of a parameterized model,
// thus we need to stash this info.
collectPins(clonemapp, newmodp);
// Relink parameter vars to the new module
relinkPins(clonemapp, cellp->paramsp());
// Fix any interface references
for (auto it = ifaceRefRefs.cbegin(); it != ifaceRefRefs.cend(); ++it) {
AstIfaceRefDType* portIrefp = it->first;
AstIfaceRefDType* pinIrefp = it->second;
AstIfaceRefDType* cloneIrefp = portIrefp->clonep();
UINFO(8, " IfaceOld " << portIrefp << endl);
UINFO(8, " IfaceTo " << pinIrefp << endl);
UASSERT_OBJ(cloneIrefp, portIrefp, "parameter clone didn't hit AstIfaceRefDType");
UINFO(8, " IfaceClo " << cloneIrefp << endl);
cloneIrefp->ifacep(pinIrefp->ifaceViaCellp());
UINFO(8, " IfaceNew " << cloneIrefp << endl);
}
// Assign parameters to the constants specified
// DOES clone() so must be finished with module clonep() before here
for (AstPin* pinp = cellp->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
if (pinp->exprp()) {
if (newmodp->hierBlock()) checkSupportedParam(newmodp, pinp);
if (AstVar* modvarp = pinp->modVarp()) {
AstNode* newp = pinp->exprp(); // Const or InitArray
// Remove any existing parameter
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
// Set this parameter to value requested by cell
modvarp->valuep(newp->cloneTree(false));
modvarp->overriddenParam(true);
} else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType);
UASSERT_OBJ(dtypep, pinp, "unlinked param dtype");
if (modptp->childDTypep()) {
pushDeletep(modptp->childDTypep()->unlinkFrBack());
}
// Set this parameter to value requested by cell
modptp->childDTypep(dtypep->cloneTree(false));
// Later V3LinkDot will convert the ParamDType to a Typedef
// Not done here as may be localparams, etc, that also need conversion
}
}
}
return newmodp;
}
void visitCell(AstCell* nodep, const string& hierName);
void visitModules() {
// Loop on all modules left to process
@ -887,7 +983,6 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) {
if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) {
portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType);
}
AstIfaceRefDType* pinIrefp = nullptr;
AstNode* exprp = pinp->exprp();
AstVar* varp
@ -954,116 +1049,23 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) {
// We don't do this always, as it aids debugability to have intuitive naming.
// TODO can use new V3Name hash replacement instead of this
// Shorter name is convenient for hierarchical block
string newname = longname;
if (longname.length() > 30 || srcModp->hierBlock()) {
const auto iter = m_longMap.find(longname);
if (iter != m_longMap.end()) {
newname = iter->second;
} else {
if (srcModp->hierBlock()) {
newname = parametrizedHierBlockName(srcModp, nodep->paramsp());
} else {
newname = srcModp->name();
// We use all upper case above, so lower here can't conflict
newname += "__pi" + cvtToStr(++m_longId);
}
m_longMap.insert(make_pair(longname, newname));
}
}
string newname = moduleCalcName(srcModp, nodep, longname);
UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl);
//
// Already made this flavor?
AstNodeModule* cellmodp = nullptr;
auto iter = m_modNameMap.find(newname);
if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp;
if (!cellmodp) {
// Deep clone of new module
// Note all module internal variables will be re-linked to the new modules by clone
// However links outside the module (like on the upper cells) will not.
cellmodp = srcModp->cloneTree(false);
cellmodp->name(newname);
cellmodp->user5(false); // We need to re-recurse this module once changed
cellmodp->recursive(false);
cellmodp->recursiveClone(false);
// Only the first generation of clone holds this property
cellmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone());
nodep->recursive(false);
// Recursion may need level cleanups
if (cellmodp->level() <= m_modp->level()) cellmodp->level(m_modp->level() + 1);
if ((cellmodp->level() - srcModp->level())
>= (v3Global.opt.moduleRecursionDepth() - 2)) {
nodep->v3error("Exceeded maximum --module-recursion-depth of "
<< v3Global.opt.moduleRecursionDepth());
}
// Keep tree sorted by level
AstNodeModule* insertp = srcModp;
while (VN_IS(insertp->nextp(), NodeModule)
&& VN_CAST(insertp->nextp(), NodeModule)->level() < cellmodp->level()) {
insertp = VN_CAST(insertp->nextp(), NodeModule);
}
insertp->addNextHere(cellmodp);
m_modNameMap.insert(make_pair(cellmodp->name(), ModInfo(cellmodp)));
cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs);
iter = m_modNameMap.find(newname);
CloneMap* clonemapp = &(iter->second.m_cloneMap);
UINFO(4, " De-parameterize to new: " << cellmodp << endl);
// Grab all I/O so we can remap our pins later
// Note we allow multiple users of a parameterized model,
// thus we need to stash this info.
collectPins(clonemapp, cellmodp);
// Relink parameter vars to the new module
relinkPins(clonemapp, nodep->paramsp());
// Fix any interface references
for (IfaceRefRefs::iterator it = ifaceRefRefs.begin(); it != ifaceRefRefs.end();
++it) {
AstIfaceRefDType* portIrefp = it->first;
AstIfaceRefDType* pinIrefp = it->second;
AstIfaceRefDType* cloneIrefp = portIrefp->clonep();
UINFO(8, " IfaceOld " << portIrefp << endl);
UINFO(8, " IfaceTo " << pinIrefp << endl);
UASSERT_OBJ(cloneIrefp, portIrefp,
"parameter clone didn't hit AstIfaceRefDType");
UINFO(8, " IfaceClo " << cloneIrefp << endl);
cloneIrefp->ifacep(pinIrefp->ifaceViaCellp());
UINFO(8, " IfaceNew " << cloneIrefp << endl);
}
// Assign parameters to the constants specified
// DOES clone() so must be finished with module clonep() before here
for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
if (pinp->exprp()) {
if (cellmodp->hierBlock()) checkSupportedParam(cellmodp, pinp);
if (AstVar* modvarp = pinp->modVarp()) {
AstNode* newp = pinp->exprp(); // Const or InitArray
// Remove any existing parameter
if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree();
// Set this parameter to value requested by cell
modvarp->valuep(newp->cloneTree(false));
modvarp->overriddenParam(true);
} else if (AstParamTypeDType* modptp = pinp->modPTypep()) {
AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType);
UASSERT_OBJ(dtypep, pinp, "unlinked param dtype");
if (modptp->childDTypep()) {
pushDeletep(modptp->childDTypep()->unlinkFrBack());
}
// Set this parameter to value requested by cell
modptp->childDTypep(dtypep->cloneTree(false));
// Later V3LinkDot will convert the ParamDType to a Typedef
// Not done here as may be localparams, etc, that also need conversion
}
}
}
UASSERT(iter != m_modNameMap.end(), "should find just-made module");
} else {
UINFO(4, " De-parameterize to old: " << cellmodp << endl);
}
// Have child use this module instead.
nodep->modp(cellmodp);
nodep->modName(newname);
// We need to relink the pins to the new module
CloneMap* clonemapp = &(iter->second.m_cloneMap);
relinkPins(clonemapp, nodep->pinsp());