From fcf0d03cd4cbf5017635d60e32159a816117d23d Mon Sep 17 00:00:00 2001 From: Krzysztof Bieganski Date: Sat, 22 Oct 2022 14:05:39 +0000 Subject: [PATCH] Dynamic triggers for non-static contexts (#3599) In non-static contexts like class objects or stack frames, the use of global trigger evaluation is not feasible. The concept of dynamic triggers allows for trigger evaluation in such cases. These triggers are simply local variables, and coroutines are themselves responsible for evaluating them. They await the global dynamic trigger scheduler object, which is responsible for resuming them during the trigger evaluation step in the 'act' eval region. Once the trigger is set, they await the dynamic trigger scheduler once again, and then get resumed during the resumption step in the 'act' eval region. Signed-off-by: Krzysztof Bieganski --- docs/internals.rst | 30 + include/verilated_timing.cpp | 48 + include/verilated_timing.h | 74 ++ src/V3Ast.h | 36 +- src/V3AstNodeDType.h | 3 + src/V3AstNodes.cpp | 2 + src/V3EmitCFunc.cpp | 2 + src/V3Sched.cpp | 37 +- src/V3Sched.h | 6 +- src/V3SchedTiming.cpp | 22 +- src/V3SenExprBuilder.h | 32 +- src/V3Timing.cpp | 186 +++- test_regress/t/t_mailbox_class.out | 17 - test_regress/t/t_mailbox_class.pl | 17 +- test_regress/t/t_semaphore_class.out | 6 - test_regress/t/t_semaphore_class.pl | 17 +- test_regress/t/t_timing_class.v | 81 +- test_regress/t/t_timing_class_unsup.out | 6 - test_regress/t/t_timing_class_unsup.v | 12 - test_regress/t/t_timing_debug2.out | 892 +++++++++--------- test_regress/t/t_timing_debug2.pl | 2 +- test_regress/t/t_timing_localevent_unsup.out | 6 + ..._unsup.pl => t_timing_localevent_unsup.pl} | 0 test_regress/t/t_timing_localevent_unsup.v | 24 + 24 files changed, 947 insertions(+), 611 deletions(-) delete mode 100644 test_regress/t/t_mailbox_class.out delete mode 100644 test_regress/t/t_semaphore_class.out delete mode 100644 test_regress/t/t_timing_class_unsup.out delete mode 100644 test_regress/t/t_timing_class_unsup.v create mode 100644 test_regress/t/t_timing_localevent_unsup.out rename test_regress/t/{t_timing_class_unsup.pl => t_timing_localevent_unsup.pl} (100%) create mode 100644 test_regress/t/t_timing_localevent_unsup.v diff --git a/docs/internals.rst b/docs/internals.rst index c2031c857..a3f70ea36 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -588,6 +588,31 @@ This split is done to avoid self-triggering and triggering coroutines multiple times. See the `Scheduling with timing` section for details on how this is used. +``VlDynamicTriggerScheduler`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Like ``VlTriggerScheduler``, ``VlDynamicTriggerScheduler`` manages processes +that await triggers. However, it does not rely on triggers evaluated externally +by the 'act' trigger eval function. Instead, it is also responsible for trigger +evaluation. Coroutines that make use of this scheduler must adhere to a certain +procedure: + +:: + __Vtrigger = 0; + + while (!__Vtrigger) { + co_await __VdynSched.evaluation(); +
;
+      __Vtrigger = ;
+      [optionally] co_await __VdynSched.postUpdate();
+      ;
+  }
+  co_await __VdynSched.resumption();
+
+The coroutines get resumed at trigger evaluation time, evaluate their local
+triggers, optionally await the post update step, and if the trigger is set,
+await proper resumption in the 'act' eval step.
+
 ``VlForkSync``
 ^^^^^^^^^^^^^^
 
@@ -616,6 +641,11 @@ The visitor in ``V3Timing.cpp`` transforms each timing control into a ``co_await
   ``trigger`` method. The awaited trigger scheduler is the one corresponding to
   the sentree referenced by the event control. This sentree is also referenced
   by the ``AstCAwait`` node, to be used later by the static scheduling code.
+* if an event control waits on a local variable or class member, it uses a
+  local trigger which it evaluates inline. It awaits a dynamic trigger
+  scheduler multiple times: for trigger evaluation, updates, and resumption.
+  The dynamic trigger scheduler is responsible for resuming the coroutine at
+  the correct point of evaluation.
 * delays are turned into ``co_await`` on a delay scheduler's ``delay`` method.
   The created ``AstCAwait`` nodes also reference a special sentree related to
   delays, to be used later by the static scheduling code.
diff --git a/include/verilated_timing.cpp b/include/verilated_timing.cpp
index 7f996d7f7..f644ed64f 100644
--- a/include/verilated_timing.cpp
+++ b/include/verilated_timing.cpp
@@ -139,6 +139,54 @@ void VlTriggerScheduler::dump(const char* eventDescription) const {
 }
 #endif
 
+//======================================================================
+// VlDynamicTriggerScheduler:: Methods
+
+bool VlDynamicTriggerScheduler::evaluate() {
+    VL_DEBUG_IF(dump(););
+    std::swap(m_suspended, m_evaluated);
+    for (auto& coro : m_evaluated) coro.resume();
+    m_evaluated.clear();
+    return !m_triggered.empty();
+}
+
+void VlDynamicTriggerScheduler::doPostUpdates() {
+    VL_DEBUG_IF(if (!m_post.empty())
+                    VL_DBG_MSGF("         Doing post updates for processes:\n");  //
+                for (const auto& susp
+                     : m_post) {
+                    VL_DBG_MSGF("           - ");
+                    susp.dump();
+                });
+    for (auto& coro : m_post) coro.resume();
+    m_post.clear();
+}
+
+void VlDynamicTriggerScheduler::resume() {
+    VL_DEBUG_IF(if (!m_triggered.empty()) VL_DBG_MSGF("         Resuming processes:\n");  //
+                for (const auto& susp
+                     : m_triggered) {
+                    VL_DBG_MSGF("           - ");
+                    susp.dump();
+                });
+    for (auto& coro : m_triggered) coro.resume();
+    m_triggered.clear();
+}
+
+#ifdef VL_DEBUG
+void VlDynamicTriggerScheduler::dump() const {
+    if (m_suspended.empty()) {
+        VL_DBG_MSGF("         No suspended processes waiting for dynamic trigger evaluation\n");
+    } else {
+        for (const auto& susp : m_suspended) {
+            VL_DBG_MSGF("         Suspended processes waiting for dynamic trigger evaluation:\n");
+            VL_DBG_MSGF("           - ");
+            susp.dump();
+        }
+    }
+}
+#endif
+
 //======================================================================
 // VlForkSync:: Methods
 
diff --git a/include/verilated_timing.h b/include/verilated_timing.h
index 79eb1c0dd..f39d88ed6 100644
--- a/include/verilated_timing.h
+++ b/include/verilated_timing.h
@@ -238,6 +238,80 @@ public:
     }
 };
 
+//=============================================================================
+// VlDynamicTriggerScheduler is used for cases where triggers cannot be statically referenced and
+// evaluated. Coroutines that make use of this scheduler must adhere to a certain procedure:
+//     __Vtrigger = 0;
+//     
+//     while (!__Vtrigger) {
+//         co_await __VdynSched.evaluation();
+//         
;
+//         __Vtrigger = ;
+//         [optionally] co_await __VdynSched.postUpdate();
+//         ;
+//     }
+//    co_await __VdynSched.resumption();
+// The coroutines get resumed at trigger evaluation time, evaluate their local triggers, optionally
+// await the post update step, and if the trigger is set, await proper resumption in the 'act' eval
+// step.
+
+class VlDynamicTriggerScheduler final {
+    // TYPES
+    using VlCoroutineVec = std::vector;
+
+    // MEMBERS
+    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
+    VlCoroutineVec m_post;  // Coroutines awaiting the post update step (only relevant for triggers
+                            // with destructive post updates, e.g. named events)
+
+    // METHODS
+    auto awaitable(VlCoroutineVec& queue, const char* filename, int lineno) {
+        struct Awaitable {
+            VlCoroutineVec& suspended;  // Coros waiting on trigger
+            VlFileLineDebug fileline;
+
+            bool await_ready() const { return false; }  // Always suspend
+            void await_suspend(std::coroutine_handle<> coro) {
+                suspended.emplace_back(coro, fileline);
+            }
+            void await_resume() const {}
+        };
+        return Awaitable{queue, VlFileLineDebug{filename, lineno}};
+    }
+
+public:
+    // Evaluates all dynamic triggers (resumed coroutines that co_await evaluation())
+    bool evaluate();
+    // 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())
+    void resume();
+#ifdef VL_DEBUG
+    void dump() const;
+#endif
+    // Used by coroutines for co_awaiting trigger evaluation
+    auto evaluation(const char* eventDescription, const char* filename, int lineno) {
+        VL_DEBUG_IF(VL_DBG_MSGF("         Suspending process waiting for %s at %s:%d\n",
+                                eventDescription, filename, lineno););
+        return awaitable(m_suspended, filename, lineno);
+    }
+    // Used by coroutines for co_awaiting the trigger post update step
+    auto postUpdate(const char* eventDescription, const char* filename, int lineno) {
+        VL_DEBUG_IF(
+            VL_DBG_MSGF("         Process waiting for %s at %s:%d awaiting the post update step\n",
+                        eventDescription, filename, lineno););
+        return awaitable(m_post, filename, lineno);
+    }
+    // Used by coroutines for co_awaiting the resumption step (in 'act' eval)
+    auto resumption(const char* eventDescription, const char* filename, int lineno) {
+        VL_DEBUG_IF(VL_DBG_MSGF("         Process waiting for %s at %s:%d awaiting resumption\n",
+                                eventDescription, filename, lineno););
+        return awaitable(m_triggered, filename, lineno);
+    }
+};
+
 //=============================================================================
 // VlNow is a helper awaitable type that always suspends, and then immediately resumes a coroutine.
 // Allows forcing the move of coroutine locals to the heap.
diff --git a/src/V3Ast.h b/src/V3Ast.h
index ecac64da1..0253e20fe 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -460,6 +460,7 @@ public:
         TRIGGERVEC,
         DELAY_SCHEDULER,
         TRIGGER_SCHEDULER,
+        DYNAMIC_TRIGGER_SCHEDULER,
         FORK_SYNC,
         // Unsigned and two state; fundamental types
         UINT32,
@@ -490,6 +491,7 @@ public:
                                             "VlTriggerVec",
                                             "VlDelayScheduler",
                                             "VlTriggerScheduler",
+                                            "VlDynamicTriggerScheduler",
                                             "VlFork",
                                             "IData",
                                             "QData",
@@ -498,30 +500,12 @@ public:
         return names[m_e];
     }
     const char* dpiType() const {
-        static const char* const names[] = {"%E-unk",
-                                            "svBit",
-                                            "char",
-                                            "void*",
-                                            "char",
-                                            "int",
-                                            "%E-integer",
-                                            "svLogic",
-                                            "long long",
-                                            "double",
-                                            "short",
-                                            "%E-time",
-                                            "const char*",
-                                            "dpiScope",
-                                            "const char*",
-                                            "%E-mtaskstate",
-                                            "%E-triggervec",
-                                            "%E-dly-sched",
-                                            "%E-trig-sched",
-                                            "%E-fork",
-                                            "IData",
-                                            "QData",
-                                            "%E-logic-implct",
-                                            " MAX"};
+        static const char* const names[]
+            = {"%E-unk",        "svBit",         "char",         "void*",           "char",
+               "int",           "%E-integer",    "svLogic",      "long long",       "double",
+               "short",         "%E-time",       "const char*",  "dpiScope",        "const char*",
+               "%E-mtaskstate", "%E-triggervec", "%E-dly-sched", "%E-trig-sched",   "%E-dyn-sched",
+               "%E-fork",       "IData",         "QData",        "%E-logic-implct", " MAX"};
         return names[m_e];
     }
     static void selfTest() {
@@ -558,6 +542,7 @@ public:
         case TRIGGERVEC: return 0;  // opaque
         case DELAY_SCHEDULER: return 0;  // opaque
         case TRIGGER_SCHEDULER: return 0;  // opaque
+        case DYNAMIC_TRIGGER_SCHEDULER: return 0;  // opaque
         case FORK_SYNC: return 0;  // opaque
         case UINT32: return 32;
         case UINT64: return 64;
@@ -596,7 +581,8 @@ public:
     bool isOpaque() const VL_MT_SAFE {  // IE not a simple number we can bit optimize
         return (m_e == EVENT || m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR
                 || m_e == MTASKSTATE || m_e == TRIGGERVEC || m_e == DELAY_SCHEDULER
-                || m_e == TRIGGER_SCHEDULER || m_e == FORK_SYNC || m_e == DOUBLE);
+                || m_e == TRIGGER_SCHEDULER || m_e == DYNAMIC_TRIGGER_SCHEDULER || m_e == FORK_SYNC
+                || m_e == DOUBLE);
     }
     bool isDouble() const VL_MT_SAFE { return m_e == DOUBLE; }
     bool isEvent() const { return m_e == EVENT; }
diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h
index f8547b265..010a78d20 100644
--- a/src/V3AstNodeDType.h
+++ b/src/V3AstNodeDType.h
@@ -440,6 +440,9 @@ public:
     bool isTriggerScheduler() const VL_MT_SAFE {
         return keyword() == VBasicDTypeKwd::TRIGGER_SCHEDULER;
     }
+    bool isDynamicTriggerScheduler() const VL_MT_SAFE {
+        return keyword() == VBasicDTypeKwd::DYNAMIC_TRIGGER_SCHEDULER;
+    }
     bool isOpaque() const VL_MT_SAFE { return keyword().isOpaque(); }
     bool isString() const VL_MT_SAFE { return keyword().isString(); }
     bool isZeroInit() const { return keyword().isZeroInit(); }
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index bb0ca080e..92e0b2fce 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -754,6 +754,8 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const {
             info.m_type = "VlDelayScheduler";
         } else if (bdtypep->isTriggerScheduler()) {
             info.m_type = "VlTriggerScheduler";
+        } else if (bdtypep->isDynamicTriggerScheduler()) {
+            info.m_type = "VlDynamicTriggerScheduler";
         } else if (bdtypep->isForkSync()) {
             info.m_type = "VlForkSync";
         } else if (bdtypep->isEvent()) {
diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp
index 7ec97f234..f81998976 100644
--- a/src/V3EmitCFunc.cpp
+++ b/src/V3EmitCFunc.cpp
@@ -694,6 +694,8 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
         return "";
     } else if (basicp && basicp->isTriggerScheduler()) {
         return "";
+    } else if (basicp && basicp->isDynamicTriggerScheduler()) {
+        return "";
     } else if (basicp) {
         const bool zeroit
             = (varp->attrFileDescr()  // Zero so we don't do file IO if never $fopen
diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp
index bb48fa171..36a23771f 100644
--- a/src/V3Sched.cpp
+++ b/src/V3Sched.cpp
@@ -363,7 +363,8 @@ public:
 //============================================================================
 // Create a TRIGGERVEC and the related TriggerKit for the given AstSenTree vector
 
-const TriggerKit createTriggers(AstNetlist* netlistp, SenExprBuilder& senExprBuilder,
+const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
+                                SenExprBuilder& senExprBuilder,
                                 const std::vector& senTreeps,
                                 const string& name, const ExtraTriggers& extraTriggers,
                                 bool slow = false) {
@@ -463,7 +464,10 @@ const TriggerKit createTriggers(AstNetlist* netlistp, SenExprBuilder& senExprBui
         //
         ++triggerNumber;
     }
-    // Add the update statements
+    // Add the init and update statements
+    for (AstNodeStmt* const nodep : senExprBuilder.getAndClearInits()) {
+        initFuncp->addStmtsp(nodep);
+    }
     for (AstNodeStmt* const nodep : senExprBuilder.getAndClearPostUpdates()) {
         funcp->addStmtsp(nodep);
     }
@@ -604,7 +608,7 @@ std::pair makeEvalLoop(AstNetlist* netlistp, const strin
 //============================================================================
 // Order the combinational logic to create the settle loop
 
-void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
+void createSettle(AstNetlist* netlistp, AstCFunc* const initFuncp, SenExprBuilder& senExprBulider,
                   LogicClasses& logicClasses) {
     AstCFunc* const funcp = makeTopFunction(netlistp, "_eval_settle", true);
 
@@ -622,8 +626,8 @@ void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
 
     // Gather the relevant sensitivity expressions and create the trigger kit
     const auto& senTreeps = getSenTreesUsedBy({&comb, &hybrid});
-    const TriggerKit& trig
-        = createTriggers(netlistp, senExprBulider, senTreeps, "stl", extraTriggers, true);
+    const TriggerKit& trig = createTriggers(netlistp, initFuncp, senExprBulider, senTreeps, "stl",
+                                            extraTriggers, true);
 
     // Remap sensitivities (comb has none, so only do the hybrid)
     remapSensitivities(hybrid, trig.m_map);
@@ -662,8 +666,8 @@ void createSettle(AstNetlist* netlistp, SenExprBuilder& senExprBulider,
 //============================================================================
 // Order the replicated combinational logic to create the 'ico' region
 
-AstNode* createInputCombLoop(AstNetlist* netlistp, SenExprBuilder& senExprBuilder,
-                             LogicByScope& logic) {
+AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
+                             SenExprBuilder& senExprBuilder, LogicByScope& logic) {
     // Nothing to do if no combinational logic is sensitive to top level inputs
     if (logic.empty()) return nullptr;
 
@@ -693,7 +697,7 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, SenExprBuilder& senExprBuilde
     // Gather the relevant sensitivity expressions and create the trigger kit
     const auto& senTreeps = getSenTreesUsedBy({&logic});
     const TriggerKit& trig
-        = createTriggers(netlistp, senExprBuilder, senTreeps, "ico", extraTriggers);
+        = createTriggers(netlistp, initFuncp, senExprBuilder, senTreeps, "ico", extraTriggers);
 
     if (dpiExportTriggerVscp) {
         trig.addDpiExportTriggerAssignment(dpiExportTriggerVscp, dpiExportTriggerIndex);
@@ -904,10 +908,12 @@ void schedule(AstNetlist* netlistp) {
 
     // We pass around a single SenExprBuilder instance, as we only need one set of 'prev' variables
     // for edge/change detection in sensitivity expressions, which this keeps track of.
-    SenExprBuilder senExprBuilder{netlistp, initp};
+    AstTopScope* const topScopep = netlistp->topScopep();
+    AstScope* const scopeTopp = topScopep->scopep();
+    SenExprBuilder senExprBuilder{scopeTopp};
 
     // Step 4: Create 'settle' region that restores the combinational invariant
-    createSettle(netlistp, senExprBuilder, logicClasses);
+    createSettle(netlistp, initp, senExprBuilder, logicClasses);
     if (v3Global.opt.stats()) V3Stats::statsStage("sched-settle");
 
     // Step 5: Partition the clocked and combinational (including hybrid) logic into pre/act/nba.
@@ -932,7 +938,8 @@ void schedule(AstNetlist* netlistp) {
     }
 
     // Step 7: Create input combinational logic loop
-    AstNode* const icoLoopp = createInputCombLoop(netlistp, senExprBuilder, logicReplicas.m_ico);
+    AstNode* const icoLoopp
+        = createInputCombLoop(netlistp, initp, senExprBuilder, logicReplicas.m_ico);
     if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-ico");
 
     // Step 8: Create the pre/act/nba triggers
@@ -949,15 +956,15 @@ void schedule(AstNetlist* netlistp) {
                                                &logicRegions.m_nba,  //
                                                &timingKit.m_lbs});
     const TriggerKit& actTrig
-        = createTriggers(netlistp, senExprBuilder, senTreeps, "act", extraTriggers);
+        = createTriggers(netlistp, initp, senExprBuilder, senTreeps, "act", extraTriggers);
+
+    // Add post updates from the timing kit
+    if (timingKit.m_postUpdates) actTrig.m_funcp->addStmtsp(timingKit.m_postUpdates);
 
     if (dpiExportTriggerVscp) {
         actTrig.addDpiExportTriggerAssignment(dpiExportTriggerVscp, dpiExportTriggerIndex);
     }
 
-    AstTopScope* const topScopep = netlistp->topScopep();
-    AstScope* const scopeTopp = topScopep->scopep();
-
     AstVarScope* const actTrigVscp = actTrig.m_vscp;
     AstVarScope* const preTrigVscp = scopeTopp->createTempLike("__VpreTriggered", actTrigVscp);
     AstVarScope* const nbaTrigVscp = scopeTopp->createTempLike("__VnbaTriggered", actTrigVscp);
diff --git a/src/V3Sched.h b/src/V3Sched.h
index 9846ada1d..efde069af 100644
--- a/src/V3Sched.h
+++ b/src/V3Sched.h
@@ -125,6 +125,7 @@ class TimingKit final {
 
 public:
     LogicByScope m_lbs;  // Actives that resume timing schedulers
+    AstNodeStmt* m_postUpdates = nullptr;  // Post updates for the trigger eval function
 
     // Remaps external domains using the specified trigger map
     std::map>
@@ -135,10 +136,11 @@ public:
     AstCCall* createCommit(AstNetlist* const netlistp);
 
     TimingKit() = default;
-    TimingKit(LogicByScope&& lbs,
+    TimingKit(LogicByScope&& lbs, AstNodeStmt* postUpdates,
               std::map>&& externalDomains)
         : m_externalDomains{externalDomains}
-        , m_lbs{lbs} {}
+        , m_lbs{lbs}
+        , m_postUpdates{postUpdates} {}
     VL_UNCOPYABLE(TimingKit);
     TimingKit(TimingKit&&) = default;
     TimingKit& operator=(TimingKit&&) = default;
diff --git a/src/V3SchedTiming.cpp b/src/V3SchedTiming.cpp
index ac208122a..de8845b43 100644
--- a/src/V3SchedTiming.cpp
+++ b/src/V3SchedTiming.cpp
@@ -89,7 +89,8 @@ AstCCall* TimingKit::createCommit(AstNetlist* const netlistp) {
             UASSERT_OBJ(!resumep->nextp(), resumep, "Should be the only statement here");
             AstVarScope* const schedulerp = VN_AS(resumep->fromp(), VarRef)->varScopep();
             UASSERT_OBJ(schedulerp->dtypep()->basicp()->isDelayScheduler()
-                            || schedulerp->dtypep()->basicp()->isTriggerScheduler(),
+                            || schedulerp->dtypep()->basicp()->isTriggerScheduler()
+                            || schedulerp->dtypep()->basicp()->isDynamicTriggerScheduler(),
                         schedulerp, "Unexpected type");
             if (!schedulerp->dtypep()->basicp()->isTriggerScheduler()) continue;
             // Create the global commit function only if we have trigger schedulers
@@ -143,6 +144,7 @@ TimingKit prepareTiming(AstNetlist* const netlistp) {
         bool m_gatherVars = false;  // Should we gather vars in m_writtenBySuspendable?
         AstScope* const m_scopeTopp;  // Scope at the top
         LogicByScope& m_lbs;  // Timing resume actives
+        AstNodeStmt*& m_postUpdatesr;  // Post updates for the trigger eval function
         // Additional var sensitivities
         std::map>& m_externalDomains;
         std::set m_processDomains;  // Sentrees from the current process
@@ -159,11 +161,15 @@ TimingKit prepareTiming(AstNetlist* const netlistp) {
             // Create a resume() call on the timing scheduler
             auto* const resumep = new AstCMethodHard{
                 flp, new AstVarRef{flp, schedulerp, VAccess::READWRITE}, "resume"};
-            if (schedulerp->dtypep()->basicp()->isTriggerScheduler() && methodp->pinsp()) {
-                resumep->addPinsp(methodp->pinsp()->cloneTree(false));
-            }
             resumep->statement(true);
             resumep->dtypeSetVoid();
+            if (schedulerp->dtypep()->basicp()->isTriggerScheduler()) {
+                if (methodp->pinsp()) resumep->addPinsp(methodp->pinsp()->cloneTree(false));
+            } else if (schedulerp->dtypep()->basicp()->isDynamicTriggerScheduler()) {
+                auto* const postp = resumep->cloneTree(false);
+                postp->name("doPostUpdates");
+                m_postUpdatesr = AstNode::addNext(m_postUpdatesr, postp);
+            }
             // Put it in an active and put that in the global resume function
             auto* const activep = new AstActive{flp, "_timing", sensesp};
             activep->addStmtsp(resumep);
@@ -215,19 +221,21 @@ TimingKit prepareTiming(AstNetlist* const netlistp) {
 
     public:
         // CONSTRUCTORS
-        explicit AwaitVisitor(AstNetlist* nodep, LogicByScope& lbs,
+        explicit AwaitVisitor(AstNetlist* nodep, LogicByScope& lbs, AstNodeStmt*& postUpdatesr,
                               std::map>& externalDomains)
             : m_scopeTopp{nodep->topScopep()->scopep()}
             , m_lbs{lbs}
+            , m_postUpdatesr{postUpdatesr}
             , m_externalDomains{externalDomains} {
             iterate(nodep);
         }
         ~AwaitVisitor() override = default;
     };
     LogicByScope lbs;
+    AstNodeStmt* postUpdates = nullptr;
     std::map> externalDomains;
-    AwaitVisitor{netlistp, lbs, externalDomains};
-    return {std::move(lbs), std::move(externalDomains)};
+    AwaitVisitor{netlistp, lbs, postUpdates, externalDomains};
+    return {std::move(lbs), postUpdates, std::move(externalDomains)};
 }
 
 //============================================================================
diff --git a/src/V3SenExprBuilder.h b/src/V3SenExprBuilder.h
index c1e5ef57c..97b31e5b2 100644
--- a/src/V3SenExprBuilder.h
+++ b/src/V3SenExprBuilder.h
@@ -29,10 +29,10 @@
 
 class SenExprBuilder final {
     // STATE
-    AstCFunc* const m_initp;  // The initialization function
-    AstScope* const m_scopeTopp;  // Top level scope
+    AstScope* const m_scopep;  // The scope
 
     std::vector m_locals;  // Trigger eval local variables
+    std::vector m_inits;  // Initialization statements for prevoius values
     std::vector m_preUpdates;  // Pre update assignments
     std::vector m_postUpdates;  // Post update assignments
 
@@ -76,8 +76,8 @@ class SenExprBuilder final {
                 = new AstVar{flp, VVarType::BLOCKTEMP, m_currNames.get(exprp), exprp->dtypep()};
             varp->funcLocal(true);
             m_locals.push_back(varp);
-            AstVarScope* vscp = new AstVarScope{flp, m_scopeTopp, varp};
-            m_scopeTopp->addVarsp(vscp);
+            AstVarScope* vscp = new AstVarScope{flp, m_scopep, varp};
+            m_scopep->addVarsp(vscp);
             result.first->second = vscp;
         }
         AstVarScope* const currp = result.first->second;
@@ -106,13 +106,23 @@ class SenExprBuilder final {
                 name = m_prevNames.get(exprp);
             }
 
-            AstVarScope* const prevp = m_scopeTopp->createTemp(name, exprp->dtypep());
+            AstVarScope* prevp;
+            if (m_scopep->isTop()) {
+                prevp = m_scopep->createTemp(name, exprp->dtypep());
+            } else {
+                AstVar* const varp = new AstVar{flp, VVarType::BLOCKTEMP, m_prevNames.get(exprp),
+                                                exprp->dtypep()};
+                varp->funcLocal(true);
+                m_locals.push_back(varp);
+                prevp = new AstVarScope{flp, m_scopep, varp};
+                m_scopep->addVarsp(prevp);
+            }
             it = m_prev.emplace(*exprp, prevp).first;
 
             // Add the initializer init
-            AstNode* const initp = exprp->cloneTree(false);
-            m_initp->addStmtsp(
-                new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE}, initp});
+            AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
+                                                   exprp->cloneTree(false)};
+            m_inits.push_back(initp);
         }
 
         AstVarScope* const prevp = it->second;
@@ -222,6 +232,7 @@ public:
         return {resultp, firedAtInitialization};
     }
 
+    std::vector getAndClearInits() { return std::move(m_inits); }
     std::vector getAndClearLocals() { return std::move(m_locals); }
 
     std::vector getAndClearPreUpdates() {
@@ -235,9 +246,8 @@ public:
     }
 
     // CONSTRUCTOR
-    SenExprBuilder(AstNetlist* netlistp, AstCFunc* initp)
-        : m_initp{initp}
-        , m_scopeTopp{netlistp->topScopep()->scopep()} {}
+    SenExprBuilder(AstScope* scopep)
+        : m_scopep{scopep} {}
 };
 
 #endif  // Guard
diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp
index 02cdee3e5..8f657e0b0 100644
--- a/src/V3Timing.cpp
+++ b/src/V3Timing.cpp
@@ -50,6 +50,7 @@
 #include "V3Const.h"
 #include "V3EmitV.h"
 #include "V3Graph.h"
+#include "V3SenExprBuilder.h"
 #include "V3SenTree.h"
 #include "V3UniqueNames.h"
 
@@ -114,6 +115,7 @@ private:
     V3UniqueNames m_intraLsbNames{"__Vintralsb"};  // Intra assign delay LSB var names
     V3UniqueNames m_forkNames{"__Vfork"};  // Fork name generator
     V3UniqueNames m_trigSchedNames{"__VtrigSched"};  // Trigger scheduler name generator
+    V3UniqueNames m_dynTrigNames{"__VdynTrigger"};  // Dynamic trigger name generator
 
     // DTypes
     AstBasicDType* m_forkDtp = nullptr;  // Fork variable type
@@ -121,7 +123,9 @@ private:
 
     // Timing-related globals
     AstVarScope* m_delaySchedp = nullptr;  // Global delay scheduler
+    AstVarScope* m_dynamicSchedp = nullptr;  // Global dynamic trigger scheduler
     AstSenTree* m_delaySensesp = nullptr;  // Domain to trigger if a delayed coroutine is resumed
+    AstSenTree* m_dynamicSensesp = nullptr;  // Domain to trigger if a dynamic trigger is set
 
     // Other
     V3Graph m_depGraph;  // Dependency graph where a node is a dependency of another if it being
@@ -228,6 +232,44 @@ private:
         m_netlistp->topScopep()->addSenTreesp(m_delaySensesp);
         return m_delaySensesp;
     }
+    // Creates the global dynamic trigger scheduler variable
+    AstVarScope* getCreateDynamicTriggerScheduler() {
+        if (m_dynamicSchedp) return m_dynamicSchedp;
+        auto* const dynSchedDtp
+            = new AstBasicDType{m_scopeTopp->fileline(), VBasicDTypeKwd::DYNAMIC_TRIGGER_SCHEDULER,
+                                VSigning::UNSIGNED};
+        m_netlistp->typeTablep()->addTypesp(dynSchedDtp);
+        m_dynamicSchedp = m_scopeTopp->createTemp("__VdynSched", dynSchedDtp);
+        return m_dynamicSchedp;
+    }
+    // Creates the dynamic trigger sentree
+    AstSenTree* getCreateDynamicTriggerSenTree() {
+        if (m_dynamicSensesp) return m_dynamicSensesp;
+        FileLine* const flp = m_scopeTopp->fileline();
+        auto* const awaitingCurrentTimep = new AstCMethodHard{
+            flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::READ},
+            "evaluate"};
+        awaitingCurrentTimep->dtypeSetBit();
+        m_dynamicSensesp
+            = new AstSenTree{flp, new AstSenItem{flp, VEdgeType::ET_TRUE, awaitingCurrentTimep}};
+        m_netlistp->topScopep()->addSenTreesp(m_dynamicSensesp);
+        return m_dynamicSensesp;
+    }
+    // Returns true if we are under a class or the given tree has any references to locals. These
+    // are cases where static, globally-evaluated triggers are not suitable.
+    bool needDynamicTrigger(AstNode* const nodep) const {
+        return m_classp || nodep->exists([](const AstNodeVarRef* const refp) {
+            return refp->varp()->isFuncLocal();
+        });
+    }
+    // Returns true if the given trigger expression needs a destructive post update after trigger
+    // evaluation. Currently this only applies to named events.
+    bool destructivePostUpdate(AstNode* const exprp) const {
+        return exprp->exists([](const AstNodeVarRef* const refp) {
+            AstBasicDType* const dtypep = refp->dtypep()->basicp();
+            return dtypep && dtypep->isEvent();
+        });
+    }
     // Creates a trigger scheduler variable
     AstVarScope* getCreateTriggerSchedulerp(AstSenTree* const sensesp) {
         if (!sensesp->user1p()) {
@@ -483,26 +525,90 @@ private:
         VL_DO_DANGLING(nodep->deleteTree(), nodep);
     }
     void visit(AstEventControl* nodep) override {
-        if (m_classp) nodep->v3warn(E_UNSUPPORTED, "Unsupported: event controls in methods");
-        auto* const sensesp = m_finder.getSenTree(nodep->sensesp());
-        nodep->sensesp()->unlinkFrBack()->deleteTree();
-        // Get this sentree's trigger scheduler
-        FileLine* const flp = nodep->fileline();
-        // Replace self with a 'co_await trigSched.trigger()'
-        auto* const triggerMethodp = new AstCMethodHard{
-            flp, new AstVarRef{flp, getCreateTriggerSchedulerp(sensesp), VAccess::WRITE},
-            "trigger"};
-        triggerMethodp->dtypeSetVoid();
-        // Add debug info
-        addEventDebugInfo(triggerMethodp, sensesp);
-        // Create the co_await
-        auto* const awaitp = new AstCAwait{flp, triggerMethodp, sensesp};
-        awaitp->statement(true);
-        // Relink child statements after the co_await
-        if (nodep->stmtsp()) {
-            AstNode::addNext(awaitp, nodep->stmtsp()->unlinkFrBackWithNext());
+        // Do not allow waiting on local named events, as they get enqueued for clearing, but can
+        // go out of scope before that happens
+        if (nodep->sensesp()->exists([](const AstNodeVarRef* refp) {
+                AstBasicDType* const dtypep = refp->dtypep()->skipRefp()->basicp();
+                return dtypep && dtypep->isEvent() && refp->varp()->isFuncLocal();
+            })) {
+            nodep->v3warn(E_UNSUPPORTED, "Unsupported: waiting on local event variables");
+        }
+        FileLine* const flp = nodep->fileline();
+        // Relink child statements after the event control
+        if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
+        if (needDynamicTrigger(nodep->sensesp())) {
+            // Create the trigger variable and init it with 0
+            AstVarScope* const trigvscp
+                = createTemp(flp, m_dynTrigNames.get(nodep), nodep->findBitDType(), nodep);
+            auto* const initp = new AstAssign{flp, new AstVarRef{flp, trigvscp, VAccess::WRITE},
+                                              new AstConst{flp, AstConst::BitFalse{}}};
+            nodep->addHereThisAsNext(initp);
+            // Await the eval step with the dynamic trigger scheduler. First, create the method
+            // call
+            auto* const evalMethodp = new AstCMethodHard{
+                flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::WRITE},
+                "evaluation"};
+            evalMethodp->dtypeSetVoid();
+            auto* const sensesp = nodep->sensesp();
+            addEventDebugInfo(evalMethodp, sensesp);
+            // Create the co_await
+            auto* const awaitEvalp
+                = new AstCAwait{flp, evalMethodp, getCreateDynamicTriggerSenTree()};
+            awaitEvalp->statement(true);
+            // Construct the sen expression for this sentree
+            SenExprBuilder senExprBuilder{m_scopep};
+            auto* const assignp = new AstAssign{flp, new AstVarRef{flp, trigvscp, VAccess::WRITE},
+                                                senExprBuilder.build(sensesp).first};
+            // Put all the locals and inits before the trigger eval loop
+            for (AstVar* const varp : senExprBuilder.getAndClearLocals()) {
+                nodep->addHereThisAsNext(varp);
+            }
+            for (AstNodeStmt* const stmtp : senExprBuilder.getAndClearInits()) {
+                nodep->addHereThisAsNext(stmtp);
+            }
+            // Create the trigger eval loop, which will await the evaluation step and check the
+            // trigger
+            auto* const loopp = new AstWhile{
+                flp, new AstLogNot{flp, new AstVarRef{flp, trigvscp, VAccess::READ}}, awaitEvalp};
+            // Put pre updates before the trigger check and assignment
+            for (AstNodeStmt* const stmtp : senExprBuilder.getAndClearPreUpdates()) {
+                loopp->addStmtsp(stmtp);
+            }
+            // Then the trigger check and assignment
+            loopp->addStmtsp(assignp);
+            // If the post update is destructive (e.g. event vars are cleared), create an await for
+            // the post update step
+            if (destructivePostUpdate(sensesp)) {
+                auto* const awaitPostUpdatep = awaitEvalp->cloneTree(false);
+                VN_AS(awaitPostUpdatep->exprp(), CMethodHard)->name("postUpdate");
+                loopp->addStmtsp(awaitPostUpdatep);
+            }
+            // Put the post updates at the end of the loop
+            for (AstNodeStmt* const stmtp : senExprBuilder.getAndClearPostUpdates()) {
+                loopp->addStmtsp(stmtp);
+            }
+            // Finally, await the resumption step in 'act'
+            auto* const awaitResumep = awaitEvalp->cloneTree(false);
+            VN_AS(awaitResumep->exprp(), CMethodHard)->name("resumption");
+            AstNode::addNext(loopp, awaitResumep);
+            // Replace the event control with the loop
+            nodep->replaceWith(loopp);
+        } else {
+            auto* const sensesp = m_finder.getSenTree(nodep->sensesp());
+            nodep->sensesp()->unlinkFrBack()->deleteTree();
+            // Get this sentree's trigger scheduler
+            FileLine* const flp = nodep->fileline();
+            // Replace self with a 'co_await trigSched.trigger()'
+            auto* const triggerMethodp = new AstCMethodHard{
+                flp, new AstVarRef{flp, getCreateTriggerSchedulerp(sensesp), VAccess::WRITE},
+                "trigger"};
+            triggerMethodp->dtypeSetVoid();
+            addEventDebugInfo(triggerMethodp, sensesp);
+            // Create the co_await
+            auto* const awaitp = new AstCAwait{flp, triggerMethodp, sensesp};
+            awaitp->statement(true);
+            nodep->replaceWith(awaitp);
         }
-        nodep->replaceWith(awaitp);
         VL_DO_DANGLING(nodep->deleteTree(), nodep);
     }
     void visit(AstNodeAssign* nodep) override {
@@ -584,22 +690,14 @@ private:
     }
     void visit(AstWait* nodep) override {
         // Wait on changed events related to the vars in the wait statement
-        AstSenItem* const senItemsp = varRefpsToSenItemsp(nodep->condp());
-        AstNode* const condp = nodep->condp()->unlinkFrBack();
+        FileLine* const flp = nodep->fileline();
         AstNode* const stmtsp = nodep->stmtsp();
         if (stmtsp) stmtsp->unlinkFrBackWithNext();
-        FileLine* const flp = nodep->fileline();
-        if (senItemsp) {
-            // Put the event control in a while loop with the wait expression as condition
-            AstNode* const loopp
-                = new AstWhile{flp, new AstLogNot{flp, condp},
-                               new AstEventControl{flp, new AstSenTree{flp, senItemsp}, nullptr}};
-            if (stmtsp) loopp->addNext(stmtsp);
-            nodep->replaceWith(loopp);
-        } else {
+        AstNode* const condp = V3Const::constifyEdit(nodep->condp()->unlinkFrBack());
+        auto* const constp = VN_CAST(condp, Const);
+        if (constp) {
             condp->v3warn(WAITCONST, "Wait statement condition is constant");
-            auto* constCondp = VN_AS(V3Const::constifyEdit(condp), Const);
-            if (constCondp->isZero()) {
+            if (constp->isZero()) {
                 // We have to await forever instead of simply returning in case we're deep in a
                 // callstack
                 auto* const awaitp = new AstCAwait{flp, new AstCStmt{flp, "VlForever{}"}};
@@ -607,10 +705,30 @@ private:
                 nodep->replaceWith(awaitp);
                 if (stmtsp) VL_DO_DANGLING(stmtsp->deleteTree(), stmtsp);
             } else if (stmtsp) {
-                // Just put the body there
+                // Just put the statements there
                 nodep->replaceWith(stmtsp);
             }
-            VL_DO_DANGLING(constCondp->deleteTree(), condp);
+            VL_DO_DANGLING(condp->deleteTree(), condp);
+        } else if (needDynamicTrigger(condp)) {
+            // No point in making a sentree, just use the expression as sensitivity
+            // Put the event control in an if so we only wait if the condition isn't met already
+            auto* const ifp = new AstIf{
+                flp, new AstLogNot{flp, condp},
+                new AstEventControl{flp,
+                                    new AstSenTree{flp, new AstSenItem{flp, VEdgeType::ET_TRUE,
+                                                                       condp->cloneTree(false)}},
+                                    nullptr}};
+            if (stmtsp) AstNode::addNext(ifp, stmtsp);
+            nodep->replaceWith(ifp);
+        } else {
+            AstSenItem* const senItemsp = varRefpsToSenItemsp(condp);
+            UASSERT_OBJ(senItemsp, nodep, "No varrefs in wait statement condition");
+            // Put the event control in a while loop with the wait expression as condition
+            auto* const loopp
+                = new AstWhile{flp, new AstLogNot{flp, condp},
+                               new AstEventControl{flp, new AstSenTree{flp, senItemsp}, nullptr}};
+            if (stmtsp) AstNode::addNext(loopp, stmtsp);
+            nodep->replaceWith(loopp);
         }
         VL_DO_DANGLING(nodep->deleteTree(), nodep);
     }
diff --git a/test_regress/t/t_mailbox_class.out b/test_regress/t/t_mailbox_class.out
deleted file mode 100644
index da24a9ec0..000000000
--- a/test_regress/t/t_mailbox_class.out
+++ /dev/null
@@ -1,17 +0,0 @@
-%Error-UNSUPPORTED: t/t_mailbox_class.v:21:25: Unsupported: event controls in methods
-                                             : ... In instance $unit::mailbox_cls
-   21 |       if (m_bound != 0) wait (m_q.size() < m_bound);
-      |                         ^~~~
-                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
-%Error-UNSUPPORTED: t/t_mailbox_class.v:35:7: Unsupported: event controls in methods
-                                            : ... In instance $unit::mailbox_cls
-   35 |       wait (m_q.size() != 0);
-      |       ^~~~
-%Error-UNSUPPORTED: t/t_mailbox_class.v:49:7: Unsupported: event controls in methods
-                                            : ... In instance $unit::mailbox_cls
-   49 |       wait (m_q.size() != 0);
-      |       ^~~~
-%Error-UNSUPPORTED: t/t_mailbox_class.v:21:31: Unsupported: Cannot detect changes on expression of complex type (see combinational cycles reported by UNOPTFLAT)
-   21 |       if (m_bound != 0) wait (m_q.size() < m_bound);
-      |                               ^~~
-%Error: Exiting due to
diff --git a/test_regress/t/t_mailbox_class.pl b/test_regress/t/t_mailbox_class.pl
index 830c5f044..3329d516e 100755
--- a/test_regress/t/t_mailbox_class.pl
+++ b/test_regress/t/t_mailbox_class.pl
@@ -10,15 +10,14 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 scenarios(simulator => 1);
 
-compile(
-    verilator_flags2 => ["--timing"],
-    fails => $Self->{vlt_all},
-    expect_filename => $Self->{golden_filename},
-    );
-
-execute(
-    check_finished => 1,
-    ) if !$Self->{vlt_all};
+if (!$Self->have_coroutines) {
+    skip("No coroutine support");
+}
+else {
+    compile(
+        verilator_flags2 => ["--timing"],
+        );
+}
 
 ok(1);
 1;
diff --git a/test_regress/t/t_semaphore_class.out b/test_regress/t/t_semaphore_class.out
deleted file mode 100644
index 54be71860..000000000
--- a/test_regress/t/t_semaphore_class.out
+++ /dev/null
@@ -1,6 +0,0 @@
-%Error-UNSUPPORTED: t/t_semaphore_class.v:17:7: Unsupported: event controls in methods
-                                              : ... In instance $unit::semaphore_cls
-   17 |       wait (m_keys >= keyCount);
-      |       ^~~~
-                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
-%Error: Exiting due to
diff --git a/test_regress/t/t_semaphore_class.pl b/test_regress/t/t_semaphore_class.pl
index 830c5f044..3329d516e 100755
--- a/test_regress/t/t_semaphore_class.pl
+++ b/test_regress/t/t_semaphore_class.pl
@@ -10,15 +10,14 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 scenarios(simulator => 1);
 
-compile(
-    verilator_flags2 => ["--timing"],
-    fails => $Self->{vlt_all},
-    expect_filename => $Self->{golden_filename},
-    );
-
-execute(
-    check_finished => 1,
-    ) if !$Self->{vlt_all};
+if (!$Self->have_coroutines) {
+    skip("No coroutine support");
+}
+else {
+    compile(
+        verilator_flags2 => ["--timing"],
+        );
+}
 
 ok(1);
 1;
diff --git a/test_regress/t/t_timing_class.v b/test_regress/t/t_timing_class.v
index b79139153..263b2e44f 100644
--- a/test_regress/t/t_timing_class.v
+++ b/test_regress/t/t_timing_class.v
@@ -15,27 +15,95 @@ module t;
     // EVENTS
     class EventClass;
         event e;
+        int trig_count;
 
-        task sleep; /* @e; */ endtask  // Unsupported
-        task wake; ->e; endtask
+        function new;
+            trig_count = 0;
+        endfunction
+
+        task inc_trig_count;
+            trig_count++;
+        endtask;
+
+        task sleep;
+            @e inc_trig_count;
+            `WRITE_VERBOSE(("Event in class triggered at time %0t!\n", $time));
+        endtask
+
+        task wake;
+            ->e;
+        endtask
+    endclass
+
+    class WaitClass;
+        int a;
+        int b;
+        logic ok;
+
+        function new;
+            a = 0;
+            b = 0;
+            ok = 0;
+        endfunction
+
+        task await;
+            wait(a == 4 && b > 16) if (a != 4 || b <= 16) $stop;
+            ok = 1;
+            `WRITE_VERBOSE(("Condition in object met at time %0t!\n", $time));
+        endtask
+    endclass
+
+    class LocalWaitClass;
+        logic ok;
+
+        function new;
+            ok = 0;
+        endfunction
+
+        task await;
+            int a = 0;
+            int b = 100;
+            fork
+                wait(a == 42 || b != 100) if (a != 42 && b == 100) $stop;
+                #10 a = 42;
+            join
+            ok = 1;
+            `WRITE_VERBOSE(("Condition with local variables met at time %0t!\n", $time));
+        endtask
     endclass
 
     EventClass ec = new;
-    int event_trig_count = 0;
+    WaitClass wc = new;
+    LocalWaitClass lc = new;
 
     initial begin
         @ec.e;
         ec.sleep;
+        if (wc.ok) $stop;
+        wc.await;
+        if (lc.ok) $stop;
+        lc.await;
     end
 
-    initial #25 ec.wake;
-    initial #50 ->ec.e;
+    initial #20 ec.wake;
+    initial #40 ->ec.e;
+    initial begin
+        wc.a = #50 4;
+        wc.b = #10 32;
+    end
 
     always @ec.e begin
-        event_trig_count++;
+        ec.inc_trig_count;
         `WRITE_VERBOSE(("Event in class triggered at time %0t!\n", $time));
     end
 
+    initial begin
+        #80
+        if (ec.trig_count != 3) $stop;
+        if (!wc.ok) $stop;
+        if (!lc.ok) $stop;
+    end
+
     // =============================================
     // DELAYS
     virtual class DelayClass;
@@ -120,7 +188,6 @@ module t;
         fork #5 dAsgn.x = 0; join_none
         dAsgn.do_assign;
         if ($time != 80) $stop;
-        if (event_trig_count != 2) $stop;
         if (dAsgn.y != 1) $stop;
         // Test if the object is deleted before do_assign finishes:
         fork dAsgn.do_assign; join_none
diff --git a/test_regress/t/t_timing_class_unsup.out b/test_regress/t/t_timing_class_unsup.out
deleted file mode 100644
index 0cb96600b..000000000
--- a/test_regress/t/t_timing_class_unsup.out
+++ /dev/null
@@ -1,6 +0,0 @@
-%Error-UNSUPPORTED: t/t_timing_class_unsup.v:10:17: Unsupported: event controls in methods
-                                                  : ... In instance $unit::EventClass
-   10 |     task sleep; @e; endtask
-      |                 ^
-                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
-%Error: Exiting due to
diff --git a/test_regress/t/t_timing_class_unsup.v b/test_regress/t/t_timing_class_unsup.v
deleted file mode 100644
index 01795aa00..000000000
--- a/test_regress/t/t_timing_class_unsup.v
+++ /dev/null
@@ -1,12 +0,0 @@
-// DESCRIPTION: Verilator: Verilog Test module
-//
-// This file ONLY is placed under the Creative Commons Public Domain, for
-// any use, without warranty, 2022 by Antmicro Ltd.
-// SPDX-License-Identifier: CC0-1.0
-
-class EventClass;
-    event e;
-
-    task sleep; @e; endtask
-    task wake; ->e; endtask
-endclass
diff --git a/test_regress/t/t_timing_debug2.out b/test_regress/t/t_timing_debug2.out
index 4988bab73..6243cc26c 100644
--- a/test_regress/t/t_timing_debug2.out
+++ b/test_regress/t/t_timing_debug2.out
@@ -1,55 +1,109 @@
 -V{t#,#}- Verilated::debug is on. Message prefix indicates {,}.
 -V{t#,#}+    Vt_timing_debug2___024root___ctor_var_reset
+-V{t#,#}+      Vt_timing_debug2_t___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aAssignDelayClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aDelay10__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aDelay20__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aDelay40__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aDelayClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aEventClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aForkClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aForkDelayClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aLocalWaitClass__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aNoDelay__Vclpkg___ctor_var_reset
+-V{t#,#}+  Vt_timing_debug2_t__03a__03aWaitClass__Vclpkg___ctor_var_reset
 -V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
 -V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
 -V{t#,#}+ Initial
 -V{t#,#}+    Vt_timing_debug2___024root___eval_static
+-V{t#,#}+      Vt_timing_debug2_t___eval_static__TOP__t
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aWaitClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aWaitClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::_ctor_var_reset
 -V{t#,#}+    Vt_timing_debug2___024root___eval_initial
--V{t#,#}+    Vt_timing_debug2___024root___eval_initial__TOP__0
--V{t#,#}             Process forked at t/t_timing_fork_join.v:14 finished
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__1
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__2
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__3
-[0] fork..join process 4
--V{t#,#}             Process forked at t/t_timing_fork_join.v:18 finished
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__5
--V{t#,#}             Awaiting join of fork at: t/t_timing_fork_join.v:13
--V{t#,#}+    Vt_timing_debug2___024root___eval_initial__TOP__1
--V{t#,#}+    Vt_timing_debug2___024root___eval_initial__TOP__2
--V{t#,#}             Awaiting join of fork at: t/t_timing_fork_join.v:83
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__0
+-V{t#,#}         Suspending process waiting for @([event] t.ec.e) at t/t_timing_class.v:80
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__1
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__2
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__3
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__4
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__5
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay10::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay10::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay20::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay20::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay40::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay40::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aNoDelay::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aNoDelay::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aAssignDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aAssignDelayClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay10::__VnoInFunc_do_delay
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__6
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::_ctor_var_reset
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::__VnoInFunc_do_fork
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::__Vfork_h########__0__0
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::__Vfork_h########__0__1
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::__Vfork_h########__0__2
+-V{t#,#}             Awaiting join of fork at: t/t_timing_class.v:209
+-V{t#,#}+      Vt_timing_debug2_t___eval_initial__TOP__t__7
 -V{t#,#}+    Vt_timing_debug2___024root___eval_settle
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}         Committing processes waiting for @([event] t.ec.e):
+-V{t#,#}           - Process waiting at t/t_timing_class.v:80
 -V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
 -V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 2: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 8: Process waiting at t/t_timing_fork_join.v:16
--V{t#,#}             Awaiting time 4: Process waiting at t/t_timing_fork_join.v:17
--V{t#,#}             Awaiting time 16: Process waiting at t/t_timing_fork_join.v:19
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:79
+-V{t#,#}             Awaiting time 10: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 20: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 10: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 30: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 40: Process waiting at t/t_timing_class.v:137
+-V{t#,#}             Awaiting time 50: Process waiting at t/t_timing_class.v:211
+-V{t#,#}             Awaiting time 20: Process waiting at t/t_timing_class.v:215
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:220
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:236
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:79
-[2] fork..join process 3
--V{t#,#}             Process forked at t/t_timing_fork_join.v:17 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:236
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay10::__VnoInFunc_do_sth_else
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay20::__VnoInFunc_do_delay
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:138
+-V{t#,#}             Process forked at t/t_timing_class.v:210 finished
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -58,26 +112,235 @@
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 4: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 8: Process waiting at t/t_timing_fork_join.v:16
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:17
--V{t#,#}             Awaiting time 16: Process waiting at t/t_timing_fork_join.v:19
+-V{t#,#}             Awaiting time 20: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 20: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 30: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 30: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 40: Process waiting at t/t_timing_class.v:137
+-V{t#,#}             Awaiting time 50: Process waiting at t/t_timing_class.v:211
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:215
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:220
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:19
-[4] fork..join process 2
--V{t#,#}             Process forked at t/t_timing_fork_join.v:16 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:220
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkDelayClass::new
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkDelayClass::_ctor_var_reset
+-V{t#,#}             Process forked at t/t_timing_class.v:214 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:215
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::__VnoInFunc_wake
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         'act' region trigger index 0 is active: @([event] t.ec.e)
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___timing_resume
+-V{t#,#}         Ready processes waiting for @([event] t.ec.e):
+-V{t#,#}           - Process waiting at t/t_timing_class.v:80
+-V{t#,#}         Resuming processes waiting for @([event] t.ec.e)
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:80
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::__VnoInFunc_sleep
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___eval_nba
+-V{t#,#}+      Vt_timing_debug2_t___nba_sequent__TOP__t__0
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::__VnoInFunc_inc_trig_count
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
+-V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
+-V{t#,#}+ Eval
+-V{t#,#}+    Vt_timing_debug2___024root___eval
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___timing_resume
+-V{t#,#}         Delayed processes:
+-V{t#,#}             Awaiting time 30: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 30: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 50: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 40: Process waiting at t/t_timing_class.v:137
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:211
+-V{t#,#}         Resuming delayed processes
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:211
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay20::__VnoInFunc_do_sth_else
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay40::__VnoInFunc_do_delay
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:139
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkDelayClass::__VnoInFunc_do_delay
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___eval_nba
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
+-V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
+-V{t#,#}+ Eval
+-V{t#,#}+    Vt_timing_debug2___024root___eval
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting the post update step
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Suspending process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___timing_resume
+-V{t#,#}         Delayed processes:
+-V{t#,#}             Awaiting time 40: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 50: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:137
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:202
+-V{t#,#}         Resuming delayed processes
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:202
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 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#,#}         Doing post updates for processes:
+-V{t#,#}           - Process waiting at t/t_timing_class.v:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}         Process waiting for @([event] t::EventClass.e) at t/t_timing_class.v:29 awaiting resumption
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-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#,#}         No suspended processes waiting for dynamic trigger evaluation
+-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:29
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:29
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::__VnoInFunc_inc_trig_count
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aWaitClass::__VnoInFunc_await
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
+-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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___eval_nba
+-V{t#,#}+      Vt_timing_debug2_t___nba_sequent__TOP__t__0
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::__VnoInFunc_inc_trig_count
+-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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
+-V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
+-V{t#,#}+ Eval
+-V{t#,#}+    Vt_timing_debug2___024root___eval
+-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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___timing_resume
+-V{t#,#}         Delayed processes:
+-V{t#,#}             Awaiting time 50: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:137
+-V{t#,#}         Resuming delayed processes
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:137
+-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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -86,25 +349,55 @@
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 8: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 16: Process waiting at t/t_timing_fork_join.v:16
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:17
+-V{t#,#}             Awaiting time 60: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:92
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:17
-[8] fork..join process 1
--V{t#,#}             Process forked at t/t_timing_fork_join.v:15 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:92
 -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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}         Process waiting for @([true] ((32'sh4 == t::WaitClass.a) & (32'sh10 < t::WaitClass.b))) at t/t_timing_class.v:50 awaiting resumption
+-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:50
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:50
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::__VnoInFunc_await
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::__Vfork_h########__0__0
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh2a == t::LocalWaitClass.a) | (32'sh64 != t::LocalWaitClass.b))) at t/t_timing_class.v:67
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::__Vfork_h########__0__1
+-V{t#,#}             Awaiting join of fork at: t/t_timing_class.v:66
+-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:67
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:67
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh2a == t::LocalWaitClass.a) | (32'sh64 != t::LocalWaitClass.b))) at t/t_timing_class.v:67
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -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:67
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:67
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh2a == t::LocalWaitClass.a) | (32'sh64 != t::LocalWaitClass.b))) at t/t_timing_class.v:67
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -113,114 +406,87 @@
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -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:67
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:67
+-V{t#,#}         Suspending process waiting for @([true] ((32'sh2a == t::LocalWaitClass.a) | (32'sh64 != t::LocalWaitClass.b))) at t/t_timing_class.v:67
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 16: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:16
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:101
+-V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_class.v:68
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:16
-[16] fork in fork starts
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__0
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__1
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__2
-[16] fork..join process 8
--V{t#,#}             Process forked at t/t_timing_fork_join.v:25 finished
--V{t#,#}             Awaiting join of fork at: t/t_timing_fork_join.v:21
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 20: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 24: Process waiting at t/t_timing_fork_join.v:22
--V{t#,#}             Awaiting time 32: Process waiting at t/t_timing_fork_join.v:23
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:24
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:24
-[20] fork..join process 7
--V{t#,#}             Process forked at t/t_timing_fork_join.v:24 finished
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 24: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:22
--V{t#,#}             Awaiting time 32: Process waiting at t/t_timing_fork_join.v:23
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:23
-[24] fork..join process 6
--V{t#,#}             Process forked at t/t_timing_fork_join.v:23 finished
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 32: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:22
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:22
-[32] fork..join process 5
--V{t#,#}             Process forked at t/t_timing_fork_join.v:22 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:68
+-V{t#,#}             Process forked at t/t_timing_class.v:219 finished
 -V{t#,#}             Resuming: Process waiting at (null):0
-[32] fork..join in fork ends
--V{t#,#}             Process forked at t/t_timing_fork_join.v:19 finished
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:101
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay40::__VnoInFunc_do_sth_else
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aNoDelay::__VnoInFunc_do_delay
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aNoDelay::__VnoInFunc_do_sth_else
+-V{t#,#}+      Vt_timing_debug2_t____Vfork_h########__0__0
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aAssignDelayClass::__VnoInFunc_do_assign
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:154
+-V{t#,#}             Process forked at t/t_timing_class.v:68 finished
+-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:67
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:67
+-V{t#,#}         Process waiting for @([true] ((32'sh2a == t::LocalWaitClass.a) | (32'sh64 != t::LocalWaitClass.b))) at t/t_timing_class.v:67 awaiting resumption
+-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:67
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:67
+-V{t#,#}             Process forked at t/t_timing_class.v:67 finished
 -V{t#,#}             Resuming: Process waiting at (null):0
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
+-V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkDelayClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aForkClass::~
+-V{t#,#}+ Eval
+-V{t#,#}+    Vt_timing_debug2___024root___eval
+-V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___timing_resume
+-V{t#,#}         Delayed processes:
+-V{t#,#}             Awaiting time 75: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:188
+-V{t#,#}         Resuming delayed processes
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:188
+-V{t#,#}+    Vt_timing_debug2___024root___eval_act
+-V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
+-V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
+-V{t#,#}         No triggers active
+-V{t#,#}+    Vt_timing_debug2___024root___timing_commit
+-V{t#,#}+    Vt_timing_debug2___024root___eval_nba
+-V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -229,31 +495,29 @@
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 64: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:30
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 80: Process waiting at t/t_timing_class.v:89
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:91
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:30
-[64] main process
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__0
--V{t#,#}         Suspending process waiting for @([event] t.event1) at t/t_timing_fork_join.v:33
-fork..join_any process 2
--V{t#,#}             Process forked at t/t_timing_fork_join.v:37 finished
--V{t#,#}             Awaiting join of fork at: t/t_timing_fork_join.v:31
-back in main process
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:91
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:89
+-V{t#,#}+      Vt_timing_debug2_t____Vfork_h########__0__1
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aAssignDelayClass::__VnoInFunc_do_assign
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}         Committing processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:33
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -262,42 +526,26 @@ back in main process
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 65: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:40
+-V{t#,#}             Awaiting time 85: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:154
+-V{t#,#}             Awaiting time 90: Process waiting at t/t_timing_class.v:194
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:40
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 1 is active: @([event] t.event1)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:33
--V{t#,#}         Resuming processes waiting for @([event] t.event1)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:33
-fork..join_any process 1
--V{t#,#}             Process forked at t/t_timing_fork_join.v:32 finished
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 1 is active: @([event] t.event1)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         No ready processes waiting for @([event] t.event1)
--V{t#,#}         Resuming processes waiting for @([event] t.event1)
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:194
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
@@ -306,323 +554,67 @@ fork..join_any process 1
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 66: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:41
+-V{t#,#}             Awaiting time 90: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:154
+-V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_class.v:195
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:41
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__0
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__1
--V{t#,#}         Suspending process waiting for @([event] t.event1) at t/t_timing_fork_join.v:44
--V{t#,#}             Awaiting join of fork at: t/t_timing_fork_join.v:41
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}         Committing processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:44
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 68: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:42
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:42
-fork..join_any process 1
--V{t#,#}             Process forked at t/t_timing_fork_join.v:42 finished
--V{t#,#}             Resuming: Process waiting at (null):0
-back in main process
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:195
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
 -V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aAssignDelayClass::~
 -V{t#,#}+ Eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
+-V{t#,#}         'act' region trigger index 1 is active: @([true] __VdlySched.awaitingCurrentTime())
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___timing_resume
 -V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 69: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:50
+-V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_class.v:88
+-V{t#,#}             Awaiting time 101: Process waiting at t/t_timing_class.v:154
 -V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:50
--V{t#,#}         Suspending process waiting for @([event] t.event1) at t/t_timing_fork_join.v:51
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 1 is active: @([event] t.event1)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:44
--V{t#,#}         Uncommitted processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:51
--V{t#,#}         Resuming processes waiting for @([event] t.event1)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:44
-fork..join_any process 2
--V{t#,#}             Process forked at t/t_timing_fork_join.v:43 finished
--V{t#,#}         Committing processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:51
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 1 is active: @([event] t.event1)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:51
--V{t#,#}         Resuming processes waiting for @([event] t.event1)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:51
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__0
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__1
--V{t#,#}         Suspending process waiting for @([event] t.event2) at t/t_timing_fork_join.v:62
--V{t#,#}+    Vt_timing_debug2___024root____Vfork_h########__0__2
--V{t#,#}         Suspending process waiting for @([event] t.event3) at t/t_timing_fork_join.v:68
-in main process
--V{t#,#}         Suspending process waiting for @([event] t.event1) at t/t_timing_fork_join.v:75
--V{t#,#}         Committing processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:75
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}         Committing processes waiting for @([event] t.event2):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:62
--V{t#,#}         Committing processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:68
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 70: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:56
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:56
-fork..join_none process 1
--V{t#,#}         Suspending process waiting for @([event] t.event2) at t/t_timing_fork_join.v:58
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 2 is active: @([event] t.event2)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event2):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:62
--V{t#,#}         Uncommitted processes waiting for @([event] t.event2):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:58
--V{t#,#}         Resuming processes waiting for @([event] t.event2)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:62
-fork..join_none process 2
--V{t#,#}         Committing processes waiting for @([event] t.event2):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:58
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 71: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:63
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:63
--V{t#,#}         Suspending process waiting for @([event] t.event3) at t/t_timing_fork_join.v:64
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 3 is active: @([event] t.event3)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:68
--V{t#,#}         Uncommitted processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:64
--V{t#,#}         Resuming processes waiting for @([event] t.event3)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:68
-fork..join_none process 3
--V{t#,#}         Committing processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:64
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 72: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:69
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:69
--V{t#,#}         Suspending process waiting for @([event] t.event3) at t/t_timing_fork_join.v:70
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 3 is active: @([event] t.event3)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:64
--V{t#,#}         Uncommitted processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:70
--V{t#,#}         Resuming processes waiting for @([event] t.event3)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:64
-fork..join_none process 2 again
--V{t#,#}         Committing processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:70
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 73: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:65
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:65
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 2 is active: @([event] t.event2)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event2):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:58
--V{t#,#}         Resuming processes waiting for @([event] t.event2)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:58
-fork..join_none process 1 again
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___eval_nba
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         No triggers active
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+++++TOP Evaluate Vt_timing_debug2::eval_step
--V{t#,#}+    Vt_timing_debug2___024root___eval_debug_assertions
--V{t#,#}+ Eval
--V{t#,#}+    Vt_timing_debug2___024root___eval
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 0 is active: @([true] __VdlySched.awaitingCurrentTime())
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Delayed processes:
--V{t#,#}             Awaiting time 74: Process waiting at t/t_timing_fork_join.v:15
--V{t#,#}             Awaiting time 100: Process waiting at t/t_timing_fork_join.v:59
--V{t#,#}         Resuming delayed processes
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:59
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 3 is active: @([event] t.event3)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event3):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:70
--V{t#,#}         Resuming processes waiting for @([event] t.event3)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:70
-fork..join_none process 3 again
--V{t#,#}+    Vt_timing_debug2___024root___eval_act
--V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
--V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
--V{t#,#}         'act' region trigger index 1 is active: @([event] t.event1)
--V{t#,#}+    Vt_timing_debug2___024root___timing_commit
--V{t#,#}+    Vt_timing_debug2___024root___timing_resume
--V{t#,#}         Ready processes waiting for @([event] t.event1):
--V{t#,#}           - Process waiting at t/t_timing_fork_join.v:75
--V{t#,#}         Resuming processes waiting for @([event] t.event1)
--V{t#,#}             Resuming: Process waiting at t/t_timing_fork_join.v:75
+-V{t#,#}             Resuming: Process waiting at t/t_timing_class.v:154
 *-* All Finished *-*
 -V{t#,#}+    Vt_timing_debug2___024root___eval_act
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_nba
 -V{t#,#}+    Vt_timing_debug2___024root___eval_triggers__act
+-V{t#,#}         No suspended processes waiting for dynamic trigger evaluation
 -V{t#,#}+    Vt_timing_debug2___024root___dump_triggers__act
 -V{t#,#}         No triggers active
 -V{t#,#}+    Vt_timing_debug2___024root___timing_commit
 -V{t#,#}+    Vt_timing_debug2___024root___eval_final
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay40::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay20::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelay10::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aNoDelay::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aDelayClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aLocalWaitClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aWaitClass::~
+-V{t#,#}+        Vt_timing_debug2_t__03a__03aEventClass::~
diff --git a/test_regress/t/t_timing_debug2.pl b/test_regress/t/t_timing_debug2.pl
index c5b6b9286..56ef19876 100755
--- a/test_regress/t/t_timing_debug2.pl
+++ b/test_regress/t/t_timing_debug2.pl
@@ -14,7 +14,7 @@ if (!$Self->have_coroutines) {
     skip("No coroutine support");
 }
 else {
-    top_filename("t/t_timing_fork_join.v");
+    top_filename("t/t_timing_class.v");
 
     compile(
         verilator_flags2 => ["--exe --main --timing"],
diff --git a/test_regress/t/t_timing_localevent_unsup.out b/test_regress/t/t_timing_localevent_unsup.out
new file mode 100644
index 000000000..46578cb94
--- /dev/null
+++ b/test_regress/t/t_timing_localevent_unsup.out
@@ -0,0 +1,6 @@
+%Error-UNSUPPORTED: t/t_timing_localevent_unsup.v:12:17: Unsupported: waiting on local event variables
+                                                       : ... In instance t::Sleeper
+   12 |                 @e;
+      |                 ^
+                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
+%Error: Exiting due to
diff --git a/test_regress/t/t_timing_class_unsup.pl b/test_regress/t/t_timing_localevent_unsup.pl
similarity index 100%
rename from test_regress/t/t_timing_class_unsup.pl
rename to test_regress/t/t_timing_localevent_unsup.pl
diff --git a/test_regress/t/t_timing_localevent_unsup.v b/test_regress/t/t_timing_localevent_unsup.v
new file mode 100644
index 000000000..8091e2a4b
--- /dev/null
+++ b/test_regress/t/t_timing_localevent_unsup.v
@@ -0,0 +1,24 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t;
+    class Sleeper;
+        task sleep;
+            event e;
+            fork
+                @e;
+                #1 ->e;
+            join;
+        endtask
+    endclass
+
+    initial begin
+        Sleeper sleeper = new;
+        sleeper.sleep;
+        $write("*-* All Finished *-*\n");
+        $finish;
+    end
+endmodule