[dv/alert_handler] support escalator

Add support for the escalator pairs in alert_agent
Add a driver and monitor for escalator pairs
Add escalator signals into alert_if

Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/dv/sv/alert_agent/alert_agent.core b/hw/dv/sv/alert_agent/alert_agent.core
index 80db449..23af6fe 100644
--- a/hw/dv/sv/alert_agent/alert_agent.core
+++ b/hw/dv/sv/alert_agent/alert_agent.core
@@ -16,15 +16,21 @@
       - alert_agent_cfg.sv: {is_include_file: true}
       - alert_agent.sv: {is_include_file: true}
       - alert_agent_cov.sv: {is_include_file: true}
+      - alert_esc_base_driver.sv: {is_include_file: true}
       - alert_sender_driver.sv: {is_include_file: true}
       - alert_receiver_driver.sv: {is_include_file: true}
+      - alert_sender_driver.sv: {is_include_file: true}
+      - esc_receiver_driver.sv: {is_include_file: true}
+      - alert_esc_base_monitor.sv: {is_include_file: true}
       - alert_monitor.sv: {is_include_file: true}
+      - esc_monitor.sv: {is_include_file: true}
       - alert_seq_item.sv: {is_include_file: true}
       - alert_sequencer.sv: {is_include_file: true}
       - seq_lib/alert_receiver_alert_rsp_seq.sv: {is_include_file: true}
       - seq_lib/alert_receiver_seq.sv: {is_include_file: true}
       - seq_lib/alert_sender_ping_rsp_seq.sv: {is_include_file: true}
       - seq_lib/alert_sender_seq.sv: {is_include_file: true}
+      - seq_lib/esc_receiver_esc_rsp_seq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 targets:
diff --git a/hw/dv/sv/alert_agent/alert_agent.sv b/hw/dv/sv/alert_agent/alert_agent.sv
index e65db00..77989c2 100644
--- a/hw/dv/sv/alert_agent/alert_agent.sv
+++ b/hw/dv/sv/alert_agent/alert_agent.sv
@@ -7,11 +7,9 @@
 // ---------------------------------------------
 class alert_agent extends dv_base_agent#(
     .CFG_T           (alert_agent_cfg),
-    .DRIVER_T        (alert_base_driver),
-    .HOST_DRIVER_T   (alert_sender_driver),
-    .DEVICE_DRIVER_T (alert_receiver_driver),
+    .DRIVER_T        (alert_esc_base_driver),
     .SEQUENCER_T     (alert_sequencer),
-    .MONITOR_T       (alert_monitor),
+    .MONITOR_T       (alert_esc_base_monitor),
     .COV_T           (alert_agent_cov)
   );
 
@@ -20,6 +18,34 @@
   `uvm_component_new
 
   function void build_phase(uvm_phase phase);
+    alert_agent_cfg cfg;
+    if (!uvm_config_db#(CFG_T)::get(this, "", "cfg", cfg)) begin
+      `uvm_fatal(`gfn, $sformatf("failed to get %s from uvm_config_db", cfg.get_type_name()))
+    end
+    // override monitor
+    if (cfg.is_alert) begin
+      alert_esc_base_monitor::type_id::set_type_override(alert_monitor::get_type());
+    end else begin
+      alert_esc_base_monitor::type_id::set_type_override(esc_monitor::get_type());
+    end
+
+    // override driver
+    if (cfg.is_active) begin
+      if (cfg.is_alert) begin
+        if (cfg.if_mode == Host) begin
+          alert_esc_base_driver::type_id::set_type_override(alert_sender_driver::get_type());
+        end else begin
+          alert_esc_base_driver::type_id::set_type_override(alert_receiver_driver::get_type());
+        end
+      end else begin
+        if (cfg.if_mode == Host) begin
+          alert_esc_base_driver::type_id::set_type_override(esc_sender_driver::get_type());
+        end else begin
+          alert_esc_base_driver::type_id::set_type_override(esc_receiver_driver::get_type());
+        end
+      end
+    end
+
     super.build_phase(phase);
     // get alert_if handle
     if (!uvm_config_db#(virtual alert_if)::get(this, "", "vif", cfg.vif)) begin
diff --git a/hw/dv/sv/alert_agent/alert_agent_cfg.sv b/hw/dv/sv/alert_agent/alert_agent_cfg.sv
index 017067f..2bab10d 100644
--- a/hw/dv/sv/alert_agent/alert_agent_cfg.sv
+++ b/hw/dv/sv/alert_agent/alert_agent_cfg.sv
@@ -8,6 +8,8 @@
 // ---------------------------------------------
 class alert_agent_cfg extends dv_base_agent_cfg;
   virtual alert_if vif;
+
+  bit     is_alert = 1;
   // sender mode
   bit use_seq_item_alert_delay;
   int unsigned alert_delay_min = 0;
@@ -30,13 +32,13 @@
 
   `uvm_object_utils_begin(alert_agent_cfg)
     `uvm_field_int(alert_delay_min, UVM_DEFAULT)
-    `uvm_field_int(alert_delay_min, UVM_DEFAULT)
+    `uvm_field_int(alert_delay_max, UVM_DEFAULT)
     `uvm_field_int(ack_delay_min,   UVM_DEFAULT)
-    `uvm_field_int(ack_delay_min,   UVM_DEFAULT)
+    `uvm_field_int(ack_delay_max,   UVM_DEFAULT)
     `uvm_field_int(ack_stable_min,  UVM_DEFAULT)
-    `uvm_field_int(ack_stable_min,  UVM_DEFAULT)
+    `uvm_field_int(ack_stable_max,  UVM_DEFAULT)
     `uvm_field_int(ping_delay_min,  UVM_DEFAULT)
-    `uvm_field_int(ping_delay_min,  UVM_DEFAULT)
+    `uvm_field_int(ping_delay_max,  UVM_DEFAULT)
   `uvm_object_utils_end
   `uvm_object_new
 
diff --git a/hw/dv/sv/alert_agent/alert_agent_pkg.sv b/hw/dv/sv/alert_agent/alert_agent_pkg.sv
index 40768d6..6854799 100644
--- a/hw/dv/sv/alert_agent/alert_agent_pkg.sv
+++ b/hw/dv/sv/alert_agent/alert_agent_pkg.sv
@@ -11,22 +11,29 @@
 
   typedef class alert_seq_item;
   typedef class alert_agent_cfg;
-  // reuse dv_base_driver as is with the right parameter set
-  typedef dv_base_driver #(alert_seq_item, alert_agent_cfg) alert_base_driver;
 
   typedef enum {
-    PingTrans,
-    AlertTrans,
-    IntFail
-  } alert_type_e;
+    AlertEscPingTrans,
+    AlertEscSigTrans,
+    AlertEscIntFail
+  } alert_esc_trans_type_e;
 
   typedef enum {
     AlertReceived,
-    AckReceived,
+    AlertAckReceived,
     AlertComplete,
-    AckComplete
+    AlertAckComplete
   } alert_handshake_e;
 
