[spi_host/dv] Enhanced Smoke Test
- Added Speed Test
- Added Constraints to Segment Item
- Added Quad And Dual To Device Resp Seq
- Added Tag For Cover Points To Speed Test
Signed-off-by: Viswanadha Bazawada <viswanadha.bazawada@ensilica.com>
diff --git a/hw/dv/sv/spi_agent/seq_lib/spi_device_cmd_rsp_seq.sv b/hw/dv/sv/spi_agent/seq_lib/spi_device_cmd_rsp_seq.sv
index 02e376b..7ffa4c7 100644
--- a/hw/dv/sv/spi_agent/seq_lib/spi_device_cmd_rsp_seq.sv
+++ b/hw/dv/sv/spi_agent/seq_lib/spi_device_cmd_rsp_seq.sv
@@ -78,7 +78,7 @@
SpiData: begin
case (cmd)
- ReadStd: begin
+ ReadStd, ReadDual, ReadQuad: begin
// read_until CSB low
data = $urandom();
addr_cnt += 4;
@@ -100,7 +100,7 @@
end
end
- WriteStd: begin
+ WriteStd, WriteDual, WriteQuad: begin
get_nxt_req(item);
if (item.first_byte) begin
// decode command
diff --git a/hw/ip/spi_host/data/spi_host_testplan.hjson b/hw/ip/spi_host/data/spi_host_testplan.hjson
index 9d49fbf..61a7469 100644
--- a/hw/ip/spi_host/data/spi_host_testplan.hjson
+++ b/hw/ip/spi_host/data/spi_host_testplan.hjson
@@ -77,7 +77,7 @@
- verify that the DUT can handle different sck -> cs_n timings
'''
milestone: V2
- tests: []
+ tests: ["spi_host_speed"]
}
{
name: speed
@@ -89,7 +89,7 @@
- verify that all speeds are supported
'''
milestone: V2
- tests: []
+ tests: ["spi_host_speed"]
}
{
name: chip_select_timing
@@ -101,7 +101,7 @@
- Check that the DUT operates correctly under different SPI clock speeds
'''
milestone: V2
- tests: []
+ tests: ["spi_host_speed"]
}
{
name: sw_reset
@@ -143,7 +143,7 @@
- Check that the DUT operates correctly under different cs_n settings
'''
milestone: V2
- tests: []
+ tests: ["spi_host_speed"]
}
{
name: full_cycle
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_smoke_vseq.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_smoke_vseq.sv
index 70fce53..5cce96f 100644
--- a/hw/ip/spi_host/dv/env/seq_lib/spi_host_smoke_vseq.sv
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_smoke_vseq.sv
@@ -7,21 +7,26 @@
`uvm_object_utils(spi_host_smoke_vseq)
`uvm_object_new
- int num_transactions = 2;
-
virtual task body();
fork
- begin: isolation_fork
+ begin : isolation_fork
fork
start_reactive_seq();
join_none
- wait_ready_for_command();
- start_spi_host_trans(num_transactions);
- read_rx_fifo();
+ begin
+ wait_ready_for_command();
+ start_spi_host_trans(num_trans);
+ csr_spinwait(.ptr(ral.status.active), .exp_data(1'b0));
+ csr_spinwait(.ptr(ral.status.rxqd), .exp_data(8'h0));
+ cfg.clk_rst_vif.wait_clks(100);
+ end
disable fork;
end
+ begin
+ read_rx_fifo();
+ end
join
endtask : body
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_speed_vseq.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_speed_vseq.sv
new file mode 100644
index 0000000..d241442
--- /dev/null
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_speed_vseq.sv
@@ -0,0 +1,21 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// speed test vseq
+class spi_host_speed_vseq extends spi_host_smoke_vseq;
+ `uvm_object_utils(spi_host_speed_vseq)
+ `uvm_object_new
+
+ int num_transactions = 2;
+
+ virtual task start_spi_host_trans(int num_transactions);
+ cfg.seq_cfg.std_en = 1;
+ cfg.seq_cfg.dual_en = 1;
+ //TODO: enable quad_en
+ cfg.seq_cfg.quad_en = 0;
+ super.start_spi_host_trans(num_transactions);
+ endtask
+
+endclass : spi_host_speed_vseq
+
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
index f969594..3e9737c 100644
--- a/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
@@ -26,26 +26,33 @@
cfg.seq_cfg.host_spi_min_len = 4;
cfg.seq_cfg.host_spi_max_len = 16;
- for(int n = 0; n < num_transactions; n++) begin
+ for (int n = 0; n < num_transactions; n++) begin
generate_transaction();
send_trans(transaction);
- cfg.clk_rst_vif.wait_clks(100);
+ wait_ready_for_command();
end
endtask
virtual task read_rx_fifo();
- bit [7:0] fifo_entries = 0;
bit [7:0] read_q[$];
+ bit active = 0;
+ bit rxempty;
+ spi_host_status_t status;
- csr_rd(.ptr(ral.status.rxqd), .value(fifo_entries));
- do begin
- for(int i = 0; i <fifo_entries; i++) begin
- access_data_fifo(read_q, RxFifo);
+ csr_spinwait(.ptr(ral.status.active), .exp_data(1'b1));
+ csr_spinwait(.ptr(ral.status.rxempty), .exp_data(1'b0));
+ forever begin
+ do begin
+ csr_rd(.ptr(ral.status), .value(status));
+ for (int i = 0; i < status.rx_qd; i++) begin
+ access_data_fifo(read_q, RxFifo);
+ end
+ end while (status.rx_qd > 0);
+ if (!status.active && status.rxempty && (status.rx_qd == 0)) begin
+ break;
end
- csr_spinwait(.ptr(ral.status.active), .exp_data(1'b0));
- csr_rd(.ptr(ral.status.rxqd), .value(fifo_entries));
- end while (fifo_entries > 0 );
+ end // forever loop
// wait for all accesses to complete
wait_no_outstanding_access();
@@ -65,7 +72,7 @@
// lock fifo to this seq
spi_host_atomic.get(1);
// write data to fifo
- if(segment.command_reg.direction != RxOnly) begin
+ if (segment.command_reg.direction != RxOnly) begin
access_data_fifo(segment.spi_data, TxFifo);
end
program_command_reg(segment.command_reg);
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_vseq_list.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_vseq_list.sv
index 80c1683..b738552 100644
--- a/hw/ip/spi_host/dv/env/seq_lib/spi_host_vseq_list.sv
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_vseq_list.sv
@@ -5,4 +5,5 @@
`include "spi_host_base_vseq.sv"
`include "spi_host_tx_rx_vseq.sv"
`include "spi_host_smoke_vseq.sv"
+`include "spi_host_speed_vseq.sv"
`include "spi_host_common_vseq.sv"
diff --git a/hw/ip/spi_host/dv/env/spi_host_env.core b/hw/ip/spi_host/dv/env/spi_host_env.core
index b95abb1..1cd803e 100644
--- a/hw/ip/spi_host/dv/env/spi_host_env.core
+++ b/hw/ip/spi_host/dv/env/spi_host_env.core
@@ -26,6 +26,7 @@
- seq_lib/spi_host_tx_rx_vseq.sv: {is_include_file: true}
- seq_lib/spi_host_common_vseq.sv: {is_include_file: true}
- seq_lib/spi_host_smoke_vseq.sv: {is_include_file: true}
+ - seq_lib/spi_host_speed_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
generate:
diff --git a/hw/ip/spi_host/dv/env/spi_segment_item.sv b/hw/ip/spi_host/dv/env/spi_segment_item.sv
index c88c3bf..ac5ee3d 100644
--- a/hw/ip/spi_host/dv/env/spi_segment_item.sv
+++ b/hw/ip/spi_host/dv/env/spi_segment_item.sv
@@ -18,79 +18,110 @@
// i.e the rx setting does not affect
// the tx distribution
// for the use the knob for the cmd
- int rx_only_weight = 20;
- int tx_only_weight = 20;
- int dummy_weight = 0;
+ int rx_only_weight = 20;
+ int tx_only_weight = 20;
+ int dummy_weight = 0;
// num dummy cycles
- int num_dummy = 0;
+ int num_dummy = 0;
//num_addr_bytes
- int num_cmd_bytes = 4;
+ int num_cmd_bytes = 4;
// transaction len
- int spi_len_min = 2;
- int spi_len_max = 4;
+ int spi_len_min = 2;
+ int spi_len_max = 4;
- spi_cmd_e cmd;
- spi_segment_type_e seg_type = Data;
- rand spi_host_command_t command_reg;
- rand bit [7:0] spi_data[$];
+ spi_cmd_e cmd;
+ spi_segment_type_e seg_type = Data;
+ rand spi_host_command_t command_reg;
+ rand bit [7:0] spi_data [$];
constraint command_reg_c {
//make sure the direction matches the segtype /cmd address are always tx/standard
- if ( (cmd inside {ReadStd, ReadDual, ReadQuad}) && (seg_type inside {Dummy, Data}) ) {
- command_reg.direction dist { RxOnly := rx_only_weight,
- None := dummy_weight/2,
- Bidir := 100 - (rx_only_weight + dummy_weight)};
+ if ((cmd inside {ReadStd}) && (seg_type inside {Dummy, Data})) {
+ command_reg.direction dist {
+ RxOnly := rx_only_weight,
+ None := dummy_weight / 2,
+ Bidir := 100 - (rx_only_weight + dummy_weight)
+ };
+ } else
+ if ((cmd inside {ReadDual, ReadQuad}) && (seg_type inside {Dummy, Data})) {
+ command_reg.direction dist {
+ RxOnly := rx_only_weight,
+ None := dummy_weight / 2
+ };
+ } else
+ if ((cmd inside {WriteDual, WriteQuad}) && (seg_type inside {Dummy, Data})) {
+ command_reg.direction dist {
+ TxOnly := tx_only_weight,
+ None := dummy_weight / 2
+ };
} else {
- command_reg.direction dist { TxOnly := tx_only_weight,
- None := dummy_weight/2,
- Bidir := 100 - (tx_only_weight + dummy_weight)};
+ command_reg.direction dist {
+ TxOnly := tx_only_weight,
+ None := dummy_weight / 2,
+ Bidir := 100 - (tx_only_weight + dummy_weight)
+ };
}
if (seg_type == Command) {
command_reg.mode == Standard;
} else {
- if (cmd inside {ReadStd, WriteStd}) { command_reg.mode == Standard; }
- else if (cmd inside {ReadDual, WriteDual}) { command_reg.mode == Dual; }
- else { command_reg.mode == Quad; }
+ if (cmd inside {ReadStd, WriteStd}) {
+ command_reg.mode == Standard;
+ } else
+ if (cmd inside {ReadDual, WriteDual}) {
+ command_reg.mode == Dual;
+ } else {
+ command_reg.mode == Quad;
+ }
}
- if (seg_type == Command) { command_reg.len == num_cmd_bytes-1; }
- else if (seg_type == Dummy ) { command_reg.len == num_dummy-1; }
- else { command_reg.len inside { [spi_len_min-1:spi_len_max-1]}; }
+ if (seg_type == Command) {
+ command_reg.len == num_cmd_bytes - 1;
+ } else
+ if (seg_type == Dummy) {
+ command_reg.len == num_dummy - 1;
+ } else {
+ command_reg.len inside {[spi_len_min - 1 : spi_len_max - 1]};
+ }
// ensure we only half or full word writes
- (command_reg.len+1)%2 == 0;
+ (command_reg.len + 1) % 2 == 0;
// default set keep transaction going
command_reg.csaat == 1;
}
constraint data_c {
- if (seg_type == Command) { spi_data.size() == num_cmd_bytes; }
- else if (seg_type == Dummy) { spi_data.size() == num_dummy; }
- else { spi_data.size() == command_reg.len+1; }
+ if (seg_type == Command) {
+ spi_data.size() == num_cmd_bytes;
+ } else
+ if (seg_type == Dummy) {
+ spi_data.size() == num_dummy;
+ } else {
+ spi_data.size() == command_reg.len + 1;
+ }
solve command_reg.len before spi_data;
}
- virtual function void do_copy( uvm_object rhs);
+ virtual function void do_copy(uvm_object rhs);
spi_segment_item rhs_;
`downcast(rhs_, rhs);
super.do_copy(rhs);
- cmd = rhs_.cmd;
- rx_only_weight = rhs_.rx_only_weight;
- tx_only_weight = rhs_.tx_only_weight;
- num_dummy = rhs_.num_dummy;
- num_cmd_bytes = rhs_.num_cmd_bytes;
- seg_type = rhs_.seg_type;
- command_reg.csaat = rhs_.command_reg.csaat;
- command_reg.direction = rhs_.command_reg.direction;
- command_reg.mode = rhs_.command_reg.mode;
- command_reg.len = rhs_.command_reg.len;
- spi_data = rhs_.spi_data;
+ cmd = rhs_.cmd;
+ rx_only_weight = rhs_.rx_only_weight;
+ tx_only_weight = rhs_.tx_only_weight;
+ num_dummy = rhs_.num_dummy;
+ num_cmd_bytes = rhs_.num_cmd_bytes;
+ seg_type = rhs_.seg_type;
+ command_reg.csaat = rhs_.command_reg.csaat;
+ command_reg.direction = rhs_.command_reg.direction;
+ command_reg.mode = rhs_.command_reg.mode;
+ command_reg.len = rhs_.command_reg.len;
+ spi_data = rhs_.spi_data;
endfunction
@@ -102,17 +133,17 @@
function string convert2string();
- string txt ="";
+ string txt = "";
txt = {txt, $sformatf("\n ----| Command Register |----")};
txt = {txt, $sformatf("\n ----| Command: %s", cmd.name)};
txt = {txt, $sformatf("\n ----| Segment %s", seg_type.name)};
txt = {txt, $sformatf("\n ----| Length: %d", command_reg.len)};
- txt = {txt, $sformatf("\n ----| Mode: %s", command_reg.mode.name )};
- txt = {txt, $sformatf("\n ----| CSAAT: %d", command_reg.csaat )};
- txt = {txt, $sformatf("\n ----| Direction: %s", command_reg.direction.name )};
+ txt = {txt, $sformatf("\n ----| Mode: %s", command_reg.mode.name)};
+ txt = {txt, $sformatf("\n ----| CSAAT: %d", command_reg.csaat)};
+ txt = {txt, $sformatf("\n ----| Direction: %s", command_reg.direction.name)};
txt = {txt, $sformatf("\n ----| DATA |----")};
- foreach ( spi_data[i]) begin
+ foreach (spi_data[i]) begin
txt = {txt, $sformatf("\n ----| [%d] %2h |----", i, spi_data[i])};
end
return txt;
diff --git a/hw/ip/spi_host/dv/spi_host_sim_cfg.hjson b/hw/ip/spi_host/dv/spi_host_sim_cfg.hjson
index 90bc694..fb8569e 100644
--- a/hw/ip/spi_host/dv/spi_host_sim_cfg.hjson
+++ b/hw/ip/spi_host/dv/spi_host_sim_cfg.hjson
@@ -68,6 +68,10 @@
name: spi_host_smoke
uvm_test_seq: spi_host_smoke_vseq
}
+ {
+ name: spi_host_speed
+ uvm_test_seq: spi_host_speed_vseq
+ }
// TODO: add more tests here
]