[dv/alert] Fix alert init

Before alert_init finish, there might be another reset happen.
Previous code only handled the monitor part, this PR fixes the driver
part as well.
This PR also create a separate thread for alert_init from reset_thread.

Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/dv/sv/alert_esc_agent/alert_monitor.sv b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
index 33c31fd..fbd6bc3 100644
--- a/hw/dv/sv/alert_esc_agent/alert_monitor.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
@@ -22,12 +22,12 @@
       ping_thread();
       reset_thread();
       int_fail_thread();
+      alert_init_thread();
     join_none
   endtask : run_phase
 
   virtual task reset_thread();
     under_reset = 1;
-    wait_alert_init_done();
     forever begin
       @(negedge cfg.vif.rst_n);
       under_reset = 1;
@@ -35,11 +35,16 @@
       @(posedge cfg.vif.rst_n);
       // Reset signals at posedge rst_n to avoid race condition at negedge rst_n
       reset_signals();
-      // Wait for alert init with an intentional integrity fail to finish.
-      wait_alert_init_done();
     end
   endtask : reset_thread
 
+  virtual task alert_init_thread();
+    wait_alert_init_done();
+    forever @(posedge cfg.vif.rst_n) begin
+      wait_alert_init_done();
+    end
+  endtask : alert_init_thread
+
   virtual function void reset_signals();
     under_ping_rsp = 0;
   endfunction : reset_signals
@@ -48,25 +53,15 @@
   // process. However, it can still block alert handshake via the `cfg.alert_init_done` flag.
   // To handle the scenario where reset is issued during alert init, we use a fork join_any thread.
   virtual task wait_alert_init_done();
