test(spi_device): Upload sequence
This commit adds failed upload sequence to the test.
https://github.com/lowRISC/opentitan/issues/11871#issuecomment-1127940485
The Page Program sees incorrect command with this test.
Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/spi_device/pre_dv/program/prog_passthrough_host.sv b/hw/ip/spi_device/pre_dv/program/prog_passthrough_host.sv
index 149d10e..c43baa1 100644
--- a/hw/ip/spi_device/pre_dv/program/prog_passthrough_host.sv
+++ b/hw/ip/spi_device/pre_dv/program/prog_passthrough_host.sv
@@ -46,7 +46,8 @@
spi_device_pkg::CmdEn4B,
spi_device_pkg::CmdEx4B,
spi_device_pkg::CmdReadSfdp,
- spi_device_pkg::CmdResetDevice;
+ spi_device_pkg::CmdResetDevice,
+ spi_device_pkg::CmdChipErase;
// Timeout
initial begin
@@ -91,6 +92,10 @@
test_program(subtask_pass);
end
+ "upload": begin
+ test_upload(subtask_pass);
+ end
+
default: begin
$display("Passthrough test requires '+TESTNAME=%%s'");
end
@@ -457,6 +462,48 @@
endtask : test_program
+ static task test_upload(output bit pass);
+ SpiTransProgram trans;
+ // Sequence
+
+ // Issue Chip Erase
+ spiflash_oponly(
+ sif.tb,
+ CmdChipErase
+ );
+
+ wait_trans();
+
+ // Issue two ~ more Read Status until BUSY is cleared
+
+ read_status();
+
+ do begin
+ #1us
+ @(negedge clk);
+ read_status();
+ end while (status[0][0] == 1'b 1);
+
+ // Issue Page Program
+ trans = new();
+ trans.randomize() with {
+ address < (local::FlashSize - size);
+ };
+ trans.display();
+
+ spiflash_program(
+ sif.tb,
+ trans.cmd,
+ trans.address,
+ trans.addr_mode,
+ trans.program_data
+ );
+
+ wait_trans();
+
+ // TODO: Check in scoreboard if opcode/ payload matches
+ endtask : test_upload
+
// Access to Mirrored storage
function automatic void write_byte(int unsigned addr, spi_data_t data);
mirrored_storage[addr] = data;
diff --git a/hw/ip/spi_device/pre_dv/program/prog_passthrough_sw.sv b/hw/ip/spi_device/pre_dv/program/prog_passthrough_sw.sv
index 24d1410..c0388a8 100644
--- a/hw/ip/spi_device/pre_dv/program/prog_passthrough_sw.sv
+++ b/hw/ip/spi_device/pre_dv/program/prog_passthrough_sw.sv
@@ -12,7 +12,9 @@
input logic rst_n,
output tlul_pkg::tl_h2d_t h2d,
- input tlul_pkg::tl_d2h_t d2h
+ input tlul_pkg::tl_d2h_t d2h,
+
+ input interrupt_t intr
);
initial begin
@@ -44,6 +46,11 @@
// SPIFlash
test_program();
end
+
+ "upload": begin
+ // TODO: Read and check if cmds...
+ test_upload();
+ end
endcase
forever begin
@@ -141,6 +148,8 @@
init_dpsram();
+ init_interrupts();
+
endtask : init_spidevice_passthrough
task automatic init_cmdinfo_list();
@@ -207,6 +216,16 @@
end
endfunction : init_dpsram
+ task automatic init_interrupts();
+ // Enable CMDFIFO Not Empty
+ tlul_write(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_INTR_ENABLE_OFFSET),
+ 32'h 0000_0000 | (1 << BitCmdfifoNotEmpty),
+ 4'b 1111
+ );
+ endtask : init_interrupts
+
static task test_program();
// Turning off INTERCEPT
tlul_write(
@@ -227,4 +246,87 @@
endtask : test_program
+ static task test_upload();
+ automatic logic [31:0] tl_rdata;
+ automatic logic [ 7:0] opcode; // cmd opcode
+ automatic logic [31:0] address;
+ automatic spi_data_t payload [256];
+
+ // Wait Upload Command FIFO
+ wait(intr.upload_cmdfifo_not_empty);
+
+ // Fetch CMDFIFO
+ tlul_read(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_UPLOAD_CMDFIFO_OFFSET),
+ tl_rdata
+ );
+
+ opcode = tl_rdata[7:0];
+
+ $display("SW: Received Command: %2Xh", opcode);
+
+ if (opcode != spi_device_pkg::CmdChipErase) begin
+ $display("SW: Unexpected Command: %2Xh / EXP(%2Xh)",
+ opcode,
+ spi_device_pkg::CmdChipErase);
+ end
+
+ // Process cmd (or push to TLM to process later)
+
+ // Clear Interrupt
+ tlul_write(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_INTR_STATE_OFFSET),
+ 1 << BitCmdfifoNotEmpty,
+ 4'b 1111
+ );
+
+ // Expect CMDFIFO Depth 0 (the delay is short so that Page Program should not arrived yet)
+ tlul_read(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_UPLOAD_STATUS_OFFSET),
+ tl_rdata
+ );
+
+ if (tl_rdata[4:0] != 0) begin
+ $display("SW: CMDFIFO not empty after fetching: %2d", tl_rdata[4:0]);
+ end
+
+ // Will have two or more Read Status
+
+ #($urandom_range(5,2) * 1us);
+
+ @(negedge clk);
+
+ // Clear BUSY
+ tlul_rmw(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_FLASH_STATUS_OFFSET),
+ 32'h 0, // value
+ 32'h 1 // mask
+ );
+
+ // Wait for Page Program
+ wait(intr.upload_cmdfifo_not_empty);
+
+ // Fetch CMDFIFO
+ tlul_read(
+ clk, h2d, d2h,
+ 32'(spi_device_reg_pkg::SPI_DEVICE_UPLOAD_CMDFIFO_OFFSET),
+ tl_rdata
+ );
+
+ opcode = tl_rdata[7:0];
+
+ $display("SW: Received Command: %2Xh", opcode);
+
+ if (opcode != spi_device_pkg::CmdPageProgram) begin
+ $display("SW: Unexpected Command: %2Xh / EXP(%2Xh)",
+ opcode,
+ spi_device_pkg::CmdChipErase);
+ end
+
+ endtask : test_upload
+
endprogram : prog_passthrough_sw
diff --git a/hw/ip/spi_device/pre_dv/spid_passthrough_sim_cfg.hjson b/hw/ip/spi_device/pre_dv/spid_passthrough_sim_cfg.hjson
index e7b5aca..432ebd6 100644
--- a/hw/ip/spi_device/pre_dv/spid_passthrough_sim_cfg.hjson
+++ b/hw/ip/spi_device/pre_dv/spid_passthrough_sim_cfg.hjson
@@ -43,6 +43,13 @@
"+TESTNAME=program"
]
}
+ {
+ name: spid_passthrough_upload
+ // Chip Erase + Read Status + Page Program test
+ run_opts: [
+ "+TESTNAME=upload"
+ ]
+ }
]
regressions: [
diff --git a/hw/ip/spi_device/pre_dv/tb/spid_common.sv b/hw/ip/spi_device/pre_dv/tb/spid_common.sv
index e8117fd..854fb9f 100644
--- a/hw/ip/spi_device/pre_dv/tb/spid_common.sv
+++ b/hw/ip/spi_device/pre_dv/tb/spid_common.sv
@@ -60,6 +60,26 @@
dir_e dir;
} spi_fifo_t;
+ typedef struct packed {
+ logic generic_rx_full;
+ logic generic_rx_watermark;
+ logic generic_tx_watermark;
+ logic generic_rx_error;
+ logic generic_rx_overflow;
+ logic generic_tx_underflow;
+ logic upload_cmdfifo_not_empty;
+ logic upload_payload_not_empty;
+ logic upload_payload_overflow;
+ logic readbuf_watermark;
+ logic readbuf_flip;
+ logic tpm_header_not_empty;
+ } interrupt_t;
+
+ // Register parameters
+ parameter int unsigned BitCmdfifoNotEmpty = 6;
+ parameter int unsigned BitReadbufWatermark = 9;
+ parameter int unsigned BitReadbufFlip = 10;
+
// Command list parameters
import spi_device_pkg::cmd_info_t;
import spi_device_pkg::NumTotalCmdInfo;
@@ -1123,6 +1143,24 @@
endtask : tlul_read
+ task automatic tlul_rmw(
+ const ref logic clk,
+
+ ref tlul_pkg::tl_h2d_t h2d,
+ const ref tlul_pkg::tl_d2h_t d2h,
+
+ input logic [31:0] address,
+ input logic [31:0] data,
+ input logic [31:0] mask
+ );
+
+ automatic logic [31:0] tl_data;
+
+ tlul_read(clk, h2d, d2h, address, tl_data);
+ tl_data = (tl_data & ~mask) | (mask & data);
+ tlul_write(clk, h2d, d2h, address, tl_data, 4'b 1111);
+ endtask : tlul_rmw
+
// classes
class SpiTrans;
rand spi_device_pkg::spi_cmd_e cmd;
diff --git a/hw/ip/spi_device/pre_dv/tb/spid_passthrough_tb.sv b/hw/ip/spi_device/pre_dv/tb/spid_passthrough_tb.sv
index 948064e..0c8ea71 100644
--- a/hw/ip/spi_device/pre_dv/tb/spid_passthrough_tb.sv
+++ b/hw/ip/spi_device/pre_dv/tb/spid_passthrough_tb.sv
@@ -79,6 +79,8 @@
prim_ram_2p_pkg::ram_2p_cfg_t ram_cfg; // tied
+ interrupt_t intr;
+
// TB
initial begin
sck_clk.set_period_ps(SckPeriod);
@@ -104,7 +106,9 @@
// TL ports
.h2d (tl_h2d),
- .d2h (tl_d2h)
+ .d2h (tl_d2h),
+
+ .intr (intr)
);
// Passthrough SPI Flash device
@@ -154,22 +158,22 @@
// Interrupts
// INTR: Generic mode : Not Testing here
- .intr_generic_rx_full_o (), // RX FIFO Full
- .intr_generic_rx_watermark_o(), // RX FIFO above level
- .intr_generic_tx_watermark_o(), // TX FIFO below level
- .intr_generic_rx_error_o (), // RX Frame error
- .intr_generic_rx_overflow_o (), // RX Async FIFO Overflow
- .intr_generic_tx_underflow_o(), // TX Async FIFO Underflow
+ .intr_generic_rx_full_o (intr.generic_rx_full),
+ .intr_generic_rx_watermark_o(intr.generic_rx_watermark),
+ .intr_generic_tx_watermark_o(intr.generic_tx_watermark),
+ .intr_generic_rx_error_o (intr.generic_rx_error),
+ .intr_generic_rx_overflow_o (intr.generic_rx_overflow),
+ .intr_generic_tx_underflow_o(intr.generic_tx_underflow),
// INTR: Flash mode : Not testing here
- .intr_upload_cmdfifo_not_empty_o(),
- .intr_upload_payload_not_empty_o(),
- .intr_upload_payload_overflow_o (),
- .intr_readbuf_watermark_o (),
- .intr_readbuf_flip_o (),
+ .intr_upload_cmdfifo_not_empty_o(intr.upload_cmdfifo_not_empty),
+ .intr_upload_payload_not_empty_o(intr.upload_payload_not_empty),
+ .intr_upload_payload_overflow_o (intr.upload_payload_overflow),
+ .intr_readbuf_watermark_o (intr.readbuf_watermark),
+ .intr_readbuf_flip_o (intr.readbuf_flip),
// INTR: TPM mode : Not Testing here
- .intr_tpm_header_not_empty_o(),
+ .intr_tpm_header_not_empty_o(intr.tpm_header_not_empty),
// Memory configuration
.ram_cfg_i (ram_cfg),
diff --git a/hw/ip/spi_device/rtl/spi_device_pkg.sv b/hw/ip/spi_device/rtl/spi_device_pkg.sv
index af14149..9d0a05c 100644
--- a/hw/ip/spi_device/rtl/spi_device_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_pkg.sv
@@ -368,6 +368,8 @@
CmdReadSfdp = 8'h 5A,
+ CmdChipErase = 8'h C7,
+
CmdEnableReset = 8'h 66,
CmdResetDevice = 8'h 99
} spi_cmd_e;