[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