Command filtering passthrough and start of scb for it

Signed-off-by: Kosta Kojdic <kosta.kojdic@ensilica.com>
diff --git a/hw/ip/spi_device/dv/env/seq_lib/spi_device_base_vseq.sv b/hw/ip/spi_device/dv/env/seq_lib/spi_device_base_vseq.sv
index 5c73fde..fd1f8d1 100644
--- a/hw/ip/spi_device/dv/env/seq_lib/spi_device_base_vseq.sv
+++ b/hw/ip/spi_device/dv/env/seq_lib/spi_device_base_vseq.sv
@@ -77,9 +77,19 @@
     core_spi_freq_ratio inside {[1:8]};
     spi_freq_faster -> core_spi_freq_ratio <= 4;
   }
+  // re-active sequence
+  spi_device_seq m_spi_device_seq;
 
   `uvm_object_new
 
+  virtual task start_reactive_seq();
+    // start device seq's
+    fork
+        m_spi_device_seq = spi_device_seq::type_id::create("m_spi_device_seq");
+        m_spi_device_seq.start(p_sequencer.spi_sequencer_d);
+    join
+  endtask // start_reactive_seq
+
   virtual task apply_reset(string kind = "HARD");
     super.apply_reset(kind);
   endtask
diff --git a/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_cmd_filtering_vseq.sv b/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_cmd_filtering_vseq.sv
new file mode 100644
index 0000000..9865ff8
--- /dev/null
+++ b/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_cmd_filtering_vseq.sv
@@ -0,0 +1,89 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Passthrough mode filtering of commands scenario, filter on and off
+class spi_device_pass_cmd_filtering_vseq extends spi_device_base_vseq;
+  `uvm_object_utils(spi_device_pass_cmd_filtering_vseq)
+  `uvm_object_new
+
+  virtual task cfg_cmd_filter(bit not_enable, bit[7:0] cmd);
+    bit [7:0] cmd_position;
+    bit [7:0] cmd_offset;
+    // Calculate filter bit position
+    cmd_position = cmd / 32;
+    cmd_offset = cmd % 32;
+    ral.cmd_filter[cmd_position].filter[cmd_offset].set(not_enable);
+    csr_update(.csr(ral.cmd_filter[cmd_position]));
+  endtask
+
+  virtual task body();
+    bit [31:0] device_word_rsp;
+    bit [7:0]  pass_cmd;
+    bit [23:0] pass_addr;
+    bit [31:0] address_command;
+
+    bit [31:0] host_data;
+    bit [31:0] device_data;
+    bit [31:0] device_data_exp;
+    uint       avail_bytes;
+    bit [31:0] host_data_exp_q[$];
+    fork
+      start_reactive_seq();
+    join_none
+
+    spi_device_init();
+
+    // Fixed config for this scenario
+    cfg.m_spi_agent_cfg.sck_polarity[0] = 0;
+    cfg.m_spi_agent_cfg.sck_phase[0] = 0;
+    cfg.m_spi_agent_cfg.host_bit_dir = 1;
+    cfg.m_spi_agent_cfg.device_bit_dir = 1;
+    ral.cfg.tx_order.set(1);
+    ral.cfg.rx_order.set(1);
+    ral.cfg.cpol.set(1'b0);
+    ral.cfg.cpha.set(1'b0);
+    csr_update(.csr(ral.cfg)); // TODO check if randomization possible
+
+    repeat (num_trans) begin
+      // Set the passthrough mode
+      ral.control.mode.set(PassthroughMode);
+      csr_update(.csr(ral.control));
+
+      // Randomize opcode and address
+      `DV_CHECK_STD_RANDOMIZE_FATAL(pass_addr)
+      `DV_CHECK_STD_RANDOMIZE_FATAL(pass_cmd)
+
+      // Configure unused CMD_INFO and enable this opcode
+      ral.cmd_info[11].valid.set(1'b1); // Enable this OPCODE
+      ral.cmd_info[11].opcode.set(pass_cmd);
+      ral.cmd_info[11].addr_mode.set(Addr3B); //  3B address for this scenario
+      csr_update(.csr(ral.cmd_info[11]));
+
+      // Make sure filter is not blocking command opcode
+      cfg_cmd_filter(0, pass_cmd);
+
+      // Prepare data for transfer
+      pass_cmd = {<<1{pass_cmd}};
+      pass_addr = {<<1{pass_addr}};
+      address_command = {pass_addr, pass_cmd};
+      spi_host_xfer_word(address_command, device_word_rsp);
+
+      cfg.clk_rst_vif.wait_clks(100);
+
+      // Set filtering of this command
+      cfg_cmd_filter(1, pass_cmd);
+      spi_host_xfer_word(address_command, device_word_rsp);
+
+      cfg.clk_rst_vif.wait_clks(100);
+
+      // Unset filtering and check if pass works again
+      cfg_cmd_filter(0, pass_cmd);
+      spi_host_xfer_word(address_command, device_word_rsp);
+
+      cfg.clk_rst_vif.wait_clks(100);
+    end
+
+  endtask : body
+
+endclass : spi_device_pass_cmd_filtering_vseq
diff --git a/hw/ip/spi_device/dv/env/seq_lib/spi_device_vseq_list.sv b/hw/ip/spi_device/dv/env/seq_lib/spi_device_vseq_list.sv
index 5658f0b..9bfea8c 100644
--- a/hw/ip/spi_device/dv/env/seq_lib/spi_device_vseq_list.sv
+++ b/hw/ip/spi_device/dv/env/seq_lib/spi_device_vseq_list.sv
@@ -22,3 +22,4 @@
 `include "spi_device_abort_vseq.sv"
 `include "spi_device_tpm_locality_vseq.sv"
 `include "spi_device_tpm_read_vseq.sv"