+  typedef enum {
+    EscPingReceived,
+    EscReceived,
+    EscRespReceived,
+    EscComplete,
+    EscRespComplete,
+    EscIntFail
+  } esc_handshake_e;
+
   // macro includes
   `include "uvm_macros.svh"
   `include "dv_macros.svh"
@@ -35,13 +42,19 @@
   `include "alert_seq_item.sv"
   `include "alert_agent_cfg.sv"
   `include "alert_agent_cov.sv"
+  `include "alert_esc_base_driver.sv"
   `include "alert_sender_driver.sv"
   `include "alert_receiver_driver.sv"
+  `include "esc_sender_driver.sv"
+  `include "esc_receiver_driver.sv"
   `include "alert_sequencer.sv"
+  `include "alert_esc_base_monitor.sv"
   `include "alert_monitor.sv"
+  `include "esc_monitor.sv"
   `include "alert_agent.sv"
   `include "seq_lib/alert_receiver_alert_rsp_seq.sv"
   `include "seq_lib/alert_receiver_seq.sv"
   `include "seq_lib/alert_sender_ping_rsp_seq.sv"
   `include "seq_lib/alert_sender_seq.sv"
+  `include "seq_lib/esc_receiver_esc_rsp_seq.sv"
 endpackage
diff --git a/hw/dv/sv/alert_agent/alert_esc_base_driver.sv b/hw/dv/sv/alert_agent/alert_esc_base_driver.sv
new file mode 100644
index 0000000..a566234
--- /dev/null
+++ b/hw/dv/sv/alert_agent/alert_esc_base_driver.sv
@@ -0,0 +1,45 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// ---------------------------------------------
+// Alert_esc_base driver
+// ---------------------------------------------
+class alert_esc_base_driver extends dv_base_driver#(alert_seq_item, alert_agent_cfg);
+  alert_seq_item r_alert_ping_send_q[$], r_alert_rsp_q[$], r_esc_rsp_q[$],
+                 s_alert_send_q[$], s_alert_ping_rsp_q[$];
+
+  `uvm_component_utils(alert_esc_base_driver)
+
+  `uvm_component_new
+
+  // drive trans received from sequencer
+  virtual task get_and_drive();
+    fork
+      get_req();
+      drive_req();
+    join_none
+  endtask
+
+  virtual task drive_req();
+    `uvm_fatal(`gfn, "this is implemented as pure virtual task - please extend")
+  endtask
+
+  virtual task get_req();
+    forever begin
+      alert_seq_item req_clone;
+      seq_item_port.get(req);
+      $cast(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);
+      if (req.r_alert_rsp)       r_alert_rsp_q.push_back(req_clone);
+      if (req.r_esc_rsp)         r_esc_rsp_q.push_back(req_clone);
+      // sender mode
+      if (req.s_alert_send)      s_alert_send_q.push_back(req_clone);
+      if (req.s_alert_ping_rsp)  s_alert_ping_rsp_q.push_back(req_clone);
+    end
+  endtask : get_req
+
+endclass
diff --git a/hw/dv/sv/alert_agent/alert_esc_base_monitor.sv b/hw/dv/sv/alert_agent/alert_esc_base_monitor.sv
new file mode 100644
index 0000000..966cc58
--- /dev/null
+++ b/hw/dv/sv/alert_agent/alert_esc_base_monitor.sv
@@ -0,0 +1,29 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// ---------------------------------------------
+// Alert sender receiver interface base monitor
+// ---------------------------------------------
+
+class alert_esc_base_monitor extends dv_base_monitor#(
+    .ITEM_T (alert_seq_item),
+    .CFG_T  (alert_agent_cfg),
+    .COV_T  (alert_agent_cov)
+  );
+
+  `uvm_component_utils(alert_esc_base_monitor)
+  uvm_analysis_port #(alert_seq_item) alert_port;
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+    alert_port = new("alert_port", this);
+  endfunction : build_phase
+
+  virtual task run_phase(uvm_phase phase);
+    // TODO: implement the run phase
+  endtask : run_phase
+
+endclass
diff --git a/hw/dv/sv/alert_agent/alert_if.sv b/hw/dv/sv/alert_agent/alert_if.sv
index d1fb357..265eaed 100644
--- a/hw/dv/sv/alert_agent/alert_if.sv
+++ b/hw/dv/sv/alert_agent/alert_if.sv
@@ -8,25 +8,35 @@
 interface alert_if(input clk, input rst_n);
   wire prim_pkg::alert_tx_t alert_tx;
   wire prim_pkg::alert_rx_t alert_rx;
+  wire prim_pkg::esc_tx_t esc_tx;
+  wire prim_pkg::esc_rx_t esc_rx;
 
   clocking sender_cb @(posedge clk);
     input  rst_n;
     output alert_tx;
     input  alert_rx;
+    output esc_tx;
+    input  esc_rx;
   endclocking
 
   clocking receiver_cb @(posedge clk);
     input  rst_n;
     input  alert_tx;
     output alert_rx;
+    input  esc_tx;
+    output esc_rx;
   endclocking
 
   clocking monitor_cb @(posedge clk);
-    input  rst_n;
-    input  alert_tx;
-    input  alert_rx;
+    input rst_n;
+    input alert_tx;
+    input alert_rx;
+    input esc_tx;
+    input esc_rx;
   endclocking
 
+  // tasks for alert sender/receiver pairs
+
   task automatic wait_alert();
     while (alert_tx.alert_p !== 1'b1) @(monitor_cb);
   endtask : wait_alert
@@ -81,4 +91,45 @@
     receiver_cb.alert_rx.ping_n <= 1'b1;
   endtask
 
+  function automatic bit get_ack_p();
+    return monitor_cb.alert_rx.ack_p;
+  endfunction
+
+  function automatic bit get_alert_p();
+    return monitor_cb.alert_tx.alert_p;
+  endfunction
+
+  function automatic bit get_ping_p();
+    return monitor_cb.alert_rx.ping_p;
+  endfunction
+
+  // tasks for escalator sender/receiver pairs
+
+  task automatic wait_esc();
+    while (esc_tx.esc_p !== 1'b1) @(monitor_cb);
+  endtask : wait_esc
+
+  task automatic reset_esc();
+    sender_cb.esc_tx.esc_p <= 1'b0;
+    sender_cb.esc_tx.esc_n <= 1'b1;
+  endtask
+
+  task automatic set_resp();
+    receiver_cb.esc_rx.resp_p <= 1'b1;
+    receiver_cb.esc_rx.resp_n <= 1'b0;
+  endtask
+
+  task automatic reset_resp();
+    receiver_cb.esc_rx.resp_p <= 1'b0;
+    receiver_cb.esc_rx.resp_n <= 1'b1;
+  endtask
+
+  function automatic bit get_esc_p();
+    return monitor_cb.esc_tx.esc_p;
+  endfunction
+
+  function automatic bit get_resp_p();
+    return monitor_cb.esc_rx.resp_p;
+  endfunction
+
 endinterface: alert_if
diff --git a/hw/dv/sv/alert_agent/alert_monitor.sv b/hw/dv/sv/alert_agent/alert_monitor.sv
index e73b321..210c875 100644
--- a/hw/dv/sv/alert_agent/alert_monitor.sv
+++ b/hw/dv/sv/alert_agent/alert_monitor.sv
@@ -7,25 +7,14 @@
 // Alert sender receiver interface monitor
 // ---------------------------------------------
 
-class alert_monitor extends dv_base_monitor#(
-    .ITEM_T (alert_seq_item),
-    .CFG_T  (alert_agent_cfg),
-    .COV_T  (alert_agent_cov)
-  );
+class alert_monitor extends alert_esc_base_monitor;
 
   `uvm_component_utils(alert_monitor)
 
   bit under_ping_rsp;
 
