diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index c6f68242c..af064246b 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -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; }; diff --git a/test_regress/t/t_flag_csplit.v b/test_regress/t/t_flag_csplit.v index 70aaf9b40..15182c347 100644 --- a/test_regress/t/t_flag_csplit.v +++ b/test_regress/t/t_flag_csplit.v @@ -39,6 +39,7 @@ module t (/*AUTOARG*/ $write("[%0t] cyc==%0d sum=%x\n", $time, cyc, w[CNT]); `endif if (w[CNT] !== `EXPECTED_SUM) $stop; + $display("cyc: %0d $past(cyc): %0d", cyc, $past(cyc)); $write("*-* All Finished *-*\n"); $finish; end @@ -55,7 +56,7 @@ module sub (input clk, input [31:0] i, output [31:0] z); assign z = z_tmp; 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 endmodule diff --git a/test_regress/t/t_flag_csplit_groups.py b/test_regress/t/t_flag_csplit_groups.py index c5f90a657..0bfb1eb83 100755 --- a/test_regress/t/t_flag_csplit_groups.py +++ b/test_regress/t/t_flag_csplit_groups.py @@ -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") # 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_SLOW + (\d+)', 2)