+`include "spi_device_pass_cmd_filtering_vseq.sv"
diff --git a/hw/ip/spi_device/dv/env/spi_device_env.core b/hw/ip/spi_device/dv/env/spi_device_env.core
index ac61ce9..94056e5 100644
--- a/hw/ip/spi_device/dv/env/spi_device_env.core
+++ b/hw/ip/spi_device/dv/env/spi_device_env.core
@@ -38,6 +38,7 @@
       - seq_lib/spi_device_abort_vseq.sv: {is_include_file: true}
       - seq_lib/spi_device_tpm_locality_vseq.sv: {is_include_file: true}
       - seq_lib/spi_device_tpm_read_vseq.sv: {is_include_file: true}
+      - seq_lib/spi_device_pass_cmd_filtering_vseq.sv: {is_include_file: true}
     file_type: systemVerilogSource
 
 generate:
diff --git a/hw/ip/spi_device/dv/env/spi_device_env.sv b/hw/ip/spi_device/dv/env/spi_device_env.sv
index 16afa6a..f36782b 100644
--- a/hw/ip/spi_device/dv/env/spi_device_env.sv
+++ b/hw/ip/spi_device/dv/env/spi_device_env.sv
@@ -33,6 +33,8 @@
           scoreboard.host_spi_data_fifo.analysis_export);
       m_spi_agent.monitor.device_analysis_port.connect(
           scoreboard.device_spi_data_fifo.analysis_export);
+      spi_device_agent.monitor.host_analysis_port.connect(
+          scoreboard.pass_spi_data_fifo.analysis_export);
     end
     if (cfg.m_spi_agent_cfg.is_active) begin
       virtual_sequencer.spi_sequencer_h = m_spi_agent.sequencer;
diff --git a/hw/ip/spi_device/dv/env/spi_device_env_pkg.sv b/hw/ip/spi_device/dv/env/spi_device_env_pkg.sv
index 2527bf8..fc76b39 100644
--- a/hw/ip/spi_device/dv/env/spi_device_env_pkg.sv
+++ b/hw/ip/spi_device/dv/env/spi_device_env_pkg.sv
@@ -51,6 +51,13 @@
     PassthroughMode
   } device_mode_e;
 
+  typedef enum {
+    AddrDisabled,
+    AddrCfg,
+    Addr3B,
+    Addr4B
+  } addr_mode_e;
+
   // alerts
   parameter uint NUM_ALERTS = 1;
   parameter string LIST_OF_ALERTS[] = {"fatal_fault"};
diff --git a/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv b/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv
index 68d5eb2..a3109b6 100644
--- a/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv
+++ b/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv
@@ -10,6 +10,7 @@
   // TLM fifos to pick up the packets
   uvm_tlm_analysis_fifo #(spi_item) host_spi_data_fifo;
   uvm_tlm_analysis_fifo #(spi_item) device_spi_data_fifo;
+  uvm_tlm_analysis_fifo #(spi_item) pass_spi_data_fifo;
 
   // mem model to save expected value
   local mem_model tx_mem;
@@ -30,6 +31,7 @@
     super.build_phase(phase);
     host_spi_data_fifo = new("host_spi_data_fifo", this);
     device_spi_data_fifo = new("device_spi_data_fifo", this);
+    pass_spi_data_fifo = new("pass_spi_data_fifo", this);
     tx_mem = mem_model#()::type_id::create("tx_mem", this);
     rx_mem = mem_model#()::type_id::create("rx_mem", this);
   endfunction
@@ -39,6 +41,7 @@
     fork
       process_host_spi_fifo();
       process_device_spi_fifo();
+      process_pass_spi_fifo();
     join_none
   endtask
 
@@ -62,6 +65,15 @@
     end
   endtask
 
+  virtual task process_pass_spi_fifo();
+    spi_item item;
+    forever begin
+      pass_spi_data_fifo.get(item);
+      //TODO Implement checking of passthrough data
+      `uvm_info(`gfn, $sformatf("received pass spi item:\n%0s", item.sprint()), UVM_HIGH)
+    end
+  endtask
+
   // process_tl_access:this task processes incoming access into the IP over tl interface
   // this is already called in cip_base_scoreboard::process_tl_a/d_chan_fifo tasks
   virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name);
diff --git a/hw/ip/spi_device/dv/spi_device_sim_cfg.hjson b/hw/ip/spi_device/dv/spi_device_sim_cfg.hjson
index e909f33..ba3ef0d 100644
--- a/hw/ip/spi_device/dv/spi_device_sim_cfg.hjson
+++ b/hw/ip/spi_device/dv/spi_device_sim_cfg.hjson
@@ -131,6 +131,11 @@
       name: spi_device_tpm_read
       uvm_test_seq: spi_device_tpm_read_vseq
     }
+    
+    {
+      name: spi_device_pass_cmd_filtering
+      uvm_test_seq: spi_device_pass_cmd_filtering_vseq
+    }
   ]
 
   // List of regressions.
diff --git a/hw/ip/spi_device/dv/tests/spi_device_base_test.sv b/hw/ip/spi_device/dv/tests/spi_device_base_test.sv
index 4c5bef3..d1e7453 100644
--- a/hw/ip/spi_device/dv/tests/spi_device_base_test.sv
+++ b/hw/ip/spi_device/dv/tests/spi_device_base_test.sv
@@ -15,6 +15,7 @@
     cfg.m_spi_agent_cfg.if_mode = Host;
     // configure passthrough agent to be in Device mode
     cfg.spi_device_agent_cfg.if_mode = Device;
+    cfg.spi_device_agent_cfg.has_req_fifo = 1'b1;
   endfunction
 
 endclass : spi_device_base_test