From 2ac7cf51a9d96df6876c17e0d3a364ded5bd0e1a Mon Sep 17 00:00:00 2001 From: Igor Zaworski Date: Fri, 10 Oct 2025 16:05:47 +0200 Subject: [PATCH] Optimization of typedef params (#6543) (#6547) --- src/V3Param.cpp | 27 ++++++++++++++++----------- src/V3Width.cpp | 9 --------- src/V3Width.h | 3 --- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3127601e6..665c0f4e7 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -1277,12 +1277,12 @@ class ParamVisitor final : public VNVisitor { string m_unlinkedTxt; // Text for AstUnlinkedRef std::multimap m_cellps; // Cells left to process (in current module) std::deque m_strings; // Allocator for temporary strings + std::map + m_isCircular; // Stores information whether `AstRefDType` is circular // STATE - for current visit position (use VL_RESTORER) AstNodeModule* m_modp; // Module iterating string m_generateHierName; // Generate portion of hierarchy name - std::map - m_isCircularTypeCache; // Caches return values of `V3Width::isCircularType` calls // METHODS @@ -1417,16 +1417,21 @@ class ParamVisitor final : public VNVisitor { processWorkQ(); } } - void visit(AstRefDType* nodep) override { - const auto iter = m_isCircularTypeCache.find(nodep); - bool isCircular; - if (iter != m_isCircularTypeCache.end()) { - isCircular = iter->second; - } else { - isCircular = V3Width::isCircularType(nodep); - m_isCircularTypeCache.emplace(nodep, isCircular); + + bool isCircularType(const AstRefDType* nodep) { + const auto iter = m_isCircular.emplace(nodep, true); + if (!iter.second) return iter.first->second; + if (const AstRefDType* const subDTypep = VN_CAST(nodep->subDTypep(), RefDType)) { + const bool ret = isCircularType(subDTypep); + iter.first->second = ret; + return ret; } - if (isCircular) { + iter.first->second = false; + return false; + } + + void visit(AstRefDType* nodep) override { + if (isCircularType(nodep)) { nodep->v3error("Typedef's type is circular: " << nodep->prettyName()); } else if (nodep->typedefp() && nodep->subDTypep() && (VN_IS(nodep->subDTypep()->skipRefOrNullp(), IfaceRefDType) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 99336502d..eafd432dc 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -8952,12 +8952,3 @@ AstNode* V3Width::widthGenerateParamsEdit( // No WidthRemoveVisitor, as don't want to drop $signed etc inside gen blocks return nodep; } - -bool V3Width::isCircularType(const AstRefDType* nodep) { - std::set visited; - while (nodep) { - if (!visited.insert(nodep).second) return true; - nodep = VN_CAST(nodep->subDTypep(), RefDType); - } - return false; -} diff --git a/src/V3Width.h b/src/V3Width.h index b4a977941..88eb86c2a 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -23,7 +23,6 @@ class AstNetlist; class AstNode; class AstNodeDType; -class AstRefDType; //============================================================================ @@ -37,8 +36,6 @@ public: // Replace AstSelBit, etc with AstSel/AstArraySel // Returns replacement node if nodep was deleted, or null if none. static AstNode* widthSelNoIterEdit(AstNode* nodep) VL_MT_DISABLED; - - static bool isCircularType(const AstRefDType* nodep); }; #endif // Guard