[dv/sram] extend tl_errors_test to the SRAM

this PR adds a TLUL protocol error test to the SRAM memory interface,
and does so by extending the `cip_base_vseq__tl_errors.svh` to allow
the `tl_protocol_err()` task to take an input sequencer, allowing
protocol error tests to be run on any generic TLUL agent.

Only this task was updated in this way as all of the other error cases
are specific to CSR and uvm_mem interfaces, making them unfit to use on
the SRAM memory TLUL interface.

The `run_tl_errors_vseq()` task is extended by this test sequence to run
the custom TLUL protocol testcases, and is done so that it still remains
compatible with `stress_all_with_rand_reset` tests.

Signed-off-by: Udi Jonnalagadda <udij@google.com>
diff --git a/hw/dv/sv/cip_lib/cip_base_vseq__tl_errors.svh b/hw/dv/sv/cip_lib/cip_base_vseq__tl_errors.svh
index fb869e2..7745d6a 100644
--- a/hw/dv/sv/cip_lib/cip_base_vseq__tl_errors.svh
+++ b/hw/dv/sv/cip_lib/cip_base_vseq__tl_errors.svh
@@ -5,11 +5,12 @@
 // Shorthand to create and send a TL error seq
 // Set low priority (1) to send error item to TL agent, so when crossing error item with normal
 // seq, normal seq with default priority (100) has the priority to access TL driver
