[alert_handler/dv] Generate DV files and hook up DUT

This adds the alert handler DV testbench and all CSR exclusions
required to successfully run the CSR test.
diff --git a/hw/ip/alert_handler/dv/Makefile b/hw/ip/alert_handler/dv/Makefile
new file mode 100644
index 0000000..600bd67
--- /dev/null
+++ b/hw/ip/alert_handler/dv/Makefile
@@ -0,0 +1,41 @@
+####################################################################################################
+## Copyright lowRISC contributors.                                                                ##
+## Licensed under the Apache License, Version 2.0, see LICENSE for details.                       ##
+## SPDX-License-Identifier: Apache-2.0                                                            ##
+####################################################################################################
+## Entry point test Makefile for building and running tests.                                      ##
+## These are generic set of option groups that apply to all testbenches.                          ##
+## This flow requires the following options to be set:                                            ##
+## DV_DIR       - current dv directory that contains the test Makefile                            ##
+## DUT_TOP      - top level dut module name                                                       ##
+## TB_TOP       - top level tb module name                                                        ##
+## DOTF         - .f file used for compilation                                                    ##
+## COMPILE_KEY  - compile option set                                                              ##
+## TEST_NAME    - name of the test to run - this is supplied on the command line                  ##
+####################################################################################################
+DV_DIR          := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+export DUT_TOP  := alert_handler
+export TB_TOP   := tb
+FUSESOC_CORE    := lowrisc:dv:alert_handler_sim:0.1
+COMPILE_KEY     ?= default
+
+UVM_TEST        ?= alert_handler_base_test
+UVM_TEST_SEQ    ?= alert_handler_base_vseq
+
+####################################################################################################
+##                     A D D    I N D I V I D U A L    T E S T S    B E L O W                     ##
+####################################################################################################
+TEST_NAME       ?= alert_handler_sanity
+UVM_TEST        ?= alert_handler_base_test
+UVM_TEST_SEQ    ?= alert_handler_base_vseq
+
+# TODO:
+# ifeq (${TEST_NAME},alert_handler_sanity)
+#   UVM_TEST_SEQ   = alert_handler_sanity_vseq
+# endif
+
+####################################################################################################
+## Include the tool Makefile below                                                                ##
+## Dont add anything else below it!                                                               ##
+####################################################################################################
+include ${DV_DIR}/../../../dv/tools/Makefile
diff --git a/hw/ip/alert_handler/dv/alert_handler_sim.core b/hw/ip/alert_handler/dv/alert_handler_sim.core
new file mode 100644
index 0000000..f1c7883
--- /dev/null
+++ b/hw/ip/alert_handler/dv/alert_handler_sim.core
@@ -0,0 +1,28 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:alert_handler_sim:0.1"
+description: "ALERT_HANDLER DV sim target"
+filesets:
+  files_rtl:
+    depend:
+      - lowrisc:ip:alert_handler:0.1
+    files:
+      - tb/alert_handler_bind.sv
+    file_type: systemVerilogSource
+
+  files_dv:
+    depend:
+      - lowrisc:dv:alert_handler_test
+    files:
+      - tb/tb.sv
+    file_type: systemVerilogSource
+
+targets:
+  sim:
+    toplevel: tb
+    filesets:
+      - files_rtl
+      - files_dv
+    default_tool: vcs
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.core b/hw/ip/alert_handler/dv/env/alert_handler_env.core
new file mode 100644
index 0000000..788b4e1
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env.core
@@ -0,0 +1,24 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:alert_handler_env:0.1"
+description: "ALERT_HANDLER DV UVM environment"
+filesets:
+  files_dv:
+    depend:
+      - lowrisc:dv:cip_lib
+    files:
+      - alert_handler_env_pkg.sv
+      - alert_handler_env_cfg.sv: {is_include_file: true}
+      - alert_handler_env_cov.sv: {is_include_file: true}
+      - alert_handler_env.sv: {is_include_file: true}
+      - alert_handler_reg_block.sv: {is_include_file: true}
+      - alert_handler_scoreboard.sv: {is_include_file: true}
+      - seq_lib/alert_handler_vseq_list.sv: {is_include_file: true}
+    file_type: systemVerilogSource
+
+targets:
+  default:
+    filesets:
+      - files_dv
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env.sv b/hw/ip/alert_handler/dv/env/alert_handler_env.sv
new file mode 100644
index 0000000..6905b4b
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env.sv
@@ -0,0 +1,31 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_env extends cip_base_env #(
+    .CFG_T              (alert_handler_env_cfg),
+    .COV_T              (alert_handler_env_cov),
+    .VIRTUAL_SEQUENCER_T(alert_handler_virtual_sequencer),
+    .SCOREBOARD_T       (alert_handler_scoreboard)
+  );
+  `uvm_component_utils(alert_handler_env)
+
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+
+    // 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")
+    end
+    if (!uvm_config_db#(entropy_vif)::get(this, "", "entropy_vif", cfg.entropy_vif)) begin
+      `uvm_fatal(get_full_name(), "failed to get entropy_vif from uvm_config_db")
+    end
+  endfunction
+
+  function void connect_phase(uvm_phase phase);
+    super.connect_phase(phase);
+  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
new file mode 100644
index 0000000..82b19db
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env_cfg.sv
@@ -0,0 +1,30 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_env_cfg extends cip_base_env_cfg #(.RAL_T(alert_handler_reg_block));
+
+  // ext component cfgs
+  esc_en_vif  esc_en_vif;
+  entropy_vif entropy_vif;
+
+  `uvm_object_utils_begin(alert_handler_env_cfg)
+  `uvm_object_utils_end
+
+  `uvm_object_new
+
+  virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1,
+                                   bit [TL_AW-1:0] csr_addr_map_size = 2048);
+    super.initialize(csr_base_addr, csr_addr_map_size);
+
+    // set num_interrupts & num_alerts
+    begin
+      uvm_reg rg = ral.get_reg_by_name("intr_state");
+      if (rg != null) begin
+        num_interrupts = ral.intr_state.get_n_used_bits();
+      end
+      num_alerts = 0;
+    end
+  endfunction
+
+endclass
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_cov.sv b/hw/ip/alert_handler/dv/env/alert_handler_env_cov.sv
new file mode 100644
index 0000000..464960b
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env_cov.sv
@@ -0,0 +1,18 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_env_cov extends cip_base_env_cov #(.CFG_T(alert_handler_env_cfg));
+  `uvm_component_utils(alert_handler_env_cov)
+
+  // the base class provides the following handles for use:
+  // alert_handler_env_cfg: cfg
+
+  // covergroups
+
+  function new(string name, uvm_component parent);
+    super.new(name, parent);
+    // instantiate all covergroups here
+  endfunction : new
+
+endclass
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_env_pkg.sv b/hw/ip/alert_handler/dv/env/alert_handler_env_pkg.sv
new file mode 100644
index 0000000..7d3aa65
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_env_pkg.sv
@@ -0,0 +1,38 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+package alert_handler_env_pkg;
+  // dep packages
+  import uvm_pkg::*;
+  import top_pkg::*;
+  import dv_utils_pkg::*;
+  import csr_utils_pkg::*;
+  import tl_agent_pkg::*;
+  import dv_lib_pkg::*;
+  import cip_base_pkg::*;
+
+  // macro includes
+  `include "uvm_macros.svh"
+  `include "dv_macros.svh"
+
+  // parameters
+  parameter int NUM_MAX_ESC_SEV = 8;
+
+  // types
+  // forward declare classes to allow typedefs below
+  typedef virtual pins_if #(NUM_MAX_ESC_SEV) esc_en_vif;
+  typedef virtual pins_if #(1) entropy_vif;
+
+  // functions
+
+  // package sources
+  `include "alert_handler_reg_block.sv"
+  `include "alert_handler_env_cfg.sv"
+  `include "alert_handler_env_cov.sv"
+  `include "alert_handler_virtual_sequencer.sv"
+  `include "alert_handler_scoreboard.sv"
+  `include "alert_handler_env.sv"
+  `include "alert_handler_vseq_list.sv"
+
+endpackage
diff --git a/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv b/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
new file mode 100644
index 0000000..adcf7ed
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
@@ -0,0 +1,86 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_scoreboard extends cip_base_scoreboard #(
+    .CFG_T(alert_handler_env_cfg),
+    .RAL_T(alert_handler_reg_block),
+    .COV_T(alert_handler_env_cov)
+  );
+  `uvm_component_utils(alert_handler_scoreboard)
+
+  // local variables
+
+  // TLM agent fifos
+
+  // local queues to hold incoming packets pending comparison
+
+  `uvm_component_new
+
+  function void build_phase(uvm_phase phase);
+    super.build_phase(phase);
+  endfunction
+
+  function void connect_phase(uvm_phase phase);
+    super.connect_phase(phase);
+  endfunction
+
+  task run_phase(uvm_phase phase);
+    super.run_phase(phase);
+    fork
+    join_none
+  endtask
+
+  virtual task process_tl_access(tl_seq_item item, tl_channels_e channel = DataChannel);
+    uvm_reg csr;
+    bit     do_read_check   = 1'b1;
+    bit     write           = item.is_write();
+    uvm_reg_addr_t csr_addr = {item.a_addr[TL_AW-1:2], 2'b00};
+
+    // if access was to a valid csr, get the csr handle
+    if (csr_addr inside {cfg.csr_addrs}) begin
+      csr = ral.default_map.get_reg_by_offset(csr_addr);
+      `DV_CHECK_NE_FATAL(csr, null)
+    end
+    if (csr == null) begin
+      // we hit an oob addr - expect error response and return
+      `DV_CHECK_EQ(item.d_error, 1'b1)
+      return;
+    end
+
+    if (channel == AddrChannel) begin
+      // if incoming access is a write to a valid csr, then make updates right away
+      if (write) csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask));
+    end
+
+    // process the csr req
+    // for write, update local variable and fifo at address phase
+    // for read, update predication at address phase and compare at data phase
+    case (csr.get_name())
+      // add individual case item for each csr
+      default: begin
+        `uvm_fatal(`gfn, $sformatf("invalid csr: %0s", csr.get_full_name()))
+      end
+    endcase
+
+    // On reads, if do_read_check, is set, then check mirrored_value against item.d_data
+    if (!write && channel == DataChannel) begin
+      if (do_read_check) begin
+        `DV_CHECK_EQ(csr.get_mirrored_value(), item.d_data,
+                     $sformatf("reg name: %0s", csr.get_full_name()))
+      end
+      csr.predict(.value(item.d_data), .kind(UVM_PREDICT_READ));
+    end
+  endtask
+
+  virtual function void reset(string kind = "HARD");
+    super.reset(kind);
+    // reset local fifos queues and variables
+  endfunction
+
+  function void check_phase(uvm_phase phase);
+    super.check_phase(phase);
+    // post test checks - ensure that all local fifos and queues are empty
+  endfunction
+
+endclass
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
new file mode 100644
index 0000000..30fab28
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/alert_handler_virtual_sequencer.sv
@@ -0,0 +1,14 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_virtual_sequencer extends cip_base_virtual_sequencer #(
+    .CFG_T(alert_handler_env_cfg),
+    .COV_T(alert_handler_env_cov)
+  );
+  `uvm_component_utils(alert_handler_virtual_sequencer)
+
+
+  `uvm_component_new
+
+endclass
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
new file mode 100644
index 0000000..b7c547e
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -0,0 +1,32 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_base_vseq extends cip_base_vseq #(
+    .CFG_T               (alert_handler_env_cfg),
+    .RAL_T               (alert_handler_reg_block),
+    .COV_T               (alert_handler_env_cov),
+    .VIRTUAL_SEQUENCER_T (alert_handler_virtual_sequencer)
+  );
+  `uvm_object_utils(alert_handler_base_vseq)
+
+  // various knobs to enable certain routines
+  bit do_alert_handler_init = 1'b1;
+
+  `uvm_object_new
+
+  virtual task dut_init(string reset_kind = "HARD");
+    super.dut_init();
+    if (do_alert_handler_init) alert_handler_init();
+  endtask
+
+  virtual task dut_shutdown();
+    // nothing special yet
+  endtask
+
+  // setup basic alert_handler features
+  virtual task alert_handler_init();
+    // `uvm_error(`gfn, "FIXME")
+  endtask
+
+endclass : alert_handler_base_vseq
diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv
new file mode 100644
index 0000000..e6a0659
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_common_vseq.sv
@@ -0,0 +1,41 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_common_vseq extends alert_handler_base_vseq;
+  `uvm_object_utils(alert_handler_common_vseq)
+
+  constraint num_trans_c {
+    num_trans inside {[1:2]};
+  }
+  `uvm_object_new
+
+  virtual task body();
+    run_common_vseq_wrapper(num_trans);
+  endtask : body
+
+  // function to add csr exclusions of the given type using the csr_excl_item item
+  virtual function void add_csr_exclusions(string           csr_test_type,
+                                           csr_excl_item    csr_excl,
+                                           string           scope = "ral");
+
+    // write exclusions - these should not apply to hw_reset test
+    if (csr_test_type != "hw_reset") begin
+      // these should not be written since they have sideffects on write access
+      // of the other regs
+      csr_excl.add_excl({scope, ".", "regen"},        CsrExclWrite);
+      csr_excl.add_excl({scope, ".", "classa_clren"}, CsrExclWrite);
+      csr_excl.add_excl({scope, ".", "classb_clren"}, CsrExclWrite);
+      csr_excl.add_excl({scope, ".", "classc_clren"}, CsrExclWrite);
+      csr_excl.add_excl({scope, ".", "classd_clren"}, CsrExclWrite);
+      // these regs are write only
+      csr_excl.add_excl({scope, ".", "classa_clr"},   CsrExclWriteCheck);
+      csr_excl.add_excl({scope, ".", "classb_clr"},   CsrExclWriteCheck);
+      csr_excl.add_excl({scope, ".", "classc_clr"},   CsrExclWriteCheck);
+      csr_excl.add_excl({scope, ".", "classd_clr"},   CsrExclWriteCheck);
+      // exclude due to side effects on intr state reg
+      csr_excl.add_excl({scope, ".", "intr_test"},    CsrExclWrite);
+    end
+  endfunction
+
+endclass
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
new file mode 100644
index 0000000..c284383
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_sanity_vseq.sv
@@ -0,0 +1,15 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// basic sanity test vseq
+class alert_handler_sanity_vseq extends alert_handler_base_vseq;
+  `uvm_object_utils(alert_handler_sanity_vseq)
+
+  `uvm_object_new
+
+  task body();
+
+  endtask : body
+
+endclass : alert_handler_sanity_vseq
diff --git a/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
new file mode 100644
index 0000000..44d5684
--- /dev/null
+++ b/hw/ip/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
@@ -0,0 +1,7 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "alert_handler_base_vseq.sv"
+`include "alert_handler_sanity_vseq.sv"
+`include "alert_handler_common_vseq.sv"
diff --git a/hw/ip/alert_handler/dv/tb/alert_handler_bind.sv b/hw/ip/alert_handler/dv/tb/alert_handler_bind.sv
new file mode 100644
index 0000000..2d134d6
--- /dev/null
+++ b/hw/ip/alert_handler/dv/tb/alert_handler_bind.sv
@@ -0,0 +1,14 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+module alert_handler_bind;
+
+  bind alert_handler tlul_assert tlul_assert_host (
+    .clk_i,
+    .rst_ni,
+    .h2d  (tl_i),
+    .d2h  (tl_o)
+  );
+
+endmodule
diff --git a/hw/ip/alert_handler/dv/tb/tb.sv b/hw/ip/alert_handler/dv/tb/tb.sv
new file mode 100644
index 0000000..dae3ba9
--- /dev/null
+++ b/hw/ip/alert_handler/dv/tb/tb.sv
@@ -0,0 +1,111 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+module tb;
+  // dep packages
+  import uvm_pkg::*;
+  import dv_utils_pkg::*;
+  import alert_handler_env_pkg::*;
+  import alert_handler_test_pkg::*;
+
+  // macro includes
+  `include "uvm_macros.svh"
+  `include "dv_macros.svh"
+
+  wire clk, rst_n;
+  wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
+  wire [NUM_MAX_ALERTS-1:0] alerts;
+  wire [NUM_MAX_ESC_SEV-1:0] esc_en;
+  wire entropy;
+
+  // interfaces
+  clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
+  pins_if #(NUM_MAX_INTERRUPTS) intr_if(interrupts);
+  pins_if #(NUM_MAX_ALERTS) alerts_if(alerts);
+  pins_if #(NUM_MAX_ESC_SEV) esc_en_if(esc_en);
+  pins_if #(1) entropy_if(entropy);
+  pins_if #(1) devmode_if();
+  tl_if tl_if(.clk(clk), .rst_n(rst_n));
+
+  // dut signals
+  logic [alert_pkg::NAlerts-1:0]    alert_p;
+  logic [alert_pkg::NAlerts-1:0]    alert_n;
+  logic [alert_pkg::NAlerts-1:0]    ack_p;
+  logic [alert_pkg::NAlerts-1:0]    ack_n;
+  logic [alert_pkg::NAlerts-1:0]    ping_p;
+  logic [alert_pkg::NAlerts-1:0]    ping_n;
+
+  logic [alert_pkg::N_ESC_SEV-1:0]  esc_p;
+  logic [alert_pkg::N_ESC_SEV-1:0]  esc_n;
+  logic [alert_pkg::N_ESC_SEV-1:0]  resp_p;
+  logic [alert_pkg::N_ESC_SEV-1:0]  resp_n;
+
+  // escalation sender duts
+  for (genvar k = 0; k < alert_pkg::NAlerts; k++) begin : gen_alert_tx
+    prim_alert_sender #(
+      .AsyncOn(alert_pkg::AsyncOn[k])
+    ) i_prim_alert_sender (
+      .clk_i    ( clk        ),
+      .rst_ni   ( rst_n      ),
+      .alert_i  ( alerts[k]  ),
+      .ping_pi  ( ping_p[k]  ),
+      .ping_ni  ( ping_n[k]  ),
+      .ack_pi   ( ack_p[k]   ),
+      .ack_ni   ( ack_n[k]   ),
+      .alert_po ( alert_p[k] ),
+      .alert_no ( alert_n[k] )
+    );
+  end
+
+  // main dut
+  alert_handler dut (
+    .clk_i                ( clk          ),
+    .rst_ni               ( rst_n        ),
+    .tl_i                 ( tl_if.h2d    ),
+    .tl_o                 ( tl_if.d2h    ),
+    .irq_o                ( interrupts[alert_pkg::N_CLASSES-1:0] ),
+    .crashdump_o          (              ),
+    .entropy_i            ( entropy      ),
+    .alert_pi             ( alert_p      ),
+    .alert_ni             ( alert_n      ),
+    .ack_po               ( ack_p        ),
+    .ack_no               ( ack_n        ),
+    .ping_po              ( ping_p       ),
+    .ping_no              ( ping_n       ),
+    .esc_po               ( esc_p        ),
+    .esc_no               ( esc_n        ),
+    .resp_pi              ( resp_p       ),
+    .resp_ni              ( resp_n       )
+  );
+
+  // 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] ),
+      .resp_po  ( resp_p[k] ),
+      .resp_no  ( resp_n[k] ),
+      .esc_pi   ( esc_p[k]  ),
+      .esc_ni   ( esc_n[k]  )
+    );
+  end
+
+  initial begin
+    // drive clk and rst_n from clk_if
+    clk_rst_if.set_active();
+    uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if);
+    uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
+    uvm_config_db#(alerts_vif)::set(null, "*.env", "alerts_vif", alerts_if);
+    uvm_config_db#(esc_en_vif)::set(null, "*.env", "esc_en_vif", esc_en_if);
+    uvm_config_db#(entropy_vif)::set(null, "*.env", "entropy_vif", entropy_if);
+    uvm_config_db#(devmode_vif)::set(null, "*.env", "devmode_vif", devmode_if);
+    uvm_config_db#(tlul_assert_vif)::set(null, "*.env", "tlul_assert_vif",
+                                         tb.dut.tlul_assert_host);
+    uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
+    $timeformat(-12, 0, " ps", 12);
+    run_test();
+  end
+
+endmodule
diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_base_test.sv b/hw/ip/alert_handler/dv/tests/alert_handler_base_test.sv
new file mode 100644
index 0000000..ff8d256
--- /dev/null
+++ b/hw/ip/alert_handler/dv/tests/alert_handler_base_test.sv
@@ -0,0 +1,21 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+class alert_handler_base_test extends cip_base_test #(
+    .ENV_T(alert_handler_env),
+    .CFG_T(alert_handler_env_cfg)
+  );
+
+  `uvm_component_utils(alert_handler_base_test)
+  `uvm_component_new
+
+  // the base class dv_base_test creates the following instances:
+  // alert_handler_env_cfg: cfg
+  // alert_handler_env:     env
+
+  // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in
+  // the run_phase; as such, nothing more needs to be done
+
+endclass : alert_handler_base_test
+
diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_test.core b/hw/ip/alert_handler/dv/tests/alert_handler_test.core
new file mode 100644
index 0000000..06a3f50
--- /dev/null
+++ b/hw/ip/alert_handler/dv/tests/alert_handler_test.core
@@ -0,0 +1,19 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:alert_handler_test:0.1"
+description: "ALERT_HANDLER DV UVM test"
+filesets:
+  files_dv:
+    depend:
+      - lowrisc:dv:alert_handler_env
+    files:
+      - alert_handler_test_pkg.sv
+      - alert_handler_base_test.sv: {is_include_file: true}
+    file_type: systemVerilogSource
+
+targets:
+  default:
+    filesets:
+      - files_dv
diff --git a/hw/ip/alert_handler/dv/tests/alert_handler_test_pkg.sv b/hw/ip/alert_handler/dv/tests/alert_handler_test_pkg.sv
new file mode 100644
index 0000000..c3f6d76
--- /dev/null
+++ b/hw/ip/alert_handler/dv/tests/alert_handler_test_pkg.sv
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+package alert_handler_test_pkg;
+  // dep packages
+  import uvm_pkg::*;
+  import cip_base_pkg::*;
+  import alert_handler_env_pkg::*;
+
+  // macro includes
+  `include "uvm_macros.svh"
+  `include "dv_macros.svh"
+
+  // local types
+
+  // functions
+
+  // package sources
+  `include "alert_handler_base_test.sv"
+
+endpackage