mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Fix linking parameterized hierarchical blocks and recursive hierarchical blocks (#4654)
This commit is contained in:
+26
-17
@@ -74,6 +74,7 @@ class ParameterizedHierBlocks final {
|
||||
using GParamsMap = std::map<const std::string, AstVar*>; // key:parameter name value:parameter
|
||||
|
||||
// MEMBERS
|
||||
const bool m_hierSubRun; // Is in sub-run for hierarchical verilation
|
||||
// key:Original module name, value:HiearchyBlockOption*
|
||||
// If a module is parameterized, the module is uniquified to overridden parameters.
|
||||
// This is why HierBlockOptsByOrigName is multimap.
|
||||
@@ -88,7 +89,8 @@ class ParameterizedHierBlocks final {
|
||||
// METHODS
|
||||
|
||||
public:
|
||||
ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep) {
|
||||
ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep)
|
||||
: m_hierSubRun(!v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild()) {
|
||||
for (const auto& hierOpt : hierOpts) {
|
||||
m_hierBlockOptsByOrigName.emplace(hierOpt.second.origName(), &hierOpt.second);
|
||||
const V3HierarchicalBlockOption::ParamStrMap& params = hierOpt.second.params();
|
||||
@@ -109,7 +111,11 @@ public:
|
||||
if (hierOpts.find(modp->prettyName()) != hierOpts.end()) {
|
||||
m_hierBlockMod.emplace(modp->name(), modp);
|
||||
}
|
||||
const auto defParamIt = m_modParams.find(modp->name());
|
||||
// Recursive hierarchical module may change its name, so we have to match its origName.
|
||||
// Collect values from recursive cloned module as parameters in the top module could be
|
||||
// overridden.
|
||||
const string actualModName = modp->recursiveClone() ? modp->origName() : modp->name();
|
||||
const auto defParamIt = m_modParams.find(actualModName);
|
||||
if (defParamIt != m_modParams.end()) {
|
||||
// modp is the original of parameterized hierarchical block
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
@@ -120,11 +126,13 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hierSubRun() const { return m_hierSubRun; }
|
||||
bool isHierBlock(const string& origName) const {
|
||||
return m_hierBlockOptsByOrigName.find(origName) != m_hierBlockOptsByOrigName.end();
|
||||
}
|
||||
AstNodeModule* findByParams(const string& origName, AstPin* firstPinp,
|
||||
const AstNodeModule* modp) {
|
||||
if (m_hierBlockOptsByOrigName.find(origName) == m_hierBlockOptsByOrigName.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
UASSERT(isHierBlock(origName), origName << " is not hierarchical block\n");
|
||||
// This module is a hierarchical block. Need to replace it by the --lib-create wrapper.
|
||||
const std::pair<HierMapIt, HierMapIt> candidates
|
||||
= m_hierBlockOptsByOrigName.equal_range(origName);
|
||||
@@ -510,9 +518,9 @@ class ParamProcessor final {
|
||||
pair.first->second = std::move(params);
|
||||
}
|
||||
const auto paramsIt = pair.first;
|
||||
if (paramsIt->second.empty()) return modp->name(); // modp has no parameter
|
||||
if (paramsIt->second.empty()) return modp->origName(); // modp has no parameter
|
||||
|
||||
string longname = modp->name();
|
||||
string longname = modp->origName();
|
||||
for (auto&& defaultValue : paramsIt->second) {
|
||||
const auto pinIt = pins.find(defaultValue.first);
|
||||
const AstConst* const constp
|
||||
@@ -536,7 +544,7 @@ class ParamProcessor final {
|
||||
// Hex string must be a safe suffix for any symbol
|
||||
const string hashStr = hashStrGen.digestHex();
|
||||
for (string::size_type i = 1; i < hashStr.size(); ++i) {
|
||||
string newName = modp->name();
|
||||
string newName = modp->origName();
|
||||
// Don't use '__' not to be encoded when this module is loaded later by Verilator
|
||||
if (newName.at(newName.size() - 1) != '_') newName += '_';
|
||||
newName += hashStr.substr(0, i);
|
||||
@@ -586,8 +594,6 @@ class ParamProcessor final {
|
||||
newmodp->user2(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());
|
||||
// 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)) {
|
||||
@@ -851,7 +857,16 @@ class ParamProcessor final {
|
||||
cellInterfaceCleanup(pinsp, srcModpr, longname /*ref*/, any_overrides /*ref*/,
|
||||
ifaceRefRefs /*ref*/);
|
||||
|
||||
if (!any_overrides) {
|
||||
if (m_hierBlocks.hierSubRun() && m_hierBlocks.isHierBlock(srcModpr->origName())) {
|
||||
AstNodeModule* const paramedModp
|
||||
= m_hierBlocks.findByParams(srcModpr->origName(), paramsp, m_modp);
|
||||
UASSERT_OBJ(paramedModp, nodep, "Failed to find sub-module for hierarchical block");
|
||||
paramedModp->dead(false);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(pinsp, paramedModp);
|
||||
srcModpr = paramedModp;
|
||||
any_overrides = true;
|
||||
} else if (!any_overrides) {
|
||||
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
|
||||
// If it's the first use of the default instance, create a copy and store it in user3p.
|
||||
// user3p will also be used to check if the default instance is used.
|
||||
@@ -863,12 +878,6 @@ class ParamProcessor final {
|
||||
srcModpr->user3p(classCopyp);
|
||||
storeOriginalParams(classCopyp);
|
||||
}
|
||||
} else if (AstNodeModule* const paramedModp
|
||||
= m_hierBlocks.findByParams(srcModpr->name(), paramsp, m_modp)) {
|
||||
paramedModp->dead(false);
|
||||
// We need to relink the pins to the new module
|
||||
relinkPinsByName(pinsp, paramedModp);
|
||||
srcModpr = paramedModp;
|
||||
} else {
|
||||
const string newname
|
||||
= srcModpr->hierBlock() ? longname : moduleCalcName(srcModpr, longname);
|
||||
|
||||
Reference in New Issue
Block a user