-  uvm_analysis_port #(alert_seq_item) alert_port;
-
   `uvm_component_new
 
-  function void build_phase(uvm_phase phase);
-    super.build_phase(phase);
-    alert_port = new("alert_port", this);
-  endfunction : build_phase
-
   //TODO: currently only support sync mode
   //TODO: add support for signal int err and reset
   virtual task run_phase(uvm_phase phase);
@@ -48,11 +37,11 @@
     alert_seq_item req;
     bit            ping_p;
     forever @(cfg.vif.monitor_cb) begin
-      if (ping_p != cfg.vif.monitor_cb.alert_rx.ping_p) begin
+      if (ping_p != cfg.vif.get_ping_p()) begin
         phase.raise_objection(this);
         under_ping_rsp = 1;
         req = alert_seq_item::type_id::create("req");
-        req.alert_type = PingTrans;
+        req.alert_esc_type = AlertEscPingTrans;
         fork
           begin : isolation_fork
             fork
@@ -64,25 +53,25 @@
                 cfg.vif.wait_alert();
                 req.alert_handshake_sta = AlertReceived;
                 cfg.vif.wait_ack();
-                req.alert_handshake_sta = AckReceived;
+                req.alert_handshake_sta = AlertAckReceived;
                 cfg.vif.wait_alert_complete();
                 req.alert_handshake_sta = AlertComplete;
                 under_ping_rsp = 0;
                 // TODO: if now another alert triggered, will both sample the ack signal?
                 cfg.vif.wait_ack_complete();
-                req.alert_handshake_sta = AckComplete;
+                req.alert_handshake_sta = AlertAckComplete;
               end
             join_any
             disable fork;
           end : isolation_fork
         join
         `uvm_info("alert_monitor", $sformatf("[%s]: handshake status is %s",
-            req.alert_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
+            req.alert_esc_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
         alert_port.write(req);
         phase.drop_objection(this);
         under_ping_rsp = 0;
       end
-      ping_p = cfg.vif.monitor_cb.alert_rx.ping_p;
+      ping_p = cfg.vif.get_ping_p();
     end
   endtask : ping_thread
 
@@ -90,10 +79,10 @@
     alert_seq_item req;
     bit            alert_p;
     forever @(cfg.vif.monitor_cb) begin
-      if (!alert_p && cfg.vif.monitor_cb.alert_tx.alert_p === 1'b1 && !under_ping_rsp) begin
+      if (!alert_p && cfg.vif.get_alert_p() === 1'b1 && !under_ping_rsp) begin
         phase.raise_objection(this);
         req = alert_seq_item::type_id::create("req");
-        req.alert_type = AlertTrans;
+        req.alert_esc_type = AlertEscSigTrans;
         req.alert_handshake_sta = AlertReceived;
         // Write alert packet to scb when receiving alert signal
         alert_port.write(req);
@@ -108,22 +97,22 @@
               end
               begin : wait_alert_handshake
                 cfg.vif.wait_ack();
-                req.alert_handshake_sta = AckReceived;
+                req.alert_handshake_sta = AlertAckReceived;
                 cfg.vif.wait_alert_complete();
                 req.alert_handshake_sta = AlertComplete;
                 cfg.vif.wait_ack_complete();
-                req.alert_handshake_sta = AckComplete;
+                req.alert_handshake_sta = AlertAckComplete;
               end
             join_any
             disable fork;
           end : isolation_fork
         join
         `uvm_info("alert_monitor", $sformatf("[%s]: handshake status is %s",
-            req.alert_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
+            req.alert_esc_type.name(), req.alert_handshake_sta.name()), UVM_HIGH)
         alert_port.write(req);
         phase.drop_objection(this);
       end
-      alert_p = cfg.vif.monitor_cb.alert_tx.alert_p;
+      alert_p = cfg.vif.get_alert_p();
     end
   endtask : alert_thread
 
diff --git a/hw/dv/sv/alert_agent/alert_receiver_driver.sv b/hw/dv/sv/alert_agent/alert_receiver_driver.sv
index 48bd7fc..8468cbe 100644
--- a/hw/dv/sv/alert_agent/alert_receiver_driver.sv
+++ b/hw/dv/sv/alert_agent/alert_receiver_driver.sv
@@ -6,39 +6,23 @@
 // ---------------------------------------------
 // Alert_handler receiver driver
 // ---------------------------------------------
-class alert_receiver_driver extends alert_base_driver;
-
-  alert_seq_item ping_q[$];
-  alert_seq_item alert_q[$];
+class alert_receiver_driver extends alert_esc_base_driver;
 
   `uvm_component_utils(alert_receiver_driver)
 
   `uvm_component_new
 
-  virtual task reset_signals();
-    cfg.vif.reset_ping();
-    cfg.vif.reset_ack();
-  endtask
-
-  virtual task get_and_drive();
+  virtual task drive_req();
     fork
-      get_req();
       send_ping();
       rsp_alert();
     join_none
-  endtask : get_and_drive
+  endtask : drive_req
 
-  virtual task get_req();
-    forever begin
-      alert_seq_item req_clone;
-      seq_item_port.get(req);
-      $cast(req_clone, req.clone());
-      req_clone.set_id_info(req);
-      // TODO: if ping or alert queue size is larger than 2, need additional support
-      if (req.ping_send) ping_q.push_back(req_clone);
-      if (req.alert_rsp) alert_q.push_back(req_clone);
-    end
-  endtask : get_req
+  virtual task reset_signals();
+    cfg.vif.reset_ack();
+    cfg.vif.reset_ping();
+  endtask
 
   virtual task send_ping();
     forever begin
@@ -46,15 +30,15 @@
       alert_seq_item req, rsp;
       ping_delay = (cfg.use_seq_item_ping_delay) ? req.ping_delay :
           $urandom_range(cfg.ping_delay_max, cfg.ping_delay_min);
-      wait(ping_q.size() > 0);
-      req = ping_q.pop_front();
+      wait(r_alert_ping_send_q.size() > 0);
+      req = r_alert_ping_send_q.pop_front();
       $cast(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",
-          req.ping_send, req.alert_rsp, req.ping_int_err), UVM_HIGH)
+          req.r_alert_ping_send, req.r_alert_rsp, req.int_err), UVM_HIGH)
 
-      if (!req.ping_int_err) begin
+      if (!req.int_err) begin
         @(cfg.vif.receiver_cb);
         repeat (ping_delay) @(cfg.vif.receiver_cb);
         cfg.vif.set_ping();
@@ -75,7 +59,7 @@
 
       `uvm_info(`gfn,
           $sformatf("finished sending receiver item, ping_send=%0b, alert_rsp=%0b, int_fail=%0b",
-          req.ping_send, req.alert_rsp, req.ping_int_err), UVM_HIGH)
+          req.r_alert_ping_send, req.r_alert_rsp, req.int_err), UVM_HIGH)
       seq_item_port.put_response(rsp);
     end // end forever
   endtask : send_ping
@@ -83,20 +67,20 @@
   virtual task rsp_alert();
     forever begin
       alert_seq_item req, rsp;
-      wait(alert_q.size() > 0);
-      req = alert_q.pop_front();
+      wait(r_alert_rsp_q.size() > 0);
+      req = r_alert_rsp_q.pop_front();
       $cast(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",
-          req.ping_send, req.alert_rsp, req.ping_int_err), UVM_HIGH)
+          req.r_alert_ping_send, req.r_alert_rsp, req.int_err), UVM_HIGH)
 
       cfg.vif.wait_alert();
       set_ack_pins(req);
 
       `uvm_info(`gfn,
           $sformatf("finished sending receiver item, ping_send=%0b, alert_rsp=%0b, int_fail=%0b",
-          req.ping_send, req.alert_rsp, req.ping_int_err), UVM_HIGH)
+          req.r_alert_ping_send, req.r_alert_rsp, req.int_err), UVM_HIGH)
       seq_item_port.put_response(rsp);
     end // end forever
   endtask : rsp_alert
@@ -107,7 +91,7 @@
         $urandom_range(cfg.ack_delay_max, cfg.ack_delay_min);
     ack_stable = (cfg.use_seq_item_ack_stable) ? req.ack_stable :
         $urandom_range(cfg.ack_stable_max, cfg.ack_stable_min);
-    if (!req.ack_int_err) begin
+    if (!req.int_err) begin
       @(cfg.vif.receiver_cb);
       repeat (ack_delay) @(cfg.vif.receiver_cb);
       cfg.vif.set_ack();
diff --git a/hw/dv/sv/alert_agent/alert_sender_driver.sv b/hw/dv/sv/alert_agent/alert_sender_driver.sv
index 4000a78..4211aa8 100644
--- a/hw/dv/sv/alert_agent/alert_sender_driver.sv
+++ b/hw/dv/sv/alert_agent/alert_sender_driver.sv
@@ -6,9 +6,7 @@
 // ---------------------------------------------
 // Alert_handler sender driver
 // ---------------------------------------------
-class alert_sender_driver extends alert_base_driver;
-  alert_seq_item alert_q[$];
-  alert_seq_item ping_q[$];
+class alert_sender_driver extends alert_esc_base_driver;
 
   `uvm_component_utils(alert_sender_driver)
 
@@ -21,41 +19,29 @@
   // alert_sender drive responses by sending the alert_p and alert_n
   // one alert sent by sequence driving the alert_send signal
   // another alert sent by responding to the ping signal
-  virtual task get_and_drive();
+  virtual task drive_req();
     fork
-      get_req();
       send_alert();
       rsp_ping();
     join_none
-  endtask : get_and_drive
-
-  virtual task get_req();
-    forever begin
-      alert_seq_item req_clone;
-      seq_item_port.get(req);
-      $cast(req_clone, req.clone());
-      req_clone.set_id_info(req);
-      if (req.alert_send) alert_q.push_back(req_clone);
-      if (req.ping_rsp)   ping_q.push_back(req_clone);
-    end
-  endtask : get_req
+  endtask : drive_req
 
   virtual task send_alert();
     forever begin
       alert_seq_item req, rsp;
-      wait(alert_q.size() > 0);
-      req = alert_q.pop_front();
+      wait(s_alert_send_q.size() > 0);
+      req = s_alert_send_q.pop_front();
       $cast(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.alert_send, req.ping_rsp, req.alert_int_err), UVM_HIGH)
+          req.s_alert_send, req.s_alert_ping_rsp, req.int_err), UVM_HIGH)
 
       set_alert_pins(req);
 
       `uvm_info(`gfn,
           $sformatf("finished sending sender item, alert_send=%0b, ping_rsp=%0b, int_err=%0b",
-          req.alert_send, req.ping_rsp, req.alert_int_err), UVM_HIGH)
+          req.s_alert_send, req.s_alert_ping_rsp, req.int_err), UVM_HIGH)
       seq_item_port.put_response(rsp);
     end // end forever
   endtask : send_alert
