diff --git a/include/verilated_timing.cpp b/include/verilated_timing.cpp index 30b3fbf7f..c14eaf2c7 100644 --- a/include/verilated_timing.cpp +++ b/include/verilated_timing.cpp @@ -153,11 +153,12 @@ void VlTriggerScheduler::dump(const char* eventDescription) const { // VlDynamicTriggerScheduler:: Methods bool VlDynamicTriggerScheduler::evaluate() { + m_anyTriggered = false; VL_DEBUG_IF(dump();); std::swap(m_suspended, m_evaluated); for (auto& coro : m_evaluated) coro.resume(); m_evaluated.clear(); - return !m_triggered.empty(); + return m_anyTriggered; } void VlDynamicTriggerScheduler::doPostUpdates() { diff --git a/include/verilated_timing.h b/include/verilated_timing.h index 54b505e2a..48646de69 100644 --- a/include/verilated_timing.h +++ b/include/verilated_timing.h @@ -275,6 +275,7 @@ public: // co_await __VdynSched.evaluation(); //
;
 //         __Vtrigger = ;
+//         __VdynShed.anyTriggered(__Vtrigger);
 //         [optionally] co_await __VdynSched.postUpdate();
 //         ;
 //     }
@@ -288,6 +289,7 @@ class VlDynamicTriggerScheduler final {
     using VlCoroutineVec = std::vector;
 
     // MEMBERS
+    bool m_anyTriggered = false;  // If true, at least one trigger was set
     VlCoroutineVec m_suspended;  // Suspended coroutines awaiting trigger evaluation
     VlCoroutineVec m_evaluated;  // Coroutines currently being evaluated (for evaluate())
     VlCoroutineVec m_triggered;  // Coroutines whose triggers were set, and are awaiting resumption
@@ -313,6 +315,8 @@ class VlDynamicTriggerScheduler final {
 public:
     // Evaluates all dynamic triggers (resumed coroutines that co_await evaluation())
     bool evaluate();
+    // Called by coroutines that evaluate triggers to notify the scheduler if any triggers were set
+    void anyTriggered(bool triggered) { m_anyTriggered = m_anyTriggered || triggered; }
     // Runs post updates for all dynamic triggers (resumes coroutines that co_await postUpdate())
     void doPostUpdates();
     // Resumes all coroutines whose triggers are set (those that co_await resumption())
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index 4720c4b01..c48ef68ec 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -2424,6 +2424,7 @@ int AstCMethodHard::instrCount() const {
 void AstCMethodHard::setPurity() {
     static const std::map isPureMethod{{"andNot", false},
                                                           {"any", true},
+                                                          {"anyTriggered", false},
                                                           {"assign", false},
                                                           {"at", true},
                                                           {"atBack", true},
diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp
index d2d6bae96..132d3d6bf 100644
--- a/src/V3Timing.cpp
+++ b/src/V3Timing.cpp
@@ -931,6 +931,13 @@ private:
             }
             // Then the trigger check and assignment
             loopp->addStmtsp(assignp);
+            // Let the dynamic trigger scheduler know if this trigger was set
+            // If it was, a call to the scheduler's evaluate() will return true
+            AstCMethodHard* const anyTriggeredMethodp = new AstCMethodHard{
+                flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::WRITE},
+                "anyTriggered", new AstVarRef{flp, trigvscp, VAccess::READ}};
+            anyTriggeredMethodp->dtypeSetVoid();
+            loopp->addStmtsp(anyTriggeredMethodp->makeStmt());
             // If the post update is destructive (e.g. event vars are cleared), create an await for
             // the post update step
             if (destructivePostUpdate(sensesp)) {
diff --git a/test_regress/t/t_timing_debug2.out b/test_regress/t/t_timing_debug2.out
index 6698864f4..0e22dcd4e 100644
--- a/test_regress/t/t_timing_debug2.out
+++ b/test_regress/t/t_timing_debug2.out
@@ -649,6 +649,7 @@
 -V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:37 awaiting the post update step
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         'act' region trigger index 0 is active: @([event] t.ec.e)
+-V{t#,#}         'act' region trigger index 2 is active: @([true] __VdynSched.evaluate())
 -V{t#,#}         Doing post updates for processes:
 -V{t#,#}           - Process waiting at t/t_timing_class.v:37
 -V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:37
@@ -657,16 +658,6 @@
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         No ready processes waiting for @([event] t.ec.e)
 -V{t#,#}         Resuming processes waiting for @([event] t.ec.e)
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}         Suspended processes waiting for dynamic trigger evaluation:
--V{t#,#}           - Process waiting at t/t_timing_class.v:101
--V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:101
--V{t#,#}         Suspending process waiting for @(posedge t::ClkClass.clk) at t/t_timing_class.v:101
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 2 is active: @([true] __VdynSched.evaluate())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Resuming processes:
 -V{t#,#}           - Process waiting at t/t_timing_class.v:37
 -V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:37