diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 07746302b..23f2756ed 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -29,7 +29,6 @@ #include "V3Stats.h" -// EOM #include "V3UndrivenCapture.h" #include @@ -54,7 +53,6 @@ class UndrivenVarEntry final { const FileLine* m_nodeFileLinep = nullptr; // File line of varref if driven, else nullptr bool m_underGen = false; // Under a generate - // EOM const AstNode* m_callNodep = nullptr; // call node if driven via writeSummary, else nullptr const FileLine* m_callFileLinep = nullptr; // file line of call node if driven via summary @@ -286,7 +284,6 @@ public: } } - // EOM void drivenViaCall(const AstNode* nodep, const FileLine* fileLinep) { drivenWhole(); if (!m_callNodep) { @@ -322,7 +319,6 @@ class UndrivenVisitor final : public VNVisitorConst { const AstAlways* m_alwaysp = nullptr; // Current always of either type const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr - // EOM V3UndrivenCapture* const m_capturep = nullptr; const bool m_enableWriteSummary = false; @@ -443,21 +439,9 @@ class UndrivenVisitor final : public VNVisitorConst { } } - // EOM // If writeSummary is enabled, task/function definitions are treated as non-executed. // Their effects are applied at call sites via writeSummary(), so don't let definition // traversal create phantom "other writes" for MULTIDRIVEN. - - //const auto inExecutedContext = [this, nodep]() { - // return !(m_enableWriteSummary && m_taskp && !m_alwaysp && !m_inContAssign && - // !m_inInitialStatic - // && !m_inBBox && !m_taskp->dpiExport() && !nodep->varp()->isFuncLocal()); - //}; - - //if (!inExecutedContext()) { - // return; - //} - if (m_enableWriteSummary && m_taskp && !m_alwaysp && !m_inContAssign && !m_inInitialStatic && !m_inBBox && !m_taskp->dpiExport()) { AstVar* const retVarp = VN_CAST(m_taskp->fvarp(), Var); @@ -477,11 +461,8 @@ class UndrivenVisitor final : public VNVisitorConst { && !VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType) && nodep->fileline() != entryp->getNodeFileLinep() && !entryp->isUnderGen() - // EOM - //&& entryp->getNodep()) { && (entryp->getNodep() || (m_enableWriteSummary && entryp->getCallNodep()))) { - // EOM const AstNode* const otherWritep = entryp->getNodep() ? static_cast(entryp->getNodep()) @@ -498,11 +479,8 @@ class UndrivenVisitor final : public VNVisitorConst { << nodep->warnOther() << '\n' << nodep->warnContextPrimary() << '\n' - // EOM - //<< entryp->getNodep()->warnOther() << otherWritep->warnOther() << "... Location of other write\n" - //<< entryp->getNodep()->warnContextSecondary()); << otherWritep->warnContextSecondary()); } if (!m_alwaysCombp && entryp->isDrivenAlwaysCombWhole()) { @@ -513,11 +491,8 @@ class UndrivenVisitor final : public VNVisitorConst { << nodep->warnOther() << '\n' << nodep->warnContextPrimary() << '\n' - //EOM - //<< entryp->getNodep()->warnOther() << otherWritep->warnOther() << "... Location of always_comb write\n" - //<< entryp->getNodep()->warnContextSecondary()); << otherWritep->warnContextSecondary()); } } @@ -651,8 +626,6 @@ class UndrivenVisitor final : public VNVisitorConst { public: // CONSTRUCTORS - // EOM - // explicit UndrivenVisitor(AstNetlist* nodep) { iterateConst(nodep); } explicit UndrivenVisitor(AstNetlist* nodep, V3UndrivenCapture* capturep, bool enableWriteSummary) : m_capturep{capturep} @@ -673,7 +646,6 @@ public: void V3Undriven::undrivenAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ":"); - // EOM const bool enable = V3UndrivenCapture::enableWriteSummary; if (enable) { V3UndrivenCapture capture{nodep}; diff --git a/src/V3UndrivenCapture.cpp b/src/V3UndrivenCapture.cpp index 935e03eb0..7e62b8040 100644 --- a/src/V3UndrivenCapture.cpp +++ b/src/V3UndrivenCapture.cpp @@ -58,24 +58,20 @@ private: VL_RESTORER(m_curTaskp); m_curTaskp = nodep; ++g_stats.ftasks; - UINFO(DBG, "UndrivenCapture: enter ftask " << nodep << " " << nodep->prettyNameQ()); - m_cap.info(nodep); + UINFO(DBG, "undriven capture enter ftask " << nodep << " " << nodep->prettyNameQ()); + m_cap.noteTask(nodep); iterateListConst(*this, nodep->stmtsp()); } void visit(AstNodeVarRef* nodep) override { if (m_curTaskp && nodep->access().isWriteOrRW()) { ++g_stats.varWrites; - UINFO(DBG, "UndrivenCapture: direct write in " + UINFO(DBG, "undriven capture direct write in " << taskNameQ(m_curTaskp) << " var=" << nodep->varp()->prettyNameQ() << " at " << nodep->fileline()); - //m_cap.info(m_curTaskp).directWrites.push_back(nodep->varp()); - AstVar* const retVarp = VN_CAST(m_curTaskp->fvarp(), Var); - if (retVarp && nodep->varp() == retVarp) { - // Skip: function return variable is local, not a side-effect - } else { - m_cap.info(m_curTaskp).directWrites.push_back(nodep->varp()); - } + + m_cap.noteDirectWrite(m_curTaskp, nodep->varp()); + } iterateChildrenConst(nodep); } @@ -85,12 +81,11 @@ private: if (m_curTaskp) { if (AstNodeFTask* const calleep = nodep->taskp()) { ++g_stats.callEdges; - UINFO(DBG, "UndrivenCapture: call edge " << taskNameQ(m_curTaskp) << " -> " + UINFO(DBG, "undriven capture call edge " << taskNameQ(m_curTaskp) << " -> " << taskNameQ(calleep)); - m_cap.info(m_curTaskp).callees.push_back(calleep); - m_cap.info(calleep); + m_cap.noteCallEdge(m_curTaskp, calleep); } else { - UINFO(DBG, "UndrivenCapture: unresolved call in " << taskNameQ(m_curTaskp) + UINFO(DBG, "undriven capture unresolved call in " << taskNameQ(m_curTaskp) << " name=" << nodep->name()); } } @@ -128,7 +123,7 @@ V3UndrivenCapture::V3UndrivenCapture(AstNetlist* netlistp) { // Compute summaries for all tasks for (const auto& kv : m_info) (void)computeWriteSummary(kv.first); - UINFO(DBG, "UndrivenCapture: stats ftasks=" + UINFO(DBG, "undriven capture stats ftasks=" << g_stats.ftasks << " varWrites=" << g_stats.varWrites << " callEdges=" << g_stats.callEdges << " uniqueTasks=" << m_info.size()); } @@ -154,12 +149,12 @@ const std::vector& V3UndrivenCapture::computeWriteSummar FTaskInfo& info = m_info[taskp]; if (info.state == State::DONE) { - UINFO(DBG, "UndrivenCapture: writeSummary cached size=" << info.writeSummary.size() + UINFO(DBG, "undriven capture writeSummary cached size=" << info.writeSummary.size() << " for " << taskNameQ(taskp)); return info.writeSummary; } if (info.state == State::VISITING) { - UINFO(DBG, "UndrivenCapture: recursion detected at " + UINFO(DBG, "undriven capture recursion detected at " << taskNameQ(taskp) << " returning directWrites size=" << info.directWrites.size()); // Cycle detected. Simple behaviour: @@ -183,23 +178,38 @@ const std::vector& V3UndrivenCapture::computeWriteSummar sortUniqueVars(info.writeSummary); - UINFO(DBG, "UndrivenCapture: writeSummary computed size=" << info.writeSummary.size() + UINFO(DBG, "undriven capture writeSummary computed size=" << info.writeSummary.size() << " for " << taskNameQ(taskp)); info.state = State::DONE; return info.writeSummary; } +void V3UndrivenCapture::noteTask(FTask taskp) { (void)m_info[taskp]; } + +void V3UndrivenCapture::noteDirectWrite(FTask taskp, Var varp) { + FTaskInfo& info = m_info[taskp]; + + // Exclude function return variable (not an externally visible side-effect) + AstVar* const retVarp = VN_CAST(taskp->fvarp(), Var); + if (retVarp && varp == retVarp) return; + + info.directWrites.push_back(varp); +} + +void V3UndrivenCapture::noteCallEdge(FTask callerp, FTask calleep) { + m_info[callerp].callees.push_back(calleep); + (void)m_info[calleep]; // ensure callee entry exists +} + void V3UndrivenCapture::debugDumpTask(FTask taskp, int level) const { const auto* const infop = find(taskp); if (!infop) { - UINFO(level, "UndrivenCapture: no entry for task " << taskp); + UINFO(level, "undriven capture no entry for task " << taskp); return; } - UINFO(level, "UndrivenCapture: dump task " << taskp << " " << taskp->prettyNameQ() + UINFO(level, "undriven capture dump task " << taskp << " " << taskp->prettyNameQ() << " directWrites=" << infop->directWrites.size() << " callees=" << infop->callees.size() << " writeSummary=" << infop->writeSummary.size()); } - -V3UndrivenCapture::FTaskInfo& V3UndrivenCapture::info(FTask taskp) { return m_info[taskp]; } diff --git a/src/V3UndrivenCapture.h b/src/V3UndrivenCapture.h index c940c53bf..e3803af6b 100644 --- a/src/V3UndrivenCapture.h +++ b/src/V3UndrivenCapture.h @@ -47,9 +47,6 @@ public: static bool enableWriteSummary; - // Get (and create if needed) mutable info entry for a task/function. - FTaskInfo& info(FTask taskp); - private: // Per-task/function capture info keyed by resolved AstNodeFTask* identity. std::unordered_map m_info; @@ -74,6 +71,11 @@ public: // (creates empty entry if needed). const std::vector& writeSummary(FTask taskp); + // used by the capture visitor + void noteTask(FTask taskp); + void noteDirectWrite(FTask taskp, Var varp); + void noteCallEdge(FTask callerp, FTask calleep); + // Optional: dump one task's summary (for debug bring-up). void debugDumpTask(FTask taskp, int level = 9) const; };