[dv] Adjust the chance of  partial_access and add partial_access tests

when we fully randomize it, the chance of doing partial access is really
high. Change to 10%, which is closer to real use case.
Create 2 dedicated cases (partial_access and partial_access_b2d) to have
90% partial accesses

Signed-off-by: Weicai Yang <weicai@google.com>
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 5dac0cf..7891aad 100644
--- a/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson
+++ b/hw/ip/sram_ctrl/data/sram_ctrl_base_testplan.hjson
@@ -122,6 +122,17 @@
       tests: ["{variant}_executable"]
     }
     {
+      name: partial_access
+      desc: '''
+            This test is intended to test a lot of partial accesses with random addresses or
+            back-to-back accesses.
+
+            Reuse the `smoke` and `stress_pipeline` by setting `partial_access_pct` = 90%
+            '''
+      milestone: V2
+      tests: ["{variant}_partial_access, {variant}_partial_access_b2b"]
+    }
+    {
       name: parity
       desc: '''
             TODO - to be changed into an ECC test
diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
index cd82fa9..3214c74 100644
--- a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
+++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
@@ -16,6 +16,14 @@
 
   bit stress_pipeline = 1'b0;
 
+  int partial_access_pct = 10;
+
+  virtual task pre_start();
+    super.pre_start();
+    void'($value$plusargs("partial_access_pct=%0d", partial_access_pct));
+    `DV_CHECK_LE(partial_access_pct, 100)
+  endtask
+
   virtual task dut_init(string reset_kind = "HARD");
     super.dut_init();
     if (do_sram_ctrl_init) sram_ctrl_init();
@@ -65,7 +73,7 @@
 
   // Task to perform a single SRAM read at the specified location
   virtual task do_single_read(input bit [TL_AW-1:0]    addr,
-                              input bit [TL_DBW-1:0]   mask         = get_rand_contiguous_mask(),
+                              input bit [TL_DBW-1:0]   mask         = get_rand_mask(.write(0)),
                               input bit                blocking     = $urandom_range(0, 1),
                               input bit                check_rdata  = 0,
                               input bit [TL_DW-1:0]    exp_rdata    = '0,
@@ -87,7 +95,7 @@
   // Task to perform a single SRAM write at the specified location
   virtual task do_single_write(bit [TL_AW-1:0]  addr,
                                bit [TL_DW-1:0]  data,
-                               bit [TL_DBW-1:0] mask        = get_rand_contiguous_mask(),
+                               bit [TL_DBW-1:0] mask        = get_rand_mask(.write(1)),
                                bit              blocking    = $urandom_range(0, 1),
                                mubi4_t          instr_type  = MuBi4False);
     tl_access(.addr(addr),
@@ -109,6 +117,7 @@
     mubi4_t instr_type;
 
     repeat (num_stress_ops) begin
+      bit write = $urandom_range(0, 1);
       // fully randomize data
       `DV_CHECK_STD_RANDOMIZE_FATAL(data)
 
@@ -118,8 +127,8 @@
 
       tl_access(.addr(addr),
                 .data(data),
-                .mask(get_rand_contiguous_mask()),
-                .write($urandom_range(0, 1)),
+                .mask(get_rand_mask(write)),
+                .write(write),
                 .check_rsp(!en_ifetch),
                 .blocking(1'b0),
                 .instr_type(instr_type),
@@ -143,6 +152,7 @@
     mubi4_t instr_type;
     repeat (num_ops) begin
       bit completed, saw_err;
+      bit write = $urandom_range(0, 1);
 
       // full randomize addr and data
       `DV_CHECK_STD_RANDOMIZE_FATAL(data)
@@ -156,8 +166,8 @@
                         .data(data),
                         .completed(completed),
                         .saw_err(saw_err),
-                        .mask(get_rand_contiguous_mask()),
-                        .write($urandom_range(0, 1)),
+                        .mask(get_rand_mask(write)),
+                        .write(write),
                         .blocking(blocking),
                         .check_rsp(!en_ifetch),
                         .instr_type(instr_type),
@@ -167,4 +177,15 @@
     csr_utils_pkg::wait_no_outstanding_access();
   endtask
 
+  // the input write argument will be used in extended test where this function is overridden
+  virtual function bit[bus_params_pkg::BUS_DBW-1:0] get_rand_mask(bit write);
+    bit [bus_params_pkg::BUS_DBW-1:0] mask;
+    `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(mask,
+        // mask to be contiguous
+        $countones(mask ^ {mask[bus_params_pkg::BUS_DBW-2:0], 1'b0}) <= 2;
+        mask dist {'1 :/ 100 - partial_access_pct,
+                   [0 : '1 - 1] :/ partial_access_pct};)
+    return mask;
+  endfunction
+
 endclass : sram_ctrl_base_vseq
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 43b7d28..3ad8182 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
@@ -97,6 +97,16 @@
       run_opts: ["+zero_delays=1"]
     }
     {
+      name: "{variant}_partial_write"
+      uvm_test_seq: sram_ctrl_smoke_vseq
+      run_opts: ["+partial_access_pct=90"]
+    }
+    {
+      name: "{variant}_partial_write_b2b"
+      uvm_test_seq: sram_ctrl_stress_pipeline_vseq
+      run_opts: ["+partial_access_pct=90"]
+    }
+    {
       name: "{variant}_lc_escalation"
       uvm_test_seq: sram_ctrl_lc_escalation_vseq
     }