diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index 933ba26fa..07f7741d2 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -54,7 +54,7 @@ private: // VISITORS virtual void visit(AstTopScope* nodep) VL_OVERRIDE { m_topscopep = nodep; - m_finder.main(m_topscopep); + m_finder.init(m_topscopep); iterateChildren(nodep); m_topscopep = NULL; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index eb8b9a593..701b8149f 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -965,8 +965,8 @@ private: m_activep = NULL; m_topScopep = nodep; m_scopetopp = nodep->scopep(); - // Find sentree's - m_finder.main(m_topScopep); + // Find global SenTrees + m_finder.init(m_topScopep); // ProcessDomainsIterate will use these when it needs to move // something to a combodomain. This saves a ton of find() operations. AstSenTree* combp diff --git a/src/V3SenTree.h b/src/V3SenTree.h index deca31018..d4f5c3ecc 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -13,17 +13,7 @@ // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 // //************************************************************************* -// V3Block's Transformations: -// -// Note this can be called multiple times. -// Create a IBLOCK(initial), SBLOCK(combo) -// ALWAYS: Remove any-edges from sense list -// If no POS/NEG in senselist, Fold into SBLOCK(combo) -// Else fold into SBLOCK(sequent). -// OPTIMIZE: When support async clocks, fold into that block if possible -// INITIAL: Move into IBLOCK -// WIRE: Move into SBLOCK(combo) -// +// AstSenTree related utilities. //************************************************************************* #ifndef _V3SENTREE_H_ @@ -32,14 +22,9 @@ #include "config_build.h" #include "verilatedos.h" -#include "V3Global.h" #include "V3Ast.h" #include "V3Hashed.h" -#include -#include -#include -#include #include VL_INCLUDE_UNORDERED_SET //###################################################################### @@ -50,22 +35,16 @@ class SenTreeSet { // Hash table of sensitive blocks. private: // TYPES - class HashSenTree { - public: - HashSenTree() {} + struct HashSenTree { size_t operator()(const AstSenTree* kp) const { return V3Hashed::uncachedHash(kp).fullValue(); } - // Copying required for OSX's libc++ }; - class EqSenTree { - public: - EqSenTree() {} + struct EqSenTree { bool operator()(const AstSenTree* ap, const AstSenTree* bp) const { return ap->sameTree(bp); } - // Copying required for OSX's libc++ }; // MEMBERS @@ -78,76 +57,57 @@ public: // METHODS void add(AstSenTree* nodep) { m_trees.insert(nodep); } + AstSenTree* find(AstSenTree* likep) { AstSenTree* resultp = NULL; Set::iterator it = m_trees.find(likep); if (it != m_trees.end()) resultp = *it; return resultp; } + void clear() { m_trees.clear(); } private: VL_UNCOPYABLE(SenTreeSet); }; -class SenTreeFinder : public AstNVisitor { +class SenTreeFinder { private: // STATE - AstTopScope* m_topscopep; // Top scope to add statement to - SenTreeSet m_trees; // Set of sensitive blocks, for folding + AstTopScope* m_topScopep; // Top scope to add global SenTrees to + SenTreeSet m_trees; // Set of global SenTrees - // VISITORS - VL_DEBUG_FUNC; // Declare debug() + VL_UNCOPYABLE(SenTreeFinder); - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - // Only do the top - if (nodep->isTop()) iterateChildren(nodep); - } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { - m_topscopep = nodep; - iterateChildren(nodep); - // Don't clear topscopep, the namer persists beyond this visit - } - virtual void visit(AstScope* nodep) VL_OVERRIDE { - // But no SenTrees under TopScope's scope - } - // Memorize existing block names - virtual void visit(AstActive* nodep) VL_OVERRIDE { - // Don't grab SenTrees under Actives, only those that are global (under Scope directly) - iterateChildren(nodep); - } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { // - m_trees.add(nodep); - } - virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } +public: + // CONSTRUCTORS + SenTreeFinder() + : m_topScopep(NULL) {} // METHODS -public: - void clear() { - m_topscopep = NULL; - m_trees.clear(); - } - AstSenTree* getSenTree(AstSenTree* sensesp) { - // Return a global sentree that matches given sense list. - AstSenTree* treep = m_trees.find(sensesp); + AstSenTree* getSenTree(AstSenTree* senTreep) { + // Return a global SenTree that matches given SenTree. If no such global + // SenTree exists, create one and add it to the stored TopScope. + AstSenTree* treep = m_trees.find(senTreep); // Not found, form a new one if (!treep) { - UASSERT(m_topscopep, "Never called main()"); - treep = sensesp->cloneTree(false); - m_topscopep->addStmtsp(treep); + UASSERT(m_topScopep, "Never called init()"); + treep = senTreep->cloneTree(false); + m_topScopep->addStmtsp(treep); UINFO(8, " New SENTREE " << treep << endl); m_trees.add(treep); - // Note blocks may have also been added above in the Active visitor } return treep; } -public: - // CONSTRUCTORS - SenTreeFinder() { clear(); } - virtual ~SenTreeFinder() {} - void main(AstTopScope* nodep) { iterate(nodep); } + void init(AstTopScope* topScopep) { + // Keep hold of top scope so we can add global SenTrees later + m_topScopep = topScopep; + // Gather existing global SenTrees + for (AstNode* nodep = topScopep->stmtsp(); nodep; nodep = nodep->nextp()) { + if (AstSenTree* senTreep = VN_CAST(nodep, SenTree)) m_trees.add(senTreep); + } + } }; #endif // Guard