[alert_esc_agent/dv] clean up alert_esc agent
As suggested by @rasmus on PR #2667, this PR cleans up alert_esc_agent
by:
1). Separate the wait_clk inside `check_esc_resp` task to make it more
readable.
2). Update `$cast` to `downcast` macro
3). Insert a new line before comments and new line before/after large
code block
Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/dv/sv/alert_esc_agent/alert_esc_base_driver.sv b/hw/dv/sv/alert_esc_agent/alert_esc_base_driver.sv
index 7dccb62..3b5d0a7 100644
--- a/hw/dv/sv/alert_esc_agent/alert_esc_base_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_esc_base_driver.sv
@@ -30,7 +30,7 @@
forever begin
alert_esc_seq_item req_clone;
seq_item_port.get(req);
- $cast(req_clone, req.clone());
+ `downcast(req_clone, req.clone());
req_clone.set_id_info(req);
// TODO: if any of the queue size is larger than 2, need additional support
if (req.r_alert_ping_send) r_alert_ping_send_q.push_back(req_clone);
diff --git a/hw/dv/sv/alert_esc_agent/alert_monitor.sv b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
index ebbcba8..4fce4ed 100644
--- a/hw/dv/sv/alert_esc_agent/alert_monitor.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_monitor.sv
@@ -39,6 +39,7 @@
under_ping_rsp = 1;
req = alert_esc_seq_item::type_id::create("req");
req.alert_esc_type = AlertEscPingTrans;
+
fork
begin : isolation_fork
fork
@@ -62,6 +63,7 @@
disable fork;
end : isolation_fork
join
+
`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);
@@ -80,10 +82,13 @@
req = alert_esc_seq_item::type_id::create("req");
req.alert_esc_type = AlertEscSigTrans;
req.alert_handshake_sta = AlertReceived;
+
// Write alert packet to scb when receiving alert signal
alert_esc_port.write(req);
+
// Duplicate req for writing alert packet at the end of alert handshake
`downcast(req, req.clone())
+
fork
begin : isolation_fork
fork
@@ -106,6 +111,7 @@
disable fork;
end : isolation_fork
join
+
`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);
@@ -156,4 +162,5 @@
ok_to_end = !cfg.vif.monitor_cb.alert_tx.alert_p && cfg.vif.monitor_cb.alert_tx.alert_n;
end
endtask
+
endclass : alert_monitor
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 19d6492..3c5ec92 100644
--- a/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_receiver_driver.sv
@@ -35,7 +35,7 @@
alert_esc_seq_item req, rsp;
wait(r_alert_ping_send_q.size() > 0 && !under_reset);
req = r_alert_ping_send_q.pop_front();
- $cast(rsp, req.clone());
+ `downcast(rsp, req.clone());
rsp.set_id_info(req);
`uvm_info(`gfn,
$sformatf("starting to send receiver item, ping_send=%0b, alert_rsp=%0b, int_fail=%0b",
@@ -61,7 +61,7 @@
alert_esc_seq_item req, rsp;
wait(r_alert_rsp_q.size() > 0 && !under_reset);
req = r_alert_rsp_q.pop_front();
- $cast(rsp, req.clone());
+ `downcast(rsp, req.clone());
rsp.set_id_info(req);
`uvm_info(`gfn,
$sformatf("starting to send receiver item, ping_send=%0b, alert_rsp=%0b, int_fail=%0b",
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 2bc4cd0..aa8514c 100644
--- a/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_sender_driver.sv
@@ -37,7 +37,7 @@
alert_esc_seq_item req, rsp;
wait(s_alert_send_q.size() > 0 && !under_reset);
req = s_alert_send_q.pop_front();
- $cast(rsp, req.clone());
+ `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",
@@ -65,7 +65,7 @@
alert_esc_seq_item req, rsp;
wait(s_alert_ping_rsp_q.size() > 0 && !under_reset);
req = s_alert_ping_rsp_q.pop_front();
- $cast(rsp, req.clone());
+ `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",
@@ -105,6 +105,7 @@
if (!req.int_err) begin
set_alert_pins(alert_delay);
reset_alert_pins(ack_delay);
+
// alert signals integrity fail
end else begin
if (req.alert_int_err_type & HasAlertBeforeIntFailOnly) set_alert_pins(alert_delay);
@@ -115,12 +116,15 @@
reset_alert();
end
end
+
endtask : drive_alert_pins
// this task set alert_p=1 and alert_n=0 after certain delay
virtual task set_alert_pins(int alert_delay);
- @(cfg.vif.sender_cb);
- repeat (alert_delay) @(cfg.vif.sender_cb);
+ repeat (alert_delay + 1) begin
+ if (under_reset) return;
+ else @(cfg.vif.sender_cb);
+ end
set_alert();
endtask : set_alert_pins
diff --git a/hw/dv/sv/alert_esc_agent/esc_monitor.sv b/hw/dv/sv/alert_esc_agent/esc_monitor.sv
index d7f6624..041a93f 100644
--- a/hw/dv/sv/alert_esc_agent/esc_monitor.sv
+++ b/hw/dv/sv/alert_esc_agent/esc_monitor.sv
@@ -31,23 +31,23 @@
virtual task esc_thread();
alert_esc_seq_item req, req_clone;
- logic esc_p = get_esc();
forever @(cfg.vif.monitor_cb) begin
- if (!under_reset && !esc_p && get_esc() === 1'b1) begin
+ if (!under_reset && get_esc() === 1'b1) begin
req = alert_esc_seq_item::type_id::create("req");
req.sig_cycle_cnt++;
if (is_sig_int_err()) req.esc_handshake_sta = EscIntFail;
else req.esc_handshake_sta = EscRespHi;
@(cfg.vif.monitor_cb);
+
// esc_p/n only goes high for a cycle, detect it is a ping signal
if (get_esc() === 1'b0) begin
int ping_cnter = 1;
under_esc_ping = 1;
req.alert_esc_type = AlertEscPingTrans;
- check_esc_resp(.req(req), .is_ping(1), .do_wait_clk(0));
+ check_esc_resp(.req(req), .is_ping(1));
do begin
@(cfg.vif.monitor_cb);
- check_esc_resp(.req(req), .is_ping(1), .do_wait_clk(0));
+ check_esc_resp(.req(req), .is_ping(1));
ping_cnter ++;
end
while (req.esc_handshake_sta != EscRespComplete && ping_cnter < cfg.ping_timeout_cycle &&
@@ -55,12 +55,12 @@
if (under_reset) continue;
if (ping_cnter >= cfg.ping_timeout_cycle) begin
alert_esc_seq_item req_clone;
- $cast(req_clone, req.clone());
+ `downcast(req_clone, req.clone());
req_clone.timeout = 1;
alert_esc_port.write(req_clone);
if (!cfg.probe_vif.get_esc_en()) begin
@(cfg.vif.monitor_cb);
- check_esc_resp(.req(req), .is_ping(1), .do_wait_clk(0));
+ check_esc_resp(.req(req), .is_ping(1));
end
end
if (cfg.probe_vif.get_esc_en()) begin
@@ -69,21 +69,34 @@
end
under_esc_ping = 0;
end
- // when it is not a ping
+
+ // when it is not a ping, there are two preconditions to reach this code:
+ // 1). standalone escalation signals
+ // 2). originally ping response, but interrupted by real escalation signals, then ping
+ // response is aborted, and immediately jumps to escalation responses
if (get_esc() === 1'b1) begin
req.alert_esc_type = AlertEscSigTrans;
- req.sig_cycle_cnt++;
- check_esc_resp(.req(req), .is_ping(0), .do_wait_clk(1));
- while (get_esc() === 1) check_esc_resp(.req(req), .is_ping(0), .do_wait_clk(1));
- check_esc_resp(.req(req), .is_ping(0), .do_wait_clk(0));
- $cast(req_clone, req.clone());
- req_clone.esc_handshake_sta = EscRespComplete;
- alert_esc_port.write(req_clone);
+ `downcast(req_clone, req.clone());
+
+ // check resp_p/n response until esc_p/n completes
+ // Sig_cycle_cnt records how many cycles esc_p stayed high, which is used for scb check
+ // Check_esc_resp() task checks the first cycle when esp_p reset, because esc_receiver
+ // will still drive resp_p/n at this clock cycle
+ while (req.esc_handshake_sta != EscRespComplete) begin
+ req.sig_cycle_cnt++;
+ check_esc_resp(.req(req_clone), .is_ping(0));
+ @(cfg.vif.monitor_cb);
+ if (get_esc() === 1'b0) begin
+ check_esc_resp(.req(req_clone), .is_ping(0));
+ req.esc_handshake_sta = EscRespComplete;
+ alert_esc_port.write(req);
+ end
+ end
end
+
`uvm_info("esc_monitor", $sformatf("[%s]: handshake status is %s, timeout=%0b",
req.alert_esc_type.name(), req.esc_handshake_sta.name(), req.timeout), UVM_HIGH)
end
- esc_p = get_esc();
end
endtask : esc_thread
@@ -116,13 +129,13 @@
// this task checks if resp_p/n is correct by:
// if it is not a ping_response, it should follow: low -> high .. until esc_p goes low.
// if it is a ping_response, it should follow: low -> high -> low -> high
- // if any time the pattern is missed, it is expect to go back to "low" state
- // if waited a clk and it is not a ping_response, sig_cyc_cnt is incremented
- virtual task check_esc_resp(alert_esc_seq_item req, bit is_ping, bit do_wait_clk);
+ // if any clock cycle resp_p/n does not match the expected pattern, reset back to "low" state
+ // if any clock cycle resp_p/n are not complement, reset back to "low" state
+ virtual task check_esc_resp(alert_esc_seq_item req, bit is_ping);
if (req.esc_handshake_sta inside {EscIntFail, EscReceived}) begin
if (cfg.vif.monitor_cb.esc_rx.resp_p !== 0) begin
alert_esc_seq_item req_clone;
- $cast(req_clone, req.clone());
+ `downcast(req_clone, req.clone());
req_clone.esc_handshake_sta = EscIntFail;
alert_esc_port.write(req_clone);
end
@@ -165,11 +178,6 @@
end
if (is_sig_int_err()) req.esc_handshake_sta = EscIntFail;
-
- if (do_wait_clk) begin
- @(cfg.vif.monitor_cb);
- if (get_esc() === 1 && !is_ping) req.sig_cycle_cnt++;
- end
endtask : check_esc_resp
virtual function bit get_esc();
diff --git a/hw/dv/sv/alert_esc_agent/esc_receiver_driver.sv b/hw/dv/sv/alert_esc_agent/esc_receiver_driver.sv
index da67b31..c0c8b6c 100644
--- a/hw/dv/sv/alert_esc_agent/esc_receiver_driver.sv
+++ b/hw/dv/sv/alert_esc_agent/esc_receiver_driver.sv
@@ -63,10 +63,9 @@
alert_esc_seq_item req, rsp;
wait(r_esc_rsp_q.size() > 0 && !under_reset);
req = r_esc_rsp_q.pop_front();
- $cast(rsp, req.clone());
+ `downcast(rsp, req.clone());
rsp.set_id_info(req);
- `uvm_info(`gfn,
- $sformatf("starting to send receiver item, esc_rsp=%0b int_fail=%0b",
+ `uvm_info(`gfn, $sformatf("starting to send receiver item, esc_rsp=%0b int_fail=%0b",
req.r_esc_rsp, req.int_err), UVM_HIGH)
fork
begin : non_blocking_fork
@@ -110,21 +109,27 @@
if (is_ping) begin
int toggle_cycle = 1;
if (req.int_err) toggle_cycle = $urandom_range(0, cfg.ping_timeout_cycle);
- repeat (toggle_cycle) toggle_resp_signal(req);
- is_ping = 0;
- end
+ repeat (toggle_cycle) toggle_resp_signal(req);
+ is_ping = 0;
+ end
if (req.int_err) reset_resp();
end
endtask
+ // If do not request int_err: Toggle resp_p/n for two cycles,
+ // first cycle drives resp_p = 1, resp_n = 0; second cycle drives resp_p = 0, resp_n = 1
+ // If request int_err: random drives resp_p/n for two cycles
task toggle_resp_signal(alert_esc_seq_item req);
- if (req.int_err) random_drive_resp_signal();
- else set_resp();
- @(cfg.vif.receiver_cb);
-
- if (req.int_err) random_drive_resp_signal();
- else reset_resp();
- @(cfg.vif.receiver_cb);
+ bit first_cycle_finished;
+ repeat(2) begin
+ if (req.int_err) random_drive_resp_signal();
+ else begin
+ if (!first_cycle_finished) set_resp();
+ else reset_resp();
+ end
+ @(cfg.vif.receiver_cb);
+ first_cycle_finished = 1;
+ end
endtask : toggle_resp_signal
task random_drive_resp_signal();