From 13933743ade09175723e49f3c2df20e4d055adb1 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 22 Jul 2021 20:50:03 -0400 Subject: [PATCH] Suppress creating change_request if not needed. --- src/V3AstNodes.h | 3 ++ src/V3Changed.cpp | 37 +++++++++------- src/V3EmitCFunc.cpp | 2 +- src/V3EmitCModel.cpp | 63 ++++++++++++++++------------ test_regress/t/t_protect_ids_key.out | 2 - test_regress/t/t_verilated_debug.out | 6 --- 6 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 55239b529..580e34c08 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -9155,6 +9155,7 @@ private: AstExecGraph* m_execGraphp = nullptr; // Execution MTask graph for threads>1 mode VTimescale m_timeunit; // Global time unit VTimescale m_timeprecision; // Global time precision + bool m_changeRequest = false; // Have _change_request method bool m_timescaleSpecified = false; // Input HDL specified timescale public: AstNetlist(); @@ -9178,6 +9179,8 @@ public: AstNode* miscsp() const { return op3p(); } // op3 = List of dtypes etc void addMiscsp(AstNode* nodep) { addOp3p(nodep); } AstTypeTable* typeTablep() { return m_typeTablep; } + void changeRequest(bool specified) { m_changeRequest = specified; } + bool changeRequest() const { return m_changeRequest; } AstConstPool* constPoolp() { return m_constPoolp; } AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; } AstPackage* dollarUnitPkgAddp() { diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 062da8eac..dc3343f87 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -47,11 +47,33 @@ public: AstCFunc* m_tlChgFuncp = nullptr; // Top level change function we're building int m_numStmts = 0; // Number of statements added to m_chgFuncp int m_funcNum = 0; // Number of change functions emitted + bool m_madeTopChg = false; ChangedState() = default; ~ChangedState() = default; void maybeCreateChgFuncp() { + maybeCreateTopChg(); + maybeCreateMidChg(); + } + void maybeCreateTopChg() { + if (m_madeTopChg) return; + m_madeTopChg = true; + v3Global.rootp()->changeRequest(true); + + // Create a wrapper change detection function that calls each change detection function + m_tlChgFuncp + = new AstCFunc{m_scopetopp->fileline(), "_change_request", m_scopetopp, "QData"}; + m_tlChgFuncp->isStatic(false); + m_tlChgFuncp->isLoose(true); + m_tlChgFuncp->declPrivate(true); + m_scopetopp->addActivep(m_tlChgFuncp); + // Each change detection function needs at least one AstChangeDet + // to ensure that V3EmitC outputs the necessary code. + maybeCreateMidChg(); + m_chgFuncp->addStmtsp(new AstChangeDet{m_scopetopp->fileline(), nullptr, nullptr, false}); + } + void maybeCreateMidChg() { // Don't create an extra function call if splitting is disabled if (!v3Global.opt.outputSplitCFuncs()) { m_chgFuncp = m_tlChgFuncp; @@ -242,24 +264,11 @@ private: UINFO(4, " TS " << nodep << endl); // Clearing AstNode::user1ClearTree(); - // Create the change detection function + // Prep for if make change detection function AstScope* const scopep = nodep->scopep(); UASSERT_OBJ(scopep, nodep, "No scope found on top level, perhaps you have no statements?"); m_statep->m_scopetopp = scopep; - // Create a wrapper change detection function that calls each change detection function - m_statep->m_tlChgFuncp - = new AstCFunc{nodep->fileline(), "_change_request", scopep, "QData"}; - m_statep->m_tlChgFuncp->isStatic(false); - m_statep->m_tlChgFuncp->isLoose(true); - m_statep->m_tlChgFuncp->declPrivate(true); - m_statep->m_scopetopp->addActivep(m_statep->m_tlChgFuncp); - // Each change detection function needs at least one AstChangeDet - // to ensure that V3EmitC outputs the necessary code. - m_statep->maybeCreateChgFuncp(); - m_statep->m_chgFuncp->addStmtsp( - new AstChangeDet{nodep->fileline(), nullptr, nullptr, false}); - iterateChildren(nodep); } virtual void visit(AstVarScope* nodep) override { diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp index 5729c51e2..ed130c578 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -772,7 +772,7 @@ void EmitCFunc::emitChangeDet() { puts("QData __req = false; // Logically a bool\n"); // But not because it results in // faster code bool gotOne = false; - for (AstChangeDet* changep : m_blkChangeDetVec) { + for (AstChangeDet* const changep : m_blkChangeDetVec) { if (changep->lhsp()) { if (!gotOne) { // Not a clocked block puts("__req |= ("); diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index 5b3922e6d..965cf56c0 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -312,8 +312,10 @@ class EmitCModel final : public EmitCFunc { const string topModNameProtected = prefixNameProtect(modp); putsDecoration("// Evaluate till stable\n"); - puts("int __VclockLoop = 0;\n"); - puts("QData __Vchange = 1;\n"); + if (v3Global.rootp()->changeRequest()) { + puts("int __VclockLoop = 0;\n"); + puts("QData __Vchange = 1;\n"); + } if (v3Global.opt.trace()) puts("vlSymsp->__Vm_activity = true;\n"); puts("do {\n"); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ "); @@ -322,29 +324,34 @@ class EmitCModel final : public EmitCFunc { if (initial) puts(topModNameProtected + "__" + protect("_eval_settle") + "(&(vlSymsp->TOP));\n"); puts(topModNameProtected + "__" + protect("_eval") + "(&(vlSymsp->TOP));\n"); - puts("if (VL_UNLIKELY(++__VclockLoop > " + cvtToStr(v3Global.opt.convergeLimit()) - + ")) {\n"); - puts("// About to fail, so enable debug to see what's not settling.\n"); - puts("// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); - puts("int __Vsaved_debug = Verilated::debug();\n"); - puts("Verilated::debug(1);\n"); - puts("__Vchange = " + topModNameProtected + "__" + protect("_change_request") - + "(&(vlSymsp->TOP));\n"); - puts("Verilated::debug(__Vsaved_debug);\n"); - puts("VL_FATAL_MT("); - putsQuoted(protect(modp->fileline()->filename())); - puts(", "); - puts(cvtToStr(modp->fileline()->lineno())); - puts(", \"\",\n"); - puts("\"Verilated model didn't "); - if (initial) puts("DC "); - puts("converge\\n\"\n"); - puts("\"- See https://verilator.org/warn/DIDNOTCONVERGE\");\n"); - puts("} else {\n"); - puts("__Vchange = " + topModNameProtected + "__" + protect("_change_request") - + "(&(vlSymsp->TOP));\n"); - puts("}\n"); - puts("} while (VL_UNLIKELY(__Vchange));\n"); + if (v3Global.rootp()->changeRequest()) { + puts("if (VL_UNLIKELY(++__VclockLoop > " + cvtToStr(v3Global.opt.convergeLimit()) + + ")) {\n"); + puts("// About to fail, so enable debug to see what's not settling.\n"); + puts("// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); + puts("int __Vsaved_debug = Verilated::debug();\n"); + puts("Verilated::debug(1);\n"); + puts("__Vchange = " + topModNameProtected + "__" + protect("_change_request") + + "(&(vlSymsp->TOP));\n"); + puts("Verilated::debug(__Vsaved_debug);\n"); + puts("VL_FATAL_MT("); + putsQuoted(protect(modp->fileline()->filename())); + puts(", "); + puts(cvtToStr(modp->fileline()->lineno())); + puts(", \"\",\n"); + puts("\"Verilated model didn't "); + if (initial) puts("DC "); + puts("converge\\n\"\n"); + puts("\"- See https://verilator.org/warn/DIDNOTCONVERGE\");\n"); + puts("} else {\n"); + puts("__Vchange = " + topModNameProtected + "__" + protect("_change_request") + + "(&(vlSymsp->TOP));\n"); + puts("}\n"); + } + puts("} while (" + + (v3Global.rootp()->changeRequest() ? std::string{"VL_UNLIKELY(__Vchange)"} + : std::string{"0"}) + + ");\n"); } void emitStandardMethods(AstNodeModule* modp) { @@ -360,8 +367,10 @@ class EmitCModel final : public EmitCFunc { puts("void " + topModNameProtected + "__" + protect("_eval_initial") + selfDecl + ";\n"); puts("void " + topModNameProtected + "__" + protect("_eval_settle") + selfDecl + ";\n"); puts("void " + topModNameProtected + "__" + protect("_eval") + selfDecl + ";\n"); - puts("QData " + topModNameProtected + "__" + protect("_change_request") + selfDecl - + ";\n"); + if (v3Global.rootp()->changeRequest()) { + puts("QData " + topModNameProtected + "__" + protect("_change_request") + selfDecl + + ";\n"); + } puts("#ifdef VL_DEBUG\n"); puts("void " + topModNameProtected + "__" + protect("_eval_debug_assertions") + selfDecl + ";\n"); diff --git a/test_regress/t/t_protect_ids_key.out b/test_regress/t/t_protect_ids_key.out index 7a7d53d4b..4575b30b0 100644 --- a/test_regress/t/t_protect_ids_key.out +++ b/test_regress/t/t_protect_ids_key.out @@ -22,8 +22,6 @@ - - diff --git a/test_regress/t/t_verilated_debug.out b/test_regress/t/t_verilated_debug.out index 5ac844a6b..932ee8483 100644 --- a/test_regress/t/t_verilated_debug.out +++ b/test_regress/t/t_verilated_debug.out @@ -13,18 +13,12 @@ internalsDump: -V{t#,#}+ Initial loop -V{t#,#}+ Vt_verilated_debug___024root___eval_settle -V{t#,#}+ Vt_verilated_debug___024root___eval --V{t#,#}+ Vt_verilated_debug___024root___change_request --V{t#,#}+ Vt_verilated_debug___024root___change_request_1 -V{t#,#}+ Clock loop -V{t#,#}+ Vt_verilated_debug___024root___eval --V{t#,#}+ Vt_verilated_debug___024root___change_request --V{t#,#}+ Vt_verilated_debug___024root___change_request_1 -V{t#,#}+++++TOP Evaluate Vt_verilated_debug::eval_step -V{t#,#}+ Vt_verilated_debug___024root___eval_debug_assertions -V{t#,#}+ Clock loop -V{t#,#}+ Vt_verilated_debug___024root___eval -V{t#,#}+ Vt_verilated_debug___024root___sequent__TOP__2 *-* All Finished *-* --V{t#,#}+ Vt_verilated_debug___024root___change_request --V{t#,#}+ Vt_verilated_debug___024root___change_request_1 -V{t#,#}+ Vt_verilated_debug___024root___final