Add multi-threaded Verilating at emit stage (#3608)

This commit is contained in:
Kamil Rakoczy 2023-05-05 14:36:20 +02:00 committed by GitHub
parent 3bb4e34044
commit 61e1483b74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 22 additions and 7 deletions

View File

@ -22,6 +22,7 @@
#include "V3EmitCFunc.h"
#include "V3Global.h"
#include "V3String.h"
#include "V3ThreadPool.h"
#include "V3UniqueNames.h"
#include <map>
@ -145,7 +146,7 @@ class EmitCGatherDependencies final : VNVisitorConst {
}
public:
static const std::set<std::string> gather(AstCFunc* cfuncp) {
static const std::set<std::string> 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<AstCFile*>& cfilesr) {
static void main(const AstNodeModule* modp, bool slow,
std::deque<AstCFile*>& 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<AstCFile*>& cfilesr) {
static void main(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& 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<std::deque<AstCFile*>> cfiles;
std::list<std::future<void>> 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<void>(
[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<void>(
[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<void>([&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<void>([&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);
}