diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index c153fd551..35a0689b4 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -288,6 +288,27 @@ public: class AstCStmt final : public AstNodeStmt { // C statement emitted into output, with some arbitrary nodes interspersed // @astgen op1 := nodesp : List[AstNode] + + static AstCStmt* profExecSection(FileLine* flp, const std::string& section, bool push) { + // Compute the label + std::string label; + if (v3Global.opt.hierChild()) label += v3Global.opt.topModule() + ":"; + label += section; + // The profiler statement + std::string pStmt = "VL_EXEC_TRACE_ADD_RECORD(vlSymsp)"; + pStmt += push ? ".sectionPush" : ".sectionPop"; + pStmt += "("; + if (push) pStmt += "\"" + label + "\""; + pStmt += ");"; + // The debug statement + std::string dStmt = "VL_DEBUG_IF(VL_DBG_MSGF(\"+ --prof-exec "; + dStmt += push ? "sectionPush " : "sectionPop "; + dStmt += label; + dStmt += "\\n\"););"; + // Concatenate + return new AstCStmt{flp, push ? pStmt + "\n" + dStmt : dStmt + "\n" + pStmt}; + } + public: explicit AstCStmt(FileLine* fl, const std::string& text = "") : ASTGEN_SUPER_CStmt(fl) { @@ -302,6 +323,13 @@ public: // Add some text, or a node to this statement void add(const std::string& text) { addNodesp(new AstText{fileline(), text}); } void add(AstNode* nodep) { addNodesp(nodep); } + // Static factory methods for specific cases + static AstCStmt* profExecSectionPush(FileLine* flp, const std::string& section) { + return profExecSection(flp, section, true); + } + static AstCStmt* profExecSectionPop(FileLine* flp, const std::string& section) { + return profExecSection(flp, section, false); + } }; class AstCStmtUser final : public AstNodeStmt { // User '$c' statement, also used for handling some AstSystemCSection. diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 7b6503440..7c61b8fc5 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -156,14 +156,11 @@ AstCFunc* V3Order::order(AstNetlist* netlistp, // // Assemble the body if (v3Global.opt.profExec()) { - const std::string name - = (v3Global.opt.hierChild() ? (v3Global.opt.topModule() + " ") : "") + "func " + tag; - funcp->addStmtsp( - new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"" + name + "\");"}); + funcp->addStmtsp(AstCStmt::profExecSectionPush(flp, "func " + tag)); } funcp->addStmtsp(stmtsp); - if (v3Global.opt.profExec()) { - funcp->addStmtsp(new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPop();"}); + if (v3Global.opt.profExec()) { // + funcp->addStmtsp(AstCStmt::profExecSectionPop(flp, "func " + tag)); } // Done diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp index 48fc3d49b..33f234c72 100644 --- a/src/V3Sched.cpp +++ b/src/V3Sched.cpp @@ -175,7 +175,9 @@ EvalLoop createEvalLoop( AstNodeStmt* stmtps = nullptr; // Prof-exec section push - if (v3Global.opt.profExec()) stmtps = util::profExecSectionPush(flp, "loop " + tag); + if (v3Global.opt.profExec()) { // + stmtps = AstCStmt::profExecSectionPush(flp, "loop " + tag); + } const auto addVar = [&](const std::string& name, int width, uint32_t initVal) { AstVarScope* const vscp = scopeTopp->createTemp("__V" + tag + name, width); @@ -215,7 +217,9 @@ EvalLoop createEvalLoop( } // Prof-exec section pop - if (v3Global.opt.profExec()) stmtps->addNext(util::profExecSectionPop(flp)); + if (v3Global.opt.profExec()) { + stmtps->addNext(AstCStmt::profExecSectionPop(flp, "loop " + tag)); + } return {firstIterFlagp, stmtps}; } @@ -684,7 +688,7 @@ void createEval(AstNetlist* netlistp, // AstCFunc* const funcp = util::makeTopFunction(netlistp, "_eval", false); netlistp->evalp(funcp); - if (v3Global.opt.profExec()) funcp->addStmtsp(util::profExecSectionPush(flp, "eval")); + if (v3Global.opt.profExec()) funcp->addStmtsp(AstCStmt::profExecSectionPush(flp, "eval")); // Start with the ico loop, if any if (icoLoop) funcp->addStmtsp(icoLoop); @@ -695,7 +699,7 @@ void createEval(AstNetlist* netlistp, // // Add the Postponed eval call if (postponedFuncp) funcp->addStmtsp(util::callVoidFunc(postponedFuncp)); - if (v3Global.opt.profExec()) funcp->addStmtsp(util::profExecSectionPop(flp)); + if (v3Global.opt.profExec()) funcp->addStmtsp(AstCStmt::profExecSectionPop(flp, "eval")); } } // namespace diff --git a/src/V3Sched.h b/src/V3Sched.h index 6690e312f..45e16ca17 100644 --- a/src/V3Sched.h +++ b/src/V3Sched.h @@ -405,10 +405,6 @@ AstNodeStmt* callVoidFunc(AstCFunc* funcp); // Create statement that checks counterp' to see if the eval loop iteration limit is reached AstNodeStmt* checkIterationLimit(AstNetlist* netlistp, const string& name, AstVarScope* counterp, AstNodeStmt* dumpCallp); -// Create statement that pushed a --prof-exec section -AstNodeStmt* profExecSectionPush(FileLine* flp, const string& section); -// Create statement that pops a --prof-exec section -AstNodeStmt* profExecSectionPop(FileLine* flp); // Split large function according to --output-split-cfuncs void splitCheck(AstCFunc* ofuncp); // Build an AstIf conditional on the given SenTree being triggered diff --git a/src/V3SchedTrigger.cpp b/src/V3SchedTrigger.cpp index d04d2d359..aa579bc60 100644 --- a/src/V3SchedTrigger.cpp +++ b/src/V3SchedTrigger.cpp @@ -661,7 +661,9 @@ TriggerKit TriggerKit::create(AstNetlist* netlistp, // AstCFunc* const fp = kit.m_compp; AstScope* const scopep = netlistp->topScopep()->scopep(); // Profiling push - if (v3Global.opt.profExec()) fp->addStmtsp(util::profExecSectionPush(flp, "trig " + name)); + if (v3Global.opt.profExec()) { + fp->addStmtsp(AstCStmt::profExecSectionPush(flp, "trig " + name)); + } // Trigger computation for (AstNodeStmt* const nodep : senResults.m_preUpdates) fp->addStmtsp(nodep); fp->addStmtsp(trigStmtsp); @@ -702,7 +704,9 @@ TriggerKit TriggerKit::create(AstNetlist* netlistp, // // Add a call to the dumping function if debug is enabled fp->addStmtsp(kit.newDumpCall(kit.m_vscp, name, true)); // Profiling pop - if (v3Global.opt.profExec()) fp->addStmtsp(util::profExecSectionPop(flp)); + if (v3Global.opt.profExec()) { + fp->addStmtsp(AstCStmt::profExecSectionPop(flp, "trig " + name)); + } // Done with the trigger computation function, split as might be large util::splitCheck(fp); }; diff --git a/src/V3SchedUtil.cpp b/src/V3SchedUtil.cpp index a919c9506..41c706f36 100644 --- a/src/V3SchedUtil.cpp +++ b/src/V3SchedUtil.cpp @@ -101,16 +101,6 @@ AstNodeStmt* checkIterationLimit(AstNetlist* netlistp, const string& name, AstVa return ifp; } -AstNodeStmt* profExecSectionPush(FileLine* flp, const string& section) { - const string name - = (v3Global.opt.hierChild() ? (v3Global.opt.topModule() + " ") : "") + section; - return new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"" + name + "\");"}; -} - -AstNodeStmt* profExecSectionPop(FileLine* flp) { - return new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPop();"}; -} - static AstCFunc* splitCheckCreateNewSubFunc(AstCFunc* ofuncp) { static std::map s_funcNums; // What split number to attach to a function const uint32_t funcNum = s_funcNums[ofuncp]++; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 9ccbb707a..bd82d3624 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1064,10 +1064,9 @@ class TaskVisitor final : public VNVisitor { AstCFunc* dpiFuncp) { const char* const tmpSuffixp = V3Task::dpiTemporaryVarSuffix(); - if (v3Global.opt.profExec()) - cfuncp->addStmtsp( - new AstCStmt{nodep->fileline(), - "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"dpiimports\");"}); + if (v3Global.opt.profExec()) { + cfuncp->addStmtsp(AstCStmt::profExecSectionPush(nodep->fileline(), "dpiimports")); + } // Convert input/inout arguments to DPI types string args; @@ -1161,9 +1160,9 @@ class TaskVisitor final : public VNVisitor { } } - if (v3Global.opt.profExec()) - cfuncp->addStmtsp(new AstCStmt{nodep->fileline(), - "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPop();"}); + if (v3Global.opt.profExec()) { + cfuncp->addStmtsp(AstCStmt::profExecSectionPop(nodep->fileline(), "dpiimports")); + } } AstVarScope* getDpiExporTrigger() {