@@ -63,20 +49,20 @@
   virtual task rsp_ping();
     forever begin
       alert_seq_item req, rsp;
-      wait(ping_q.size() > 0);
-      req = ping_q.pop_front();
+      wait(s_alert_ping_rsp_q.size() > 0);
+      req = s_alert_ping_rsp_q.pop_front();
       $cast(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.alert_send, req.ping_rsp, req.alert_int_err), UVM_HIGH)
+          req.s_alert_send, req.s_alert_ping_rsp, req.int_err), UVM_HIGH)
 
       cfg.vif.wait_ping();
       set_alert_pins(req);
 
       `uvm_info(`gfn,
           $sformatf("finished sending sender item, alert_send=%0b, ping_rsp=%0b, int_err=%0b",
-          req.alert_send, req.ping_rsp, req.alert_int_err), UVM_HIGH)
+          req.s_alert_send, req.s_alert_ping_rsp, req.int_err), UVM_HIGH)
       seq_item_port.put_response(rsp);
     end
   endtask : rsp_ping
@@ -88,7 +74,7 @@
     ack_delay = (cfg.use_seq_item_ack_delay) ? req.ack_delay :
         $urandom_range(cfg.ack_delay_max, cfg.ack_delay_min);
     repeat (alert_delay) @(cfg.vif.sender_cb);
-    if (!req.alert_int_err) begin
+    if (!req.int_err) begin
       @(cfg.vif.sender_cb);
       repeat (alert_delay) @(cfg.vif.sender_cb);
       cfg.vif.set_alert();
diff --git a/hw/dv/sv/alert_agent/alert_seq_item.sv b/hw/dv/sv/alert_agent/alert_seq_item.sv
index 5eae64f..c6948f6 100644
--- a/hw/dv/sv/alert_agent/alert_seq_item.sv
+++ b/hw/dv/sv/alert_agent/alert_seq_item.sv
@@ -8,18 +8,19 @@
 
 class alert_seq_item extends uvm_sequence_item;
 
-  rand bit alert_send;
-  rand bit alert_rsp; // receiver response to alert using ack
-  rand bit alert_int_err;
-  rand bit ping_rsp; // sender response to ping using alert
-  rand bit ack_int_err;
-  rand bit ping_send;
-  rand bit ping_int_err;
+  // prefix 's' for sender, 'r' for receiver
+  rand bit s_alert_send;
+  rand bit s_alert_ping_rsp; // sender response to ping using alert
+  rand bit r_alert_rsp;      // receiver response to alert using ack
+  rand bit r_alert_ping_send;
+  rand bit r_esc_rsp;
+  rand bit int_err;
   rand bit timeout;
 
