From 9a8c878f2d5581d57b48cf2b589f6ba09fe3fa7a Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Mon, 20 Dec 2021 14:42:15 +0000 Subject: [PATCH] Avoid repeated traversal for SC text sections in emit when not needed Repeatedly traversing whole modules in emit (due to file splitting) looking for `systemc_* sections can add up to a lot of time on large designs that have been flattened and need to be split into many files. Assuming `systemc_* is a rarely used feature, just don't bother if we don't need to. This gain 9% verilation speed improvement on a large benchmark. --- src/V3EmitCBase.cpp | 4 ++++ src/V3Global.h | 3 +++ src/verilog.y | 12 ++++++------ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/V3EmitCBase.cpp b/src/V3EmitCBase.cpp index 9d3204432..0fa62cc25 100644 --- a/src/V3EmitCBase.cpp +++ b/src/V3EmitCBase.cpp @@ -235,6 +235,10 @@ void EmitCBaseVisitor::emitModCUse(const AstNodeModule* modp, VUseType useType) } void EmitCBaseVisitor::emitTextSection(const AstNodeModule* modp, VNType type) { + // Short circuit if nothing to do. This can save a lot of time on large designs as this + // function needs to traverse the entire module linearly. + if (!v3Global.hasSCTextSections()) return; + int last_line = -999; for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstNodeText* const textp = VN_CAST(nodep, NodeText)) { diff --git a/src/V3Global.h b/src/V3Global.h index ba9ff302f..edf10a7ed 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -104,6 +104,7 @@ class V3Global final { bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols bool m_dpi = false; // Need __Dpi include files bool m_useForce = false; // Need force/release processing + bool m_hasSCTextSections = false; // Has `systemc_* sections that need to be emitted bool m_useParallelBuild = false; // Use parallel build for model bool m_useRandomizeMethods = false; // Need to define randomize() class methods @@ -146,6 +147,8 @@ public: void needTraceDumper(bool flag) { m_needTraceDumper = flag; } bool dpi() const { return m_dpi; } void dpi(bool flag) { m_dpi = flag; } + bool hasSCTextSections() const { return m_hasSCTextSections; } + void setHasSCTextSections() { m_hasSCTextSections = true; } V3HierBlockPlan* hierPlanp() const { return m_hierPlanp; } void hierPlanp(V3HierBlockPlan* plan) { UASSERT(!m_hierPlanp, "call once"); diff --git a/src/verilog.y b/src/verilog.y index 38641c88b..29678bcf2 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2293,12 +2293,12 @@ non_port_module_item: // ==IEEE: non_port_module_item { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); } | timeunits_declaration { $$ = $1; } // // Verilator specific - | yaSCHDR { $$ = new AstScHdr($1,*$1); } - | yaSCINT { $$ = new AstScInt($1,*$1); } - | yaSCIMP { $$ = new AstScImp($1,*$1); } - | yaSCIMPH { $$ = new AstScImpHdr($1,*$1); } - | yaSCCTOR { $$ = new AstScCtor($1,*$1); } - | yaSCDTOR { $$ = new AstScDtor($1,*$1); } + | yaSCHDR { $$ = new AstScHdr($1,*$1); v3Global.setHasSCTextSections(); } + | yaSCINT { $$ = new AstScInt($1,*$1); v3Global.setHasSCTextSections(); } + | yaSCIMP { $$ = new AstScImp($1,*$1); v3Global.setHasSCTextSections(); } + | yaSCIMPH { $$ = new AstScImpHdr($1,*$1); v3Global.setHasSCTextSections(); } + | yaSCCTOR { $$ = new AstScCtor($1,*$1); v3Global.setHasSCTextSections(); } + | yaSCDTOR { $$ = new AstScDtor($1,*$1); v3Global.setHasSCTextSections(); } | yVL_HIER_BLOCK { $$ = new AstPragma($1,VPragmaType::HIER_BLOCK); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,VPragmaType::INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,VPragmaType::NO_INLINE_MODULE); }