mirror of
https://github.com/verilator/verilator.git
synced 2026-08-31 18:14:33 +02:00
Fix slow compilation of generated sampled value code (#6652)
For handling $past and similar functions, we used to collect sampled values of variables at the beginning of the main _eval function. If we have many of these, this can grow _eval very large which can make C++ compilation very slow. Apply usual fix of emitting the necessary code in a separate function and then splitting it based on size.
This commit is contained in:
+23
-15
@@ -24,6 +24,7 @@
|
||||
#include "V3Clock.h"
|
||||
|
||||
#include "V3Const.h"
|
||||
#include "V3Sched.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
@@ -62,7 +63,7 @@ class ClockVisitor final : public VNVisitor {
|
||||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstCFunc* const m_evalp = nullptr; // The '_eval' function
|
||||
AstCFunc* m_sampleCFuncp = nullptr; // The CFunc to populate with sampled value assignments
|
||||
|
||||
// VISITORS
|
||||
void visit(AstCoverToggle* nodep) override {
|
||||
@@ -98,19 +99,20 @@ class ClockVisitor final : public VNVisitor {
|
||||
//========== Move sampled assignments
|
||||
void visit(AstVarScope* nodep) override {
|
||||
AstVar* const varp = nodep->varp();
|
||||
if (varp->valuep() && varp->name().substr(0, strlen("__Vsampled")) == "__Vsampled") {
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstNodeExpr* const rhsp = VN_AS(varp->valuep()->unlinkFrBack(), NodeExpr);
|
||||
AstVarRef* const lhsp = new AstVarRef{flp, nodep, VAccess::WRITE};
|
||||
AstAssign* const assignp = new AstAssign{flp, lhsp, rhsp};
|
||||
if (AstNode* const stmtsp = m_evalp->stmtsp()) {
|
||||
stmtsp->addHereThisAsNext(assignp);
|
||||
} else {
|
||||
m_evalp->addStmtsp(assignp);
|
||||
}
|
||||
varp->direction(VDirection::NONE); // Restore defaults
|
||||
varp->primaryIO(false);
|
||||
if (!varp->valuep()) return;
|
||||
if (!VString::startsWith(varp->name(), "__Vsampled")) return;
|
||||
|
||||
// Create the containing function on first encounter
|
||||
if (!m_sampleCFuncp) {
|
||||
m_sampleCFuncp = V3Sched::util::makeSubFunction(v3Global.rootp(), "_sample", false);
|
||||
}
|
||||
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstNodeExpr* const rhsp = VN_AS(varp->valuep()->unlinkFrBack(), NodeExpr);
|
||||
AstVarRef* const lhsp = new AstVarRef{flp, nodep, VAccess::WRITE};
|
||||
m_sampleCFuncp->addStmtsp(new AstAssign{flp, lhsp, rhsp});
|
||||
varp->direction(VDirection::NONE); // Restore defaults
|
||||
varp->primaryIO(false);
|
||||
}
|
||||
|
||||
//--------------------
|
||||
@@ -118,9 +120,15 @@ class ClockVisitor final : public VNVisitor {
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ClockVisitor(AstNetlist* netlistp)
|
||||
: m_evalp{netlistp->evalp()} {
|
||||
explicit ClockVisitor(AstNetlist* netlistp) {
|
||||
iterate(netlistp);
|
||||
// If we need a sample function, call it at the begining of eval
|
||||
if (m_sampleCFuncp) {
|
||||
V3Sched::util::splitCheck(m_sampleCFuncp);
|
||||
AstCCall* const callp = new AstCCall{m_sampleCFuncp->fileline(), m_sampleCFuncp};
|
||||
callp->dtypeSetVoid();
|
||||
netlistp->evalp()->stmtsp()->addHereThisAsNext(callp->makeStmt());
|
||||
}
|
||||
}
|
||||
~ClockVisitor() override = default;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user