diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 87b9e0b26..7b0a4ecd3 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -29,6 +29,7 @@ #include "V3Inline.h" #include "V3AstUserAllocator.h" +#include "V3Graph.h" #include "V3Inst.h" #include "V3Stats.h" @@ -41,208 +42,334 @@ VL_DEFINE_DEBUG_FUNCTIONS; static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it //###################################################################### -// Inlining state. Kept as AstNodeModule::user1p via AstUser1Allocator +// Bipartite module instantiation graph containing module and cell vertices -namespace { +class InlineModModuleVertex; +class InlineModCellVertex; -struct ModuleState final { - bool m_inlined = false; // Whether to inline this module - unsigned m_cellRefs = 0; // Number of AstCells instantiating this module - std::vector m_childCells; // AstCells under this module (to speed up traversal) -}; - -using ModuleStateUser1Allocator = AstUser1Allocator; - -} // namespace - -//###################################################################### -// Visitor that determines which modules will be inlined - -class InlineMarkVisitor final : public VNVisitor { +class InlineModGraph final : public V3Graph { // NODE STATE - // Output - // AstNodeModule::user1() // OUTPUT: ModuleState instance (via m_moduleState) - // Internal state (can be cleared after this visit completes) - // AstNodeModule::user2() // CIL_*. Allowed to automatically inline module - // AstNodeModule::user4() // int. Statements in module - const VNUser2InUse m_inuser2; - const VNUser4InUse m_inuser4; + // AstNodeModule::user4p() -> InlineModModuleVertex*, the module vertex + // AstCell::user4p() -> InlineModCellVertex*, the cell vertex - ModuleStateUser1Allocator& m_moduleState; + VNUser4InUse m_user4InUse; - // For the user2 field: - enum : uint8_t { - CIL_NOTHARD = 0, // Inline not supported - CIL_NOTSOFT, // Don't inline unless user overrides - CIL_MAYBE, // Might inline - CIL_USER - }; // Pragma suggests inlining - - // STATE - AstNodeModule* m_modp = nullptr; // Current module - VDouble0 m_statUnsup; // Statistic tracking - std::vector m_allMods; // All modules, in top-down order. - - // Within the context of a given module, LocalInstanceMap maps - // from child modules to the count of each child's local instantiations. - using LocalInstanceMap = std::unordered_map; - - // We keep a LocalInstanceMap for each module in the design - std::unordered_map m_instances; +public: + InlineModGraph() + : V3Graph{} {} + ~InlineModGraph() override = default; // METHODS - void cantInline(const char* reason, bool hard) { - if (hard) { - if (m_modp->user2() != CIL_NOTHARD) { - UINFO(4, " No inline hard: " << reason << " " << m_modp); - m_modp->user2(CIL_NOTHARD); - ++m_statUnsup; - } - } else { - if (m_modp->user2() == CIL_MAYBE) { - UINFO(4, " No inline soft: " << reason << " " << m_modp); - m_modp->user2(CIL_NOTSOFT); + InlineModModuleVertex* getInlineModModuleVertexp(AstNodeModule* modp); + InlineModCellVertex* getInlineModCellVertexp(AstCell* cellp); + void addEdge(InlineModModuleVertex& from, InlineModCellVertex& to); + void addEdge(InlineModCellVertex& from, InlineModModuleVertex& to); + + // debug + std::string dotRankDir() const override { return "LR"; } +}; + +class InlineModEitherVertex VL_NOT_FINAL : public V3GraphVertex { + VL_RTTI_IMPL(InlineModEitherVertex, V3GraphVertex) +protected: + explicit InlineModEitherVertex(InlineModGraph& graph) + : V3GraphVertex{&graph} {} +}; + +class InlineModModuleVertex final : public InlineModEitherVertex { + VL_RTTI_IMPL(InlineModModuleVertex, InlineModEitherVertex) + AstNodeModule* const m_modp; // The module + const char* m_noInlineHardWyp = nullptr; // First reason the module can never be inlined + const char* m_noInlineSoftWyp = nullptr; // First reason not to inline unless forced + const char* m_shouldInlineWhyp = nullptr; // First reason why this module should be inlined + size_t m_size = 0; // The size (statement count) of the module + size_t mutable m_flattenedSize = 0; // The size of the module if flattened + bool mutable m_flattenedSizeValid = false; // Whether the flattened size is valid + size_t mutable m_instanceCount = 0; // The number of total instances of this module + bool mutable m_instanceCountValid = false; // Whether the instance count is valid + +public: + InlineModModuleVertex(InlineModGraph& graph, AstNodeModule* modp) + : InlineModEitherVertex{graph} + , m_modp{modp} {} + ~InlineModModuleVertex() override = default; + + // ACCESSORS + AstNodeModule* modp() const { return m_modp; } + size_t size() const { return m_size; } + void size(size_t value) { m_size = value; } + void sizeInc(size_t value = 1) { m_size += value; } + bool noInlineHard() const { return m_noInlineHardWyp; } + void setNoInlineHard(const char* whyp) { + if (!m_noInlineHardWyp) m_noInlineHardWyp = whyp; + } + bool noInlineSoft() const { return m_noInlineSoftWyp; } + void setNoInlineSoft(const char* whyp) { + if (!m_noInlineSoftWyp) m_noInlineSoftWyp = whyp; + } + bool shouldInline() const { return m_shouldInlineWhyp; } + void setShouldInline(const char* whyp) { + if (!m_shouldInlineWhyp) m_shouldInlineWhyp = whyp; + } + // Mark every instance below this module for inlining + void setFlatten(); + + // Total size of module, with all hierarchy below flattened + size_t flattenedSize() const { + if (!m_flattenedSizeValid) { + m_flattenedSizeValid = true; + m_flattenedSize = m_size; + for (const V3GraphEdge& e1 : outEdges()) { + for (const V3GraphEdge& e2 : e1.top()->outEdges()) { + InlineModModuleVertex* const mVtxp = e2.top()->as(); + m_flattenedSize += mVtxp->flattenedSize(); + } } } + return m_flattenedSize; } + // Total number of instances of this module in the whole hierarchy of the design + size_t instanceCount() const { + if (!m_instanceCountValid) { + m_instanceCountValid = true; + m_instanceCount = 0; + for (const V3GraphEdge& e1 : inEdges()) { + for (const V3GraphEdge& e2 : e1.fromp()->inEdges()) { + InlineModModuleVertex* const mVtxp = e2.fromp()->as(); + m_instanceCount += mVtxp->instanceCount(); + } + } + if (!m_instanceCount) { + UASSERT_OBJ(m_modp->isTop(), m_modp, "non-top level module should have instances"); + m_instanceCount = 1; + } + } + return m_instanceCount; + } + + // debug + FileLine* fileline() const override { return m_modp->fileline(); } + std::string dotShape() const override { return "box"; } + std::string dotColor() const override { + return m_noInlineHardWyp ? "red" + : m_shouldInlineWhyp ? "blue" + : m_noInlineSoftWyp ? "orange" + : "black"; + } + std::string name() const override VL_MT_STABLE { + std::string str = m_modp->typeName() + " "s + cvtToHex(m_modp); + str += "\n" + m_modp->name() + " @ " + fileline()->ascii(); + str += "\ninstanceCount: " + std::to_string(instanceCount()); + str += "\nsize: " + std::to_string(m_size); + str += "\nflattenedSize: " + std::to_string(flattenedSize()); + if (m_shouldInlineWhyp) str += "\nShouldInline: "s + m_shouldInlineWhyp; + if (m_noInlineHardWyp) str += "\nNoInlineHard: "s + m_noInlineHardWyp; + if (m_noInlineSoftWyp) str += "\nNoInlineSoft: "s + m_noInlineSoftWyp; + str += "\n"; + return str; + } +}; + +class InlineModCellVertex final : public InlineModEitherVertex { + VL_RTTI_IMPL(InlineModCellVertex, InlineModEitherVertex) + AstCell* const m_cellp; // The cell (instance) + const char* m_doInlineWyp = nullptr; // First reason this instance should be inlined + bool m_flatten = false; // Whether this cell and below already flattened (avoid O(n^2)) + +public: + InlineModCellVertex(InlineModGraph& graph, AstCell* cellp) + : InlineModEitherVertex{graph} + , m_cellp{cellp} {} + ~InlineModCellVertex() override = default; + + // ACCESSORS + AstCell* cellp() const { return m_cellp; } + bool doInline() const { return m_doInlineWyp; } + void setDoInline(const char* whyp) { + if (!m_doInlineWyp) m_doInlineWyp = whyp; + } + bool flatten() const { return m_flatten; } + void setFlatten() { m_flatten = true; } + + // The module vertx this cell is instantiating + InlineModModuleVertex& instanceOf() const { + UASSERT_OBJ(outSize1(), this, "Cell should have exactly one outgoing edge"); + return *outEdges().frontp()->top()->as(); + } + // The module vertex this cell is instantiated in + InlineModModuleVertex& instanceIn() const { + UASSERT_OBJ(inSize1(), this, "Cell should have exactly one incoming edge"); + return *inEdges().frontp()->fromp()->as(); + } + + // debug + FileLine* fileline() const override { return m_cellp->fileline(); } + std::string dotColor() const override { return m_doInlineWyp ? "green" : "black"; } + std::string dotShape() const override { return "ellipse"; } + std::string name() const override VL_MT_STABLE { + std::string str = m_cellp->typeName() + " "s + cvtToHex(m_cellp); + str += "\n" + m_cellp->name() + " @ " + fileline()->ascii(); + if (m_doInlineWyp) str += "\nDoInline: "s + m_doInlineWyp; + str += "\n"; + return str; + } +}; + +InlineModModuleVertex* InlineModGraph::getInlineModModuleVertexp(AstNodeModule* modp) { + if (!modp->user4p()) modp->user4p(new InlineModModuleVertex{*this, modp}); + return modp->user4u().to(); +} +InlineModCellVertex* InlineModGraph::getInlineModCellVertexp(AstCell* cellp) { + if (!cellp->user4p()) cellp->user4p(new InlineModCellVertex{*this, cellp}); + return cellp->user4u().to(); +} + +void InlineModGraph::addEdge(InlineModModuleVertex& parent, InlineModCellVertex& cell) { + UASSERT_OBJ(cell.inEmpty(), &cell, "Cell should have at most one incoming edge"); + new V3GraphEdge{this, &parent, &cell, 1, /* cutable: */ false}; +} +void InlineModGraph::addEdge(InlineModCellVertex& cell, InlineModModuleVertex& submodule) { + UASSERT_OBJ(cell.outEmpty(), &cell, "Cell should have at most one outgoing edge"); + new V3GraphEdge{this, &cell, &submodule, 1, /* cutable: */ false}; +} + +void InlineModModuleVertex::setFlatten() { + for (V3GraphEdge& edge : outEdges()) { + InlineModCellVertex& cVtx = *edge.top()->as(); + if (cVtx.flatten()) continue; + cVtx.setFlatten(); + InlineModModuleVertex& iVtx = cVtx.instanceOf(); + if (!iVtx.noInlineHard() && !iVtx.noInlineSoft()) cVtx.setDoInline("flatten parent"); + iVtx.setFlatten(); + } +} + +//###################################################################### +// Visitor that builds the bipartite module instantiation graph + +class InlineModGraphBuilder final : public VNVisitor { + // STATE + std::unique_ptr m_graphp{new InlineModGraph}; // The graph being built + InlineModModuleVertex* m_modVtxp = nullptr; // Vertex of module currently being iterated // VISITORS void visit(AstNodeModule* nodep) override { - UASSERT_OBJ(!m_modp, nodep, "Unsupported: Nested modules"); - VL_RESTORER(m_modp); - m_modp = nodep; - m_allMods.push_back(nodep); - m_modp->user2(CIL_MAYBE); - m_modp->user4(0); // statement count - if (VN_IS(m_modp, Iface)) { - // Inlining an interface means we no longer have a cell handle to resolve to. - // If inlining moves post-scope this can perhaps be relaxed. - cantInline("modIface", true); - } - if (m_modp->modPublic() && (m_modp->isTop() || !v3Global.opt.flatten())) { - cantInline("modPublic", false); - } - // If the instance is a --lib-create library stub instance, and need tracing, - // then don't inline as we need to know its a lib stub for sepecial handling - // in V3TraceDecl. See #7001. - if (m_modp->verilatorLib() && v3Global.opt.trace()) { - cantInline("verilatorLib with --trace", false); + if (nodep == v3Global.rootp()->constPoolp()->modp()) return; // Ignore const pool module + + UASSERT_OBJ(!m_modVtxp, nodep, "Unsupported: Nested modules"); + + // Create the module vertex + InlineModModuleVertex* const vtxp = m_graphp->getInlineModModuleVertexp(nodep); + + // Check if the module itself is not inlineable + + // Inlining an interface means we no longer have a cell handle to resolve to. + // If inlining moves post-scope this can perhaps be relaxed. + if (VN_IS(nodep, Iface)) vtxp->setNoInlineHard("Interface"); + // Never inline packages - TODO: conceptually fine, but why not? + if (VN_IS(nodep, Package)) vtxp->setNoInlineHard("Package"); + // A --lib-create library stub instance that needs tracing must not be + // inlined, so we still know it is a lib stub in V3TraceDecl (see #7001) + if (nodep->verilatorLib() && v3Global.opt.trace()) { + vtxp->setNoInlineHard("verilatorLib with --trace"); } - iterateChildren(nodep); + // Don't inline public modules by default + if (nodep->modPublic()) vtxp->setNoInlineSoft("Public module"); + + // Iterate children + VL_RESTORER(m_modVtxp); + m_modVtxp = vtxp; + iterateChildrenConst(nodep); } + void visit(AstClass* nodep) override { - // TODO allow inlining of modules that have classes - // (Probably wait for new inliner scheme) - cantInline("class", true); - iterateChildren(nodep); + // TODO allow inlining of modules that contain classes + if (m_modVtxp) m_modVtxp->setNoInlineHard("Contains class"); + iterateChildrenConst(nodep); // TODO: this is only needed or FTaskRef cleanup } + + // Cells instantiate modules void visit(AstCell* nodep) override { - m_moduleState(nodep->modp()).m_cellRefs++; - m_moduleState(m_modp).m_childCells.push_back(nodep); - m_instances[m_modp][nodep->modp()]++; - iterateChildren(nodep); + UASSERT_OBJ(m_modVtxp, nodep, "Cell should be under a module"); + + // Create the cell vertex + InlineModCellVertex* const vtxp = m_graphp->getInlineModCellVertexp(nodep); + + // Add containing-module/instantiated-module edges + m_graphp->addEdge(*m_modVtxp, *vtxp); + m_graphp->addEdge(*vtxp, *m_graphp->getInlineModModuleVertexp(nodep->modp())); + + // Iterate children + iterateChildrenConst(nodep); } + void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::INLINE_MODULE) { - if (!m_modp) { + if (!m_modVtxp) { nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE - } else if (m_modp->user2() == CIL_MAYBE || m_modp->user2() == CIL_NOTSOFT) { - m_modp->user2(CIL_USER); + } else { + m_modVtxp->setShouldInline("Pragma INLINE_MODULE"); } - // Remove so it does not propagate to upper cell - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } else if (nodep->pragType() == VPragmaType::NO_INLINE_MODULE) { - if (!m_modp) { - nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE - } else if (!v3Global.opt.flatten()) { - cantInline("Pragma NO_INLINE_MODULE", false); - } - // Remove so it does not propagate to upper cell - // Remove so don't propagate to upper cell... VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; } + + if (nodep->pragType() == VPragmaType::NO_INLINE_MODULE) { + if (!m_modVtxp) { + nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE + } else { + m_modVtxp->setNoInlineSoft("Pragma NO_INLINE_MODULE"); + } + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; + } + + iterateChildrenConst(nodep); } - void visit(AstVarXRef* nodep) override { - // Keep varp - V3Const::constifyEdit is called during pinReconnectSimple - // which needs varp to be set. V3LinkDot will re-resolve after inlining. - } + + // TODO: Bit nasty to do this here, but historically present, and still necessary void visit(AstNodeFTaskRef* nodep) override { + if (m_modVtxp) m_modVtxp->sizeInc(); // Remove link. V3LinkDot will reestablish it after inlining. // MethodCalls not currently supported by inliner, so keep linked if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) { nodep->taskp(nullptr); VIsCached::clearCacheTree(); } - iterateChildren(nodep); + iterateChildrenConst(nodep); } - void visit(AstAlways* nodep) override { - if (nodep->keyword() != VAlwaysKwd::CONT_ASSIGN) nodep->user4Inc(); // statement count - iterateChildren(nodep); - } - void visit(AstNodeAssign* nodep) override { - // Don't count assignments, as they'll likely flatten out - // Still need to iterate though to nullify VarXRefs - const int oldcnt = m_modp->user4(); - iterateChildren(nodep); - m_modp->user4(oldcnt); - } - void visit(AstNetlist* nodep) override { - // Build ModuleState, user2, and user4 for all modules. - // Also build m_allMods and m_instances. - iterateChildren(nodep); - // Iterate through all modules in bottom-up order. - // Make a final inlining decision for each. - for (AstNodeModule* const modp : vlstd::reverse_view(m_allMods)) { - - // If we're going to inline some modules into this one, - // update user4 (statement count) to reflect that: - int statements = modp->user4(); - for (const auto& pair : m_instances[modp]) { - const AstNodeModule* const childp = pair.first; - if (m_moduleState(childp).m_inlined) { // inlining child - statements += childp->user4() * pair.second; - } - } - modp->user4(statements); - - const int allowed = modp->user2(); - const int refs = m_moduleState(modp).m_cellRefs; - - // Should we automatically inline this module? - // If --flatten is specified, then force everything to be inlined that can be. - // inlineMult = 2000 by default. - // If a mod*#refs is < this # nodes, can inline it - // Packages aren't really "under" anything so they confuse this algorithm - const bool doit = !VN_IS(modp, Package) // - && allowed != CIL_NOTHARD // - && allowed != CIL_NOTSOFT // - && (allowed == CIL_USER // - || v3Global.opt.flatten() // - || refs == 1 // - || statements < INLINE_MODS_SMALLER // - || v3Global.opt.inlineMult() < 1 // - || refs * statements < v3Global.opt.inlineMult()); - m_moduleState(modp).m_inlined = doit; - UINFO(4, " Inline=" << doit << " Possible=" << allowed << " Refs=" << refs - << " Stmts=" << statements << " " << modp); - } - } - //-------------------- + // Base node void visit(AstNode* nodep) override { - if (m_modp) m_modp->user4Inc(); // Inc statement count - iterateChildren(nodep); + if (m_modVtxp) m_modVtxp->sizeInc(); + iterateChildrenConst(nodep); } + // CONSTRUCTORS + explicit InlineModGraphBuilder(AstNetlist* nodep) { + // Build the module instantiation graph + iterateConst(nodep); + // Order vertices (any topological order is fine), can't be cyclic at this point + m_graphp->order(); + // Check that the first vertex is the top level module (everything, including packages, + // have a corresponding AstCell under the top level at this point). + UASSERT_OBJ(m_graphp->vertices().frontp()->as()->modp()->isTop(), + nodep, "First vertex should be top level module"); +#ifdef VL_DEBUG + for (const V3GraphVertex& vtx : m_graphp->vertices()) { + // First vertex is the top levelmodule, we checked above + if (&vtx == m_graphp->vertices().frontp()) continue; + // Otherwise it should have instantiations + UASSERT_OBJ(!vtx.inEmpty(), &vtx, "Should have edges from root"); + } +#endif + } + ~InlineModGraphBuilder() override = default; + public: - // CONSTRUCTORS - explicit InlineMarkVisitor(AstNode* nodep, ModuleStateUser1Allocator& moduleState) - : m_moduleState{moduleState} { - iterate(nodep); - } - ~InlineMarkVisitor() override { - V3Stats::addStat("Optimizations, Inline unsupported", m_statUnsup); + static std::unique_ptr apply(AstNetlist* nodep) { + return std::move(InlineModGraphBuilder{nodep}.m_graphp); } }; @@ -264,8 +391,12 @@ class InlineRelinkVisitor final : public VNVisitor { m_pinSubstitutedXRefs; // VarXRefs created by pin substitution in this relink pass. // Their dotted/inlinedDots already represent the parent's scope // and must not be rewritten on the immediate visit. + InlineModGraph& m_graph; // The instance graph AstNodeModule* const m_modp; // The module we are inlining into + // The vertex of the module we are inlining into, for updating the graph + InlineModModuleVertex* const m_mVtxp = m_graph.getInlineModModuleVertexp(m_modp); const AstCell* const m_cellp; // The cell being inlined + size_t m_nPlaceholders = 0; // Unique identifier sequence number for placeholder variables // VISITORS @@ -282,6 +413,11 @@ class InlineRelinkVisitor final : public VNVisitor { void visit(AstCell* nodep) override { // Cell under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); + // Need to update graph + nodep->user4p(nullptr); // clone copied user4p, reset to make new vertex + InlineModCellVertex* const vtxp = m_graph.getInlineModCellVertexp(nodep); + m_graph.addEdge(*m_mVtxp, *vtxp); + m_graph.addEdge(*vtxp, *m_graph.getInlineModModuleVertexp(nodep->modp())); iterateChildren(nodep); } void visit(AstClass* nodep) override { @@ -464,8 +600,10 @@ class InlineRelinkVisitor final : public VNVisitor { public: // CONSTRUCTORS - InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp) - : m_modp{oldModp} + InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp, + InlineModGraph& graph) + : m_graph{graph} + , m_modp{oldModp} , m_cellp{cellp} { // CellInlines added by V3Begin for generate/named blocks have origModName // "__BEGIN__"; only those added by prior V3Inline passes carry a real module @@ -607,7 +745,7 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) { } // Inline 'cellp' into 'modp'. 'last' indicatest this is tha last instance of the inlined module -void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) { +void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last, InlineModGraph& graph) { UINFO(5, " Inline Cell " << cellp); UINFO(5, " into Module " << modp); @@ -662,8 +800,8 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) { connectPort(modp, newModVarp, pinExprp); } - // Cleanup var names, etc, to not conflict, relink replaced variables - { InlineRelinkVisitor{inlinedp, modp, cellp}; } + // Cleanup var names, etc, to not conflict, relink replaced variables, adjust graph + { InlineRelinkVisitor{inlinedp, modp, cellp, graph}; } // Move statements from the inlined module into the module we are inlining into if (AstNode* const stmtsp = inlinedp->stmtsp()) { modp->addStmtsp(stmtsp->unlinkFrBackWithNext()); @@ -675,39 +813,60 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) { } // Apply all inlining decisions -void process(AstNetlist* netlistp, ModuleStateUser1Allocator& moduleStates) { +void process(AstNetlist* netlistp, InlineModGraph& graph) { // NODE STATE - // Input: - // AstNodeModule::user1p() // ModuleState instance (via moduleState) - // // Cleared entire netlist // AstIfaceRefDType::user1() // Whether the cell pointed to by this // // AstIfaceRefDType has been inlined // AstCell::user3p() // AstCell*, the clone - // AstVar::user3p() // AstVar*, the clone clone + // AstVar::user3p() // AstVar*, the clone // Cleared each cell // AstVar::user2p() // AstVarRef*/AstConst* This port is connected to (AstPin::expr()) - const VNUser3InUse m_user3InUse; + const VNUser1InUse user1InUse; + const VNUser3InUse user3InUse; // Number of inlined instances, for statistics VDouble0 m_nInlined; - // We want to inline bottom up. The modules under the netlist are in - // dependency order (top first, leaves last), so find the end of the list. - AstNode* nodep = netlistp->modulesp(); - while (nodep->nextp()) nodep = nodep->nextp(); + // Gather all cells that need to be inlined (this is in topological order) + std::vector cVtxps; + for (V3GraphVertex& vtx : graph.vertices()) { + InlineModCellVertex* const cVtxp = vtx.cast(); + if (!cVtxp) continue; + if (!cVtxp->doInline()) continue; + cVtxps.push_back(cVtxp); + } - // Iterate module list backwards (stop when we get back to the Netlist) - while (AstNodeModule* const modp = VN_CAST(nodep, NodeModule)) { - nodep = nodep->backp(); + // Inline cells bottom up (leaves into roots) + for (InlineModCellVertex* const cVtxp : vlstd::reverse_view(cVtxps)) { + // Pick up parts before deleting + InlineModModuleVertex& mVtx = cVtxp->instanceIn(); + InlineModModuleVertex* const iVtxp = &cVtxp->instanceOf(); + AstCell* const cellp = cVtxp->cellp(); + const bool last = iVtxp->inSize1(); + UASSERT_OBJ(!iVtxp->noInlineHard(), cellp, "Should not be inlining if not possible"); - // Consider each cell inside the current module for inlining - for (AstCell* const cellp : moduleStates(modp).m_childCells) { - ModuleState& childState = moduleStates(cellp->modp()); - if (!childState.m_inlined) continue; - ++m_nInlined; - inlineCell(modp, cellp, --childState.m_cellRefs == 0); + // Update + ++m_nInlined; + mVtx.sizeInc(iVtxp->size()); // For debug dump only + + // Delete the cell we are inlining + VL_DO_DANGLING(cVtxp->unlinkDelete(&graph), cVtxp); + // Delete the module we are inlining if this is the last instance + if (last) { + while (!iVtxp->outEmpty()) { + InlineModCellVertex* const tVtxp + = iVtxp->outEdges().frontp()->top()->as(); + // Bottom up ordering ensures this + UASSERT_OBJ(!tVtxp->doInline(), tVtxp, "Should have been inlined"); + VL_DO_DANGLING(tVtxp->unlinkDelete(&graph), tVtxp); + } + VL_DO_DANGLING(iVtxp->unlinkDelete(&graph), iVtxp); } + + // Do it + inlineCell(mVtx.modp(), cellp, last, graph); + if (dumpGraphLevel() >= 9) graph.dumpDotFilePrefixed("inlinemod-cell"); } V3Stats::addStat("Optimizations, Inlined instances", m_nInlined); @@ -729,25 +888,65 @@ void process(AstNetlist* netlistp, ModuleStateUser1Allocator& moduleStates) { void V3Inline::inlineAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ":"); - { - const VNUser1InUse m_inuser1; // output of InlineMarkVisitor, input to InlineVisitor. - ModuleStateUser1Allocator moduleState; // AstUser1Allocator + // Build the bipartite module instantiation graph + std::unique_ptr graphp = InlineModGraphBuilder::apply(nodep); + if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-graph"); - // Scoped to clean up temp userN's - { InlineMarkVisitor{nodep, moduleState}; } - - // Inline the modles we decided to inline - ModuleInliner::process(nodep, moduleState); - - // Check inlined modules have been removed during traversal. Otherwise we might have blown - // up Verilator memory consumption. - for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; - modp = VN_AS(modp->nextp(), NodeModule)) { - UASSERT_OBJ(!moduleState(modp).m_inlined, modp, - "Inlined module should have been deleted when the last instance " - "referencing it was inlined"); + // Decide which instances to inline + const size_t designSize + = graphp->vertices().frontp()->as()->flattenedSize(); + for (V3GraphVertex& vtx : graphp->vertices()) { + if (InlineModModuleVertex* const mVtxp = vtx.cast()) { + // If this module is less than 10% of the design, flatten this module + if (mVtxp->flattenedSize() * 10 < designSize) mVtxp->setFlatten(); + // Don't inline if can't inline + if (mVtxp->noInlineHard()) continue; + // Don't inline if soft off + if (mVtxp->noInlineSoft()) continue; + // If all instances of this module combined are less than 20% of the design, inline all + size_t totalSize = mVtxp->flattenedSize() * mVtxp->instanceCount(); + if (totalSize * 5 < designSize) { + for (V3GraphEdge& edge : mVtxp->inEdges()) { + InlineModCellVertex* const cVtxp = edge.fromp()->as(); + cVtxp->setDoInline("< 20% of design"); + } + } + // No more decisions based on module vertex + continue; } + + // The instantiation + InlineModCellVertex& cVtx = *vtx.as(); + // The module instantiated by this cell + InlineModModuleVertex& mVtx = cVtx.instanceOf(); + + // Don't inline if can't inline, duh! + if (mVtx.noInlineHard()) continue; + + // If it should be inlined, inlined it + if (mVtx.shouldInline()) cVtx.setDoInline("should inline"); + // If --flatten, inline it + if (v3Global.opt.flatten()) cVtx.setDoInline("--flatten"); + + // Don't inline for other reasons if soft off + if (mVtx.noInlineSoft()) continue; + + // If instatiated in exactly one static site, inline it + if (mVtx.inSize1()) cVtx.setDoInline("Single static instance"); + // If small, inline it + if (mVtx.size() < INLINE_MODS_SMALLER) cVtx.setDoInline("Small"); + // If inlineMult is 0, inline it + if (v3Global.opt.inlineMult() < 1) cVtx.setDoInline("inlineMult < 1"); + // If it would yield less than the given number of ops, inline it + const size_t inlinedSize = mVtx.inEdges().size() * mVtx.size(); + const size_t limit = v3Global.opt.inlineMult(); + if (inlinedSize < limit) cVtx.setDoInline("inlinedSize < inlineMult"); } + if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-decision"); + + // Inline the modles we decided to inline + ModuleInliner::process(nodep, *graphp); + if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-inlined"); V3Global::dumpCheckGlobalTree("inline", 0, dumpTreeEitherLevel() >= 3); } diff --git a/test_regress/t/t_cover_fsm_if_unknown_enum_multi_bad.out b/test_regress/t/t_cover_fsm_if_unknown_enum_multi_bad.out index 7416b7aa4..8cf3712f6 100644 --- a/test_regress/t/t_cover_fsm_if_unknown_enum_multi_bad.out +++ b/test_regress/t/t_cover_fsm_if_unknown_enum_multi_bad.out @@ -1,33 +1,33 @@ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:26:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_then_u.state_q': assigned value 3 is not present in the declared enum - 26 | S0: state_d = sel ? 2'd3 : S1; +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:274:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_wide_direct_u.state_q': assigned value 40'hffffffffff is not present in the declared enum + 274 | S0: state_d = 40'hffff_ffff_ff; | ^ ... For warning description see https://verilator.org/warn/COVERIGN?v=latest ... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message. -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:53:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_else_u.state_q': assigned value 3 is not present in the declared enum - 53 | S0: state_d = sel ? S1 : 2'd3; - | ^ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:79:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_direct_u.state_q': assigned value 3 is not present in the declared enum - 79 | S0: state_d = 2'd3; - | ^ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:126:15: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_reset_u.state_q': assigned value 3 is not present in the declared enum - 126 | state_q <= 2'd3; - | ^~ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:150:7: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_source_u.state_q': case item value 3 is not present in the declared enum - 150 | 2'd3: state_d = S0; - | ^~~~ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:175:5: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_source_u.state_q': case item value 3 is not present in the declared enum - 175 | if (state_q == 2'd3) state_d = S0; - | ^~ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:199:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_direct_target_u.state_q': assigned value 3 is not present in the declared enum - 199 | if (state_q == S0) state_d = 2'd3; +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:249:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_else_target_u.state_q': assigned value 3 is not present in the declared enum + 249 | if (state_q == S0) state_d = sel ? S1 : 2'd3; | ^ %Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:224:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_then_target_u.state_q': assigned value 3 is not present in the declared enum 224 | if (state_q == S0) state_d = sel ? 2'd3 : S1; | ^ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:249:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_else_target_u.state_q': assigned value 3 is not present in the declared enum - 249 | if (state_q == S0) state_d = sel ? S1 : 2'd3; +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:199:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_direct_target_u.state_q': assigned value 3 is not present in the declared enum + 199 | if (state_q == S0) state_d = 2'd3; | ^ -%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:274:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_wide_direct_u.state_q': assigned value 40'hffffffffff is not present in the declared enum - 274 | S0: state_d = 40'hffff_ffff_ff; +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:175:5: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_source_u.state_q': case item value 3 is not present in the declared enum + 175 | if (state_q == 2'd3) state_d = S0; + | ^~ +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:150:7: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_source_u.state_q': case item value 3 is not present in the declared enum + 150 | 2'd3: state_d = S0; + | ^~~~ +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:126:15: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_reset_u.state_q': assigned value 3 is not present in the declared enum + 126 | state_q <= 2'd3; + | ^~ +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:79:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_direct_u.state_q': assigned value 3 is not present in the declared enum + 79 | S0: state_d = 2'd3; + | ^ +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:53:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_else_u.state_q': assigned value 3 is not present in the declared enum + 53 | S0: state_d = sel ? S1 : 2'd3; + | ^ +%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:26:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_then_u.state_q': assigned value 3 is not present in the declared enum + 26 | S0: state_d = sel ? 2'd3 : S1; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_cover_fsm_plain_always_warn_multi_bad.out b/test_regress/t/t_cover_fsm_plain_always_warn_multi_bad.out index 064ef2ff1..976c00e07 100644 --- a/test_regress/t/t_cover_fsm_plain_always_warn_multi_bad.out +++ b/test_regress/t/t_cover_fsm_plain_always_warn_multi_bad.out @@ -1,12 +1,12 @@ -%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:25:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb - 25 | case (state_q) +%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:86:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb + 86 | case (state_q) | ^~~~ ... For warning description see https://verilator.org/warn/COVERIGN?v=latest ... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message. %Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:55:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb 55 | case (state_d) | ^~~~ -%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:86:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb - 86 | case (state_q) +%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:25:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb + 25 | case (state_q) | ^~~~ %Error: Exiting due to diff --git a/test_regress/t/t_dpi_2exparg_bad.out b/test_regress/t/t_dpi_2exparg_bad.out index e908a6f57..812511578 100644 --- a/test_regress/t/t_dpi_2exparg_bad.out +++ b/test_regress/t/t_dpi_2exparg_bad.out @@ -10,12 +10,12 @@ | ^ ... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=latest ... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message. -%Error: t/t_dpi_2exparg_bad.v:21:8: Duplicate declaration of DPI function with different signature: 'dpix_twice' - 21 | task dpix_twice(input int i, output [63:0] o); - | ^~~~~~~~~~ - : ... New signature: void dpix_twice (int, svLogicVecVal* /* logic[63:0] */ ) - t/t_dpi_2exparg_bad.v:12:8: ... Original signature: void dpix_twice (int, svLogicVecVal* /* logic[2:0] */ ) +%Error: t/t_dpi_2exparg_bad.v:12:8: Duplicate declaration of DPI function with different signature: 'dpix_twice' 12 | task dpix_twice(input int i, output [2:0] o); + | ^~~~~~~~~~ + : ... New signature: void dpix_twice (int, svLogicVecVal* /* logic[2:0] */ ) + t/t_dpi_2exparg_bad.v:21:8: ... Original signature: void dpix_twice (int, svLogicVecVal* /* logic[63:0] */ ) + 21 | task dpix_twice(input int i, output [63:0] o); | ^~~~~~~~~~ ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. %Error: Exiting due to diff --git a/test_regress/t/t_fsmmulti_combo_multi_warn_bad.out b/test_regress/t/t_fsmmulti_combo_multi_warn_bad.out index 8985f2c91..367f70f55 100644 --- a/test_regress/t/t_fsmmulti_combo_multi_warn_bad.out +++ b/test_regress/t/t_fsmmulti_combo_multi_warn_bad.out @@ -1,29 +1,3 @@ -%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:36:21: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented. - 36 | B0: state_b_d = B1; - | ^ - t/t_fsmmulti_combo_multi_warn_bad.v:32:21: ... Location of first supported candidate for 't.same_u.state_a_q' - 32 | A0: state_a_d = A1; - | ^ - ... For warning description see https://verilator.org/warn/FSMMULTI?v=latest - ... Use "/* verilator lint_off FSMMULTI */" and lint_on around source to disable this message. -%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:73:19: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented. - 73 | S0: state_d = S1; - | ^ - t/t_fsmmulti_combo_multi_warn_bad.v:65:19: ... Location of first supported candidate for 't.split_u.state_q' - 65 | S0: state_d = S1; - | ^ -%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:107:5: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented. - 107 | if (state_b_q == B0) state_b_d = B1; - | ^~ - t/t_fsmmulti_combo_multi_warn_bad.v:105:5: ... Location of first supported candidate for 't.same_if_u.state_a_q' - 105 | if (state_a_q == A0) state_a_d = A1; - | ^~ -%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:140:5: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented. - 140 | if (state_q == S0) state_d = S1; - | ^~ - t/t_fsmmulti_combo_multi_warn_bad.v:134:5: ... Location of first supported candidate for 't.split_if_u.state_q' - 134 | if (state_q == S0) state_d = S1; - | ^~ %Warning-COVERIGN: t/t_fsmmulti_combo_multi_warn_bad.v:165:5: Ignoring unsupported: FSM coverage on multiple supported if-chain statements found in the same combinational always block. Only the first candidate will be instrumented. 165 | if (state_q == S1) state_d = S0; | ^~ @@ -32,4 +6,30 @@ | ^~ ... For warning description see https://verilator.org/warn/COVERIGN?v=latest ... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message. +%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:140:5: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented. + 140 | if (state_q == S0) state_d = S1; + | ^~ + t/t_fsmmulti_combo_multi_warn_bad.v:134:5: ... Location of first supported candidate for 't.split_if_u.state_q' + 134 | if (state_q == S0) state_d = S1; + | ^~ + ... For warning description see https://verilator.org/warn/FSMMULTI?v=latest + ... Use "/* verilator lint_off FSMMULTI */" and lint_on around source to disable this message. +%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:107:5: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented. + 107 | if (state_b_q == B0) state_b_d = B1; + | ^~ + t/t_fsmmulti_combo_multi_warn_bad.v:105:5: ... Location of first supported candidate for 't.same_if_u.state_a_q' + 105 | if (state_a_q == A0) state_a_d = A1; + | ^~ +%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:73:19: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented. + 73 | S0: state_d = S1; + | ^ + t/t_fsmmulti_combo_multi_warn_bad.v:65:19: ... Location of first supported candidate for 't.split_u.state_q' + 65 | S0: state_d = S1; + | ^ +%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:36:21: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented. + 36 | B0: state_b_d = B1; + | ^ + t/t_fsmmulti_combo_multi_warn_bad.v:32:21: ... Location of first supported candidate for 't.same_u.state_a_q' + 32 | A0: state_a_d = A1; + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_gen_upscope.out b/test_regress/t/t_gen_upscope.out index 3765ed4ca..bb8b8e714 100644 --- a/test_regress/t/t_gen_upscope.out +++ b/test_regress/t/t_gen_upscope.out @@ -1,12 +1,12 @@ -created tag with scope = top.t.tag -created tag with scope = top.t.b.gen[0].tag created tag with scope = top.t.b.gen[1].tag +created tag with scope = top.t.b.gen[0].tag +created tag with scope = top.t.tag mod a has scope = top.t mod a has tag = top.t.tag mod b has scope = top.t.b mod b has tag = top.t.tag -mod c has scope = top.t.b.gen[0].c -mod c has tag = top.t.b.gen[0].tag mod c has scope = top.t.b.gen[1].c mod c has tag = top.t.b.gen[1].tag +mod c has scope = top.t.b.gen[0].c +mod c has tag = top.t.b.gen[0].tag *-* All Finished *-* diff --git a/test_regress/t/t_genfor_signed.out b/test_regress/t/t_genfor_signed.out index 7f921d5a9..b99a494fc 100644 --- a/test_regress/t/t_genfor_signed.out +++ b/test_regress/t/t_genfor_signed.out @@ -1,9 +1,9 @@ -top.t.u_sub1.unnamedblk1 1..1 i=1 +top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=1 +top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=0 top.t.u_sub0.unnamedblk1 1..0 i=1 top.t.u_sub0.unnamedblk1 1..0 i=0 top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=1 top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=0 top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=-1 -top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=1 -top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=0 +top.t.u_sub1.unnamedblk1 1..1 i=1 *-* All Finished *-* diff --git a/test_regress/t/t_inst_tree_inl1_pub0.py b/test_regress/t/t_inst_tree_inl1_pub0.py index 443c7b9b1..036210aaa 100755 --- a/test_regress/t/t_inst_tree_inl1_pub0.py +++ b/test_regress/t/t_inst_tree_inl1_pub0.py @@ -20,11 +20,11 @@ test.compile( if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"t.u.u0.u0.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.u.u1.u0.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.u.u0.u1.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.u.u1.u1.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' ) test.file_grep( out_filename, diff --git a/test_regress/t/t_json_only_flat.out b/test_regress/t/t_json_only_flat.out index e90bba08b..6b3d6ca6c 100644 --- a/test_regress/t/t_json_only_flat.out +++ b/test_regress/t/t_json_only_flat.out @@ -24,20 +24,20 @@ "valuep": [ {"type":"CONST","name":"2'h2","addr":"(Z)","loc":"d,25:43,25:44","dtypep":"(T)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell1.WIDTH","addr":"(AB)","loc":"d,48:15,48:20","dtypep":"(BB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.cell2.clk","addr":"(AB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.d","addr":"(BB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.q","addr":"(CB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.WIDTH","addr":"(DB)","loc":"d,48:15,48:20","dtypep":"(EB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ - {"type":"CONST","name":"32'sh4","addr":"(CB)","loc":"d,32:14,32:15","dtypep":"(DB)"} + {"type":"CONST","name":"32'sh4","addr":"(FB)","loc":"d,32:14,32:15","dtypep":"(GB)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell1.clk","addr":"(EB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.d","addr":"(FB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.q","addr":"(GB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.IGNORED","addr":"(HB)","loc":"d,55:14,55:21","dtypep":"(BB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], + {"type":"VAR","name":"t.cell1.clk","addr":"(HB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.d","addr":"(IB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.q","addr":"(JB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.IGNORED","addr":"(KB)","loc":"d,55:14,55:21","dtypep":"(EB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ - {"type":"CONST","name":"32'sh1","addr":"(IB)","loc":"d,55:24,55:25","dtypep":"(DB)"} + {"type":"CONST","name":"32'sh1","addr":"(LB)","loc":"d,55:24,55:25","dtypep":"(GB)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell2.clk","addr":"(JB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell2.d","addr":"(KB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell2.q","addr":"(LB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,7:8,7:9","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(MB)","loc":"d,7:8,7:9","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", @@ -85,74 +85,74 @@ {"type":"VARSCOPE","name":"t.S_IDLE","addr":"(JC)","loc":"d,23:26,23:32","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(S)"}, {"type":"VARSCOPE","name":"t.S_FETCH","addr":"(KC)","loc":"d,24:26,24:33","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(W)"}, {"type":"VARSCOPE","name":"t.S_EXEC","addr":"(LC)","loc":"d,25:26,25:32","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(Y)"}, - {"type":"VARSCOPE","name":"t.cell1.WIDTH","addr":"(MC)","loc":"d,48:15,48:20","dtypep":"(BB)","isTrace":true,"scopep":"(MB)","varp":"(AB)"}, - {"type":"VARSCOPE","name":"t.cell1.clk","addr":"(NC)","loc":"d,50:11,50:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(EB)"}, - {"type":"ALWAYS","name":"","addr":"(OC)","loc":"d,50:11,50:14","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell2.clk","addr":"(MC)","loc":"d,62:11,62:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(AB)"}, + {"type":"ALWAYS","name":"","addr":"(NC)","loc":"d,62:11,62:14","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(PC)","loc":"d,50:11,50:14","dtypep":"(J)", + {"type":"ASSIGNW","name":"","addr":"(OC)","loc":"d,62:11,62:14","dtypep":"(J)", "rhsp": [ - {"type":"VARREF","name":"clk","addr":"(QC)","loc":"d,50:11,50:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"clk","addr":"(PC)","loc":"d,62:11,62:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell1.clk","addr":"(RC)","loc":"d,50:11,50:14","dtypep":"(J)","access":"WR","varp":"(EB)","varScopep":"(NC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell2.clk","addr":"(QC)","loc":"d,62:11,62:14","dtypep":"(J)","access":"WR","varp":"(AB)","varScopep":"(MC)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"VARSCOPE","name":"t.cell1.d","addr":"(SC)","loc":"d,51:23,51:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(FB)"}, - {"type":"ALWAYS","name":"","addr":"(TC)","loc":"d,51:23,51:24","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell2.d","addr":"(RC)","loc":"d,63:17,63:18","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(BB)"}, + {"type":"ALWAYS","name":"","addr":"(SC)","loc":"d,63:17,63:18","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(UC)","loc":"d,51:23,51:24","dtypep":"(H)", + {"type":"ASSIGNW","name":"","addr":"(TC)","loc":"d,63:17,63:18","dtypep":"(H)", "rhsp": [ - {"type":"VARREF","name":"d","addr":"(VC)","loc":"d,51:23,51:24","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.between","addr":"(UC)","loc":"d,63:17,63:18","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell1.d","addr":"(WC)","loc":"d,51:23,51:24","dtypep":"(H)","access":"WR","varp":"(FB)","varScopep":"(SC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell2.d","addr":"(VC)","loc":"d,63:17,63:18","dtypep":"(H)","access":"WR","varp":"(BB)","varScopep":"(RC)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"VARSCOPE","name":"t.cell1.q","addr":"(XC)","loc":"d,52:30,52:31","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(GB)"}, - {"type":"ALWAYS","name":"","addr":"(YC)","loc":"d,52:30,52:31","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell2.q","addr":"(WC)","loc":"d,64:23,64:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(CB)"}, + {"type":"ALWAYS","name":"","addr":"(XC)","loc":"d,64:23,64:24","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(ZC)","loc":"d,52:30,52:31","dtypep":"(H)", + {"type":"ASSIGNW","name":"","addr":"(YC)","loc":"d,64:23,64:24","dtypep":"(H)", "rhsp": [ - {"type":"VARREF","name":"t.between","addr":"(AD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"q","addr":"(ZC)","loc":"d,64:23,64:24","dtypep":"(H)","access":"RD","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell1.q","addr":"(BD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"WR","varp":"(GB)","varScopep":"(XC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell2.q","addr":"(AD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"WR","varp":"(CB)","varScopep":"(WC)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"VARSCOPE","name":"t.cell1.IGNORED","addr":"(CD)","loc":"d,55:14,55:21","dtypep":"(BB)","isTrace":true,"scopep":"(MB)","varp":"(HB)"}, - {"type":"VARSCOPE","name":"t.cell2.clk","addr":"(DD)","loc":"d,62:11,62:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(JB)"}, - {"type":"ALWAYS","name":"","addr":"(ED)","loc":"d,62:11,62:14","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell1.WIDTH","addr":"(BD)","loc":"d,48:15,48:20","dtypep":"(EB)","isTrace":true,"scopep":"(MB)","varp":"(DB)"}, + {"type":"VARSCOPE","name":"t.cell1.clk","addr":"(CD)","loc":"d,50:11,50:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(HB)"}, + {"type":"ALWAYS","name":"","addr":"(DD)","loc":"d,50:11,50:14","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(FD)","loc":"d,62:11,62:14","dtypep":"(J)", + {"type":"ASSIGNW","name":"","addr":"(ED)","loc":"d,50:11,50:14","dtypep":"(J)", "rhsp": [ - {"type":"VARREF","name":"clk","addr":"(GD)","loc":"d,62:11,62:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"clk","addr":"(FD)","loc":"d,50:11,50:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell2.clk","addr":"(HD)","loc":"d,62:11,62:14","dtypep":"(J)","access":"WR","varp":"(JB)","varScopep":"(DD)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell1.clk","addr":"(GD)","loc":"d,50:11,50:14","dtypep":"(J)","access":"WR","varp":"(HB)","varScopep":"(CD)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"VARSCOPE","name":"t.cell2.d","addr":"(ID)","loc":"d,63:17,63:18","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(KB)"}, - {"type":"ALWAYS","name":"","addr":"(JD)","loc":"d,63:17,63:18","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell1.d","addr":"(HD)","loc":"d,51:23,51:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(IB)"}, + {"type":"ALWAYS","name":"","addr":"(ID)","loc":"d,51:23,51:24","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(KD)","loc":"d,63:17,63:18","dtypep":"(H)", + {"type":"ASSIGNW","name":"","addr":"(JD)","loc":"d,51:23,51:24","dtypep":"(H)", "rhsp": [ - {"type":"VARREF","name":"t.between","addr":"(LD)","loc":"d,63:17,63:18","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"d","addr":"(KD)","loc":"d,51:23,51:24","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell2.d","addr":"(MD)","loc":"d,63:17,63:18","dtypep":"(H)","access":"WR","varp":"(KB)","varScopep":"(ID)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell1.d","addr":"(LD)","loc":"d,51:23,51:24","dtypep":"(H)","access":"WR","varp":"(IB)","varScopep":"(HD)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"VARSCOPE","name":"t.cell2.q","addr":"(ND)","loc":"d,64:23,64:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(LB)"}, - {"type":"ALWAYS","name":"","addr":"(OD)","loc":"d,64:23,64:24","keyword":"cont_assign","sentreep": [], + {"type":"VARSCOPE","name":"t.cell1.q","addr":"(MD)","loc":"d,52:30,52:31","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(JB)"}, + {"type":"ALWAYS","name":"","addr":"(ND)","loc":"d,52:30,52:31","keyword":"cont_assign","sentreep": [], "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(PD)","loc":"d,64:23,64:24","dtypep":"(H)", + {"type":"ASSIGNW","name":"","addr":"(OD)","loc":"d,52:30,52:31","dtypep":"(H)", "rhsp": [ - {"type":"VARREF","name":"q","addr":"(QD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"RD","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.between","addr":"(PD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.cell2.q","addr":"(RD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"WR","varp":"(LB)","varScopep":"(ND)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.cell1.q","addr":"(QD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"WR","varp":"(JB)","varScopep":"(MD)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} - ]} + ]}, + {"type":"VARSCOPE","name":"t.cell1.IGNORED","addr":"(RD)","loc":"d,55:14,55:21","dtypep":"(EB)","isTrace":true,"scopep":"(MB)","varp":"(KB)"} ], "blocksp": [ {"type":"ALWAYS","name":"","addr":"(SD)","loc":"d,27:23,27:24","keyword":"cont_assign","sentreep": [], @@ -221,34 +221,34 @@ {"type":"VARREF","name":"t.anonymous_expr","addr":"(RE)","loc":"d,29:10,29:24","dtypep":"(J)","access":"WR","varp":"(R)","varScopep":"(IC)","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []} ]}, - {"type":"ALWAYS","name":"","addr":"(SE)","loc":"d,57:3,57:9","keyword":"always", + {"type":"ALWAYS","name":"","addr":"(SE)","loc":"d,67:12,67:13","keyword":"cont_assign","sentreep": [], + "stmtsp": [ + {"type":"ASSIGNW","name":"","addr":"(TE)","loc":"d,67:12,67:13","dtypep":"(H)", + "rhsp": [ + {"type":"VARREF","name":"t.between","addr":"(UE)","loc":"d,67:14,67:15","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} + ], + "lhsp": [ + {"type":"VARREF","name":"q","addr":"(VE)","loc":"d,67:10,67:11","dtypep":"(H)","access":"WR","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"} + ],"timingControlp": [],"strengthSpecp": []} + ]}, + {"type":"ALWAYS","name":"","addr":"(WE)","loc":"d,57:3,57:9","keyword":"always", "sentreep": [ - {"type":"SENTREE","name":"","addr":"(TE)","loc":"d,57:10,57:11", + {"type":"SENTREE","name":"","addr":"(XE)","loc":"d,57:10,57:11", "sensesp": [ - {"type":"SENITEM","name":"","addr":"(UE)","loc":"d,57:12,57:19","edgeType":"POS", + {"type":"SENITEM","name":"","addr":"(YE)","loc":"d,57:12,57:19","edgeType":"POS", "sensp": [ - {"type":"VARREF","name":"clk","addr":"(VE)","loc":"d,57:20,57:23","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"clk","addr":"(ZE)","loc":"d,57:20,57:23","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"} ],"condp": []} ]} ], "stmtsp": [ - {"type":"ASSIGNDLY","name":"","addr":"(WE)","loc":"d,57:27,57:29","dtypep":"(H)", + {"type":"ASSIGNDLY","name":"","addr":"(AF)","loc":"d,57:27,57:29","dtypep":"(H)", "rhsp": [ - {"type":"VARREF","name":"d","addr":"(XE)","loc":"d,57:30,57:31","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"d","addr":"(BF)","loc":"d,57:30,57:31","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} ], "lhsp": [ - {"type":"VARREF","name":"t.between","addr":"(YE)","loc":"d,57:25,57:26","dtypep":"(H)","access":"WR","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.between","addr":"(CF)","loc":"d,57:25,57:26","dtypep":"(H)","access":"WR","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} ],"timingControlp": []} - ]}, - {"type":"ALWAYS","name":"","addr":"(ZE)","loc":"d,67:12,67:13","keyword":"cont_assign","sentreep": [], - "stmtsp": [ - {"type":"ASSIGNW","name":"","addr":"(AF)","loc":"d,67:12,67:13","dtypep":"(H)", - "rhsp": [ - {"type":"VARREF","name":"t.between","addr":"(BF)","loc":"d,67:14,67:15","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"} - ], - "lhsp": [ - {"type":"VARREF","name":"q","addr":"(CF)","loc":"d,67:10,67:11","dtypep":"(H)","access":"WR","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"} - ],"timingControlp": [],"strengthSpecp": []} ]} ],"inlinesp": []} ]} @@ -260,11 +260,11 @@ {"type":"BASICDTYPE","name":"bit","addr":"(V)","loc":"d,23:35,23:40","dtypep":"(V)","keyword":"bit","range":"1:0","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(J)","loc":"d,27:32,27:34","dtypep":"(J)","keyword":"logic","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(T)","loc":"d,23:14,23:19","dtypep":"(T)","keyword":"logic","range":"1:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(BB)","loc":"d,48:15,48:20","dtypep":"(BB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(EB)","loc":"d,48:15,48:20","dtypep":"(EB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(H)","loc":"d,16:15,16:16","dtypep":"(H)","keyword":"logic","range":"3:0","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(AE)","loc":"d,27:26,27:27","dtypep":"(AE)","keyword":"logic","range":"1:0","generic":true,"signed":true,"rangep": []}, {"type":"BASICDTYPE","name":"bit","addr":"(VD)","loc":"d,27:32,27:34","dtypep":"(VD)","keyword":"bit","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"bit","addr":"(DB)","loc":"d,29:48,29:49","dtypep":"(DB)","keyword":"bit","range":"31:0","generic":true,"signed":true,"rangep": []} + {"type":"BASICDTYPE","name":"bit","addr":"(GB)","loc":"d,29:48,29:49","dtypep":"(GB)","keyword":"bit","range":"31:0","generic":true,"signed":true,"rangep": []} ]}, {"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0", "modulep": [ diff --git a/test_regress/t/t_lint_unusedloop_removed_bad.out b/test_regress/t/t_lint_unusedloop_removed_bad.out index 792568e78..16b88ada9 100644 --- a/test_regress/t/t_lint_unusedloop_removed_bad.out +++ b/test_regress/t/t_lint_unusedloop_removed_bad.out @@ -21,12 +21,6 @@ %Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:280:5: Loop is not used and will be optimized out 280 | while (m_2_ticked); | ^~~~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false - 114 | while(always_zero < 0) begin - | ^~~~~ -%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:171:5: Loop condition is always false - 171 | while(always_false) begin - | ^~~~~ %Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:181:5: Loop condition is always false 181 | while(always_zero) begin | ^~~~~ @@ -36,4 +30,10 @@ %Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:190:5: Loop condition is always false 190 | for (int i = 0; i < always_zero; i++) | ^~~ +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:171:5: Loop condition is always false + 171 | while(always_false) begin + | ^~~~~ +%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false + 114 | while(always_zero < 0) begin + | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_opt_dedupe_clk_gate.py b/test_regress/t/t_opt_dedupe_clk_gate.py index 02778fcec..0fbd122ba 100755 --- a/test_regress/t/t_opt_dedupe_clk_gate.py +++ b/test_regress/t/t_opt_dedupe_clk_gate.py @@ -18,7 +18,7 @@ test.compile(verilator_flags2=["--no-json-edit-nums", "--stats"]) if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"t.f0.clock_gate.clken_latched","addr":"[^"]*","loc":"\w,44:[^"]*","dtypep":"\(\w+\)",.*"origName":"clken_latched",.*"isLatched":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.f1.clock_gate.clken_latched","addr":"[^"]*","loc":"\w,44:[^"]*","dtypep":"\(\w+\)",.*"origName":"clken_latched",.*"isLatched":true,.*"dtypeName":"logic"' ) test.file_grep(test.stats, r'Optimizations, Gate sigs deduped\s+(\d+)', 2) diff --git a/test_regress/t/t_unoptflat_simple_3_bad.out b/test_regress/t/t_unoptflat_simple_3_bad.out index f5ef439ae..7e31eb84d 100644 --- a/test_regress/t/t_unoptflat_simple_3_bad.out +++ b/test_regress/t/t_unoptflat_simple_3_bad.out @@ -4,8 +4,8 @@ ... For warning description see https://verilator.org/warn/UNOPTFLAT?v=latest ... Use "/* verilator lint_off UNOPTFLAT */" and lint_on around source to disable this message. t/t_unoptflat_simple_3.v:16:14: Example path: t.x - t/t_unoptflat_simple_3.v:58:18: Example path: ASSIGNW - t/t_unoptflat_simple_3.v:56:21: Example path: t.__Vcellout__test1i__xvecout - t/t_unoptflat_simple_3.v:21:8: Example path: ASSIGNW + t/t_unoptflat_simple_3.v:76:18: Example path: ASSIGNW + t/t_unoptflat_simple_3.v:74:21: Example path: t.__Vcellout__test2i__xvecout + t/t_unoptflat_simple_3.v:27:8: Example path: ASSIGNW t/t_unoptflat_simple_3.v:16:14: Example path: t.x %Error: Exiting due to diff --git a/test_regress/t/t_x_rand_mt_stability.out b/test_regress/t/t_x_rand_mt_stability.out index 30d041b29..cf0f962d9 100644 --- a/test_regress/t/t_x_rand_mt_stability.out +++ b/test_regress/t/t_x_rand_mt_stability.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x5fa24450 diff --git a/test_regress/t/t_x_rand_mt_stability_add.out b/test_regress/t/t_x_rand_mt_stability_add.out index 30d041b29..cf0f962d9 100644 --- a/test_regress/t/t_x_rand_mt_stability_add.out +++ b/test_regress/t/t_x_rand_mt_stability_add.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x5fa24450 diff --git a/test_regress/t/t_x_rand_mt_stability_add_trace.out b/test_regress/t/t_x_rand_mt_stability_add_trace.out index 30d041b29..cf0f962d9 100644 --- a/test_regress/t/t_x_rand_mt_stability_add_trace.out +++ b/test_regress/t/t_x_rand_mt_stability_add_trace.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x5fa24450 diff --git a/test_regress/t/t_x_rand_mt_stability_trace.out b/test_regress/t/t_x_rand_mt_stability_trace.out index 30d041b29..cf0f962d9 100644 --- a/test_regress/t/t_x_rand_mt_stability_trace.out +++ b/test_regress/t/t_x_rand_mt_stability_trace.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x5fa24450 diff --git a/test_regress/t/t_x_rand_mt_stability_zeros.out b/test_regress/t/t_x_rand_mt_stability_zeros.out index 2b3a3a882..eaac43644 100644 --- a/test_regress/t/t_x_rand_mt_stability_zeros.out +++ b/test_regress/t/t_x_rand_mt_stability_zeros.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0x00000000 big = 0x0000000000000000000000000000000000000000000000000000000000000000 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x0 top.t.the_sub_yes_inline_2 no_init 0x0 +top.t.the_sub_yes_inline_1 no_init 0x0 top.t.the_sub_no_inline_1 no_init 0x0 top.t.the_sub_no_inline_2 no_init 0x0 rand = 0x5fa24450 diff --git a/test_regress/t/t_x_rand_stability.out b/test_regress/t/t_x_rand_stability.out index 1db7b9396..eaa53dd1f 100644 --- a/test_regress/t/t_x_rand_stability.out +++ b/test_regress/t/t_x_rand_stability.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x24800459 diff --git a/test_regress/t/t_x_rand_stability_add.out b/test_regress/t/t_x_rand_stability_add.out index 1db7b9396..eaa53dd1f 100644 --- a/test_regress/t/t_x_rand_stability_add.out +++ b/test_regress/t/t_x_rand_stability_add.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x24800459 diff --git a/test_regress/t/t_x_rand_stability_add_trace.out b/test_regress/t/t_x_rand_stability_add_trace.out index 1db7b9396..eaa53dd1f 100644 --- a/test_regress/t/t_x_rand_stability_add_trace.out +++ b/test_regress/t/t_x_rand_stability_add_trace.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x24800459 diff --git a/test_regress/t/t_x_rand_stability_trace.out b/test_regress/t/t_x_rand_stability_trace.out index 1db7b9396..eaa53dd1f 100644 --- a/test_regress/t/t_x_rand_stability_trace.out +++ b/test_regress/t/t_x_rand_stability_trace.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0xdf5768de big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46 +top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58 top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8 top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d rand = 0x24800459 diff --git a/test_regress/t/t_x_rand_stability_zeros.out b/test_regress/t/t_x_rand_stability_zeros.out index f0fc3e106..c6dc6b6ab 100644 --- a/test_regress/t/t_x_rand_stability_zeros.out +++ b/test_regress/t/t_x_rand_stability_zeros.out @@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000 uninitialized2 = 0x00000000 big = 0x0000000000000000000000000000000000000000000000000000000000000000 random_init = 0x5fa24450 -top.t.the_sub_yes_inline_1 no_init 0x0 top.t.the_sub_yes_inline_2 no_init 0x0 +top.t.the_sub_yes_inline_1 no_init 0x0 top.t.the_sub_no_inline_1 no_init 0x0 top.t.the_sub_no_inline_2 no_init 0x0 rand = 0x24800459