Internals: Refactor V3Param through code movement only. No functional change intended.
This commit is contained in:
parent
84d7380588
commit
d89fc05da1
117
src/V3Param.cpp
117
src/V3Param.cpp
|
|
@ -196,16 +196,17 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Process parameter visitor
|
// Remove parameters from cells and build new modules
|
||||||
|
|
||||||
class ParamVisitor final : public AstNVisitor {
|
class ParamProcessor final {
|
||||||
// NODE STATE
|
// NODE STATE - Local
|
||||||
// AstNodeModule::user5() // bool True if processed
|
|
||||||
// AstGenFor::user5() // bool True if processed
|
|
||||||
// AstVar::user5() // bool True if constant propagated
|
|
||||||
// AstVar::user4() // int Global parameter number (for naming new module)
|
// AstVar::user4() // int Global parameter number (for naming new module)
|
||||||
// // (0=not processed, 1=iterated, but no number,
|
// // (0=not processed, 1=iterated, but no number,
|
||||||
// // 65+ parameter numbered)
|
// // 65+ parameter numbered)
|
||||||
|
// NODE STATE - Shared with ParamVisitor
|
||||||
|
// AstNodeModule::user5() // bool True if processed
|
||||||
|
// AstGenFor::user5() // bool True if processed
|
||||||
|
// AstVar::user5() // bool True if constant propagated
|
||||||
// AstCell::user5p() // string* Generate portion of hierarchical name
|
// AstCell::user5p() // string* Generate portion of hierarchical name
|
||||||
AstUser4InUse m_inuser4;
|
AstUser4InUse m_inuser4;
|
||||||
AstUser5InUse m_inuser5;
|
AstUser5InUse m_inuser5;
|
||||||
|
|
@ -239,16 +240,7 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
ValueMap m_valueMap; // Hash of node hash to (param value, name)
|
ValueMap m_valueMap; // Hash of node hash to (param value, name)
|
||||||
int m_nextValue = 1; // Next value to use in m_valueMap
|
int m_nextValue = 1; // Next value to use in m_valueMap
|
||||||
|
|
||||||
typedef std::multimap<int, AstNodeModule*> LevelModMap;
|
|
||||||
LevelModMap m_todoModps; // Modules left to process
|
|
||||||
|
|
||||||
typedef std::deque<AstCell*> CellList;
|
|
||||||
CellList m_cellps; // Cells left to process (in this module)
|
|
||||||
|
|
||||||
AstNodeModule* m_modp = nullptr; // Current module being processed
|
AstNodeModule* m_modp = nullptr; // Current module being processed
|
||||||
string m_unlinkedTxt; // Text for AstUnlinkedRef
|
|
||||||
UnrollStateful m_unroller; // Loop unroller
|
|
||||||
string m_generateHierName; // Generate portion of hierarchy name
|
|
||||||
|
|
||||||
// Database to get protect-lib wrapper that matches parameters in hierarchical Verilation
|
// Database to get protect-lib wrapper that matches parameters in hierarchical Verilation
|
||||||
ParameterizedHierBlocks m_hierBlocks;
|
ParameterizedHierBlocks m_hierBlocks;
|
||||||
|
|
@ -529,13 +521,13 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
}
|
}
|
||||||
return newmodp;
|
return newmodp;
|
||||||
}
|
}
|
||||||
void visitCellDeparam(AstCell* nodep, const string& hierName) {
|
|
||||||
|
public:
|
||||||
|
void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) {
|
||||||
|
m_modp = modp;
|
||||||
// Cell: Check for parameters in the instantiation.
|
// 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,
|
// We always run this, even if no parameters, as need to look for interfaces,
|
||||||
// and remove any recursive references
|
// and remove any recursive references
|
||||||
{
|
|
||||||
UINFO(4, "De-parameterize: " << nodep << endl);
|
UINFO(4, "De-parameterize: " << nodep << endl);
|
||||||
// Create new module name with _'s between the constants
|
// Create new module name with _'s between the constants
|
||||||
if (debug() >= 10) nodep->dumpTree(cout, "-cell: ");
|
if (debug() >= 10) nodep->dumpTree(cout, "-cell: ");
|
||||||
|
|
@ -563,8 +555,7 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
&& arraySubDTypep(modvarp->subDTypep())) {
|
&& arraySubDTypep(modvarp->subDTypep())) {
|
||||||
// Array assigned to array
|
// Array assigned to array
|
||||||
AstNode* exprp = pinp->exprp();
|
AstNode* exprp = pinp->exprp();
|
||||||
longname
|
longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
||||||
+= "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
|
||||||
any_overrides = true;
|
any_overrides = true;
|
||||||
} else {
|
} else {
|
||||||
AstConst* exprp = VN_CAST(pinp->exprp(), Const);
|
AstConst* exprp = VN_CAST(pinp->exprp(), Const);
|
||||||
|
|
@ -572,8 +563,7 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
if (!exprp) {
|
if (!exprp) {
|
||||||
// if (debug()) pinp->dumpTree(cout, "error:");
|
// if (debug()) pinp->dumpTree(cout, "error:");
|
||||||
pinp->v3error("Can't convert defparam value to constant: Param "
|
pinp->v3error("Can't convert defparam value to constant: Param "
|
||||||
<< pinp->prettyNameQ() << " of "
|
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||||
<< nodep->prettyNameQ());
|
|
||||||
pinp->exprp()->replaceWith(new AstConst(
|
pinp->exprp()->replaceWith(new AstConst(
|
||||||
pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0));
|
pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0));
|
||||||
} else if (origp && exprp->sameTree(origp)) {
|
} else if (origp && exprp->sameTree(origp)) {
|
||||||
|
|
@ -582,8 +572,8 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
// obvious as it won't show up under a unique module page name.
|
// obvious as it won't show up under a unique module page name.
|
||||||
} else if (exprp->num().isDouble() || exprp->num().isString()
|
} else if (exprp->num().isDouble() || exprp->num().isString()
|
||||||
|| exprp->num().isFourState() || exprp->num().width() != 32) {
|
|| exprp->num().isFourState() || exprp->num().width() != 32) {
|
||||||
longname += ("_" + paramSmallName(srcModp, modvarp)
|
longname
|
||||||
+ paramValueNumber(exprp));
|
+= ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp));
|
||||||
any_overrides = true;
|
any_overrides = true;
|
||||||
} else {
|
} else {
|
||||||
longname += ("_" + paramSmallName(srcModp, modvarp)
|
longname += ("_" + paramSmallName(srcModp, modvarp)
|
||||||
|
|
@ -601,16 +591,16 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
pinp->v3error("Parameter type variable isn't a type: Param "
|
pinp->v3error("Parameter type variable isn't a type: Param "
|
||||||
<< modvarp->prettyNameQ());
|
<< modvarp->prettyNameQ());
|
||||||
} else {
|
} else {
|
||||||
UINFO(9, "Parameter type assignment expr=" << exprp << " to " << origp
|
UINFO(9,
|
||||||
<< endl);
|
"Parameter type assignment expr=" << exprp << " to " << origp << endl);
|
||||||
if (exprp->sameTree(origp)) {
|
if (exprp->sameTree(origp)) {
|
||||||
// Setting parameter to its default value. Just ignore it.
|
// Setting parameter to its default value. Just ignore it.
|
||||||
// This prevents making additional modules, and makes coverage more
|
// This prevents making additional modules, and makes coverage more
|
||||||
// obvious as it won't show up under a unique module page name.
|
// obvious as it won't show up under a unique module page name.
|
||||||
} else {
|
} else {
|
||||||
V3Const::constifyParamsEdit(exprp);
|
V3Const::constifyParamsEdit(exprp);
|
||||||
longname += "_" + paramSmallName(srcModp, modvarp)
|
longname
|
||||||
+ paramValueNumber(exprp);
|
+= "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp);
|
||||||
any_overrides = true;
|
any_overrides = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -629,8 +619,8 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
}
|
}
|
||||||
AstIfaceRefDType* pinIrefp = nullptr;
|
AstIfaceRefDType* pinIrefp = nullptr;
|
||||||
AstNode* exprp = pinp->exprp();
|
AstNode* exprp = pinp->exprp();
|
||||||
AstVar* varp = (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp()
|
AstVar* varp
|
||||||
: nullptr;
|
= (exprp && VN_IS(exprp, VarRef)) ? VN_CAST(exprp, VarRef)->varp() : nullptr;
|
||||||
if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) {
|
if (varp && varp->subDTypep() && VN_IS(varp->subDTypep(), IfaceRefDType)) {
|
||||||
pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType);
|
pinIrefp = VN_CAST(varp->subDTypep(), IfaceRefDType);
|
||||||
} else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep())
|
} else if (varp && varp->subDTypep() && arraySubDTypep(varp->subDTypep())
|
||||||
|
|
@ -639,10 +629,9 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
} else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef)
|
} else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef)
|
||||||
&& VN_CAST(exprp->op1p(), VarRef)->varp()
|
&& VN_CAST(exprp->op1p(), VarRef)->varp()
|
||||||
&& VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()
|
&& VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()
|
||||||
&& arraySubDTypep(
|
&& arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep())
|
||||||
VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep())
|
&& VN_CAST(
|
||||||
&& VN_CAST(arraySubDTypep(
|
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
||||||
VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
|
||||||
IfaceRefDType)) {
|
IfaceRefDType)) {
|
||||||
pinIrefp = VN_CAST(
|
pinIrefp = VN_CAST(
|
||||||
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
arraySubDTypep(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep()),
|
||||||
|
|
@ -669,8 +658,7 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
if (portIrefp->ifacep() != pinIrefp->ifacep()
|
if (portIrefp->ifacep() != pinIrefp->ifacep()
|
||||||
// Might be different only due to param cloning, so check names too
|
// Might be different only due to param cloning, so check names too
|
||||||
&& portIrefp->ifaceName() != pinIrefp->ifaceName()) {
|
&& portIrefp->ifaceName() != pinIrefp->ifaceName()) {
|
||||||
pinp->v3error("Port "
|
pinp->v3error("Port " << pinp->prettyNameQ() << " expects "
|
||||||
<< pinp->prettyNameQ() << " expects "
|
|
||||||
<< AstNode::prettyNameQ(portIrefp->ifaceName())
|
<< AstNode::prettyNameQ(portIrefp->ifaceName())
|
||||||
<< " interface but pin connects "
|
<< " interface but pin connects "
|
||||||
<< AstNode::prettyNameQ(pinIrefp->ifaceName())
|
<< AstNode::prettyNameQ(pinIrefp->ifaceName())
|
||||||
|
|
@ -696,8 +684,7 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
// TODO can use new V3Name hash replacement instead of this
|
// TODO can use new V3Name hash replacement instead of this
|
||||||
// Shorter name is convenient for hierarchical block
|
// Shorter name is convenient for hierarchical block
|
||||||
string newname = moduleCalcName(srcModp, nodep, longname);
|
string newname = moduleCalcName(srcModp, nodep, longname);
|
||||||
UINFO(4,
|
UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl);
|
||||||
"Name: " << srcModp->name() << "->" << longname << "->" << newname << endl);
|
|
||||||
//
|
//
|
||||||
// Already made this flavor?
|
// Already made this flavor?
|
||||||
AstNodeModule* cellmodp = nullptr;
|
AstNodeModule* cellmodp = nullptr;
|
||||||
|
|
@ -728,10 +715,45 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now remember to process the child module at the end of the module
|
// CONSTRUCTORS
|
||||||
|
ParamProcessor(AstNetlist* nodep)
|
||||||
|
: m_hierBlocks{v3Global.opt.hierBlocks(), nodep} {
|
||||||
|
for (AstNodeModule* modp = nodep->modulesp(); modp;
|
||||||
|
modp = VN_CAST(modp->nextp(), NodeModule)) {
|
||||||
|
m_allModuleNames.insert(modp->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~ParamProcessor() = default;
|
||||||
|
VL_UNCOPYABLE(ParamProcessor);
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Process parameter visitor
|
||||||
|
|
||||||
|
class ParamVisitor final : public AstNVisitor {
|
||||||
|
// STATE
|
||||||
|
ParamProcessor m_processor; // De-parameterize a cell, build modules
|
||||||
|
UnrollStateful m_unroller; // Loop unroller
|
||||||
|
|
||||||
|
AstNodeModule* m_modp = nullptr; // Current module being processed
|
||||||
|
string m_generateHierName; // Generate portion of hierarchy name
|
||||||
|
string m_unlinkedTxt; // Text for AstUnlinkedRef
|
||||||
|
std::deque<AstCell*> m_cellps; // Cells left to process (in this module)
|
||||||
|
|
||||||
|
typedef std::multimap<int, AstNodeModule*> LevelModMap;
|
||||||
|
LevelModMap m_todoModps; // Modules left to process
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
||||||
|
void visitCellDeparam(AstCell* nodep, const string& hierName) {
|
||||||
|
// Cell: Check for parameters in the instantiation.
|
||||||
|
iterateChildren(nodep);
|
||||||
|
UASSERT_OBJ(nodep->modp(), nodep, "Not linked?");
|
||||||
|
m_processor.cellDeparam(nodep, m_modp, hierName);
|
||||||
|
// Remember to process the child module at the end of the module
|
||||||
m_todoModps.insert(make_pair(nodep->modp()->level(), nodep->modp()));
|
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,
|
||||||
|
|
@ -774,10 +796,6 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNetlist* nodep) override {
|
|
||||||
// Modules must be done in top-down-order
|
|
||||||
iterateChildren(nodep);
|
|
||||||
}
|
|
||||||
virtual void visit(AstNodeModule* nodep) override {
|
virtual void visit(AstNodeModule* nodep) override {
|
||||||
if (nodep->dead()) {
|
if (nodep->dead()) {
|
||||||
UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot
|
UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot
|
||||||
|
|
@ -1066,15 +1084,12 @@ class ParamVisitor final : public AstNVisitor {
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit ParamVisitor(AstNetlist* nodep)
|
explicit ParamVisitor(AstNetlist* nodep)
|
||||||
: m_hierBlocks{v3Global.opt.hierBlocks(), nodep} {
|
: m_processor{nodep} {
|
||||||
for (AstNodeModule* modp = nodep->modulesp(); modp;
|
// Relies on modules already being in top-down-order
|
||||||
modp = VN_CAST(modp->nextp(), NodeModule)) {
|
|
||||||
m_allModuleNames.insert(modp->name());
|
|
||||||
}
|
|
||||||
//
|
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
virtual ~ParamVisitor() override = default;
|
virtual ~ParamVisitor() override = default;
|
||||||
|
VL_UNCOPYABLE(ParamVisitor);
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue