[dv] Flash_ctrl enable polling before read/program

This PR switches randomly between backpressured reads / writes and
backpressured reads / writes.

Signed-off-by: Srikrishna Iyer <sriyer@google.com>
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
index 075802e..d5bc9cc 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
@@ -42,7 +42,7 @@
   parameter uint FlashMemAddrBankMsbBit   = FlashDataByteWidth + FlashWordLineWidth +
                                             FlashPageWidth + FlashBankWidth - 1;
 
-// types
+  // types
   typedef enum int {
     FlashCtrlIntrProgEmpty  = 0,
     FlashCtrlIntrProgLvl    = 1,
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_seq_cfg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_seq_cfg.sv
index b33ce0a..5889d00 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_seq_cfg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_seq_cfg.sv
@@ -42,6 +42,9 @@
   uint op_erase_type_bank_pc = 0;
   uint op_max_words = 512;
 
+  // Poll fifo status before writing to prog_fifo / reading from rd_fifo.
+  uint poll_fifo_status_pc = 30;
+
   `uvm_object_new
 
 endclass
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
index e2b579f..cccb523 100644
--- a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
@@ -113,6 +113,7 @@
 
   // Wait for prog fifo to not be full.
   virtual task wait_flash_ctrl_prog_fifo_not_full();
+    // TODO: if intr enabled, then check interrupt, else check status.
     bit prog_full;
     `DV_SPINWAIT(
       do begin
@@ -124,6 +125,7 @@
 
   // Wait for rd fifo to not be empty.
   virtual task wait_flash_ctrl_rd_fifo_not_empty();
+    // TODO: if intr enabled, then check interrupt, else check status.
     bit read_empty;
     `DV_SPINWAIT(
       do begin
@@ -149,12 +151,13 @@
 
   // Program data into flash, stopping whenever full.
   // The flash op is assumed to have already commenced.
-  virtual task flash_ctrl_write(bit [TL_DW-1:0] data[$]);
+  virtual task flash_ctrl_write(bit [TL_DW-1:0] data[$], bit poll_fifo_status);
     foreach (data[i]) begin
       // Check if prog fifo is full. If yes, then wait for space to become available.
-      // TODO: interface is backpressure enabled, so the above check is not needed atm.
-      // TODO: if intr enabled, then check interrupt, else check status.
-      // wait_flash_ctrl_prog_fifo_not_full();
+      // Note that this polling is not needed since the interface is backpressure enabled.
+      if (poll_fifo_status) begin
+        wait_flash_ctrl_prog_fifo_not_full();
+      end
       mem_wr(.ptr(ral.prog_fifo), .offset(0), .data(data[i]));
       `uvm_info(`gfn, $sformatf("flash_ctrl_write: 0x%0h", data[i]), UVM_MEDIUM)
     end
@@ -162,12 +165,13 @@
 
   // Read data from flash, stopping whenever empty.
   // The flash op is assumed to have already commenced.
-  virtual task flash_ctrl_read(uint num_words, ref bit [TL_DW-1:0] data[$]);
+  virtual task flash_ctrl_read(uint num_words, ref bit [TL_DW-1:0] data[$], bit poll_fifo_status);
     for (int i = 0; i < num_words; i++) begin
       // Check if rd fifo is empty. If yes, then wait for data to become available.
-      // TODO: interface is backpressure enabled, so the above check is not needed atm.
-      // TODO: if intr enabled, then check interrupt, else check status.
-      // wait_flash_ctrl_rd_fifo_not_empty();
+      // Note that this polling is not needed since the interface is backpressure enabled.
+      if (poll_fifo_status) begin
+        wait_flash_ctrl_rd_fifo_not_empty();
+      end
       mem_rd(.ptr(ral.rd_fifo), .offset(0), .data(data[i]));
       `uvm_info(`gfn, $sformatf("flash_ctrl_read: 0x%0h", data[i]), UVM_MEDIUM)
     end
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_rand_ops_vseq.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_rand_ops_vseq.sv
index 1dc1643..374da5a 100644
--- a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_rand_ops_vseq.sv
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_rand_ops_vseq.sv
@@ -178,6 +178,18 @@
     read_fifo_intr_level < flash_ctrl_pkg::FifoDepth;
   }
 
+  // Indicates whether to poll before writing to prog_fifo or reading from rd_fifo. If interupts are
+  // enabled, the interrupt signals will be used instead. When set to 0, it will continuously write
+  // to prog_fifo / read from rd_fifo, relying on their natural backpressure mechanism.
+  rand bit poll_fifo_status;
+
+  constraint poll_fifo_status_c {
+    poll_fifo_status dist {
+      0 :/ (100 - cfg.seq_cfg.poll_fifo_status_pc),
+      1 :/ cfg.seq_cfg.poll_fifo_status_pc
+    };
+  }
+
   `uvm_object_new
 
   task body();
@@ -213,12 +225,14 @@
         flash_ctrl_start_op(flash_op);
         case (flash_op.op)
           flash_ctrl_pkg::FlashOpRead: begin
-            flash_ctrl_read(flash_op.num_words, flash_op_data);
+            `DV_CHECK_MEMBER_RANDOMIZE_FATAL(poll_fifo_status)
+            flash_ctrl_read(flash_op.num_words, flash_op_data, poll_fifo_status);
             wait_flash_op_done();
             flash_mem_bkdr_read_check(flash_op, flash_op_data);
           end
           flash_ctrl_pkg::FlashOpProgram: begin
-            flash_ctrl_write(flash_op_data);
+            `DV_CHECK_MEMBER_RANDOMIZE_FATAL(poll_fifo_status)
+            flash_ctrl_write(flash_op_data, poll_fifo_status);
             wait_flash_op_done();
             flash_mem_bkdr_read_check(flash_op, flash_op_data);
           end
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_sanity_vseq.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_sanity_vseq.sv
index f9899eb..b5f3711 100644
--- a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_sanity_vseq.sv
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_sanity_vseq.sv
@@ -29,6 +29,8 @@
 
     // Allow banks to be erased.
     cfg.seq_cfg.bank_erase_en_pc = 100;
+
+    cfg.seq_cfg.poll_fifo_status_pc = 0;
   endfunction
 
 endclass : flash_ctrl_sanity_vseq