[dv/alert_handler] randomly enable and drive alerts

In sanity test, this change support randomly enable and drive all the
alert sources. Then scb will predict the alert_cause and interrupt
accordingly.

Signed-off-by: Cindy Chen <chencindy@google.com>
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 2a21e26..32118d1 100644
--- a/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
+++ b/hw/ip/alert_handler/dv/env/alert_handler_scoreboard.sv
@@ -39,28 +39,30 @@
   endtask
 
   virtual task process_alert_fifo();
-    uvm_reg_field list_of_alert_cause_fields[$];
-    uvm_reg_field list_of_intr_state_fields[$];
-    ral.alert_cause.get_fields(list_of_alert_cause_fields);
-    ral.intr_state.get_fields(list_of_intr_state_fields);
+    uvm_reg_field alert_cause_fields[$];
+    uvm_reg_field intr_state_fields[$];
+    ral.alert_cause.get_fields(alert_cause_fields);
+    ral.intr_state.get_fields(intr_state_fields);
     foreach (alert_fifo[i]) begin
+      automatic int index = i;
       fork
-        automatic int index = i;
-        alert_seq_item act_item;
         forever begin
+          alert_seq_item act_item;
           alert_fifo[index].get(act_item);
           // once the alert is received
           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;
+            bit [TL_DW-1:0] alert_en = ral.alert_en.get_mirrored_value();
 
-            alert_cause_field = list_of_alert_cause_fields[index];
-            intr_class = ral.alert_class.get_mirrored_value();
-            intr_state_field =
-                list_of_intr_state_fields[intr_class << (TL_DW-2*index) >> (TL_DW-2)];
-            void'(alert_cause_field.predict(1));
-            void'(intr_state_field.predict(1));
+            if (alert_en[index]) begin
+              bit [TL_DW-1:0] intr_class = ral.alert_class.get_mirrored_value();
+              alert_cause_field = alert_cause_fields[index];
+              // extract the two bits that indicates which intr class this alert will trigger
+              intr_state_field = intr_state_fields[(intr_class >> index*2) & 'b11];
+              void'(alert_cause_field.predict(1));
+              void'(intr_state_field.predict(1));
+            end
           end
         end
       join_none
@@ -69,10 +71,10 @@
 
   virtual task process_esc_fifo();
     foreach (esc_fifo[i]) begin
+      automatic int index = i;
       fork
-        automatic int index = i;
-        alert_seq_item act_item;
         forever begin
+          alert_seq_item act_item;
           esc_fifo[index].get(act_item);
         end
       join_none
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 fcbd854..f219b72 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
@@ -25,9 +25,10 @@
   endtask
 
   // setup basic alert_handler features
+  // alert_class default 0 -> all alert will trigger interrupt classA
   virtual task alert_handler_init(bit [NUM_ALERT_HANDLER_CLASSES-1:0] intr_en = '1,
-                                  bit                                 alert_en = 1'b1,
-                                  bit [TL_DW-1:0]                     alert_class = 'he4,
+                                  bit [alert_pkg::NAlerts-1:0]        alert_en = '1,
+                                  bit [TL_DW-1:0]                     alert_class = 'h0,
                                   bit [TL_DW-1:0]                     classA_ctrl = 'h393d);
     // TODO: cfg_interrupts does not disable interrupt, need debug
     //cfg_interrupts(.interrupts(interrupts), .enable(1'b1));
@@ -40,11 +41,25 @@
     csr_update(.csr(ral.classa_ctrl));
   endtask
 
-  virtual task drive_alert(int alert_index);
-    alert_sender_seq alert_seq;
-    `uvm_create_on(alert_seq, p_sequencer.alert_host_seqr_h[alert_index]);
-    `DV_CHECK_RANDOMIZE_FATAL(alert_seq)
-    `uvm_send(alert_seq)
+  virtual task drive_alert(bit[alert_pkg::NAlerts-1:0] alert_trigger);
+    fork
+      begin : isolation_fork
+        foreach (alert_trigger[i]) begin
+          if (alert_trigger[i]) begin
+            automatic int index = i;
+            fork
+              begin
+                alert_sender_seq alert_seq;
+                `uvm_create_on(alert_seq, p_sequencer.alert_host_seqr_h[index]);
+                `DV_CHECK_RANDOMIZE_FATAL(alert_seq)
+                `uvm_send(alert_seq)
+              end
+            join_none
+          end
+        end
+        wait fork;
+      end
+    join
   endtask
 
   virtual task clear_esc();
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 c4b1409..d58b122 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
@@ -8,12 +8,9 @@
 
   `uvm_object_new
 
-  rand bit[3:0] intr_en;
-
-  // temp disable
-  constraint only_enable_intr_class_a_c {
-    intr_en inside {0, 1};
-  }
+  rand bit [NUM_ALERT_HANDLER_CLASSES-1:0] intr_en;
+  rand bit [alert_pkg::NAlerts-1:0]        alert_trigger;
+  rand bit [alert_pkg::NAlerts-1:0]        alert_en;
 
   task body();
     run_esc_rsp_seq_nonblocking();
@@ -26,17 +23,19 @@
                                      map_e2.value inside {[0:NUM_ALERT_HANDLER_CLASSES-1]};
                                      map_e3.value inside {[0:NUM_ALERT_HANDLER_CLASSES-1]};
                                     )
-      `uvm_info(`gfn, $sformatf("starting seq %0d/%0d: intr_en=%0b", i, num_trans, intr_en),
-                UVM_LOW)
+      `uvm_info(`gfn, $sformatf("starting seq %0d/%0d: intr_en=%0b, alert_trigger=%0b, alert_en=%0b",
+                                i, num_trans, intr_en, alert_trigger, alert_en), UVM_LOW)
       `uvm_info(`gfn, ral.classa_ctrl.sprint(), UVM_HIGH)
-      alert_handler_init(.intr_en(intr_en), .classA_ctrl(ral.classa_ctrl.get()));
-      drive_alert(0);
-      if (intr_en != 0) begin
-        wait(cfg.intr_vif.pins[0] === 1'b1);
-        check_interrupts(.interrupts((1)), .check_set(1'b1));
-      end else begin
-        csr_spinwait(.ptr(ral.intr_state.classa), .exp_data(1'b1));
-        csr_wr(.csr(ral.intr_state), .value(1));
+      alert_handler_init(.intr_en(intr_en), .alert_en(alert_en), .classA_ctrl(ral.classa_ctrl.get()));
+      drive_alert(alert_trigger);
+      if (alert_en & alert_trigger) begin
+        if (intr_en[0] != 0) begin
+          wait(cfg.intr_vif.pins[0] === 1'b1);
+          check_interrupts(.interrupts((1)), .check_set(1'b1));
+        end else begin
+          csr_spinwait(.ptr(ral.intr_state.classa), .exp_data(1'b1));
+          csr_wr(.csr(ral.intr_state), .value(1));
+        end
       end
       // TODO: check escalation phases once the escalation agent is connected
       if (ral.classa_ctrl.en_e0.get() | ral.classa_ctrl.en_e1.get() |