-`define create_tl_access_error_case(task_name_, with_c_, seq_t_ = tl_host_custom_seq) \
+`define create_tl_access_error_case(task_name_, with_c_, seq_t_ = tl_host_custom_seq,
+                                    seqr_t = p_sequencer.tl_sequencer_h) \
   begin \
     seq_t_ tl_seq; \
     `uvm_info(`gfn, {"Running ", `"task_name_`"}, UVM_HIGH) \
-    `uvm_create_on(tl_seq, p_sequencer.tl_sequencer_h) \
+    `uvm_create_on(tl_seq, seqr_t) \
     if (cfg.zero_delays) begin \
       tl_seq.min_req_delay = 0; \
       tl_seq.max_req_delay = 0; \
@@ -89,11 +90,11 @@
   end
 endtask
 
-virtual task tl_protocol_err();
+virtual task tl_protocol_err(tl_sequencer tl_sequencer_h = p_sequencer.tl_sequencer_h);
   repeat ($urandom_range(10, 100)) begin
     if (cfg.under_reset) return;
     `create_tl_access_error_case(
-        tl_protocol_err, , tl_host_protocol_err_seq
+        tl_protocol_err, , tl_host_protocol_err_seq, tl_sequencer_h
         )
   end
 endtask
diff --git a/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson b/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson
index 2f7df21..51da21f 100644
--- a/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson
+++ b/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson
@@ -6,7 +6,8 @@
   // TODO: remove the common testplans if not applicable
   import_testplans: ["hw/dv/tools/dvsim/testplans/csr_testplan.hjson",
                      "hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson",
-                     "hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson",
+                     // TODO uncomment once supported
+                     //"hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson",
                      "hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson"]
   entries: [
     {
diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_lc_escalation_vseq.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_lc_escalation_vseq.sv
index 35757fa..315b7dc 100644
--- a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_lc_escalation_vseq.sv
+++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_lc_escalation_vseq.sv
@@ -91,7 +91,7 @@
           begin
             // read out STATUS csr, scoreboard will check that proper updates have been made
             csr_rd(.ptr(ral.status), .value(status));
-            csr_wr(.csr(ral.status), .value(status));
+            csr_wr(.ptr(ral.status), .value(status));
 
             `uvm_info(`gfn,
               $sformatf("Performing %0d random memory accesses after LC escalation request",
diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_mem_tl_errors_vseq.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_mem_tl_errors_vseq.sv
new file mode 100644
index 0000000..2edd2f4
--- /dev/null
+++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_mem_tl_errors_vseq.sv
@@ -0,0 +1,61 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// This sequence extends the automated mem tests to the SRAM memory interface.
+//
+// However, as the SRAM supports all kinds of reads/writes at any granularity,
+// the only error case that can be used here is the `tl_protocol_err` error sequence.
+//
+// This error sequence is interleaved with a series of random accesses to stress
+// memory operation.
+class sram_ctrl_mem_tl_errors_vseq extends sram_ctrl_multiple_keys_vseq;
+
+  `uvm_object_utils(sram_ctrl_mem_tl_errors_vseq)
+  `uvm_object_new
+
+  virtual task body();
+    run_tl_errors_vseq(num_trans);
+  endtask : body
+
+  virtual task run_tl_errors_vseq(int num_times = 1, bit do_wait_clk = 0);
+    for (int i = 0; i < num_times; i++) begin
+      `uvm_info(`gfn, $sformatf("Running run_tl_errors_vseq %0d/%0d", i, num_times), UVM_LOW)
+
+      // randomly enable zero delays
+      //
+      // TODO: Move this into the env build_phase and control with zero_delays knob
+      if ($urandom_range(0, 1)) begin
+        cfg.m_sram_cfg.a_valid_delay_min = 0;
+        cfg.m_sram_cfg.a_valid_delay_max = 0;
+
+        cfg.m_sram_cfg.a_ready_delay_min = 0;
+        cfg.m_sram_cfg.a_ready_delay_max = 0;
+
+        cfg.m_sram_cfg.d_valid_delay_min = 0;
+        cfg.m_sram_cfg.d_valid_delay_max = 0;
+
+        cfg.m_sram_cfg.d_ready_delay_min = 0;
+        cfg.m_sram_cfg.d_ready_delay_max = 0;
+      end
+
+      // spawn various threads to interleave TLUL protocol error accesses and valid memory accesses
+      fork
+        begin: isolation
+          repeat ($urandom_range(5, 20)) begin
+            fork
+              begin
+                randcase
+                  2: tl_protocol_err(p_sequencer.sram_tl_sequencer_h);
+                  1: do_rand_ops(.num_ops($urandom_range(200, 500)));
+                endcase
+              end
+            join_none
+          end
+          wait fork;
+        end: isolation
+      join
+    end
+  endtask
+
+endclass
diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_vseq_list.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_vseq_list.sv
index b729fc7..48d0404 100644
--- a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_vseq_list.sv
+++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_vseq_list.sv
@@ -9,3 +9,4 @@
 `include "sram_ctrl_bijection_vseq.sv"
 `include "sram_ctrl_stress_pipeline_vseq.sv"
 `include "sram_ctrl_lc_escalation_vseq.sv"
+`include "sram_ctrl_mem_tl_errors_vseq.sv"
diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env.core b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env.core
index 8314697..1ea8ff4 100644
--- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env.core
+++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env.core
@@ -26,6 +26,7 @@
       - seq_lib/sram_ctrl_bijection_vseq.sv: {is_include_file: true}
       - seq_lib/sram_ctrl_stress_pipeline_vseq.sv: {is_include_file: true}
       - seq_lib/sram_ctrl_lc_escalation_vseq.sv: {is_include_file: true}
+      - seq_lib/sram_ctrl_mem_tl_errors_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 generate:
diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
index dc74389..6b4d663 100644
--- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
+++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
@@ -140,6 +140,52 @@
     return bitmask;
   endfunction
 
+  // Check if the input tl_seq_item has any tl errors.
+  //
+  // NOTE: this function is designed to only work for tl_seq_item objects sent to the
+  //       TLUL interface of the SRAM scrambling memory, as this interface does not
+  //       care about CSR/uvm_mem addressing.
+  //       For the same reason, we cannot use the already-provided `predict_tl_err(...)`
+  //       function of the cip_base_scoreboard, as the SRAM TLUL interface does not have
+  //       any CSRs or uvm_mems.
+  virtual function bit sram_predict_tl_err(tl_seq_item item, tl_channels_e channel);
+    bit is_tl_err;
+
+    is_tl_err = item.get_exp_d_error();
+
+    `uvm_info(`gfn,
+              $sformatf("error_a_opcode_invalid: %0b",
+                        item.get_error_a_opcode_invalid()),
+              UVM_HIGH)
+    `uvm_info(`gfn,
+              $sformatf("error_PutFullData_mask_size_mismatch: %0b",
+                        item.get_error_PutFullData_mask_size_mismatched()),
+              UVM_HIGH)
+    `uvm_info(`gfn,
+              $sformatf("error_addr_mask_misaligned: %0b",
+                        item.get_error_addr_mask_misaligned()),
+              UVM_HIGH)
+    `uvm_info(`gfn,
+              $sformatf("error_addr_size_misaligned: %0b",
+                        item.get_error_addr_size_misaligned()),
+              UVM_HIGH)
+    `uvm_info(`gfn,
+              $sformatf("error_mask_not_in_enabled_lanes: %0b",
+                        item.get_error_mask_not_in_enabled_lanes()),
+              UVM_HIGH)
+    `uvm_info(`gfn,
+              $sformatf("error_size_over_max: %0b",
+                        item.get_error_size_over_max()),
+              UVM_HIGH)
+
+    if (channel == DataChannel) begin
+      `DV_CHECK_EQ(item.d_error, is_tl_err,
+          $sformatf("item_err: %0d", is_tl_err))
+    end
+
+    return is_tl_err;
+  endfunction
+
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
     sram_tl_a_chan_fifo = new("sram_tl_a_chan_fifo", this);
@@ -238,7 +284,13 @@
         // do not process anymore addr_phase transactions
         if (status_lc_esc) continue;
 
-        // TODO: need to ensure that we don't process TLUL errors
+        // don't process any error items
+        //
+        // TODO: sample error coverage
+        if (cfg.en_scb_tl_err_chk && sram_predict_tl_err(item, AddrChannel)) begin
+          `uvm_info(`gfn, "TL addr_phase error detected", UVM_HIGH)
+          continue;
+        end
 
         addr_trans.we    = item.is_write();
         addr_trans.addr  = word_align_addr(item.a_addr);
@@ -302,7 +354,13 @@
       if (!cfg.en_scb) continue;
       `uvm_info(`gfn, $sformatf("Received sram_tl_d_chan item:\n%0s", item.sprint()), UVM_HIGH)
 
-      // TODO: need to ensure that we don't process TLUL errors
+      // don't process any error items
+      //
+      // TODO: sample error coverage
+      if (cfg.en_scb_tl_err_chk && sram_predict_tl_err(item, DataChannel)) begin
+        `uvm_info(`gfn, "TL data_phase error detected", UVM_HIGH)
+        continue;
+      end
 
       // check packet integrity
       void'(item.is_ok());
diff --git a/hw/ip/sram_ctrl/dv/sram_ctrl_base_sim_cfg.hjson b/hw/ip/sram_ctrl/dv/sram_ctrl_base_sim_cfg.hjson
index f610e58..f447eb2 100644
--- a/hw/ip/sram_ctrl/dv/sram_ctrl_base_sim_cfg.hjson
+++ b/hw/ip/sram_ctrl/dv/sram_ctrl_base_sim_cfg.hjson
@@ -85,6 +85,11 @@
       name: "{variant}_lc_escalation"
       uvm_test_seq: sram_ctrl_lc_escalation_vseq
     }
+    {
+      name: "{variant}_mem_tl_errors"
+      uvm_test_seq: sram_ctrl_mem_tl_errors_vseq
+      run_opts: ["+run_tl_errors"]
+    }
   ]
 
   // List of regressions.