[spi_device/dv] Update for passthrough
1. support testing invalid opcodes
2. support dummy cycles
3. a few fixes
4. rename op_code -> opcode
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/dv/sv/spi_agent/seq_lib/spi_host_flash_seq.sv b/hw/dv/sv/spi_agent/seq_lib/spi_host_flash_seq.sv
index d4d7afb..0147361 100644
--- a/hw/dv/sv/spi_agent/seq_lib/spi_host_flash_seq.sv
+++ b/hw/dv/sv/spi_agent/seq_lib/spi_host_flash_seq.sv
@@ -4,13 +4,14 @@
class spi_host_flash_seq extends spi_base_seq;
- rand bit [7:0] op_code;
+ rand bit [7:0] opcode;
+ // if address isn't provided, will be randomized based on cmd_infos
rand bit [7:0] address_q[$];
rand bit [7:0] payload_q[$];
rand int read_size;
`uvm_object_utils_begin(spi_host_flash_seq)
- `uvm_field_int(op_code, UVM_DEFAULT)
+ `uvm_field_int(opcode, UVM_DEFAULT)
`uvm_field_int(read_size, UVM_DEFAULT)
`uvm_field_queue_int(payload_q, UVM_DEFAULT)
`uvm_field_queue_int(address_q, UVM_DEFAULT)
@@ -18,17 +19,32 @@
`uvm_object_new
virtual task body();
+ int addr_bytes, num_lanes, dummy_cycles;
+ bit write_command;
+
req = spi_item::type_id::create("req");
start_item(req);
+
+ cfg.extract_cmd_info_from_opcode(opcode,
+ // output
+ addr_bytes, write_command, num_lanes, dummy_cycles);
+ if (address_q.size() == 0) begin
+ `DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(address_q,
+ address_q.size == addr_bytes;)
+ end else begin
+ `DV_CHECK_EQ(address_q.size(), addr_bytes)
+ end
+
`DV_CHECK_RANDOMIZE_WITH_FATAL(req,
item_type == SpiFlashTrans;
- opcode == local::op_code;
- write_command == cfg.cmd_infos[op_code].write_command;
- address_q.size() == cfg.cmd_infos[op_code].addr_bytes;
+ opcode == local::opcode;
+ write_command == local::write_command;
+ num_lanes == local::num_lanes;
+ dummy_cycles == local::dummy_cycles;
+ address_q.size() == addr_bytes;
foreach (address_q[i]) {
address_q[i] == local::address_q[i];
}
- num_lanes == cfg.cmd_infos[op_code].num_lanes;
if (write_command) {
read_size == 0;
payload_q.size() == local::payload_q.size();
diff --git a/hw/dv/sv/spi_agent/spi_agent_cfg.sv b/hw/dv/sv/spi_agent/spi_agent_cfg.sv
index 3148a45..53bcb4f 100644
--- a/hw/dv/sv/spi_agent/spi_agent_cfg.sv
+++ b/hw/dv/sv/spi_agent/spi_agent_cfg.sv
@@ -136,9 +136,32 @@
endfunction : get_sio_size
virtual function void add_cmd_info(spi_flash_cmd_info info);
- // op_code must be unique
- `DV_CHECK_EQ(cmd_infos.exists(info.op_code), 0)
- cmd_infos[info.op_code] = info;
+ // opcode must be unique
+ `DV_CHECK_EQ(is_opcode_supported(info.opcode), 0)
+ cmd_infos[info.opcode] = info;
endfunction : add_cmd_info
+ virtual function bit is_opcode_supported(bit [7:0] opcode);
+ return cmd_infos.exists(opcode);
+ endfunction : is_opcode_supported
+
+ virtual function void extract_cmd_info_from_opcode(input bit [7:0] opcode,
+ output bit [2:0] addr_bytes,
+ output bit write_command,
+ output bit [2:0] num_lanes,
+ output int dummy_cycles);
+ if (cmd_infos.exists(opcode)) begin
+ addr_bytes = cmd_infos[opcode].addr_bytes;
+ write_command = cmd_infos[opcode].write_command;
+ num_lanes = cmd_infos[opcode].num_lanes;
+ dummy_cycles = cmd_infos[opcode].dummy_cycles;
+ end else begin
+ // if it's invalid opcode, here is the default setting
+ `uvm_info(`gfn, $sformatf("extract invalid opcode: 0x%0h", opcode), UVM_MEDIUM)
+ write_command = 1;
+ addr_bytes = 0;
+ num_lanes = 1;
+ dummy_cycles = 0;
+ end
+ endfunction : extract_cmd_info_from_opcode
endclass : spi_agent_cfg
diff --git a/hw/dv/sv/spi_agent/spi_flash_cmd_info.sv b/hw/dv/sv/spi_agent/spi_flash_cmd_info.sv
index 021b0b5..c36f8c5 100644
--- a/hw/dv/sv/spi_agent/spi_flash_cmd_info.sv
+++ b/hw/dv/sv/spi_agent/spi_flash_cmd_info.sv
@@ -5,11 +5,11 @@
// this object stores the cfg info for a command, so that when a driver/monitor receives a flash
// cmd, it knows how many addr_bytes, direction, dummy_cycles etc
class spi_flash_cmd_info extends uvm_sequence_item;
- rand bit [7:0] op_code;
+ rand bit [7:0] opcode;
rand bit [2:0] addr_bytes;
rand bit write_command;
- rand bit [2:0] dummy_cycles; // TODO add support in driver and monitor
rand bit [2:0] num_lanes;
+ rand int dummy_cycles; // TODO add support in driver and monitor
rand bit addr_swap;
rand bit data_swap;
@@ -29,14 +29,20 @@
data_swap -> num_lanes == 1 && write_command == 1;
}
+ constraint dummy_cycles_c {
+ dummy_cycles dist {
+ 0 :/ 2,
+ [1:8] :/ 2,
+ [9:100] :/ 1
+ };
+ }
// TODO, simplify setting. Remove this later
constraint simplify_c {
addr_swap == 0;
data_swap == 0;
- dummy_cycles == 0;
}
`uvm_object_utils_begin(spi_flash_cmd_info)
- `uvm_field_int(op_code, UVM_DEFAULT)
+ `uvm_field_int(opcode, UVM_DEFAULT)
`uvm_field_int(addr_bytes, UVM_DEFAULT)
`uvm_field_int(write_command, UVM_DEFAULT)
`uvm_field_int(dummy_cycles, UVM_DEFAULT)
diff --git a/hw/dv/sv/spi_agent/spi_host_driver.sv b/hw/dv/sv/spi_agent/spi_host_driver.sv
index f80b637..bbba068 100644
--- a/hw/dv/sv/spi_agent/spi_host_driver.sv
+++ b/hw/dv/sv/spi_agent/spi_host_driver.sv
@@ -130,29 +130,40 @@
endtask
task drive_flash_item();
- bit [7:0] drive_data[$];
+ bit [7:0] cmd_addr_bytes[$];
`uvm_info(`gfn, $sformatf("Driving flash item: \n%s", req.sprint()), UVM_MEDIUM)
cfg.vif.csb[cfg.csb_sel] <= 1'b0;
- drive_data = {req.opcode, req.address_q, req.payload_q};
- sck_pulses = drive_data.size() * 8;
- if (!req.write_command) begin
+ cmd_addr_bytes = {req.opcode, req.address_q};
+ sck_pulses = cmd_addr_bytes.size() * 8 + req.dummy_cycles;
+ if (req.write_command) begin
+ `DV_CHECK_EQ(req.num_lanes, 1)
+ sck_pulses += req.payload_q.size * 8;
+ end else begin
`DV_CHECK_EQ(req.payload_q.size, 0)
- sck_pulses = sck_pulses + req.read_size * (8 / req.num_lanes);
+ sck_pulses += req.read_size * (8 / req.num_lanes);
end
// for mode 1 and 3, get the leading edges out of the way
cfg.wait_sck_edge(LeadingEdge);
+ // driver cmd and address
+ issue_data(cmd_addr_bytes);
+
+ // align to DrivingEdge, if the item has more to send
+ if (req.dummy_cycles > 0 || req.payload_q.size > 0 ) cfg.wait_sck_edge(DrivingEdge);
+
+ repeat (req.dummy_cycles) begin
+ //cfg.vif.sio <= 'dz;
+ cfg.wait_sck_edge(DrivingEdge);
+ end
// drive data
- issue_data(drive_data);
+ issue_data(req.payload_q);
wait(sck_pulses == 0);
- if (cfg.csb_consecutive == 0) begin
- cfg.vif.csb[cfg.csb_sel] <= 1'b1;
- cfg.vif.sio[0] <= 1'bx;
- end
+ cfg.vif.csb[cfg.csb_sel] <= 1'b1;
+ cfg.vif.sio <= 'dx;
endtask
task drive_sck_no_csb_item();
diff --git a/hw/dv/sv/spi_agent/spi_item.sv b/hw/dv/sv/spi_agent/spi_item.sv
index 7fa207d..6e120e9 100644
--- a/hw/dv/sv/spi_agent/spi_item.sv
+++ b/hw/dv/sv/spi_agent/spi_item.sv
@@ -17,7 +17,9 @@
rand bit [7:0] address_q[$];
rand bit [7:0] opcode;
rand bit [2:0] num_lanes; // 1,2 or 4 lanes for read response
+ rand int dummy_cycles;
+ // for dummy transaction
rand uint dummy_clk_cnt;
rand uint dummy_sck_length_ns;
@@ -43,6 +45,7 @@
`uvm_field_int(write_command, UVM_DEFAULT)
`uvm_field_int(opcode, UVM_DEFAULT)
`uvm_field_int(num_lanes, UVM_DEFAULT)
+ `uvm_field_int(dummy_cycles, UVM_DEFAULT)
`uvm_field_queue_int(payload_q, UVM_DEFAULT)
`uvm_field_queue_int(address_q, UVM_DEFAULT)
`uvm_object_utils_end
diff --git a/hw/dv/sv/spi_agent/spi_monitor.sv b/hw/dv/sv/spi_agent/spi_monitor.sv
index e6a17f9..ba12062 100644
--- a/hw/dv/sv/spi_agent/spi_monitor.sv
+++ b/hw/dv/sv/spi_agent/spi_monitor.sv
@@ -189,24 +189,31 @@
fork
begin: isolation_thread
spi_item item = spi_item::type_id::create("host_item", this);
- bit [7:0] opcode;
bit opcode_received;
fork
begin: csb_deassert_thread
wait(cfg.vif.csb[cfg.csb_sel] == 1'b1);
end
begin: sample_thread
+ int addr_bytes;
opcode_received = 0;
+ item.item_type = SpiFlashTrans;
// for mode 1 and 3, get the leading edges out of the way
cfg.wait_sck_edge(LeadingEdge);
// first byte is opcode. opcode or address is always sent on single mode
- sample_flash_one_byte_data(.num_lanes(1), .is_device_rsp(0), .data(opcode));
+ sample_flash_one_byte_data(.num_lanes(1), .is_device_rsp(0), .data(item.opcode));
opcode_received = 1;
- extract_flash_cmd_info_via_opcode(item, opcode);
- `uvm_info(`gfn, $sformatf("sampled flash opcode: 0x%0h", opcode), UVM_MEDIUM)
+ cfg.extract_cmd_info_from_opcode(item.opcode,
+ // output
+ addr_bytes, item.write_command, item.num_lanes, item.dummy_cycles);
+ `uvm_info(`gfn, $sformatf("sampled flash opcode: 0x%0h", item.opcode), UVM_MEDIUM)
- sample_flash_address(cfg.cmd_infos[opcode].addr_bytes, item.address_q);
+ sample_flash_address(addr_bytes, item.address_q);
+
+ repeat (item.dummy_cycles) begin
+ cfg.wait_sck_edge(SamplingEdge);
+ end
req_analysis_port.write(item);
forever begin
@@ -227,36 +234,28 @@
join
endtask : collect_flash_trans
- virtual function void extract_flash_cmd_info_via_opcode(spi_item item, bit[7:0] opcode);
- `DV_CHECK_FATAL(cfg.cmd_infos.exists(opcode))
- item.item_type = SpiFlashTrans;
- item.opcode = opcode;
- item.num_lanes = cfg.cmd_infos[opcode].num_lanes;
- item.write_command = cfg.cmd_infos[opcode].write_command;
- endfunction : extract_flash_cmd_info_via_opcode
-
virtual task sample_flash_one_byte_data(input int num_lanes, input bit is_device_rsp,
- output byte data);
+ output bit[7:0] data);
+ int which_bit = 8;
for (int i = 0; i < 8; i += num_lanes) begin
- int which_bit = cfg.host_bit_dir ? i : 7 - i;
cfg.wait_sck_edge(SamplingEdge);
- data[which_bit] = cfg.vif.sio[0];
case(num_lanes)
- 1: data[which_bit] = is_device_rsp ? cfg.vif.sio[1] : cfg.vif.sio[0];
+ 1: data[--which_bit] = is_device_rsp ? cfg.vif.sio[1] : cfg.vif.sio[0];
2: begin
- data[which_bit] = cfg.vif.sio[0];
- data[which_bit + 1] = cfg.vif.sio[1];
+ data[--which_bit] = cfg.vif.sio[1];
+ data[--which_bit] = cfg.vif.sio[0];
end
4: begin
- data[which_bit] = cfg.vif.sio[0];
- data[which_bit + 1] = cfg.vif.sio[1];
- data[which_bit + 2] = cfg.vif.sio[2];
- data[which_bit + 3] = cfg.vif.sio[3];
+ data[--which_bit] = cfg.vif.sio[3];
+ data[--which_bit] = cfg.vif.sio[2];
+ data[--which_bit] = cfg.vif.sio[1];
+ data[--which_bit] = cfg.vif.sio[0];
end
default: `uvm_fatal(`gfn, $sformatf("Unsupported lanes num 0x%0h", num_lanes))
endcase
end
- `uvm_info(`gfn, $sformatf("sampled one byte data for flash: 0x%0h", data), UVM_HIGH)
+ `DV_CHECK_EQ(which_bit, 0)
+ `uvm_info(`gfn, $sformatf("sampled one byte data for flash: 0x%0h", data), UVM_MEDIUM)
endtask : sample_flash_one_byte_data
// address is 3 or 4 bytes
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 78230c5..215ac10 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
@@ -223,13 +223,12 @@
endtask
// transfer in command including opcode, address and payload
- virtual task spi_host_xfer_flash_item(bit [7:0] op, bit [7:0] addr_size,
- uint payload_size);
+ virtual task spi_host_xfer_flash_item(bit [7:0] op, uint payload_size);
spi_host_flash_seq m_spi_host_seq;
`uvm_create_on(m_spi_host_seq, p_sequencer.spi_sequencer_h)
`DV_CHECK_RANDOMIZE_WITH_FATAL(m_spi_host_seq,
- op_code == op;
- address_q.size() == addr_size;
+ opcode == op;
+ address_q.size() == 0;
payload_q.size() == payload_size;
read_size == payload_size;)
`uvm_send(m_spi_host_seq)
diff --git a/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_base_vseq.sv b/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_base_vseq.sv
index 6df9ac0..59e89d1 100644
--- a/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_base_vseq.sv
+++ b/hw/ip/spi_device/dv/env/seq_lib/spi_device_pass_base_vseq.sv
@@ -4,6 +4,12 @@
// Passthrough base sequence
class spi_device_pass_base_vseq extends spi_device_base_vseq;
+ // only enable this in 1-2 tests
+ bit allow_set_cmd_info_invalid;
+ bit allow_use_invalid_opcode;
+
+ bit [7:0] valid_opcode_q[$];
+
`uvm_object_utils(spi_device_pass_base_vseq)
`uvm_object_new
@@ -13,86 +19,88 @@
// Configure the first 11 commands which are fixed
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes == 0 &&
- info.op_code == READ_STATUS_1 &&
+ info.opcode == READ_STATUS_1 &&
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 0);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes == 0 &&
- info.op_code == READ_STATUS_2;
+ info.opcode == READ_STATUS_2;
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 1);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes == 0 &&
- info.op_code == READ_STATUS_3 &&
+ info.opcode == READ_STATUS_3 &&
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 2);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes == 0 &&
- info.op_code == READ_JEDEC &&
+ info.opcode == READ_JEDEC &&
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 3);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes == 0 &&
- info.op_code == READ_SFDP;
+ info.opcode == READ_SFDP;
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 4);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_NORMAL &&
+ info.opcode == READ_NORMAL &&
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 5);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_FAST &&
+ info.opcode == READ_FAST &&
info.num_lanes == 1 &&
info.write_command == 0;)
add_cmd_info(info, 6);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_DUAL &&
+ info.opcode == READ_DUAL &&
info.write_command == 0 &&
info.num_lanes == 2;)
add_cmd_info(info, 7);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_QUAD &&
+ info.opcode == READ_QUAD &&
info.write_command == 0 &&
info.num_lanes == 4;)
add_cmd_info(info, 8);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_DUALIO &&
+ info.opcode == READ_DUALIO &&
info.write_command == 0 &&
info.num_lanes == 2;)
add_cmd_info(info, 9);
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
info.addr_bytes > 0 &&
- info.op_code == READ_QUADIO &&
+ info.opcode == READ_QUADIO &&
info.write_command == 0 &&
info.num_lanes == 4;)
add_cmd_info(info, 10);
for (int i = 11; i < 24; i++) begin
info = spi_flash_cmd_info::type_id::create("info");
`DV_CHECK_RANDOMIZE_WITH_FATAL(info,
- foreach (cfg.spi_host_agent_cfg.cmd_infos[j]) {info.op_code != j;})
+ foreach (cfg.spi_host_agent_cfg.cmd_infos[j]) {info.opcode != j;})
add_cmd_info(info, i);
end
+
+ valid_opcode_q = cfg.spi_host_agent_cfg.cmd_infos.find_index() with ('1);
endtask : config_all_cmd_infos
// Task for flash or pass init
@@ -136,6 +144,7 @@
spi_device_flash_auto_rsp_nonblocking();
randomize_mem();
+ randomize_all_cmd_filters();
endtask : spi_device_flash_pass_init
// Task for configuring enable/disable of command opcode
@@ -149,6 +158,13 @@
csr_update(.csr(ral.cmd_filter[cmd_index]));
endtask : cfg_cmd_filter
+ virtual task randomize_all_cmd_filters();
+ foreach (ral.cmd_filter[idx]) begin
+ `DV_CHECK_RANDOMIZE_FATAL(ral.cmd_filter[idx])
+ csr_update(.csr(ral.cmd_filter[idx]));
+ end
+ endtask : randomize_all_cmd_filters
+
// Task for keeping opcode integrity regardless of rx_order config
virtual task order_cmd_bits(bit [7:0] pass_cmd, bit[23:0] pass_addr, ref bit [31:0] addr_cmd);
bit rx_order;
@@ -176,8 +192,15 @@
virtual task add_cmd_info(spi_flash_cmd_info info, bit [4:0] idx);
bit [3:0] lanes_en;
addr_mode_e addr_size;
- cfg.spi_host_agent_cfg.add_cmd_info(info);
- cfg.spi_device_agent_cfg.add_cmd_info(info);
+ bit valid;
+
+ if (allow_set_cmd_info_invalid) valid = $urandom_range(0, 1);
+ else valid = 1;
+
+ if (valid) begin
+ cfg.spi_host_agent_cfg.add_cmd_info(info);
+ cfg.spi_device_agent_cfg.add_cmd_info(info);
+ end
`uvm_info(`gfn, $sformatf("Add this cmd_info \n%s", info.sprint()), UVM_MEDIUM)
case (info.num_lanes)
@@ -192,7 +215,6 @@
4: addr_size = Addr4B;
default : `uvm_fatal(`gfn, $sformatf("Unsupported addr bytes 0x%0h", info.addr_bytes))
endcase
- ral.cmd_info[idx].addr_mode.set(addr_size);
// if addr_size is aligned with addr_4b_en, we could use AddrCfg instead of Addr4B/Addr3B
if (`gmv(ral.cfg.addr_4b_en) == 1 && addr_size == Addr4B ||
`gmv(ral.cfg.addr_4b_en) == 0 && addr_size == Addr3B) begin
@@ -200,8 +222,8 @@
end
ral.cmd_info[idx].addr_mode.set(addr_size);
- ral.cmd_info[idx].valid.set(1'b1); // Enable this OPCODE
- ral.cmd_info[idx].opcode.set(info.op_code);// Read Dual
+ ral.cmd_info[idx].valid.set(valid); // Enable this OPCODE
+ ral.cmd_info[idx].opcode.set(info.opcode);// Read Dual
ral.cmd_info[idx].payload_en.set(lanes_en);
ral.cmd_info[idx].payload_dir.set(!info.write_command);
ral.cmd_info[idx].addr_swap_en.set(info.addr_swap);
@@ -209,4 +231,34 @@
csr_update(.csr(ral.cmd_info[idx]));
endtask : add_cmd_info
+ function bit [7:0] get_rand_opcode();
+ bit valid_op;
+ bit [7:0] op;
+
+ if (allow_use_invalid_opcode) begin
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(valid_op,
+ valid_op dist {1 :/ 4, 0 :/ 1};)
+ end else begin
+ valid_op = 1;
+ end
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(op,
+ if (valid_op) {
+ op inside {valid_opcode_q};
+ } else {
+ !(op inside {valid_opcode_q});
+ })
+ return op;
+ endfunction
+
+ function int get_rand_payload_size();
+ uint size;
+ `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(size,
+ size dist {
+ [0:5] :/ 2,
+ 128 :/ 1,
+ 256 :/ 2, // typical value for a flash page size
+ 512 :/ 1,
+ [6:1000] :/ 1};)
+ return size;
+ endfunction
endclass : spi_device_pass_base_vseq
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
index d9317d3..0107576 100644
--- 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
@@ -9,28 +9,27 @@
virtual task body();
bit [7:0] op;
- bit [7:0] opcode_q[$];
uint payload_size;
+
+ allow_set_cmd_info_invalid = 1;
+ allow_use_invalid_opcode = 1;
spi_device_flash_pass_init(PassthroughMode);
- // cmd_infos index is the opcode, get all opcode
- opcode_q = cfg.spi_host_agent_cfg.cmd_infos.find_index() with ('1);
for (int i = 0; i < num_trans; ++i) begin
- `uvm_info(`gfn, $sformatf("running iteration %0d", i), UVM_LOW)
- `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(op,
- op inside {opcode_q};)
- `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(payload_size,
- // TODO, use distribution later
- payload_size <= 256;)
+ op = get_rand_opcode;
+ `uvm_info(`gfn, $sformatf("running iteration %0d, test op = 0x%0h", i, op), UVM_LOW)
+ payload_size = 1; //get_rand_payload_size();
// test 2 cases:
// - disable cmd filter, test cmd passthrough to downstream
// - enable cmd filter, test cmd is blocked
for (int cmd_filter = 0; cmd_filter < 2; cmd_filter++) begin
// Make sure filter is not blocking command opcode
+ `uvm_info(`gfn, $sformatf("sending op 0x%0h with filter = %0d", op, cmd_filter), UVM_MEDIUM)
cfg_cmd_filter(cmd_filter, op);
// Prepare data for transfer
- spi_host_xfer_flash_item(op, cfg.spi_host_agent_cfg.cmd_infos[op].addr_bytes, payload_size);
+ spi_host_xfer_flash_item(op, payload_size);
+ cfg.clk_rst_vif.wait_clks(10);
end
end
diff --git a/hw/ip/spi_device/dv/env/seq_lib/spi_device_tpm_base_vseq.sv b/hw/ip/spi_device/dv/env/seq_lib/spi_device_tpm_base_vseq.sv
index 2a48ecc..e3da9d6 100644
--- a/hw/ip/spi_device/dv/env/seq_lib/spi_device_tpm_base_vseq.sv
+++ b/hw/ip/spi_device/dv/env/seq_lib/spi_device_tpm_base_vseq.sv
@@ -23,8 +23,8 @@
virtual task tpm_init();
cfg.spi_host_agent_cfg.sck_polarity[0] = 0;
cfg.spi_host_agent_cfg.sck_phase[0] = 0;
- cfg.spi_host_agent_cfg.host_bit_dir = 1;
- cfg.spi_host_agent_cfg.device_bit_dir = 1;
+ cfg.spi_host_agent_cfg.host_bit_dir = 0;
+ cfg.spi_host_agent_cfg.device_bit_dir = 0;
ral.cfg.tx_order.set(1);
ral.cfg.rx_order.set(1);
ral.cfg.cpol.set(1'b0);
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 3b79297..049a4c5 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
@@ -153,12 +153,12 @@
endfunction
// return the index the cmd_filter for the input opcode
- function automatic int get_cmd_filter_index(bit[7:0] opcode);
+ function automatic int get_cmd_filter_index(bit[7:0] opcode);
return opcode / 32;
endfunction
// return the field offset of the cmd_filter for the input opcode
- function automatic int get_cmd_filter_offset(bit[7:0] opcode);
+ function automatic int get_cmd_filter_offset(bit[7:0] opcode);
return opcode % 32;
endfunction
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 911e591..087b167 100644
--- a/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv
+++ b/hw/ip/spi_device/dv/env/spi_device_scoreboard.sv
@@ -77,7 +77,11 @@
function bit is_opcode_passthrough(bit[7:0] opcode);
int cmd_index = get_cmd_filter_index(opcode);
int cmd_offset = get_cmd_filter_offset(opcode);
- return !(`gmv(ral.cmd_filter[cmd_index].filter[cmd_offset]));
+ bit filter = `gmv(ral.cmd_filter[cmd_index].filter[cmd_offset]);
+ bit valid_cmd = cfg.spi_host_agent_cfg.is_opcode_supported(opcode);
+
+ `uvm_info(`gfn, $sformatf("opcode filter: %0d, valid: %0d", filter, valid_cmd), UVM_MEDIUM)
+ return !filter && valid_cmd;
endfunction
// extract spi items sent from device
@@ -104,7 +108,10 @@
`DV_CHECK_EQ(spi_passthrough_upstream_q.size, 1)
upstream_item = spi_passthrough_upstream_q.pop_front();
- `DV_CHECK_EQ(downstream_item.compare(upstream_item), 1)
+ if (!downstream_item.compare(upstream_item)) begin
+ `uvm_error(`gfn, $sformatf("Compare item failed\ndownstream item:\n%s, upstream item:\n%s",
+ downstream_item.sprint(), upstream_item.sprint()))
+ end
end
endtask