-  // for alert_monitor
-  rand alert_type_e      alert_type;
-  rand alert_handshake_e alert_handshake_sta;
+  // for monitor only
+  rand alert_esc_trans_type_e alert_esc_type;
+  rand alert_handshake_e      alert_handshake_sta;
+  rand esc_handshake_e        esc_handshake_sta;
 
   // delays
   rand int unsigned ping_delay;
@@ -34,17 +35,29 @@
     soft ack_stable  dist {1 :/ 5, [2:10] :/ 5};
   }
 
+  // if agent is alert mode, cannot send any esc_rsp signal
+  // if agent is esc mode, cannot send any alert related signals
+  constraint alert_esc_mode_c {
+    r_esc_rsp == 1 -> (!s_alert_send && !r_alert_rsp && !r_alert_ping_send && !s_alert_ping_rsp);
+    (s_alert_send || r_alert_rsp || r_alert_ping_send || s_alert_ping_rsp) -> !r_esc_rsp;
+  }
+
+  // temp constraint
+  constraint disable_int_err_c {
+    int_err == 0;
+  }
+
   `uvm_object_utils_begin(alert_seq_item)
-    `uvm_field_int (alert_send,    UVM_DEFAULT)
-    `uvm_field_int (alert_int_err, UVM_DEFAULT)
-    `uvm_field_int (alert_rsp,     UVM_DEFAULT)
-    `uvm_field_int (ping_rsp,      UVM_DEFAULT)
-    `uvm_field_int (ack_int_err,   UVM_DEFAULT)
-    `uvm_field_int (ping_send,     UVM_DEFAULT)
-    `uvm_field_int (ping_int_err,  UVM_DEFAULT)
-    `uvm_field_int (timeout,       UVM_DEFAULT)
-    `uvm_field_enum(alert_type_e, alert_type, UVM_DEFAULT)
-    `uvm_field_enum(alert_handshake_e, alert_handshake_sta, UVM_DEFAULT)
+    `uvm_field_int (s_alert_send,      UVM_DEFAULT)
+    `uvm_field_int (s_alert_ping_rsp,  UVM_DEFAULT)
+    `uvm_field_int (r_alert_rsp,       UVM_DEFAULT)
+    `uvm_field_int (r_alert_ping_send, UVM_DEFAULT)
+    `uvm_field_int (r_esc_rsp,         UVM_DEFAULT)
+    `uvm_field_int (int_err,           UVM_DEFAULT)
+    `uvm_field_int (timeout,           UVM_DEFAULT)
+    `uvm_field_enum(alert_esc_trans_type_e, alert_esc_type,      UVM_DEFAULT)
+    `uvm_field_enum(alert_handshake_e,      alert_handshake_sta, UVM_DEFAULT)
+    `uvm_field_enum(esc_handshake_e,        esc_handshake_sta,   UVM_DEFAULT)
   `uvm_object_utils_end
 
   function new (string name = "");
diff --git a/hw/dv/sv/alert_agent/esc_monitor.sv b/hw/dv/sv/alert_agent/esc_monitor.sv
new file mode 100644
index 0000000..582ee26
--- /dev/null
+++ b/hw/dv/sv/alert_agent/esc_monitor.sv
@@ -0,0 +1,78 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// ---------------------------------------------
+// Escalator sender receiver interface monitor
+// ---------------------------------------------
+
+class esc_monitor extends alert_esc_base_monitor;
+
+  `uvm_component_utils(esc_monitor)
+
+  `uvm_component_new
+
+  //TODO: currently only support sync mode
+  //TODO: add support for signal int err and reset
+  virtual task run_phase(uvm_phase phase);
+    fork
+      esc_thread(phase);
+      reset_thread(phase);
+    join_none
+  endtask : run_phase
+
+  // TODO: placeholder to support reset
+  virtual task reset_thread(uvm_phase phase);
+    forever begin
+      @(negedge cfg.vif.rst_n);
+      @(posedge cfg.vif.rst_n);
+    end
+  endtask : reset_thread
+
+  virtual task esc_thread(uvm_phase phase);
+    alert_seq_item req;
+    bit            esc_p;
+    forever @(cfg.vif.monitor_cb) begin
+      if (!esc_p && cfg.vif.get_esc_p() === 1'b1) begin
+        phase.raise_objection(this);
+        req = alert_seq_item::type_id::create("req");
+        req.alert_esc_type = AlertEscSigTrans;
+
+        fork
+          begin : isolation_fork
+            fork
+              begin : esc_timeout
+                repeat (cfg.ping_timeout_cycle) @(cfg.vif.monitor_cb);
+              end
+              begin : wait_esc_handshake
+                @(cfg.vif.monitor_cb);
+                check_esc_resp_toggle(req);
+                while (cfg.vif.get_esc_p() === 1) begin
+                  check_esc_resp_toggle(req);
+                end
+                if (req.esc_handshake_sta != EscIntFail) begin
+                  req.esc_handshake_sta = EscRespComplete;
+                end
+              end
+            join_any
+            disable fork;
+          end : isolation_fork
+        join
+        `uvm_info("esc_monitor", $sformatf("[%s]: handshake status is %s",
+            req.alert_esc_type.name(), req.esc_handshake_sta.name()), UVM_HIGH)
+        alert_port.write(req);
+        phase.drop_objection(this);
+      end
+      esc_p = cfg.vif.get_esc_p();
+    end
+  endtask : esc_thread
+
+  virtual task check_esc_resp_toggle(alert_seq_item req);
+    if (cfg.vif.get_resp_p() != 1) req.esc_handshake_sta = EscIntFail;
+    @(cfg.vif.monitor_cb);
+    if (cfg.vif.get_resp_p() != 0) req.esc_handshake_sta = EscIntFail;
+    @(cfg.vif.monitor_cb);
+  endtask : check_esc_resp_toggle
+
+endclass : esc_monitor
diff --git a/hw/dv/sv/alert_agent/esc_receiver_driver.sv b/hw/dv/sv/alert_agent/esc_receiver_driver.sv
new file mode 100644
index 0000000..cc763d5
--- /dev/null
+++ b/hw/dv/sv/alert_agent/esc_receiver_driver.sv
@@ -0,0 +1,51 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// ---------------------------------------------
+// Alert_handler receiver driver
+// ---------------------------------------------
+class esc_receiver_driver extends alert_esc_base_driver;
+
+  `uvm_component_utils(esc_receiver_driver)
+
+  `uvm_component_new
+
+  virtual task reset_signals();
+    cfg.vif.reset_resp();
+  endtask
+
+  virtual task drive_req();
+    fork
+      rsp_escalator();
+    join_none
+  endtask : drive_req
+
+  virtual task rsp_escalator();
+    forever begin
+      alert_seq_item req, rsp;
+      wait(r_esc_rsp_q.size() > 0);
+      req = r_esc_rsp_q.pop_front();
+      $cast(rsp, req.clone());
+      rsp.set_id_info(req);
+      `uvm_info(`gfn,
+          $sformatf("starting to send receiver item, esc_rsp=%0b, int_fail=%0b",
+          req.r_esc_rsp, req.int_err), UVM_HIGH)
+
+      cfg.vif.wait_esc();
+      @(cfg.vif.receiver_cb);
+      while (cfg.vif.receiver_cb.esc_tx.esc_p === 1'b1) begin
+        cfg.vif.set_resp();
+        @(cfg.vif.receiver_cb);
+        cfg.vif.reset_resp();
+        @(cfg.vif.receiver_cb);
+      end
+
+      `uvm_info(`gfn,
+          $sformatf("finished sending receiver item, esc_rsp=%0b, int_fail=%0b",
+          req.r_esc_rsp, req.int_err), UVM_HIGH)
+      seq_item_port.put_response(rsp);
+    end
+  endtask : rsp_escalator
+endclass : esc_receiver_driver
diff --git a/hw/dv/sv/alert_agent/esc_sender_driver.sv b/hw/dv/sv/alert_agent/esc_sender_driver.sv
new file mode 100644
index 0000000..273b6b7
--- /dev/null
+++ b/hw/dv/sv/alert_agent/esc_sender_driver.sv
@@ -0,0 +1,20 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// ---------------------------------------------
+// Esc sender driver
+// ---------------------------------------------
+class esc_sender_driver extends alert_esc_base_driver;
+
+  `uvm_component_utils(esc_sender_driver)
+
+  `uvm_component_new
+
+  virtual task get_and_drive();
+    // TODO
+  endtask : get_and_drive
+
+endclass : esc_sender_driver
+
diff --git a/hw/dv/sv/alert_agent/seq_lib/alert_receiver_alert_rsp_seq.sv b/hw/dv/sv/alert_agent/seq_lib/alert_receiver_alert_rsp_seq.sv
index b5180dc..d977dc0 100644
--- a/hw/dv/sv/alert_agent/seq_lib/alert_receiver_alert_rsp_seq.sv
+++ b/hw/dv/sv/alert_agent/seq_lib/alert_receiver_alert_rsp_seq.sv
@@ -12,22 +12,15 @@
   `uvm_object_utils(alert_receiver_alert_rsp_seq)
   `uvm_object_new
 
-  rand bit  ack_int_err;
-
-  constraint no_int_err_c {
-    ack_int_err == 0;
-  }
-
   virtual task body();
     `uvm_info(`gfn, $sformatf("starting alert receiver transfer"), UVM_HIGH)
     req = REQ::type_id::create("req");
     start_item(req);
     `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
-        ping_send    == 0;
-        ping_int_err == 0;
-        alert_rsp    == 1;
-        ack_int_err  == local::ack_int_err;
+        r_alert_ping_send == 0;
+        r_alert_rsp       == 1;
     )
+    `uvm_info(`gfn, $sformatf("seq_item: alert_rsp, int_err=%0b", req.int_err), UVM_LOW)
     finish_item(req);
     get_response(rsp);
     `uvm_info(`gfn, "alert receiver transfer done", UVM_HIGH)
diff --git a/hw/dv/sv/alert_agent/seq_lib/alert_receiver_seq.sv b/hw/dv/sv/alert_agent/seq_lib/alert_receiver_seq.sv
index f60e0cc..50d9349 100644
--- a/hw/dv/sv/alert_agent/seq_lib/alert_receiver_seq.sv
+++ b/hw/dv/sv/alert_agent/seq_lib/alert_receiver_seq.sv
@@ -11,11 +11,6 @@
 
   `uvm_object_utils(alert_receiver_seq)
 
-  rand bit  ping_int_err;
-
-  constraint no_int_err_c {
-    ping_int_err == 0;
-  }
   `uvm_object_new
 
   task body();
@@ -23,12 +18,10 @@
     req = REQ::type_id::create("req");
     start_item(req);
     `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
-        ping_send    == 1;
-        ping_int_err == local::ping_int_err;
-        alert_rsp    == 0;
-        ack_int_err  == 0;
+        r_alert_ping_send == 1;
+        r_alert_rsp       == 0;
     )
-    `uvm_info(`gfn, $sformatf("seq_item: ping_send, ping_int_err=%0b", ping_int_err), UVM_LOW)
+    `uvm_info(`gfn, $sformatf("seq_item: ping_send, int_err=%0b", req.int_err), UVM_LOW)
     finish_item(req);
     get_response(rsp);
     `uvm_info(`gfn, "alert receiver transfer done", UVM_HIGH)
diff --git a/hw/dv/sv/alert_agent/seq_lib/alert_sender_ping_rsp_seq.sv b/hw/dv/sv/alert_agent/seq_lib/alert_sender_ping_rsp_seq.sv
index 8bbd3a7..a7e4a28 100644
--- a/hw/dv/sv/alert_agent/seq_lib/alert_sender_ping_rsp_seq.sv
+++ b/hw/dv/sv/alert_agent/seq_lib/alert_sender_ping_rsp_seq.sv
@@ -12,21 +12,15 @@
   `uvm_object_utils(alert_sender_ping_rsp_seq)
   `uvm_object_new
 
-  rand bit  alert_int_err;
-
-  constraint no_int_err_c {
-    alert_int_err == 0;
-  }
-
   virtual task body();
     `uvm_info(`gfn, $sformatf("starting alert receiver transfer"), UVM_HIGH)
     req = REQ::type_id::create("req");
     start_item(req);
     `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
-        alert_send    == 0;
-        ping_rsp      == 1;
-        alert_int_err == local::alert_int_err;
+        s_alert_send     == 0;
+        s_alert_ping_rsp == 1;
     )
+    `uvm_info(`gfn, $sformatf("seq_item: ping_rsp, int_err=%0b", req.int_err), UVM_LOW)
     finish_item(req);
     get_response(rsp);
     `uvm_info(`gfn, "alert receiver transfer done", UVM_HIGH)
diff --git a/hw/dv/sv/alert_agent/seq_lib/alert_sender_seq.sv b/hw/dv/sv/alert_agent/seq_lib/alert_sender_seq.sv
index fef108f..f5cde69 100644
--- a/hw/dv/sv/alert_agent/seq_lib/alert_sender_seq.sv
+++ b/hw/dv/sv/alert_agent/seq_lib/alert_sender_seq.sv
@@ -10,12 +10,6 @@
   );
 
   `uvm_object_utils(alert_sender_seq)
-
-  rand bit  alert_int_err;
-
-  constraint no_int_err_c {
-    alert_int_err == 0;
-  }
   `uvm_object_new
 
   task body();
@@ -23,11 +17,10 @@
     req = REQ::type_id::create("req");
     start_item(req);
     `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
-        alert_send    == 1;
-        alert_int_err == local::alert_int_err;
-        ping_rsp      == 0;
+        s_alert_send     == 1;
+        s_alert_ping_rsp == 0;
     )
-    `uvm_info(`gfn, $sformatf("seq_item, alert_send=%0b", req.alert_send), UVM_LOW)
+    `uvm_info(`gfn, $sformatf("seq_item: alert_send, int_err=%0b", req.int_err), UVM_LOW)
     finish_item(req);
     get_response(rsp);
     `uvm_info(`gfn, "alert sender transfer done", UVM_HIGH)
diff --git a/hw/dv/sv/alert_agent/seq_lib/esc_receiver_esc_rsp_seq.sv b/hw/dv/sv/alert_agent/seq_lib/esc_receiver_esc_rsp_seq.sv
new file mode 100644
index 0000000..2d49a19
--- /dev/null
+++ b/hw/dv/sv/alert_agent/seq_lib/esc_receiver_esc_rsp_seq.sv
@@ -0,0 +1,28 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// this sequence responses to escalation pins by sending the resp pins
+class esc_receiver_esc_rsp_seq extends dv_base_seq #(
+    .REQ         (alert_seq_item),
+    .CFG_T       (alert_agent_cfg),
+    .SEQUENCER_T (alert_sequencer)
+  );
+
+  `uvm_object_utils(esc_receiver_esc_rsp_seq)
+  `uvm_object_new
+
+  virtual task body();
+    `uvm_info(`gfn, $sformatf("starting escalator receiver transfer"), UVM_HIGH)
+    req = REQ::type_id::create("req");
+    start_item(req);
+    `DV_CHECK_RANDOMIZE_WITH_FATAL(req,
+        r_esc_rsp == 1;
+    )
+    `uvm_info(`gfn, $sformatf("seq_item: esc_rsp, int_err=%0b", req.int_err), UVM_LOW)
+    finish_item(req);
+    get_response(rsp);
+    `uvm_info(`gfn, "escalator receiver transfer done", UVM_HIGH)
+  endtask : body
+
+endclass : esc_receiver_esc_rsp_seq
diff --git a/hw/dv/sv/cip_lib/cip_base_vseq.sv b/hw/dv/sv/cip_lib/cip_base_vseq.sv
index d39ff13..0cf0c67 100644
--- a/hw/dv/sv/cip_lib/cip_base_vseq.sv
+++ b/hw/dv/sv/cip_lib/cip_base_vseq.sv
@@ -458,18 +458,4 @@
       join_none
     end
   endtask
-
-  virtual task run_ping_rsp_seq_nonblocking();
-    foreach(cfg.list_of_alerts[i]) begin
-      automatic string seqr_name = cfg.list_of_alerts[i];
-      fork
-        forever begin
-          alert_sender_ping_rsp_seq ping_seq =
-              alert_sender_ping_rsp_seq::type_id::create("ping_seq");
-          `DV_CHECK_RANDOMIZE_FATAL(ping_seq);
-          ping_seq.start(p_sequencer.alert_sequencer_h[seqr_name]);
-        end
-      join_none
-    end
-  endtask
 endclass
diff --git a/hw/formal/fpv.tcl b/hw/formal/fpv.tcl
index b1d08a4..ff5a4d5 100644
--- a/hw/formal/fpv.tcl
+++ b/hw/formal/fpv.tcl
@@ -10,8 +10,7 @@
 # Disabling the warning
 # "parameter declared inside package XXX shall be treated as localparam".
 set_message -disable VERI-2418
-check_cov -init -model {branch statement functional} \
--enable_prove_based_proof_core
+
 
 #-------------------------------------------------------------------------
 # read design
@@ -161,12 +160,10 @@
 #-------------------------------------------------------------------------
 # time limit set to 2 hours
 get_reset_info -x_value -with_reset_pin
-prove -all -time_limit 120m
+prove -all -time_limit 24h
 report
 #-------------------------------------------------------------------------
 # check coverage and report
 #-------------------------------------------------------------------------
-check_cov -measure
-check_cov -report -type all -no_return -report_file cover.html \
-    -html -force -exclude { reset waived }
+
 
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.sv b/hw/ip/alert_handler/dv/env/alert_handler_env.sv
index 7ffc506..6e327e8 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_env.sv
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env.sv
@@ -13,10 +13,11 @@
   `uvm_component_new
 
   alert_agent alert_host_agent[];
+  alert_agent esc_device_agent[];
 
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
-
+    // build alert agents
     alert_host_agent                    = new[alert_pkg::NAlerts];
     virtual_sequencer.alert_host_seqr_h = new[alert_pkg::NAlerts];
     foreach (alert_host_agent[i]) begin
@@ -25,7 +26,15 @@
       uvm_config_db#(alert_agent_cfg)::set(this,
           $sformatf("alert_host_agent[%0d]", i), "cfg", cfg.alert_host_cfg[i]);
     end
-
+    // build escalator agents
+    esc_device_agent                    = new[alert_pkg::N_ESC_SEV];
+    virtual_sequencer.esc_device_seqr_h = new[alert_pkg::N_ESC_SEV];
+    foreach (esc_device_agent[i]) begin
+      esc_device_agent[i] = alert_agent::type_id::create(
+          $sformatf("esc_device_agent[%0d]", i), this);
+      uvm_config_db#(alert_agent_cfg)::set(this,
+          $sformatf("esc_device_agent[%0d]", i), "cfg", cfg.esc_device_cfg[i]);
+    end
     // get vifs
     if (!uvm_config_db#(esc_en_vif)::get(this, "", "esc_en_vif", cfg.esc_en_vif)) begin
       `uvm_fatal(get_full_name(), "failed to get esc_en_vif from uvm_config_db")
@@ -41,6 +50,9 @@
       foreach (alert_host_agent[i]) begin
         alert_host_agent[i].monitor.alert_port.connect(scoreboard.alert_fifo[i].analysis_export);
       end
+      foreach (esc_device_agent[i]) begin
+        esc_device_agent[i].monitor.alert_port.connect(scoreboard.esc_fifo[i].analysis_export);
+      end
     end
     if (cfg.is_active) begin
       foreach (alert_host_agent[i]) begin
@@ -49,6 +61,11 @@
         end
       end
     end
+    foreach (esc_device_agent[i]) begin
+      if (cfg.esc_device_cfg[i].is_active) begin
+        virtual_sequencer.esc_device_seqr_h[i] = esc_device_agent[i].sequencer;
+      end
+    end
   endfunction
 
 endclass
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv b/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv
index 6670eaf..213a82a 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv
@@ -8,9 +8,11 @@
   esc_en_vif           esc_en_vif;
   entropy_vif          entropy_vif;
   rand alert_agent_cfg alert_host_cfg[];
+  rand alert_agent_cfg esc_device_cfg[];
 
   `uvm_object_utils_begin(alert_handler_env_cfg)
     `uvm_field_array_object(alert_host_cfg, UVM_DEFAULT)
+    `uvm_field_array_object(esc_device_cfg, UVM_DEFAULT)
   `uvm_object_utils_end
 
   `uvm_object_new
@@ -31,10 +33,16 @@
     end
 
     alert_host_cfg = new[alert_pkg::NAlerts];
+    esc_device_cfg = new[alert_pkg::N_ESC_SEV];
     foreach (alert_host_cfg[i]) begin
       alert_host_cfg[i] = alert_agent_cfg::type_id::create($sformatf("alert_host_cfg[%0d]", i));
       alert_host_cfg[i].if_mode = dv_utils_pkg::Host;
     end
+    foreach (esc_device_cfg[i]) begin
+      esc_device_cfg[i] = alert_agent_cfg::type_id::create($sformatf("esc_device_cfg[%0d]", i));
+      esc_device_cfg[i].if_mode  = dv_utils_pkg::Device;
+      esc_device_cfg[i].is_alert = 0;
+    end
   endfunction
 
 endclass
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv b/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
index 3b2aad2..2a21e26 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
+++ b/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
@@ -50,7 +50,7 @@
         forever begin
           alert_fifo[index].get(act_item);
           // once the alert is received
-          if (act_item.alert_type == AlertTrans && !act_item.timeout &&
+          if (act_item.alert_esc_type == AlertEscSigTrans && !act_item.timeout &&
               act_item.alert_handshake_sta == AlertReceived) begin
             uvm_reg_field alert_cause_field, intr_state_field;
             bit [TL_DW-1:0] intr_class;
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv b/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv
index d5aee2b..7402f84 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv
+++ b/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv
@@ -7,6 +7,7 @@
     .COV_T(alert_handler_env_cov)
   );
   alert_sequencer alert_host_seqr_h[];
+  alert_sequencer esc_device_seqr_h[];
 
   `uvm_component_utils(alert_handler_virtual_sequencer)
 
diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
index da2f9c9..fcbd854 100644
--- a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -57,4 +57,32 @@
     csr_rd(.ptr(ral.alert_cause), .value(alert_cause));
   endtask
 
+  virtual task run_esc_rsp_seq_nonblocking();
+    foreach(cfg.esc_device_cfg[i]) begin
+      automatic int index = i;
+      fork
+        forever begin
+          esc_receiver_esc_rsp_seq esc_seq =
+              esc_receiver_esc_rsp_seq::type_id::create("esc_seq");
+          `DV_CHECK_RANDOMIZE_FATAL(esc_seq);
+          esc_seq.start(p_sequencer.esc_device_seqr_h[index]);
+        end
+      join_none
+    end
+  endtask
+
+  virtual task run_ping_rsp_seq_nonblocking();
+    foreach(cfg.alert_host_cfg[i]) begin
+      automatic int index = i;
+      fork
+        forever begin
+          alert_sender_ping_rsp_seq ping_seq =
+              alert_sender_ping_rsp_seq::type_id::create("ping_seq");
+          `DV_CHECK_RANDOMIZE_FATAL(ping_seq);
+          ping_seq.start(p_sequencer.alert_host_seqr_h[i]);
+        end
+      join_none
+    end
+  endtask
+
 endclass : alert_handler_base_vseq
diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sanity_vseq.sv b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sanity_vseq.sv
index 57f5ad9..c4b1409 100644
--- a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sanity_vseq.sv
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sanity_vseq.sv
@@ -16,6 +16,7 @@
   }
 
   task body();
+    run_esc_rsp_seq_nonblocking();
     for (int i = 1; i <= num_trans; i++) begin
       `DV_CHECK_RANDOMIZE_FATAL(this)
       `DV_CHECK_RANDOMIZE_WITH_FATAL(ral.classa_ctrl,
diff --git a/hw/ip/alert_handler/dv/tb/tb.sv b/hw/ip/alert_handler/dv/tb/tb.sv
index 398df83..fd0134d 100644
--- a/hw/ip/alert_handler/dv/tb/tb.sv
+++ b/hw/ip/alert_handler/dv/tb/tb.sv
@@ -15,7 +15,7 @@
 
   wire clk, rst_n;
   wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
-  wire [NUM_MAX_ESC_SEV-1:0] esc_en;
+  wire [NUM_MAX_ESC_SEV-1:0]    esc_en;
   wire entropy;
 
   // interfaces
@@ -33,21 +33,31 @@
   prim_pkg::esc_rx_t [alert_pkg::N_ESC_SEV-1:0] esc_rx;
   prim_pkg::esc_tx_t [alert_pkg::N_ESC_SEV-1:0] esc_tx;
 
-  alert_if alert_hosts_if[alert_pkg::NAlerts](.clk(clk), .rst_n(rst_n));
-
+  alert_if alert_host_if[alert_pkg::NAlerts](.clk(clk), .rst_n(rst_n));
   for (genvar k = 0; k < alert_pkg::NAlerts; k++) begin : gen_alert_if
-    assign alert_tx[k].alert_p = alert_hosts_if[k].alert_tx.alert_p;
-    assign alert_tx[k].alert_n = alert_hosts_if[k].alert_tx.alert_n;
-    assign alert_hosts_if[k].alert_rx.ack_p  = alert_rx[k].ack_p;
-    assign alert_hosts_if[k].alert_rx.ack_n  = alert_rx[k].ack_n;
-    assign alert_hosts_if[k].alert_rx.ping_p = alert_rx[k].ping_p;
-    assign alert_hosts_if[k].alert_rx.ping_n = alert_rx[k].ping_n;
+    assign alert_tx[k].alert_p = alert_host_if[k].alert_tx.alert_p;
+    assign alert_tx[k].alert_n = alert_host_if[k].alert_tx.alert_n;
+    assign alert_host_if[k].alert_rx.ack_p  = alert_rx[k].ack_p;
+    assign alert_host_if[k].alert_rx.ack_n  = alert_rx[k].ack_n;
+    assign alert_host_if[k].alert_rx.ping_p = alert_rx[k].ping_p;
+    assign alert_host_if[k].alert_rx.ping_n = alert_rx[k].ping_n;
     initial begin
       uvm_config_db#(virtual alert_if)::set(null, $sformatf("*.env.alert_host_agent[%0d]", k),
-                                            "vif", alert_hosts_if[k]);
+                                            "vif", alert_host_if[k]);
     end
   end
 
+  alert_if esc_device_if[alert_pkg::N_ESC_SEV](.clk(clk), .rst_n(rst_n));
+  for (genvar k = 0; k < alert_pkg::N_ESC_SEV; k++) begin : gen_esc_if
+    assign esc_rx[k].resp_p = esc_device_if[k].esc_rx.resp_p;
+    assign esc_rx[k].resp_n = esc_device_if[k].esc_rx.resp_n;
+    assign esc_device_if[k].esc_tx.esc_p = esc_tx[k].esc_p;
+    assign esc_device_if[k].esc_tx.esc_n = esc_tx[k].esc_n;
+    initial begin
+      uvm_config_db#(virtual alert_if)::set(null, $sformatf("*.env.esc_device_agent[%0d]", k),
+                                            "vif", esc_device_if[k]);
+    end
+  end
   // main dut
   alert_handler dut (
     .clk_i                ( clk           ),
@@ -66,17 +76,6 @@
     .esc_tx_o             ( esc_tx        )
   );
 
-  // escalation receiver duts
-  for (genvar k = 0; k < alert_pkg::N_ESC_SEV; k++) begin : gen_esc_rx
-    prim_esc_receiver i_prim_esc_receiver (
-      .clk_i    ( clk       ),
-      .rst_ni   ( rst_n     ),
-      .esc_en_o ( esc_en[k] ),
-      .esc_rx_o ( esc_rx[k] ),
-      .esc_tx_i ( esc_tx[k] )
-    );
-  end
-
   initial begin
     // drive clk and rst_n from clk_if
     clk_rst_if.set_active();