Add multi-threaded Verilating at emit stage (#3608)
This commit is contained in:
parent
3bb4e34044
commit
61e1483b74
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue