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:
parent
47b52800bf
commit
f7e12e9219
|
|
@ -24,6 +24,7 @@
|
||||||
#include "V3Clock.h"
|
#include "V3Clock.h"
|
||||||
|
|
||||||
#include "V3Const.h"
|
#include "V3Const.h"
|
||||||
|
#include "V3Sched.h"
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
||||||
|
|
@ -62,7 +63,7 @@ class ClockVisitor final : public VNVisitor {
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstCFunc* const m_evalp = nullptr; // The '_eval' function
|
AstCFunc* m_sampleCFuncp = nullptr; // The CFunc to populate with sampled value assignments
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstCoverToggle* nodep) override {
|
void visit(AstCoverToggle* nodep) override {
|
||||||
|
|
@ -98,19 +99,20 @@ class ClockVisitor final : public VNVisitor {
|
||||||
//========== Move sampled assignments
|
//========== Move sampled assignments
|
||||||
void visit(AstVarScope* nodep) override {
|
void visit(AstVarScope* nodep) override {
|
||||||
AstVar* const varp = nodep->varp();
|
AstVar* const varp = nodep->varp();
|
||||||
if (varp->valuep() && varp->name().substr(0, strlen("__Vsampled")) == "__Vsampled") {
|
if (!varp->valuep()) return;
|
||||||
FileLine* const flp = nodep->fileline();
|
if (!VString::startsWith(varp->name(), "__Vsampled")) return;
|
||||||
AstNodeExpr* const rhsp = VN_AS(varp->valuep()->unlinkFrBack(), NodeExpr);
|
|
||||||
AstVarRef* const lhsp = new AstVarRef{flp, nodep, VAccess::WRITE};
|
// Create the containing function on first encounter
|
||||||
AstAssign* const assignp = new AstAssign{flp, lhsp, rhsp};
|
if (!m_sampleCFuncp) {
|
||||||
if (AstNode* const stmtsp = m_evalp->stmtsp()) {
|
m_sampleCFuncp = V3Sched::util::makeSubFunction(v3Global.rootp(), "_sample", false);
|
||||||
stmtsp->addHereThisAsNext(assignp);
|
|
||||||
} else {
|
|
||||||
m_evalp->addStmtsp(assignp);
|
|
||||||
}
|
|
||||||
varp->direction(VDirection::NONE); // Restore defaults
|
|
||||||
varp->primaryIO(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:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit ClockVisitor(AstNetlist* netlistp)
|
explicit ClockVisitor(AstNetlist* netlistp) {
|
||||||
: m_evalp{netlistp->evalp()} {
|
|
||||||
iterate(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;
|
~ClockVisitor() override = default;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ module t (/*AUTOARG*/
|
||||||
$write("[%0t] cyc==%0d sum=%x\n", $time, cyc, w[CNT]);
|
$write("[%0t] cyc==%0d sum=%x\n", $time, cyc, w[CNT]);
|
||||||
`endif
|
`endif
|
||||||
if (w[CNT] !== `EXPECTED_SUM) $stop;
|
if (w[CNT] !== `EXPECTED_SUM) $stop;
|
||||||
|
$display("cyc: %0d $past(cyc): %0d", cyc, $past(cyc));
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
@ -55,7 +56,7 @@ module sub (input clk, input [31:0] i, output [31:0] z);
|
||||||
assign z = z_tmp;
|
assign z = z_tmp;
|
||||||
|
|
||||||
always @(posedge z_tmp == 32'b11) begin
|
always @(posedge z_tmp == 32'b11) begin
|
||||||
$display("%m z_tmp[0]: %0d", z_tmp);
|
$display("%m z_tmp: %0d, $past(z_tmp): $0d", z_tmp, $past(z_tmp));
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_clas
|
||||||
test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_classes_2")
|
test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_classes_2")
|
||||||
|
|
||||||
# Check combine count
|
# Check combine count
|
||||||
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (219 if test.vltmt else 205))
|
test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (239 if test.vltmt else 222))
|
||||||
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_FAST + (\d+)', 2)
|
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_FAST + (\d+)', 2)
|
||||||
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_SLOW + (\d+)', 2)
|
test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_SLOW + (\d+)', 2)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue