diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp index 275f7c1c0..a25a6fdd5 100644 --- a/src/V3Timing.cpp +++ b/src/V3Timing.cpp @@ -892,8 +892,8 @@ class TimingControlVisitor final : public VNVisitor { m_underProcedure = true; // Workaround for killing `always` processes (doing that is pretty much UB) // TODO: Disallow killing `always` at runtime (throw an error) - // Combo blocks (always @*) must not become coroutines -- they have no - // suspend points and would spin forever. + // Skip for combinational blocks; if the body has timing controls + // iterateChildren will add T_SUSPENDEE, otherwise it would spin. if (hasFlags(nodep, T_HAS_PROC) && !(m_activep && m_activep->sentreep() && m_activep->sentreep()->hasCombo())) addFlags(nodep, T_SUSPENDEE); diff --git a/test_regress/t/t_wait_iface_vif.v b/test_regress/t/t_wait_iface_vif.v index f0cf919da..a91fc8445 100644 --- a/test_regress/t/t_wait_iface_vif.v +++ b/test_regress/t/t_wait_iface_vif.v @@ -54,11 +54,19 @@ endclass module t; my_if intf(); + // Verify combinational always with timing controls still works as coroutine + int combo_timing_count = 0; + always @* begin + combo_timing_count = combo_timing_count + 1; + #1; + end + initial begin automatic Driver d = new; d.vif = intf; d.run(); repeat (4) @(posedge intf.clk); + if (combo_timing_count == 0) $stop; $write("*-* All Finished *-*\n"); $finish; end