-    fork
-      begin
-        fork
-          begin
-            wait (cfg.vif.monitor_cb.alert_tx_final.alert_p ==
-                  cfg.vif.monitor_cb.alert_tx_final.alert_n);
-            wait (cfg.vif.monitor_cb.alert_tx_final.alert_p !=
-                  cfg.vif.monitor_cb.alert_tx_final.alert_n);
-            `uvm_info("alert_monitor", "Alert init done!", UVM_HIGH)
-            under_reset = 0;
-            cfg.alert_init_done = 1;
-          end
-          begin
-            @(negedge cfg.vif.rst_n);
-          end
-        join_any
-        disable fork;
-      end
-    join_none
+    `DV_SPINWAIT_EXIT(
+        wait (cfg.vif.monitor_cb.alert_tx_final.alert_p ==
+              cfg.vif.monitor_cb.alert_tx_final.alert_n);
+        wait (cfg.vif.monitor_cb.alert_tx_final.alert_p !=
+              cfg.vif.monitor_cb.alert_tx_final.alert_n);
+        `uvm_info("alert_monitor", "Alert init done!", UVM_HIGH)
+        cfg.alert_init_done = 1;
+        under_reset = 0;,
+        @(negedge cfg.vif.rst_n);)
   endtask
 
   virtual task ping_thread();
diff --git a/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv b/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv
index 3eefba8..38b2271 100644
--- a/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv
@@ -16,22 +16,27 @@
     fork
       send_ping();
       rsp_alert();
+      alert_init_thread();
     join_none
   endtask : drive_req
 
   virtual task reset_signals();
     do_reset();
-    do_alert_rx_init();
     forever begin
       @(negedge cfg.vif.rst_n);
       under_reset = 1;
       do_reset();
       @(posedge cfg.vif.rst_n);
-      do_alert_rx_init();
-      under_reset = 0;
     end
   endtask
 
+  virtual task alert_init_thread();
+    do_alert_rx_init();
+    forever @(posedge cfg.vif.rst_n) begin
+      do_alert_rx_init();
+    end
+  endtask : alert_init_thread
+
   virtual task send_ping();
     forever begin
       alert_esc_seq_item req, rsp;
@@ -179,15 +184,18 @@
   endtask
 
   virtual task do_alert_rx_init();
-    // Drive alert init signal integrity error handshake.
-    repeat ($urandom_range(1, 10)) @(cfg.vif.receiver_cb);
-    cfg.vif.alert_rx_int.ping_n <= 1'b0;
-    wait (cfg.vif.receiver_cb.alert_tx.alert_p == cfg.vif.receiver_cb.alert_tx.alert_n);
-    cfg.vif.alert_rx_int.ack_n <= 1'b0;
-    repeat ($urandom_range(1, 10)) @(cfg.vif.receiver_cb);
-    cfg.vif.alert_rx_int.ack_n  <= 1'b1;
-    cfg.vif.alert_rx_int.ping_n <= 1'b1;
-    wait (cfg.vif.receiver_cb.alert_tx.alert_p != cfg.vif.receiver_cb.alert_tx.alert_n);
+    `DV_SPINWAIT_EXIT(
+        // Drive alert init signal integrity error handshake.
+        repeat ($urandom_range(1, 10)) @(cfg.vif.receiver_cb);
+        cfg.vif.alert_rx_int.ping_n <= 1'b0;
+        wait (cfg.vif.receiver_cb.alert_tx.alert_p == cfg.vif.receiver_cb.alert_tx.alert_n);
+        cfg.vif.alert_rx_int.ack_n <= 1'b0;
+        repeat ($urandom_range(1, 10)) @(cfg.vif.receiver_cb);
+        cfg.vif.alert_rx_int.ack_n  <= 1'b1;
+        cfg.vif.alert_rx_int.ping_n <= 1'b1;
+        wait (cfg.vif.receiver_cb.alert_tx.alert_p != cfg.vif.receiver_cb.alert_tx.alert_n);
+        under_reset = 0;,
+        @(negedge cfg.vif.rst_n);)
   endtask
 
 endclass : alert_receiver_driver
diff --git a/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv b/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
index dae2429..b4590ec 100644
--- a/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
@@ -16,6 +16,7 @@
   semaphore alert_atomic = new(1);
 
   virtual task reset_signals();
+    under_reset = 1;
     do_reset();
     forever begin
       @(negedge cfg.vif.rst_n);
@@ -24,8 +25,6 @@
       @(posedge cfg.vif.rst_n);
       void'(alert_atomic.try_get(1));
       alert_atomic.put(1);
-      do_post_reset();
-      under_reset = 0;
     end
   endtask
 
@@ -36,9 +35,17 @@
     fork
       send_alert();
       rsp_ping();
+      alert_init_thread();
     join_none
   endtask : drive_req
 
+  virtual task alert_init_thread();
+    do_alert_tx_init();
+    forever @(posedge cfg.vif.rst_n) begin
+      do_alert_tx_init();
+    end
+  endtask : alert_init_thread
+
   virtual task send_alert();
     forever begin
       alert_esc_seq_item req, rsp;
@@ -221,11 +228,14 @@
   //
   // After alert_receiver is reset, it will send a signal integrity fail via `ping_n` and `ack_n`,
   // alert_sender acknowledged the init via sending an `alert_n` integrity fail.
-  virtual task do_post_reset();
-    wait (cfg.vif.alert_rx.ping_p == cfg.vif.alert_rx.ping_n);
-    cfg.vif.alert_tx_int.alert_n <= 1'b0;
-    wait (cfg.vif.alert_rx.ping_p != cfg.vif.alert_rx.ping_n);
-    cfg.vif.alert_tx_int.alert_n <= 1'b1;
+  virtual task do_alert_tx_init();
+    `DV_SPINWAIT_EXIT(
+        wait (cfg.vif.alert_rx.ping_p == cfg.vif.alert_rx.ping_n);
+        cfg.vif.alert_tx_int.alert_n <= 1'b0;
+        wait (cfg.vif.alert_rx.ping_p != cfg.vif.alert_rx.ping_n);
+        cfg.vif.alert_tx_int.alert_n <= 1'b1;
+        under_reset = 0;,
+        @(negedge cfg.vif.rst_n);)
   endtask
 
 endclass : alert_sender_driver