[sv/alert] add alert support in cip_base
In cip_base_scoreboard, add the following alert_esc_agent support:
1. Add tlm_analysis port to detect alert sent from DUT
2. Use process_alert_fifos task to filter out illegal alert_items (ping
responses and sig_int_err). If real alert happened, or real alert
handshake finished, both condition will call "process_alert_sig"
function.
In cip_base_vseq, add support:
1. add a knob to en_auto_alerts_response in cip_base_vseq - default on
2. add run_alert_response_nonblocking in dut_init
3. If user disabled the en_auto_alerts_response knob, the nonblocking
sequence will wait for current response to finish then exit
4. If user wants to re-enable the en_auto_alerts_response knob, they
have to also trigger dut_init() again
Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/dv/sv/cip_lib/cip_base_env.sv b/hw/dv/sv/cip_lib/cip_base_env.sv
index 035e374..059e972 100644
--- a/hw/dv/sv/cip_lib/cip_base_env.sv
+++ b/hw/dv/sv/cip_lib/cip_base_env.sv
@@ -42,6 +42,7 @@
// create components
m_tl_agent = tl_agent::type_id::create("m_tl_agent", this);
m_tl_reg_adapter = tl_reg_adapter#()::type_id::create("m_tl_reg_adapter");
+
// create alert agents and cfgs
foreach(cfg.list_of_alerts[i]) begin
string alert_name = cfg.list_of_alerts[i];
@@ -52,6 +53,7 @@
uvm_config_db#(alert_esc_agent_cfg)::set(this, agent_name, "cfg",
cfg.m_alert_agent_cfg[alert_name]);
end
+
uvm_config_db#(tl_agent_cfg)::set(this, "m_tl_agent*", "cfg", cfg.m_tl_agent_cfg);
endfunction
@@ -59,6 +61,12 @@
super.connect_phase(phase);
m_tl_agent.monitor.a_chan_port.connect(scoreboard.tl_a_chan_fifo.analysis_export);
m_tl_agent.monitor.d_chan_port.connect(scoreboard.tl_d_chan_fifo.analysis_export);
+ foreach (cfg.list_of_alerts[i]) begin
+ string alert_name = cfg.list_of_alerts[i];
+ m_alert_agent[alert_name].monitor.alert_esc_port.connect(
+ scoreboard.alert_fifos[alert_name].analysis_export);
+ end
+
if (cfg.is_active) begin
virtual_sequencer.tl_sequencer_h = m_tl_agent.sequencer;
end
diff --git a/hw/dv/sv/cip_lib/cip_base_scoreboard.sv b/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
index d4451b4..21f0b77 100644
--- a/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
+++ b/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
@@ -12,6 +12,9 @@
uvm_tlm_analysis_fifo #(tl_seq_item) tl_a_chan_fifo;
uvm_tlm_analysis_fifo #(tl_seq_item) tl_d_chan_fifo;
+ // Alert_fifo to notify scb if DUT sends an alert
+ uvm_tlm_analysis_fifo #(alert_esc_seq_item) alert_fifos[string];
+
mem_model#() exp_mem;
`uvm_component_new
@@ -20,6 +23,10 @@
super.build_phase(phase);
tl_a_chan_fifo = new("tl_a_chan_fifo", this);
tl_d_chan_fifo = new("tl_d_chan_fifo", this);
+ foreach(cfg.list_of_alerts[i]) begin
+ string alert_name = cfg.list_of_alerts[i];
+ alert_fifos[alert_name] = new($sformatf("alert_fifo[%s]", alert_name), this);
+ end
exp_mem = mem_model#()::type_id::create("exp_mem", this);
endfunction
@@ -28,6 +35,7 @@
fork
process_tl_a_chan_fifo();
process_tl_d_chan_fifo();
+ if (cfg.list_of_alerts.size()) process_alert_fifos();
join_none
endtask
@@ -64,6 +72,35 @@
end
endtask
+ virtual task process_alert_fifos();
+ foreach (alert_fifos[i]) begin
+ automatic string alert_name = i;
+ fork
+ forever begin
+ alert_esc_seq_item item;
+ alert_fifos[alert_name].get(item);
+ if (!cfg.en_scb) continue;
+ if (item.alert_esc_type == AlertEscSigTrans && !item.timeout &&
+ item.alert_handshake_sta inside {AlertReceived, AlertAckComplete}) begin
+ process_alert(alert_name, item);
+ // IP level alert protocol does not drive any sig_int_err or ping response
+ end else if (item.alert_esc_type == AlertEscIntFail) begin
+ `uvm_error(`gfn, $sformatf("alert %s has unexpected signal int error", alert_name))
+ end else if (item.timeout) begin
+ `uvm_error(`gfn, $sformatf("alert %s has unexpected timeout error", alert_name))
+ end else if (item.alert_esc_type == AlertEscPingTrans) begin
+ `uvm_error(`gfn, $sformatf("alert %s has unexpected alert ping response", alert_name))
+ end
+ end
+ join_none
+ end
+ endtask
+
+ virtual function void process_alert(string alert_name, alert_esc_seq_item item);
+ `uvm_info(`gfn, $sformatf("alert %0s detected, alert_status is %s", alert_name,
+ item.alert_handshake_sta), UVM_DEBUG)
+ endfunction
+
// task to process tl access
virtual task process_tl_access(tl_seq_item item, tl_channels_e channel = DataChannel);
`uvm_fatal(`gfn, "this method is not supposed to be called directly!")
diff --git a/hw/dv/sv/cip_lib/cip_base_vseq.sv b/hw/dv/sv/cip_lib/cip_base_vseq.sv
index 6b23b07..2435164 100644
--- a/hw/dv/sv/cip_lib/cip_base_vseq.sv
+++ b/hw/dv/sv/cip_lib/cip_base_vseq.sv
@@ -10,6 +10,10 @@
`uvm_object_new
// knobs to disable post_start clear interrupt routine
bit do_clear_all_interrupts = 1'b1;
+ // knobs to enable alert auto reponse, once disabled it won't be able to enable again unless
+ // dut_init is issued
+ bit en_auto_alerts_response = 1'b1;
+
// csr queue for intr test/enable/state
dv_base_reg intr_test_csrs[$];
dv_base_reg intr_state_csrs[$];
@@ -47,6 +51,11 @@
`include "cip_base_vseq__tl_errors.svh"
+ virtual task dut_init(string reset_kind = "HARD");
+ super.dut_init(reset_kind);
+ if (en_auto_alerts_response && cfg.list_of_alerts.size()) run_alert_rsp_seq_nonblocking();
+ endtask
+
task pre_start();
csr_utils_pkg::max_outstanding_accesses = 1 << TL_AIW;
super.pre_start();
@@ -556,13 +565,22 @@
virtual task run_alert_rsp_seq_nonblocking();
foreach (cfg.list_of_alerts[i]) begin
- automatic string seqr_name = cfg.list_of_alerts[i];
+ automatic string alert_name = cfg.list_of_alerts[i];
fork
- forever begin
- alert_receiver_alert_rsp_seq ack_seq =
- alert_receiver_alert_rsp_seq::type_id::create("ack_seq");
- `DV_CHECK_RANDOMIZE_FATAL(ack_seq);
- ack_seq.start(p_sequencer.alert_esc_sequencer_h[seqr_name]);
+ begin
+ fork
+ forever begin
+ alert_receiver_alert_rsp_seq ack_seq =
+ alert_receiver_alert_rsp_seq::type_id::create("ack_seq");
+ `DV_CHECK_RANDOMIZE_FATAL(ack_seq);
+ ack_seq.start(p_sequencer.alert_esc_sequencer_h[alert_name]);
+ end
+ begin
+ wait(!en_auto_alerts_response || cfg.under_reset);
+ cfg.m_alert_agent_cfg[alert_name].vif.wait_ack_complete();
+ end
+ join_any
+ disable fork;
end
join_none
end
diff --git a/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv b/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
index e47cf9c..b608497 100644
--- a/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
+++ b/hw/ip/hmac/dv/env/seq_lib/hmac_base_vseq.sv
@@ -33,17 +33,9 @@
virtual task dut_init(string reset_kind = "HARD");
super.dut_init(reset_kind);
- alert_send_ping();
if (do_hmac_init) hmac_init();
endtask
- virtual task alert_send_ping();
- alert_receiver_seq ping_seq;
- `uvm_create_on(ping_seq, p_sequencer.alert_esc_sequencer_h[cfg.list_of_alerts[0]]);
- `DV_CHECK_RANDOMIZE_FATAL(ping_seq)
- `uvm_send(ping_seq)
- endtask
-
virtual task dut_shutdown();
super.dut_shutdown();
// TODO: nothing extra to do yet