Fix linking parameterized hierarchical blocks and recursive hierarchical blocks (#4654)

This commit is contained in:
Anthony Donlon
2023-11-03 07:55:53 -04:00
committed by GitHub
parent 2733d43ea7
commit d0d39c13e7
13 changed files with 24518 additions and 23367 deletions
+26 -17
View File
@@ -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);