From 61e1483b74da8511ccc4eef4d9b1c7de2ef680a0 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Fri, 5 May 2023 14:36:20 +0200 Subject: [PATCH] Add multi-threaded Verilating at emit stage (#3608) --- src/V3EmitCImp.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 679f392ce..5574613d6 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -22,6 +22,7 @@ #include "V3EmitCFunc.h" #include "V3Global.h" #include "V3String.h" +#include "V3ThreadPool.h" #include "V3UniqueNames.h" #include @@ -145,7 +146,7 @@ class EmitCGatherDependencies final : VNVisitorConst { } public: - static const std::set gather(AstCFunc* cfuncp) { + static const std::set gather(AstCFunc* cfuncp) VL_MT_STABLE { const EmitCGatherDependencies visitor{cfuncp}; return std::move(visitor.m_dependencies); } @@ -564,7 +565,8 @@ class EmitCImp final : EmitCFunc { ~EmitCImp() override = default; public: - static void main(const AstNodeModule* modp, bool slow, std::deque& cfilesr) { + static void main(const AstNodeModule* modp, bool slow, + std::deque& cfilesr) VL_MT_STABLE { EmitCImp{modp, slow, cfilesr}; } }; @@ -908,7 +910,7 @@ class EmitCTrace final : EmitCFunc { ~EmitCTrace() override = default; public: - static void main(AstNodeModule* modp, bool slow, std::deque& cfilesr) { + static void main(AstNodeModule* modp, bool slow, std::deque& cfilesr) VL_MT_STABLE { EmitCTrace{modp, slow, cfilesr}; } }; @@ -921,24 +923,37 @@ void V3EmitC::emitcImp() { // Make parent module pointers available. const EmitCParentModule emitCParentModule; std::list> cfiles; + std::list> futures; // Process each module in turn for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) { if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage const AstNodeModule* const modp = VN_AS(nodep, NodeModule); cfiles.emplace_back(); - EmitCImp::main(modp, /* slow: */ true, cfiles.back()); + auto& slowCfilesr = cfiles.back(); + futures.push_back(V3ThreadPool::s().enqueue( + [modp, &slowCfilesr]() { EmitCImp::main(modp, /* slow: */ true, slowCfilesr); })); cfiles.emplace_back(); - EmitCImp::main(modp, /* slow: */ false, cfiles.back()); + auto& fastCfilesr = cfiles.back(); + futures.push_back(V3ThreadPool::s().enqueue( + [modp, &fastCfilesr]() { EmitCImp::main(modp, /* slow: */ false, fastCfilesr); })); } // Emit trace routines (currently they can only exist in the top module) if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) { cfiles.emplace_back(); - EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, cfiles.back()); + auto& slowCfilesr = cfiles.back(); + futures.push_back(V3ThreadPool::s().enqueue([&slowCfilesr]() { + EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, slowCfilesr); + })); cfiles.emplace_back(); - EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, cfiles.back()); + auto& fastCfilesr = cfiles.back(); + futures.push_back(V3ThreadPool::s().enqueue([&fastCfilesr]() { + EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, fastCfilesr); + })); } + // Wait for futures + V3ThreadPool::waitForFutures(futures); for (const auto& collr : cfiles) { for (const auto cfilep : collr) v3Global.rootp()->addFilesp(cfilep); }