[dv/alert_esc_agent] support lpg in alert_esc_agent
This PR supports lpg in alert_esc_agent. In alert_handler testbench, if
lpg is enabled and alert triggered from the alert sender side,
alert_handler testbench needs to ignore the alert.
Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/dv/sv/alert_esc_agent/alert_esc_agent_cfg.sv b/hw/dv/sv/alert_esc_agent/alert_esc_agent_cfg.sv
index aa5cee8..c10da26 100644
--- a/hw/dv/sv/alert_esc_agent/alert_esc_agent_cfg.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_esc_agent_cfg.sv
@@ -13,6 +13,7 @@
bit is_async = 0;
bit en_ping_cov = 1;
bit alert_init_done = 0;
+ bit en_alert_lpg = 0;
// dut clk frequency, used to generate alert async_clk frequency
int clk_freq_mhz;
diff --git a/hw/dv/sv/alert_esc_agent/alert_monitor.sv b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
index fbd6bc3..3164666 100644
--- a/hw/dv/sv/alert_esc_agent/alert_monitor.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
@@ -53,15 +53,31 @@
// 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();
- `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);)
+ 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)
+ cfg.alert_init_done = 1;
+ under_reset = 0;
+ end
+ begin
+ @(negedge cfg.vif.rst_n);
+ end
+ // Clear `under_reset` and `alert_init_done` when en_alert_lpg is on, because alert_sender
+ // can still send alerts, and alert_handler should ignore the alert_tx request.
+ begin
+ wait (cfg.en_alert_lpg == 1);
+ cfg.alert_init_done = 1;
+ under_reset = 0;
+ end
+ join_any
+ disable fork;
+ end
+ join
endtask
virtual task ping_thread();
@@ -92,7 +108,7 @@
under_ping_rsp = 0;
end
begin
- wait(under_reset);
+ wait (under_reset || cfg.en_alert_lpg);
end
join_any
// wait 1ps in case 'wait_ping_handshake' and 'wait_ping_timeout' thread finish at the
@@ -104,7 +120,7 @@
`uvm_info("alert_monitor", $sformatf("[%s]: handshake status is %s",
req.alert_esc_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
- if (!under_reset) begin
+ if (!under_reset && !cfg.en_alert_lpg) begin
alert_esc_port.write(req);
if (cfg.en_cov && cfg.en_ping_cov) cov.m_alert_esc_trans_cg.sample(req.alert_esc_type);
@@ -156,7 +172,7 @@
req.alert_handshake_sta = AlertAckComplete;
end
begin
- wait(under_reset);
+ wait (under_reset || cfg.en_alert_lpg);
end
join_any
disable fork;
@@ -165,7 +181,7 @@
`uvm_info("alert_monitor", $sformatf("[%s]: handshake status is %s",
req.alert_esc_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
- if (!under_reset) alert_esc_port.write(req);
+ if (!under_reset && !cfg.en_alert_lpg) alert_esc_port.write(req);
if (cfg.en_cov) begin
cov.m_alert_handshake_complete_cg.sample(req.alert_esc_type, req.alert_handshake_sta);
if (cfg.en_ping_cov) cov.m_alert_esc_trans_cg.sample(req.alert_esc_type);
@@ -181,7 +197,8 @@
bit prev_err;
forever @(cfg.vif.monitor_cb) begin
// use prev_err to exclude the async clk skew
- if (!under_reset && is_sig_int_err() && (!cfg.is_async || prev_err != 0)) begin
+ if (!under_reset && !cfg.en_alert_lpg && is_sig_int_err() &&
+ (!cfg.is_async || prev_err != 0)) begin
fork
begin
req = alert_esc_seq_item::type_id::create("req");
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 b4590ec..c723b35 100644
--- a/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
@@ -39,24 +39,30 @@
join_none
endtask : drive_req
+ // Two conditions can trigger alert init:
+ // 1). Reset deassert; 2). LPG disabled.
virtual task alert_init_thread();
do_alert_tx_init();
- forever @(posedge cfg.vif.rst_n) begin
- do_alert_tx_init();
- end
+ fork
+ forever @(posedge cfg.vif.rst_n) begin
+ do_alert_tx_init();
+ end
+ forever @(negedge cfg.en_alert_lpg) begin
+ do_alert_tx_init();
+ end
+ join_none
endtask : alert_init_thread
virtual task send_alert();
forever begin
alert_esc_seq_item req, rsp;
- wait(s_alert_send_q.size() > 0 && !under_reset);
+ wait (s_alert_send_q.size() > 0 && !under_reset);
req = s_alert_send_q.pop_front();
`downcast(rsp, req.clone());
rsp.set_id_info(req);
`uvm_info(`gfn,
$sformatf("starting to send sender item, alert_send=%0b, ping_rsp=%0b, int_err=%0b",
req.s_alert_send, req.s_alert_ping_rsp, req.int_err), UVM_HIGH)
-
fork
begin : isolation_fork
fork
@@ -66,7 +72,7 @@
alert_atomic.put(1);
end
begin
- wait(under_reset);
+ wait (under_reset);
end
join_any
disable fork;
@@ -83,7 +89,7 @@
virtual task rsp_ping();
forever begin
alert_esc_seq_item req, rsp;
- wait(s_alert_ping_rsp_q.size() > 0 && !under_reset);
+ wait (s_alert_ping_rsp_q.size() > 0 && !under_reset && !cfg.en_alert_lpg);
req = s_alert_ping_rsp_q.pop_front();
`downcast(rsp, req.clone());
rsp.set_id_info(req);
@@ -105,7 +111,7 @@
alert_atomic.put(1);
end
begin
- wait(under_reset);
+ wait (under_reset || cfg.en_alert_lpg);
end
join_any
disable fork;
@@ -161,14 +167,18 @@
begin : isolation_fork
fork
begin : alert_timeout
- repeat (cfg.handshake_timeout_cycle) wait_sender_clk();
+ repeat (cfg.handshake_timeout_cycle) begin
+ wait_sender_clk();
+ // If alert_lpg is enabled, alert rx request is ignored by the alert_receiver.
+ if (cfg.en_alert_lpg) break;
+ end
end
begin : wait_alert_handshake
- wait(cfg.vif.alert_rx.ack_p == 1'b1);
+ wait (cfg.vif.alert_rx.ack_p == 1'b1);
wait_sender_clk();
repeat (ack_delay) wait_sender_clk();
reset_alert();
- wait(cfg.vif.alert_rx.ack_p == 1'b0);
+ wait (cfg.vif.alert_rx.ack_p == 1'b0);
end
join_any
disable fork;
@@ -229,13 +239,28 @@
// 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_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);)
+ fork begin
+ fork
+ begin
+ 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;
+ end
+ begin
+ @(negedge cfg.vif.rst_n);
+ end
+ begin
+ // Clear `under_reset` when en_alert_lpg is on, because alert_sender can still send
+ // alerts, and alert_handler should ignore the alert_tx request.
+ wait (cfg.en_alert_lpg == 1);
+ under_reset = 0;
+ end
+ join_any
+ disable fork;
+ end
+ join
endtask
endclass : alert_sender_driver
diff --git a/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
index c2ea2d9..112726a 100644
--- a/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
+++ b/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
@@ -17,6 +17,11 @@
lpg_rst_en = '{default: MuBi4False};
endfunction
+ function automatic bit get_lpg_status(int index);
+ check_lpg_index(index);
+ return (lpg_cg_en[index] == MuBi4True || lpg_rst_en[index] == MuBi4True);
+ endfunction
+
// TODO: randomize all values outside of the mubi4 enum.
function automatic void set_lpg_cg_en(int index);
check_lpg_index(index);
diff --git a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
index 33ba638..30f86b3 100644
--- a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
+++ b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -199,7 +199,9 @@
virtual task wait_alert_handshake_done();
cfg.clk_rst_vif.wait_clks(2);
- foreach (cfg.alert_host_cfg[i]) cfg.alert_host_cfg[i].vif.wait_ack_complete();
+ foreach (cfg.alert_host_cfg[i]) begin
+ if (!cfg.alert_host_cfg[i].en_alert_lpg) cfg.alert_host_cfg[i].vif.wait_ack_complete();
+ end
endtask
virtual function bit check_esc_done(bit[TL_DW-1:0] vals[$]);
@@ -254,6 +256,31 @@
join
endtask
+ function void enable_lpg_group(bit [NUM_ALERTS-1:0] alert_en_i);
+ foreach (alert_en_i[i]) begin
+ if (alert_en_i[i]) set_alert_lpg(i);
+ end
+ endfunction
+
+ // Enable alert's LPG based on alert_i input.
+ //
+ // Only enable this alert's LPG if the lgp input `lpg_cg_en` or `lpg_rst_en` if not Mubi4True.
+ // Because one LPG will turn off a set of alert sensers. So this task will also set all LPG's
+ // alert_host_cfgs' `en_alert_lpg` to 1.
+ virtual function void set_alert_lpg(int alert_i);
+ int lpg_i = alert_handler_reg_pkg::LpgMap[alert_i];
+ bit [1:0] set_lpg;
+
+ if (cfg.alert_handler_vif.get_lpg_status(lpg_i) == 0) begin
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(set_lpg, set_lpg > 0;);
+ if (set_lpg[0]) cfg.alert_handler_vif.set_lpg_cg_en(lpg_i);
+ if (set_lpg[1]) cfg.alert_handler_vif.set_lpg_rst_en(lpg_i);
+ foreach (alert_handler_reg_pkg::LpgMap[i]) begin
+ if (alert_handler_reg_pkg::LpgMap[i] == lpg_i) cfg.alert_host_cfg[i].en_alert_lpg = 1;
+ end
+ end
+ endfunction
+
virtual task alert_handler_crashdump_phases(bit [1:0] classa_phase = $urandom(),
bit [1:0] classb_phase = $urandom(),
bit [1:0] classc_phase = $urandom(),
diff --git a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
index 68b2b83..22a4944 100644
--- a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
+++ b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
@@ -22,10 +22,6 @@
esc_ping_timeout == 0;
}
- constraint alert_trigger_c {
- alert_trigger == 0;
- }
-
// disable interrupt timeout
constraint esc_intr_timeout_c {
foreach (intr_timeout_cyc[i]) {intr_timeout_cyc[i] == 0;}
@@ -37,19 +33,11 @@
verbosity = UVM_HIGH;
endfunction
- function void disable_lpg_group(bit [NUM_ALERTS-1:0] alert_en_i);
- foreach (alert_en_i[i]) begin
- int index = alert_handler_reg_pkg::LpgMap[i];
- if ($urandom_range(0, 1)) cfg.alert_handler_vif.set_lpg_cg_en(index);
- if ($urandom_range(0, 1)) cfg.alert_handler_vif.set_lpg_rst_en(index);
- end
- endfunction
-
task body();
fork
begin : isolation_fork
trigger_non_blocking_seqs();
- disable_lpg_group(alert_en);
+ enable_lpg_group(alert_en);
run_smoke_seq();
disable fork; // disable non-blocking seqs for stress_all tests
end // end fork
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
index c2ea2d9..112726a 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
@@ -17,6 +17,11 @@
lpg_rst_en = '{default: MuBi4False};
endfunction
+ function automatic bit get_lpg_status(int index);
+ check_lpg_index(index);
+ return (lpg_cg_en[index] == MuBi4True || lpg_rst_en[index] == MuBi4True);
+ endfunction
+
// TODO: randomize all values outside of the mubi4 enum.
function automatic void set_lpg_cg_en(int index);
check_lpg_index(index);
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
index 33ba638..30f86b3 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -199,7 +199,9 @@
virtual task wait_alert_handshake_done();
cfg.clk_rst_vif.wait_clks(2);
- foreach (cfg.alert_host_cfg[i]) cfg.alert_host_cfg[i].vif.wait_ack_complete();
+ foreach (cfg.alert_host_cfg[i]) begin
+ if (!cfg.alert_host_cfg[i].en_alert_lpg) cfg.alert_host_cfg[i].vif.wait_ack_complete();
+ end
endtask
virtual function bit check_esc_done(bit[TL_DW-1:0] vals[$]);
@@ -254,6 +256,31 @@
join
endtask
+ function void enable_lpg_group(bit [NUM_ALERTS-1:0] alert_en_i);
+ foreach (alert_en_i[i]) begin
+ if (alert_en_i[i]) set_alert_lpg(i);
+ end
+ endfunction
+
+ // Enable alert's LPG based on alert_i input.
+ //
+ // Only enable this alert's LPG if the lgp input `lpg_cg_en` or `lpg_rst_en` if not Mubi4True.
+ // Because one LPG will turn off a set of alert sensers. So this task will also set all LPG's
+ // alert_host_cfgs' `en_alert_lpg` to 1.
+ virtual function void set_alert_lpg(int alert_i);
+ int lpg_i = alert_handler_reg_pkg::LpgMap[alert_i];
+ bit [1:0] set_lpg;
+
+ if (cfg.alert_handler_vif.get_lpg_status(lpg_i) == 0) begin
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(set_lpg, set_lpg > 0;);
+ if (set_lpg[0]) cfg.alert_handler_vif.set_lpg_cg_en(lpg_i);
+ if (set_lpg[1]) cfg.alert_handler_vif.set_lpg_rst_en(lpg_i);
+ foreach (alert_handler_reg_pkg::LpgMap[i]) begin
+ if (alert_handler_reg_pkg::LpgMap[i] == lpg_i) cfg.alert_host_cfg[i].en_alert_lpg = 1;
+ end
+ end
+ endfunction
+
virtual task alert_handler_crashdump_phases(bit [1:0] classa_phase = $urandom(),
bit [1:0] classb_phase = $urandom(),
bit [1:0] classc_phase = $urandom(),
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
index 68b2b83..22a4944 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_lpg_vseq.sv
@@ -22,10 +22,6 @@
esc_ping_timeout == 0;
}
- constraint alert_trigger_c {
- alert_trigger == 0;
- }
-
// disable interrupt timeout
constraint esc_intr_timeout_c {
foreach (intr_timeout_cyc[i]) {intr_timeout_cyc[i] == 0;}
@@ -37,19 +33,11 @@
verbosity = UVM_HIGH;
endfunction
- function void disable_lpg_group(bit [NUM_ALERTS-1:0] alert_en_i);
- foreach (alert_en_i[i]) begin
- int index = alert_handler_reg_pkg::LpgMap[i];
- if ($urandom_range(0, 1)) cfg.alert_handler_vif.set_lpg_cg_en(index);
- if ($urandom_range(0, 1)) cfg.alert_handler_vif.set_lpg_rst_en(index);
- end
- endfunction
-
task body();
fork
begin : isolation_fork
trigger_non_blocking_seqs();
- disable_lpg_group(alert_en);
+ enable_lpg_group(alert_en);
run_smoke_seq();
disable fork; // disable non-blocking seqs for stress_all tests
end // end fork