mirror of
https://github.com/verilator/verilator.git
synced 2025-04-30 12:36:53 +00:00
Internals: Move V3Param code. No functional change.
This commit is contained in:
parent
d56b923eaa
commit
04febb1944
409
src/V3Param.cpp
409
src/V3Param.cpp
@ -65,6 +65,7 @@
|
|||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Hierarchical block and parameter db (modules without parameter is also handled)
|
// Hierarchical block and parameter db (modules without parameter is also handled)
|
||||||
|
|
||||||
class ParameterizedHierBlocks final {
|
class ParameterizedHierBlocks final {
|
||||||
typedef std::multimap<string, const V3HierarchicalBlockOption*> HierBlockOptsByOrigName;
|
typedef std::multimap<string, const V3HierarchicalBlockOption*> HierBlockOptsByOrigName;
|
||||||
typedef HierBlockOptsByOrigName::const_iterator HierMapIt;
|
typedef HierBlockOptsByOrigName::const_iterator HierMapIt;
|
||||||
@ -195,10 +196,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Param state, as a visitor of each AstNode
|
// Process parameter visitor
|
||||||
|
|
||||||
class ParamVisitor final : public AstNVisitor {
|
class ParamVisitor final : public AstNVisitor {
|
||||||
private:
|
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// AstNodeModule::user5() // bool True if processed
|
// AstNodeModule::user5() // bool True if processed
|
||||||
// AstGenFor::user5() // bool True if processed
|
// AstGenFor::user5() // bool True if processed
|
||||||
@ -531,7 +531,209 @@ private:
|
|||||||
}
|
}
|
||||||
return newmodp;
|
return newmodp;
|
||||||
}
|
}
|
||||||
void visitCellDeparam(AstCell* nodep, const string& hierName);
|
void visitCellDeparam(AstCell* nodep, const string& hierName) {
|
||||||
|
// Cell: Check for parameters in the instantiation.
|
||||||
|
iterateChildren(nodep);
|
||||||
|
UASSERT_OBJ(nodep->modp(), nodep, "Not linked?");
|
||||||
|
// We always run this, even if no parameters, as need to look for interfaces,
|
||||||
|
// and remove any recursive references
|
||||||
|
{
|
||||||
|
UINFO(4, "De-parameterize: " << nodep << endl);
|
||||||
|
// Create new module name with _'s between the constants
|
||||||
|
if (debug() >= 10) nodep->dumpTree(cout, "-cell: ");
|
||||||
|
// Evaluate all module constants
|
||||||
|
V3Const::constifyParamsEdit(nodep);
|
||||||
|
AstNodeModule* srcModp = nodep->modp();
|
||||||
|
srcModp->hierName(hierName + "." + nodep->name());
|
||||||
|
|
||||||
|
// Make sure constification worked
|
||||||
|
// Must be a separate loop, as constant conversion may have changed some pointers.
|
||||||
|
// if (debug()) nodep->dumpTree(cout, "-cel2: ");
|
||||||
|
string longname = srcModp->name();
|
||||||
|
bool any_overrides = false;
|
||||||
|
// Must always clone __Vrcm (recursive modules)
|
||||||
|
if (nodep->recursive()) any_overrides = true;
|
||||||
|
longname += "_";
|
||||||
|
if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: ");
|
||||||
|
for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
||||||
|
if (!pinp->exprp()) continue; // No-connect
|
||||||
|
if (AstVar* modvarp = pinp->modVarp()) {
|
||||||
|
if (!modvarp->isGParam()) {
|
||||||
|
pinp->v3error("Attempted parameter setting of non-parameter: Param "
|
||||||
|
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||||
|
} else if (VN_IS(pinp->exprp(), InitArray)
|
||||||
|
&& arraySubDTypep(modvarp->subDTypep())) {
|
||||||
|
// Array assigned to array
|
||||||
|
AstNode* exprp = pinp->exprp();
|
||||||
|
longname
|
||||||
|
+= "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
||||||
|
any_overrides = true;
|
||||||
|
} else {
|
||||||
|
AstConst* exprp = VN_CAST(pinp->exprp(), Const);
|
||||||
|
AstConst* origp = VN_CAST(modvarp->valuep(), Const);
|
||||||
|
if (!exprp) {
|
||||||
|
// if (debug()) pinp->dumpTree(cout, "error:");
|
||||||
|
pinp->v3error("Can't convert defparam value to constant: Param "
|
||||||
|
<< pinp->prettyNameQ() << " of "
|
||||||
|
<< nodep->prettyNameQ());
|
||||||
|
pinp->exprp()->replaceWith(new AstConst(
|
||||||
|
pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0));
|
||||||
|
} else if (origp && exprp->sameTree(origp)) {
|
||||||
|
// Setting parameter to its default value. Just ignore it.
|
||||||
|
// This prevents making additional modules, and makes coverage more
|
||||||
|
// obvious as it won't show up under a unique module page name.
|
||||||
|
} else if (exprp->num().isDouble() || exprp->num().isString()
|
||||||
|
|| exprp->num().isFourState() || exprp->num().width() != 32) {
|
||||||
|
longname += ("_" + paramSmallName(srcModp, modvarp)
|
||||||
|
+ paramValueNumber(exprp));
|
||||||
|
any_overrides = true;
|
||||||
|
} else {
|
||||||
|
longname += ("_" + paramSmallName(srcModp, modvarp)
|
||||||
|
+ exprp->num().ascii(false));
|
||||||
|
any_overrides = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (AstParamTypeDType* modvarp = pinp->modPTypep()) {
|
||||||
|
AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType);
|
||||||
|
AstNodeDType* origp = modvarp->subDTypep();
|
||||||
|
if (!exprp) {
|
||||||
|
pinp->v3error("Parameter type pin value isn't a type: Param "
|
||||||
|
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||||
|
} else if (!origp) {
|
||||||
|
pinp->v3error("Parameter type variable isn't a type: Param "
|
||||||
|
<< modvarp->prettyNameQ());
|
||||||
|
} else {
|
||||||
|
UINFO(9, "Parameter type assignment expr=" << exprp << " to " << origp
|
||||||
|
<< endl);
|
||||||
|
if (exprp->sameTree(origp)) {
|
||||||
|
// Setting parameter to its default value. Just ignore it.
|
||||||
|
// This prevents making additional modules, and makes coverage more
|
||||||
|
// obvious as it won't show up under a unique module page name.
|
||||||
|
} else {
|
||||||
|
V3Const::constifyParamsEdit(exprp);
|
||||||
|
longname += "_" + paramSmallName(srcModp, modvarp)
|
||||||
|
+ paramValueNumber(exprp);
|
||||||
|
any_overrides = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pinp->v3error("Parameter not found in sub-module: Param "
|
||||||
|
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IfaceRefRefs ifaceRefRefs;
|
||||||
|
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
||||||
|
AstVar* modvarp = pinp->modVarp();
|
||||||
|
if (modvarp->isIfaceRef()) {
|
||||||
|
AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType);
|
||||||
|
if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) {
|
||||||
|
portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType);
|
||||||
|
}
|
||||||
|
AstIfaceRefDType* pinIrefp = nullptr;
|
||||||
|
AstNode* exprp = pinp->exprp();
|
||||||
|
AstVar* varp = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp()
|
||||||
|
: nullptr;
|
||||||
|
if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) {
|
||||||
|
pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType);
|
||||||
|
} else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep())
|
||||||
|
&& VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) {
|
||||||
|
pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType);
|
||||||
|
} else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef)
|
||||||
|
&& VN_CAST(exprp->op1p(), VarRef)->varp()
|
||||||
|
&& VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()
|
||||||
|
&& arraySubDTypep(
|
||||||
|
VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep())
|
||||||
|
&& VN_CAST(arraySubDTypep(
|
||||||
|
VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
||||||
|
IfaceRefDType)) {
|
||||||
|
pinIrefp = VN_CAST(
|
||||||
|
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
||||||
|
IfaceRefDType);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINFO(9, " portIfaceRef " << portIrefp << endl);
|
||||||
|
|
||||||
|
if (!portIrefp) {
|
||||||
|
pinp->v3error("Interface port " << modvarp->prettyNameQ()
|
||||||
|
<< " is not an interface " << modvarp);
|
||||||
|
} else if (!pinIrefp) {
|
||||||
|
pinp->v3error("Interface port "
|
||||||
|
<< modvarp->prettyNameQ()
|
||||||
|
<< " is not connected to interface/modport pin expression");
|
||||||
|
} else {
|
||||||
|
UINFO(9, " pinIfaceRef " << pinIrefp << endl);
|
||||||
|
if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) {
|
||||||
|
UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl);
|
||||||
|
longname += ("_" + paramSmallName(srcModp, pinp->modVarp())
|
||||||
|
+ paramValueNumber(pinIrefp));
|
||||||
|
any_overrides = true;
|
||||||
|
ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp));
|
||||||
|
if (portIrefp->ifacep() != pinIrefp->ifacep()
|
||||||
|
// Might be different only due to param cloning, so check names too
|
||||||
|
&& portIrefp->ifaceName() != pinIrefp->ifaceName()) {
|
||||||
|
pinp->v3error("Port "
|
||||||
|
<< pinp->prettyNameQ() << " expects "
|
||||||
|
<< AstNode::prettyNameQ(portIrefp->ifaceName())
|
||||||
|
<< " interface but pin connects "
|
||||||
|
<< AstNode::prettyNameQ(pinIrefp->ifaceName())
|
||||||
|
<< " interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!any_overrides) {
|
||||||
|
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
|
||||||
|
} else if (AstNodeModule* modp
|
||||||
|
= m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) {
|
||||||
|
nodep->modp(modp);
|
||||||
|
nodep->modName(modp->name());
|
||||||
|
modp->dead(false);
|
||||||
|
// We need to relink the pins to the new module
|
||||||
|
relinkPinsByName(nodep->pinsp(), modp);
|
||||||
|
} else {
|
||||||
|
// If the name is very long, we don't want to overwhelm the filename limit
|
||||||
|
// 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 = 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) {
|
||||||
|
cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs);
|
||||||
|
iter = m_modNameMap.find(newname);
|
||||||
|
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());
|
||||||
|
UINFO(8, " Done with " << cellmodp << endl);
|
||||||
|
} // if any_overrides
|
||||||
|
|
||||||
|
nodep->recursive(false);
|
||||||
|
|
||||||
|
// Delete the parameters from the cell; they're not relevant any longer.
|
||||||
|
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
|
UINFO(8, " Done with " << nodep << endl);
|
||||||
|
// if (debug() >= 10)
|
||||||
|
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now remember to process the child module at the end of the module
|
||||||
|
m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp()));
|
||||||
|
}
|
||||||
|
|
||||||
void visitModules() {
|
void visitModules() {
|
||||||
// Loop on all modules left to process
|
// Loop on all modules left to process
|
||||||
// Hitting a cell adds to the appropriate level of this level-sorted list,
|
// Hitting a cell adds to the appropriate level of this level-sorted list,
|
||||||
@ -877,207 +1079,6 @@ public:
|
|||||||
virtual ~ParamVisitor() override = default;
|
virtual ~ParamVisitor() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// VISITs
|
|
||||||
|
|
||||||
void ParamVisitor::visitCellDeparam(AstCell* nodep, const string& hierName) {
|
|
||||||
// Cell: Check for parameters in the instantiation.
|
|
||||||
iterateChildren(nodep);
|
|
||||||
UASSERT_OBJ(nodep->modp(), nodep, "Not linked?");
|
|
||||||
// We always run this, even if no parameters, as need to look for interfaces,
|
|
||||||
// and remove any recursive references
|
|
||||||
{
|
|
||||||
UINFO(4, "De-parameterize: " << nodep << endl);
|
|
||||||
// Create new module name with _'s between the constants
|
|
||||||
if (debug() >= 10) nodep->dumpTree(cout, "-cell: ");
|
|
||||||
// Evaluate all module constants
|
|
||||||
V3Const::constifyParamsEdit(nodep);
|
|
||||||
AstNodeModule* srcModp = nodep->modp();
|
|
||||||
srcModp->hierName(hierName + "." + nodep->name());
|
|
||||||
|
|
||||||
// Make sure constification worked
|
|
||||||
// Must be a separate loop, as constant conversion may have changed some pointers.
|
|
||||||
// if (debug()) nodep->dumpTree(cout, "-cel2: ");
|
|
||||||
string longname = srcModp->name();
|
|
||||||
bool any_overrides = false;
|
|
||||||
// Must always clone __Vrcm (recursive modules)
|
|
||||||
if (nodep->recursive()) any_overrides = true;
|
|
||||||
longname += "_";
|
|
||||||
if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: ");
|
|
||||||
for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
|
||||||
if (!pinp->exprp()) continue; // No-connect
|
|
||||||
if (AstVar* modvarp = pinp->modVarp()) {
|
|
||||||
if (!modvarp->isGParam()) {
|
|
||||||
pinp->v3error("Attempted parameter setting of non-parameter: Param "
|
|
||||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
|
||||||
} else if (VN_IS(pinp->exprp(), InitArray)
|
|
||||||
&& arraySubDTypep(modvarp->subDTypep())) {
|
|
||||||
// Array assigned to array
|
|
||||||
AstNode* exprp = pinp->exprp();
|
|
||||||
longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
|
||||||
any_overrides = true;
|
|
||||||
} else {
|
|
||||||
AstConst* exprp = VN_CAST(pinp->exprp(), Const);
|
|
||||||
AstConst* origp = VN_CAST(modvarp->valuep(), Const);
|
|
||||||
if (!exprp) {
|
|
||||||
// if (debug()) pinp->dumpTree(cout, "error:");
|
|
||||||
pinp->v3error("Can't convert defparam value to constant: Param "
|
|
||||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
|
||||||
pinp->exprp()->replaceWith(new AstConst(
|
|
||||||
pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0));
|
|
||||||
} else if (origp && exprp->sameTree(origp)) {
|
|
||||||
// Setting parameter to its default value. Just ignore it.
|
|
||||||
// This prevents making additional modules, and makes coverage more
|
|
||||||
// obvious as it won't show up under a unique module page name.
|
|
||||||
} else if (exprp->num().isDouble() || exprp->num().isString()
|
|
||||||
|| exprp->num().isFourState() || exprp->num().width() != 32) {
|
|
||||||
longname
|
|
||||||
+= ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp));
|
|
||||||
any_overrides = true;
|
|
||||||
} else {
|
|
||||||
longname += ("_" + paramSmallName(srcModp, modvarp)
|
|
||||||
+ exprp->num().ascii(false));
|
|
||||||
any_overrides = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (AstParamTypeDType* modvarp = pinp->modPTypep()) {
|
|
||||||
AstNodeDType* exprp = VN_CAST(pinp->exprp(), NodeDType);
|
|
||||||
AstNodeDType* origp = modvarp->subDTypep();
|
|
||||||
if (!exprp) {
|
|
||||||
pinp->v3error("Parameter type pin value isn't a type: Param "
|
|
||||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
|
||||||
} else if (!origp) {
|
|
||||||
pinp->v3error("Parameter type variable isn't a type: Param "
|
|
||||||
<< modvarp->prettyNameQ());
|
|
||||||
} else {
|
|
||||||
UINFO(9,
|
|
||||||
"Parameter type assignment expr=" << exprp << " to " << origp << endl);
|
|
||||||
if (exprp->sameTree(origp)) {
|
|
||||||
// Setting parameter to its default value. Just ignore it.
|
|
||||||
// This prevents making additional modules, and makes coverage more
|
|
||||||
// obvious as it won't show up under a unique module page name.
|
|
||||||
} else {
|
|
||||||
V3Const::constifyParamsEdit(exprp);
|
|
||||||
longname
|
|
||||||
+= "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
|
||||||
any_overrides = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pinp->v3error("Parameter not found in sub-module: Param "
|
|
||||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IfaceRefRefs ifaceRefRefs;
|
|
||||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
|
||||||
AstVar* modvarp = pinp->modVarp();
|
|
||||||
if (modvarp->isIfaceRef()) {
|
|
||||||
AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType);
|
|
||||||
if (!portIrefp && arraySubDTypep(modvarp->subDTypep())) {
|
|
||||||
portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType);
|
|
||||||
}
|
|
||||||
AstIfaceRefDType* pinIrefp = nullptr;
|
|
||||||
AstNode* exprp = pinp->exprp();
|
|
||||||
AstVar* varp
|
|
||||||
= (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() : nullptr;
|
|
||||||
if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) {
|
|
||||||
pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType);
|
|
||||||
} else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep())
|
|
||||||
&& VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType)) {
|
|
||||||
pinIrefp = VN_CAST(arraySubDTypep(varp->subDTypep()), IfaceRefDType);
|
|
||||||
} else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef)
|
|
||||||
&& VN_CAST(exprp->op1p(), VarRef)->varp()
|
|
||||||
&& VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()
|
|
||||||
&& arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep())
|
|
||||||
&& VN_CAST(
|
|
||||||
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
|
||||||
IfaceRefDType)) {
|
|
||||||
pinIrefp = VN_CAST(
|
|
||||||
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
|
||||||
IfaceRefDType);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINFO(9, " portIfaceRef " << portIrefp << endl);
|
|
||||||
|
|
||||||
if (!portIrefp) {
|
|
||||||
pinp->v3error("Interface port " << modvarp->prettyNameQ()
|
|
||||||
<< " is not an interface " << modvarp);
|
|
||||||
} else if (!pinIrefp) {
|
|
||||||
pinp->v3error("Interface port "
|
|
||||||
<< modvarp->prettyNameQ()
|
|
||||||
<< " is not connected to interface/modport pin expression");
|
|
||||||
} else {
|
|
||||||
UINFO(9, " pinIfaceRef " << pinIrefp << endl);
|
|
||||||
if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) {
|
|
||||||
UINFO(9, " IfaceRefDType needs reconnect " << pinIrefp << endl);
|
|
||||||
longname += ("_" + paramSmallName(srcModp, pinp->modVarp())
|
|
||||||
+ paramValueNumber(pinIrefp));
|
|
||||||
any_overrides = true;
|
|
||||||
ifaceRefRefs.push_back(make_pair(portIrefp, pinIrefp));
|
|
||||||
if (portIrefp->ifacep() != pinIrefp->ifacep()
|
|
||||||
// Might be different only due to param cloning, so check names too
|
|
||||||
&& portIrefp->ifaceName() != pinIrefp->ifaceName()) {
|
|
||||||
pinp->v3error("Port " << pinp->prettyNameQ() << " expects "
|
|
||||||
<< AstNode::prettyNameQ(portIrefp->ifaceName())
|
|
||||||
<< " interface but pin connects "
|
|
||||||
<< AstNode::prettyNameQ(pinIrefp->ifaceName())
|
|
||||||
<< " interface");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!any_overrides) {
|
|
||||||
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
|
|
||||||
} else if (AstNodeModule* modp
|
|
||||||
= m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) {
|
|
||||||
nodep->modp(modp);
|
|
||||||
nodep->modName(modp->name());
|
|
||||||
modp->dead(false);
|
|
||||||
// We need to relink the pins to the new module
|
|
||||||
relinkPinsByName(nodep->pinsp(), modp);
|
|
||||||
} else {
|
|
||||||
// If the name is very long, we don't want to overwhelm the filename limit
|
|
||||||
// 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 = 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) {
|
|
||||||
cellmodp = deepCloneModule(srcModp, nodep, newname, ifaceRefRefs);
|
|
||||||
iter = m_modNameMap.find(newname);
|
|
||||||
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());
|
|
||||||
UINFO(8, " Done with " << cellmodp << endl);
|
|
||||||
} // if any_overrides
|
|
||||||
|
|
||||||
nodep->recursive(false);
|
|
||||||
|
|
||||||
// Delete the parameters from the cell; they're not relevant any longer.
|
|
||||||
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
|
|
||||||
UINFO(8, " Done with " << nodep << endl);
|
|
||||||
// if (debug() >= 10)
|
|
||||||
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now remember to process the child module at the end of the module
|
|
||||||
m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp()));
|
|
||||||
}
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Param class functions
|
// Param class functions
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user