mirror of
https://github.com/verilator/verilator.git
synced 2025-01-19 12:54:02 +00:00
Fix performance of V3Trace when many activity blocks (#5372).
This commit is contained in:
parent
f4fe89a8c4
commit
fa32d10f39
1
Changes
1
Changes
@ -16,6 +16,7 @@ Verilator 5.029 devel
|
|||||||
* Support unconstrained randomization for unions (#5395) (#5396). [Yilou Wang]
|
* Support unconstrained randomization for unions (#5395) (#5396). [Yilou Wang]
|
||||||
* Add method to check if there are VPI callbacks of the given type (#5399). [Kaleb Barrett]
|
* Add method to check if there are VPI callbacks of the given type (#5399). [Kaleb Barrett]
|
||||||
* Improve Verilation thread pool (#5161). [Bartłomiej Chmiel, Antmicro Ltd.]
|
* Improve Verilation thread pool (#5161). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Fix performance of V3Trace when many activity blocks (#5372). [Deniz Güzel]
|
||||||
* Fix REALCVT warning on integral timescale conversions (#5378). [Liam Braun]
|
* Fix REALCVT warning on integral timescale conversions (#5378). [Liam Braun]
|
||||||
* Fix dot fallback finding wrong symbols (#5394). [Arkadiusz Kozdra, Antmicro Ltd.]
|
* Fix dot fallback finding wrong symbols (#5394). [Arkadiusz Kozdra, Antmicro Ltd.]
|
||||||
* Fix infinite recursion due to recursive functions/tasks (#5398). [Krzysztof Bieganski, Antmicro Ltd.]
|
* Fix infinite recursion due to recursive functions/tasks (#5398). [Krzysztof Bieganski, Antmicro Ltd.]
|
||||||
|
@ -221,7 +221,7 @@ void V3Stats::statsStage(const string& name) {
|
|||||||
|
|
||||||
void V3Stats::infoHeader(std::ofstream& os, const string& prefix) {
|
void V3Stats::infoHeader(std::ofstream& os, const string& prefix) {
|
||||||
os << prefix << "Information:\n";
|
os << prefix << "Information:\n";
|
||||||
os << prefix << " " << V3Options::version() << '\n';
|
os << prefix << " Version: " << V3Options::version() << '\n';
|
||||||
os << prefix << " Arguments: " << v3Global.opt.allArgsString() << '\n';
|
os << prefix << " Arguments: " << v3Global.opt.allArgsString() << '\n';
|
||||||
os << prefix << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
|
os << prefix << " Build jobs: " << v3Global.opt.buildJobs() << '\n';
|
||||||
os << prefix << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
|
os << prefix << " Verilate jobs: " << v3Global.opt.verilateJobs() << '\n';
|
||||||
|
@ -175,6 +175,7 @@ class TraceVisitor final : public VNVisitor {
|
|||||||
AstScope* const m_topScopep = v3Global.rootp()->topScopep()->scopep(); // The top AstScope
|
AstScope* const m_topScopep = v3Global.rootp()->topScopep()->scopep(); // The top AstScope
|
||||||
AstCFunc* m_cfuncp = nullptr; // C function adding to graph
|
AstCFunc* m_cfuncp = nullptr; // C function adding to graph
|
||||||
AstCFunc* m_regFuncp = nullptr; // Trace registration function
|
AstCFunc* m_regFuncp = nullptr; // Trace registration function
|
||||||
|
AstCFunc* m_actAllFuncp = nullptr; // Set all activity function
|
||||||
AstTraceDecl* m_tracep = nullptr; // Trace function adding to graph
|
AstTraceDecl* m_tracep = nullptr; // Trace function adding to graph
|
||||||
AstVarScope* m_activityVscp = nullptr; // Activity variable
|
AstVarScope* m_activityVscp = nullptr; // Activity variable
|
||||||
uint32_t m_activityNumber = 0; // Count of fields in activity variable
|
uint32_t m_activityNumber = 0; // Count of fields in activity variable
|
||||||
@ -187,8 +188,10 @@ class TraceVisitor final : public VNVisitor {
|
|||||||
const uint32_t m_parallelism
|
const uint32_t m_parallelism
|
||||||
= v3Global.opt.useTraceParallel() ? static_cast<uint32_t>(v3Global.opt.threads()) : 1;
|
= v3Global.opt.useTraceParallel() ? static_cast<uint32_t>(v3Global.opt.threads()) : 1;
|
||||||
|
|
||||||
VDouble0 m_statUniqSigs; // Statistic tracking
|
VDouble0 m_statSetters; // Statistic tracking
|
||||||
|
VDouble0 m_statSettersSlow; // Statistic tracking
|
||||||
VDouble0 m_statUniqCodes; // Statistic tracking
|
VDouble0 m_statUniqCodes; // Statistic tracking
|
||||||
|
VDouble0 m_statUniqSigs; // Statistic tracking
|
||||||
|
|
||||||
// All activity numbers applying to a given trace
|
// All activity numbers applying to a given trace
|
||||||
using ActCodeSet = std::set<uint32_t>;
|
using ActCodeSet = std::set<uint32_t>;
|
||||||
@ -395,25 +398,32 @@ class TraceVisitor final : public VNVisitor {
|
|||||||
return new AstArraySel(flp, new AstVarRef{flp, m_activityVscp, access}, acode);
|
return new AstArraySel(flp, new AstVarRef{flp, m_activityVscp, access}, acode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addActivitySetter(AstNode* insertp, uint32_t code) {
|
AstNode* newActivitySetter(AstNode* insertp, uint32_t code) {
|
||||||
|
++m_statSetters;
|
||||||
FileLine* const fl = insertp->fileline();
|
FileLine* const fl = insertp->fileline();
|
||||||
AstAssign* const setterp = new AstAssign{fl, selectActivity(fl, code, VAccess::WRITE),
|
AstAssign* const setterp = new AstAssign{fl, selectActivity(fl, code, VAccess::WRITE),
|
||||||
new AstConst{fl, AstConst::BitTrue{}}};
|
new AstConst{fl, AstConst::BitTrue{}}};
|
||||||
if (AstStmtExpr* const stmtp = VN_CAST(insertp, StmtExpr)) {
|
return setterp;
|
||||||
stmtp->addNextHere(setterp);
|
}
|
||||||
} else if (AstCFunc* const funcp = VN_CAST(insertp, CFunc)) {
|
|
||||||
// If there are awaits, insert the setter after each await
|
AstNode* newActivityAll(AstNode* insertp) {
|
||||||
if (funcp->isCoroutine() && funcp->stmtsp()) {
|
++m_statSettersSlow;
|
||||||
funcp->stmtsp()->foreachAndNext([&](AstCAwait* awaitp) {
|
if (!m_actAllFuncp) {
|
||||||
AstNode* stmtp = awaitp->backp();
|
FileLine* const flp = m_topScopep->fileline();
|
||||||
while (VN_IS(stmtp, NodeExpr)) stmtp = stmtp->backp();
|
AstCFunc* const funcp = new AstCFunc{flp, "__Vm_traceActivitySetAll", m_topScopep};
|
||||||
stmtp->addNextHere(setterp->cloneTree(false));
|
funcp->slow(true);
|
||||||
});
|
funcp->isStatic(false);
|
||||||
|
funcp->isLoose(true);
|
||||||
|
m_topScopep->addBlocksp(funcp);
|
||||||
|
for (uint32_t code = 0; code < m_activityNumber; ++code) {
|
||||||
|
AstNode* const setterp = newActivitySetter(insertp, code);
|
||||||
|
funcp->addStmtsp(setterp);
|
||||||
}
|
}
|
||||||
funcp->addStmtsp(setterp);
|
m_actAllFuncp = funcp;
|
||||||
} else {
|
|
||||||
insertp->v3fatalSrc("Bad trace activity vertex");
|
|
||||||
}
|
}
|
||||||
|
AstCCall* const callp = new AstCCall{insertp->fileline(), m_actAllFuncp};
|
||||||
|
callp->dtypeSetVoid();
|
||||||
|
return callp->makeStmt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void createActivityFlags() {
|
void createActivityFlags() {
|
||||||
@ -441,14 +451,31 @@ class TraceVisitor final : public VNVisitor {
|
|||||||
// Insert activity setters
|
// Insert activity setters
|
||||||
for (const V3GraphVertex& vtx : m_graph.vertices()) {
|
for (const V3GraphVertex& vtx : m_graph.vertices()) {
|
||||||
if (const TraceActivityVertex* const vtxp = vtx.cast<const TraceActivityVertex>()) {
|
if (const TraceActivityVertex* const vtxp = vtx.cast<const TraceActivityVertex>()) {
|
||||||
|
AstNode* setterp = nullptr;
|
||||||
if (vtxp->activitySlow()) {
|
if (vtxp->activitySlow()) {
|
||||||
|
setterp = newActivityAll(vtxp->insertp());
|
||||||
// Just set all flags in slow code as it should be rare.
|
// Just set all flags in slow code as it should be rare.
|
||||||
// This will be rolled up into a loop by V3Reloop.
|
// This will be rolled up into a loop by V3Reloop.
|
||||||
for (uint32_t code = 0; code < m_activityNumber; ++code) {
|
|
||||||
addActivitySetter(vtxp->insertp(), code);
|
|
||||||
}
|
|
||||||
} else if (!vtxp->activityAlways()) {
|
} else if (!vtxp->activityAlways()) {
|
||||||
addActivitySetter(vtxp->insertp(), vtxp->activityCode());
|
setterp = newActivitySetter(vtxp->insertp(), vtxp->activityCode());
|
||||||
|
}
|
||||||
|
if (setterp) {
|
||||||
|
AstNode* const insertp = vtxp->insertp();
|
||||||
|
if (AstStmtExpr* const stmtp = VN_CAST(insertp, StmtExpr)) {
|
||||||
|
stmtp->addNextHere(setterp);
|
||||||
|
} else if (AstCFunc* const funcp = VN_CAST(insertp, CFunc)) {
|
||||||
|
// If there are awaits, insert the setter after each await
|
||||||
|
if (funcp->isCoroutine() && funcp->stmtsp()) {
|
||||||
|
funcp->stmtsp()->foreachAndNext([&](AstCAwait* awaitp) {
|
||||||
|
AstNode* stmtp = awaitp->backp();
|
||||||
|
while (VN_IS(stmtp, NodeExpr)) stmtp = stmtp->backp();
|
||||||
|
stmtp->addNextHere(setterp->cloneTree(false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
funcp->addStmtsp(setterp);
|
||||||
|
} else {
|
||||||
|
insertp->v3fatalSrc("Bad trace activity vertex");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -901,8 +928,10 @@ public:
|
|||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
~TraceVisitor() override {
|
~TraceVisitor() override {
|
||||||
V3Stats::addStat("Tracing, Unique traced signals", m_statUniqSigs);
|
V3Stats::addStat("Tracing, Activity setters", m_statSetters);
|
||||||
|
V3Stats::addStat("Tracing, Activity slow blocks", m_statSettersSlow);
|
||||||
V3Stats::addStat("Tracing, Unique trace codes", m_statUniqCodes);
|
V3Stats::addStat("Tracing, Unique trace codes", m_statUniqCodes);
|
||||||
|
V3Stats::addStat("Tracing, Unique traced signals", m_statUniqSigs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user