From 2f8d8c02cad58e538b7d14fe9f541081cc818774 Mon Sep 17 00:00:00 2001 From: Caleb Whitehead Date: Thu, 25 Jul 2024 14:56:28 -0700 Subject: [PATCH] TB updates to support all prev. functionality; smoke_test_dma passes; add AXI assertions --- src/axi/rtl/axi_dma_ctrl.sv | 35 +- src/axi/rtl/axi_dma_reg.rdl | 2 +- src/axi/rtl/axi_mgr_rd.sv | 10 +- src/axi/rtl/axi_mgr_wr.sv | 9 +- src/axi/rtl/axi_sub_rd.sv | 43 +- src/integration/rtl/caliptra_reg.h | 8 +- src/integration/rtl/caliptra_reg_defines.svh | 8 +- src/integration/tb/caliptra_top_tb.sv | 1223 +++++------------ src/integration/tb/caliptra_top_tb_pkg.sv | 9 +- .../tb/caliptra_top_tb_services.sv | 12 +- src/integration/tb/test_caliptra_top_tb.cpp | 5 +- .../test_suites/iccm_lock/caliptra_isr.h | 5 + .../test_suites/iccm_lock/iccm_lock.c | 2 + .../test_suites/includes/caliptra_defines.h | 10 +- .../libs/caliptra_isr/caliptra_isr.c | 40 +- .../test_suites/libs/soc_ifc/soc_ifc.c | 113 ++ .../test_suites/libs/soc_ifc/soc_ifc.h | 28 + .../test_suites/smoke_test_dma/caliptra_isr.h | 317 +++++ .../smoke_test_dma/smoke_test_dma.c | 127 ++ .../smoke_test_dma/smoke_test_dma.yml | 17 + .../smoke_test_mbox/caliptra_isr.h | 5 + .../smoke_test_mbox/smoke_test_mbox.c | 2 + tools/scripts/Makefile | 8 +- 23 files changed, 1080 insertions(+), 958 deletions(-) create mode 100644 src/integration/test_suites/smoke_test_dma/caliptra_isr.h create mode 100644 src/integration/test_suites/smoke_test_dma/smoke_test_dma.c create mode 100755 src/integration/test_suites/smoke_test_dma/smoke_test_dma.yml diff --git a/src/axi/rtl/axi_dma_ctrl.sv b/src/axi/rtl/axi_dma_ctrl.sv index 8635e88c7..25571f5e3 100644 --- a/src/axi/rtl/axi_dma_ctrl.sv +++ b/src/axi/rtl/axi_dma_ctrl.sv @@ -99,7 +99,7 @@ import soc_ifc_pkg::*; axi_dma_reg_pkg::axi_dma_reg__in_t hwif_in; axi_dma_reg_pkg::axi_dma_reg__out_t hwif_out; - enum logic [2:0] { + enum logic [1:0] { DMA_IDLE, DMA_WAIT_DATA, DMA_DONE, @@ -237,6 +237,9 @@ import soc_ifc_pkg::*; ctrl_fsm_ns = DMA_IDLE; end end + default: begin + ctrl_fsm_ns = ctrl_fsm_ps; + end endcase end @@ -337,7 +340,7 @@ import soc_ifc_pkg::*; ((hwif_out.ctrl.rd_route.value == axi_dma_reg__ctrl__rd_route__rd_route_e__MBOX) || (hwif_out.ctrl.wr_route.value == axi_dma_reg__ctrl__wr_route__wr_route_e__MBOX))); // power of 2 and word-aligned - cmd_inv_block_size = |(hwif_out.block_size.size.value & hwif_out.block_size.size.value) || + cmd_inv_block_size = |(hwif_out.block_size.size.value & (hwif_out.block_size.size.value-1)) || |hwif_out.block_size.size.value[BW-1:0]; cmd_inv_rd_fixed = hwif_out.ctrl.rd_fixed.value && hwif_out.ctrl.rd_route.value == axi_dma_reg__ctrl__rd_route__rd_route_e__DISABLE; cmd_inv_wr_fixed = hwif_out.ctrl.wr_fixed.value && hwif_out.ctrl.wr_route.value == axi_dma_reg__ctrl__wr_route__wr_route_e__DISABLE; @@ -413,12 +416,12 @@ import soc_ifc_pkg::*; else if (hwif_out.block_size.size.value == 0) begin rd_req_stall <= 1'b0; end - else if (rd_req_hshake) begin - rd_req_stall <= 1'b1; - end else if (recovery_data_avail) begin rd_req_stall <= 1'b0; end + else if (rd_req_hshake || hwif_out.ctrl.go.value) begin + rd_req_stall <= 1'b1; + end end always_ff @(posedge clk or negedge rst_n) begin @@ -440,11 +443,13 @@ import soc_ifc_pkg::*; always_comb block_size_mask = hwif_out.block_size.size.value - 1; always_comb begin - rd_align_req_byte_count = (MAX_BLOCK_SIZE - r_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0]) & block_size_mask; + rd_align_req_byte_count = ~|hwif_out.block_size.size.value || (MAX_BLOCK_SIZE < hwif_out.block_size.size.value) ? (MAX_BLOCK_SIZE - r_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0]) : + hwif_out.block_size.size.value - (r_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0] & block_size_mask); rd_final_req_byte_count = hwif_out.byte_count.count.value - rd_bytes_requested; rd_req_byte_count = rd_final_req_byte_count < rd_align_req_byte_count ? rd_final_req_byte_count : rd_align_req_byte_count; - wr_align_req_byte_count = (MAX_BLOCK_SIZE - w_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0]) & block_size_mask; + wr_align_req_byte_count = ~|hwif_out.block_size.size.value || (MAX_BLOCK_SIZE < hwif_out.block_size.size.value) ? (MAX_BLOCK_SIZE - w_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0]) : + hwif_out.block_size.size.value - (w_req_if.addr[$clog2(MAX_BLOCK_SIZE)-1:0] & block_size_mask); wr_final_req_byte_count = hwif_out.byte_count.count.value - wr_bytes_requested; wr_req_byte_count = wr_final_req_byte_count < wr_align_req_byte_count ? wr_final_req_byte_count : wr_align_req_byte_count; @@ -650,11 +655,15 @@ import soc_ifc_pkg::*; end end - `ifdef VERILATOR - FIXME_ASSERT_INIT(DW == 32) - FIXME_ASSERT(rd_credits <= FIFO_BC) - FIXME_ASSERT(!((rd_credits < BC) && rd_req_hshake)) - FIXME_ASSERT(!((ctrl_fsm_ps == DMA_DONE) && (rd_credits != FIFO_BC))) - `endif + // Requests must have valid length + `CALIPTRA_ASSERT(AXI_DMA_VLD_RD_REQ_LEN, rd_req_hshake |-> r_req_if.byte_len < MAX_BLOCK_SIZE, clk, !rst_n) + `CALIPTRA_ASSERT(AXI_DMA_VLD_WR_REQ_LEN, wr_req_hshake |-> w_req_if.byte_len < MAX_BLOCK_SIZE, clk, !rst_n) + // Requests must not cross AXI boundary (4KiB) + `CALIPTRA_ASSERT(AXI_DMA_VLD_RD_REQ_BND, rd_req_hshake |-> r_req_if.addr[AW-1:AXI_LEN_BC_WIDTH] == ((r_req_if.addr + r_req_if.byte_len) >> AXI_LEN_BC_WIDTH), clk, !rst_n) + `CALIPTRA_ASSERT(AXI_DMA_VLD_WR_REQ_BND, wr_req_hshake |-> w_req_if.addr[AW-1:AXI_LEN_BC_WIDTH] == ((w_req_if.addr + w_req_if.byte_len) >> AXI_LEN_BC_WIDTH), clk, !rst_n) + `CALIPTRA_ASSERT_INIT(AXI_DMA_DW_32, DW == 32) + `CALIPTRA_ASSERT(AXI_DMA_LIM_RD_CRED, rd_credits <= FIFO_BC, clk, !rst_n) + `CALIPTRA_ASSERT(AXI_DMA_MIN_RD_CRED, !((rd_credits < BC) && rd_req_hshake), clk, !rst_n) + `CALIPTRA_ASSERT(AXI_DMA_RST_RD_CRED, (ctrl_fsm_ps == DMA_DONE) |-> (rd_credits == FIFO_BC), clk, !rst_n) endmodule diff --git a/src/axi/rtl/axi_dma_reg.rdl b/src/axi/rtl/axi_dma_reg.rdl index f7bf6e38a..9cb8e2638 100644 --- a/src/axi/rtl/axi_dma_reg.rdl +++ b/src/axi/rtl/axi_dma_reg.rdl @@ -167,7 +167,7 @@ addrmap axi_dma_reg { // Byte Count reg { name="Caliptra AXI DMA Byte Count"; - desc="Contains total number of bytes to be transferred by current operation."; + desc="Contains total number of bytes to be transferred by current operation. Must be a multiple of the AXI Data Width. (Narrow/unaligned transfers are not supported)"; field { desc="Byte Count"; sw=rw; swwel=dma_swwel; hw=r; } count[32]=32'h00000000; } byte_count; diff --git a/src/axi/rtl/axi_mgr_rd.sv b/src/axi/rtl/axi_mgr_rd.sv index 0ff8be47c..5e000fa3a 100644 --- a/src/axi/rtl/axi_mgr_rd.sv +++ b/src/axi/rtl/axi_mgr_rd.sv @@ -179,12 +179,10 @@ module axi_mgr_rd import axi_pkg::*; #( // --------------------------------------- // // Assertions // // --------------------------------------- // - `ifdef VERILATOR - `FIXME_ASSERT(req.valid && addr + len <= 4096) - `FIXME_ASSERT(req_if.byte_len[11:10] == 2'b00) - `FIXME_ASSERT(req_if.rvalid && txn_active) - `FIXME_ASSERT_NEVER(fixme_valid_and_ready && ready_i, "Received data with no space in FIFO! Is the FSM credit calculation wrong?") - `endif + `CALIPTRA_ASSERT(AXI_MGR_REQ_BND, req_if.valid |-> ((req_if.addr[11:0] + req_if.byte_len) <= 4096), clk, !rst_n) + `CALIPTRA_ASSERT(AXI_MGR_LEGAL_LEN, req_if.valid |-> (req_if.byte_len[AXI_LEN_BC_WIDTH-1:BW]) < AXI_LEN_MAX_VALUE, clk, !rst_n) + `CALIPTRA_ASSERT(AXI_MGR_DATA_WHILE_ACTIVE, valid_o |-> txn_active, clk, !rst_n) + `CALIPTRA_ASSERT_NEVER(AXI_MGR_OFLOW, m_axi_if.rready && !ready_i, clk, !rst_n) endmodule diff --git a/src/axi/rtl/axi_mgr_wr.sv b/src/axi/rtl/axi_mgr_wr.sv index 5cdd73fd6..4ce67c0c1 100644 --- a/src/axi/rtl/axi_mgr_wr.sv +++ b/src/axi/rtl/axi_mgr_wr.sv @@ -181,10 +181,9 @@ module axi_mgr_wr import axi_pkg::*; #( // --------------------------------------- // // Assertions // // --------------------------------------- // - `ifdef VERILATOR - `FIXME_ASSERT(req.valid && addr + len <= 4096) - `FIXME_ASSERT(req_if.byte_len[11:10] == 2'b00) - `FIXME_ASSERT(req_if.rvalid && txn_active) - `endif + `CALIPTRA_ASSERT(AXI_MGR_REQ_BND, req_if.valid |-> ((req_if.addr[11:0] + req_if.byte_len) <= 4096), clk, !rst_n) + `CALIPTRA_ASSERT(AXI_MGR_LEGAL_LEN, req_if.valid |-> (req_if.byte_len[AXI_LEN_BC_WIDTH-1:BW]) < AXI_LEN_MAX_VALUE, clk, !rst_n) + `CALIPTRA_ASSERT(AXI_MGR_DATA_WHILE_ACTIVE, ready_o |-> txn_active, clk, !rst_n) + `CALIPTRA_ASSERT_NEVER(AXI_MGR_UFLOW, m_axi_if.wvalid && !valid_i, clk, !rst_n) endmodule diff --git a/src/axi/rtl/axi_sub_rd.sv b/src/axi/rtl/axi_sub_rd.sv index a45d341da..3538984bc 100644 --- a/src/axi/rtl/axi_sub_rd.sv +++ b/src/axi/rtl/axi_sub_rd.sv @@ -103,8 +103,8 @@ module axi_sub_rd import axi_pkg::*; #( logic [AW-1:0] txn_addr_nxt; logic [ 7:0] txn_cnt; // Internal down-counter to track txn progress logic txn_active; - logic [C_LAT:0] txn_rvalid; - xfer_ctx_t [C_LAT:0] txn_xfer_ctx; + logic txn_rvalid [C_LAT+1]; + xfer_ctx_t txn_xfer_ctx [C_LAT+1]; logic txn_final_beat; // Data pipeline signals (skid buffer) @@ -168,9 +168,9 @@ module axi_sub_rd import axi_pkg::*; #( // Only make the request to component if we have space in the pipeline to // store the result (under worst-case AXI backpressure) - // To check this, look at the 'ready' output from the FINAL stage of the + // To check this, look at the 'ready' output from all stages of the // skidbuffer pipeline - always_comb dv = txn_active && dp_rready[C_LAT]; + always_comb dv = txn_active && &dp_rready; always_comb txn_rvalid[0] = dv && !hld; // Asserts on the final beat of the COMPONENT INF which means it lags the @@ -212,25 +212,23 @@ module axi_sub_rd import axi_pkg::*; #( // Shift Register to track requests made to component generate if (C_LAT > 0) begin: TXN_SR - always_ff@(posedge clk or negedge rst_n) begin - if (!rst_n) begin - txn_rvalid[C_LAT:1] <= C_LAT'(0); - end - else begin - txn_rvalid[C_LAT:1] <= txn_rvalid[C_LAT-1:0]; - end - end - // Context is maintained alongside request while waiting for // component response to arrive - if (C_LAT > 1) begin - for (cp = 1; cp <= C_LAT; cp++) begin: CTX_PIPELINE - // No reset needed on data path -- txn_rvalid (control path) is reset - always_ff@(posedge clk) begin - txn_xfer_ctx[cp] <= txn_xfer_ctx[cp-1]; + for (cp = 1; cp <= C_LAT; cp++) begin: CTX_PIPELINE + always_ff@(posedge clk or negedge rst_n) begin + if (!rst_n) begin + txn_rvalid[cp] <= 1'b0; end - end: CTX_PIPELINE - end + else begin + txn_rvalid[cp] <= txn_rvalid[cp-1]; + end + end + + // No reset needed on data path -- txn_rvalid (control path) is reset + always_ff@(posedge clk) begin + txn_xfer_ctx[cp] <= txn_xfer_ctx[cp-1]; + end + end: CTX_PIPELINE end: TXN_SR endgenerate @@ -395,8 +393,9 @@ module axi_sub_rd import axi_pkg::*; #( generate if (C_LAT > 0) begin for (sva_ii = 0; sva_ii < C_LAT; sva_ii++) begin - // Last stage should be first to fill and last to go empty - `CALIPTRA_ASSERT_NEVER(ERR_RD_SKD_BUF, dp_rready[sva_ii+1] && !dp_rready[sva_ii], clk, !rst_n) + // Last stage should be first to fill and first to go empty + `CALIPTRA_ASSERT_NEVER(ERR_RD_SKD_BUF_FILL, $fell(dp_rready[sva_ii+1]) && !dp_rready[sva_ii], clk, !rst_n) + `CALIPTRA_ASSERT_NEVER(ERR_RD_SKD_BUF_DRAIN, $rose(dp_rready[sva_ii+1]) && dp_rready[sva_ii], clk, !rst_n) end end endgenerate diff --git a/src/integration/rtl/caliptra_reg.h b/src/integration/rtl/caliptra_reg.h index 9099d2fdb..34edfb866 100644 --- a/src/integration/rtl/caliptra_reg.h +++ b/src/integration/rtl/caliptra_reg.h @@ -5368,6 +5368,10 @@ #define AXI_DMA_REG_ID (0x0) #define CLP_AXI_DMA_REG_CAP (0x30022004) #define AXI_DMA_REG_CAP (0x4) +#define AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_LOW (0) +#define AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_MASK (0xfff) +#define AXI_DMA_REG_CAP_RSVD_LOW (12) +#define AXI_DMA_REG_CAP_RSVD_MASK (0xfffff000) #define CLP_AXI_DMA_REG_CTRL (0x30022008) #define AXI_DMA_REG_CTRL (0x8) #define AXI_DMA_REG_CTRL_GO_LOW (0) @@ -5399,7 +5403,9 @@ #define AXI_DMA_REG_STATUS0_ERROR_LOW (1) #define AXI_DMA_REG_STATUS0_ERROR_MASK (0x2) #define AXI_DMA_REG_STATUS0_RSVD0_LOW (2) -#define AXI_DMA_REG_STATUS0_RSVD0_MASK (0xfffc) +#define AXI_DMA_REG_STATUS0_RSVD0_MASK (0xc) +#define AXI_DMA_REG_STATUS0_FIFO_DEPTH_LOW (4) +#define AXI_DMA_REG_STATUS0_FIFO_DEPTH_MASK (0xfff0) #define AXI_DMA_REG_STATUS0_AXI_DMA_FSM_PS_LOW (16) #define AXI_DMA_REG_STATUS0_AXI_DMA_FSM_PS_MASK (0x30000) #define AXI_DMA_REG_STATUS0_RSVD1_LOW (18) diff --git a/src/integration/rtl/caliptra_reg_defines.svh b/src/integration/rtl/caliptra_reg_defines.svh index 12601d5f6..02401a73c 100644 --- a/src/integration/rtl/caliptra_reg_defines.svh +++ b/src/integration/rtl/caliptra_reg_defines.svh @@ -5368,6 +5368,10 @@ `define AXI_DMA_REG_ID (32'h0) `define CLP_AXI_DMA_REG_CAP (32'h30022004) `define AXI_DMA_REG_CAP (32'h4) +`define AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_LOW (0) +`define AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_MASK (32'hfff) +`define AXI_DMA_REG_CAP_RSVD_LOW (12) +`define AXI_DMA_REG_CAP_RSVD_MASK (32'hfffff000) `define CLP_AXI_DMA_REG_CTRL (32'h30022008) `define AXI_DMA_REG_CTRL (32'h8) `define AXI_DMA_REG_CTRL_GO_LOW (0) @@ -5399,7 +5403,9 @@ `define AXI_DMA_REG_STATUS0_ERROR_LOW (1) `define AXI_DMA_REG_STATUS0_ERROR_MASK (32'h2) `define AXI_DMA_REG_STATUS0_RSVD0_LOW (2) -`define AXI_DMA_REG_STATUS0_RSVD0_MASK (32'hfffc) +`define AXI_DMA_REG_STATUS0_RSVD0_MASK (32'hc) +`define AXI_DMA_REG_STATUS0_FIFO_DEPTH_LOW (4) +`define AXI_DMA_REG_STATUS0_FIFO_DEPTH_MASK (32'hfff0) `define AXI_DMA_REG_STATUS0_AXI_DMA_FSM_PS_LOW (16) `define AXI_DMA_REG_STATUS0_AXI_DMA_FSM_PS_MASK (32'h30000) `define AXI_DMA_REG_STATUS0_RSVD1_LOW (18) diff --git a/src/integration/tb/caliptra_top_tb.sv b/src/integration/tb/caliptra_top_tb.sv index f3a0704e2..fcfabd1f2 100755 --- a/src/integration/tb/caliptra_top_tb.sv +++ b/src/integration/tb/caliptra_top_tb.sv @@ -46,6 +46,7 @@ module caliptra_top_tb ( `endif int cycleCnt; + int poll_count; logic cptra_pwrgood; @@ -56,54 +57,14 @@ module caliptra_top_tb ( logic [`CLP_OBF_KEY_DWORDS-1:0][31:0] cptra_obf_key; logic [0:`CLP_OBF_KEY_DWORDS-1][31:0] cptra_obf_key_uds, cptra_obf_key_fe; - // logic [11:0][31:0] cptra_uds_tb; - // logic [7:0][31:0] cptra_fe_tb; logic [0:`CLP_OBF_UDS_DWORDS-1][31:0] cptra_uds_tb; logic [0:`CLP_OBF_FE_DWORDS-1][31:0] cptra_fe_tb; - // logic [11:0][31:0] cptra_uds_rand; - // logic [7:0][31:0] cptra_fe_rand; logic [0:`CLP_OBF_UDS_DWORDS-1][31:0] cptra_uds_rand; logic [0:`CLP_OBF_FE_DWORDS-1][31:0] cptra_fe_rand; logic [0:`CLP_OBF_KEY_DWORDS-1][31:0] cptra_obf_key_tb; -// logic start_apb_fuse_sequence; - -// enum logic [5:0] { -// S_APB_IDLE, -// S_APB_WR_UDS, -// S_APB_WR_FE, -// S_APB_WR_SOC_STEPPING_ID, -// S_APB_WR_FUSE_DONE, -// S_APB_POLL_FLOW_ST, -// S_APB_WR_BOOT_GO, -// S_APB_WAIT_FW_TEST, -// S_APB_POLL_LOCK, -// S_APB_PRE_WR_CMD, -// S_APB_WR_CMD, -// S_APB_WR_DLEN, -// S_APB_WR_DATAIN, -// S_APB_WR_STATUS, -// S_APB_WR_EXEC, -// S_APB_WAIT_ERROR_AXS, -// S_APB_RD_HW_ERROR_FATAL, -// S_APB_WR_HW_ERROR_FATAL, -// S_APB_RD_HW_ERROR_NON_FATAL, -// S_APB_WR_HW_ERROR_NON_FATAL, -// S_APB_DONE, -// S_APB_RD_DLEN, -// S_APB_RD_DATAOUT, -// S_APB_RST_EXEC, -// S_APB_ERROR -// } n_state_apb, c_state_apb; - - parameter FW_NUM_DWORDS = 256; - -// logic [$clog2(FW_NUM_DWORDS)-1:0] apb_wr_count, apb_wr_count_nxt; -// logic [31:0] apb_rd_count, apb_rd_count_nxt, dlen; -// logic apb_enable_ph; -// logic apb_xfer_end; -// logic execute_mbox_rx_protocol; + localparam FW_NUM_DWORDS = 256; //jtag interface logic jtag_tck; // JTAG clk @@ -112,23 +73,16 @@ module caliptra_top_tb ( logic jtag_trst_n; // JTAG Reset logic jtag_tdo; // JTAG TDO logic jtag_tdoEn; // JTAG TDO enable -// //APB Interface -// logic [`CALIPTRA_APB_ADDR_WIDTH-1:0] PADDR; -// logic [2:0] PPROT; -// logic PSEL; -// logic PENABLE; -// logic PWRITE; -// logic [`CALIPTRA_APB_DATA_WIDTH-1:0] PWDATA; -// logic [`CALIPTRA_APB_USER_WIDTH-1:0] PAUSER; -// -// logic PREADY; -// logic PSLVERR; -// logic [`CALIPTRA_APB_DATA_WIDTH-1:0] PRDATA; // AXI request signals - axi_resp_e wresp, rresp[]; - logic [`CALIPTRA_AXI_DATA_WIDTH-1:0] wdata[], rdata[]; - logic [`CALIPTRA_AXI_DATA_WIDTH/8-1:0] wstrb[]; + axi_resp_e wresp, rresp; + logic [`CALIPTRA_AXI_DATA_WIDTH-1:0] wdata, rdata; + logic [`CALIPTRA_AXI_DATA_WIDTH/8-1:0] wstrb_array[]; + logic [`CALIPTRA_AXI_DATA_WIDTH-1:0] rdata_array[]; + axi_resp_e rresp_array[]; + + int byte_count; + int dw_count; // AXI Interface axi_if #( @@ -137,6 +91,18 @@ module caliptra_top_tb ( .IW(`CALIPTRA_AXI_ID_WIDTH), .UW(`CALIPTRA_AXI_USER_WIDTH) ) s_axi_if (.clk(core_clk), .rst_n(cptra_rst_b)); + axi_if #( + .AW(`CALIPTRA_AXI_DMA_ADDR_WIDTH), + .DW(CPTRA_AXI_DMA_DATA_WIDTH), + .IW(CPTRA_AXI_DMA_ID_WIDTH), + .UW(CPTRA_AXI_DMA_USER_WIDTH) + ) m_axi_if (.clk(core_clk), .rst_n(cptra_rst_b)); + axi_if #( + .AW(AXI_SRAM_ADDR_WIDTH), + .DW(CPTRA_AXI_DMA_DATA_WIDTH), + .IW(CPTRA_AXI_DMA_ID_WIDTH), + .UW(CPTRA_AXI_DMA_USER_WIDTH) + ) axi_sram_if (.clk(core_clk), .rst_n(cptra_rst_b)); // QSPI Interface logic qspi_clk; @@ -152,7 +118,6 @@ module caliptra_top_tb ( logic ready_for_fuses; logic ready_for_fw_push; logic mailbox_data_avail; - logic status_set; logic mbox_sram_cs; logic mbox_sram_we; logic [14:0] mbox_sram_addr; @@ -181,20 +146,11 @@ module caliptra_top_tb ( logic rv_dma_resp_error; - logic mbox_apb_dataout_read_ooo; - logic mbox_ooo_read_done; - logic mbox_apb_dataout_read_no_lock; - logic mbox_no_lock_read_done; - -// logic [`CALIPTRA_APB_DATA_WIDTH-1:0] soc_ifc_hw_error_wdata; + logic [`CALIPTRA_AXI_DATA_WIDTH-1:0] soc_ifc_hw_error_wdata; //Interrupt flags - //logic nmi_int; - //logic soft_int; - //logic timer_int; logic int_flag; logic cycleCnt_smpl_en; - int cycleCnt_ff; process boot_and_cmd_flow; //Reset flags @@ -210,7 +166,7 @@ module caliptra_top_tb ( el2_mem_if el2_mem_export (); - logic [FW_NUM_DWORDS-1:0][31:0] fw_blob; + logic [31:0] fw_blob []; `ifndef VERILATOR always @@ -219,97 +175,6 @@ module caliptra_top_tb ( end // clk_gen `endif - always@(negedge core_clk) begin - if(!cptra_rst_b) cycleCnt_ff <= 'h0; - else if(cycleCnt_smpl_en) cycleCnt_ff <= cycleCnt; - end - -// always@(negedge core_clk) begin -// if((cycleCnt == cycleCnt_ff + 2000) && int_flag) begin -// force caliptra_top_dut.soft_int = 'b1; -// end -// -// else if((cycleCnt == cycleCnt_ff + 7000) && int_flag) begin -// force caliptra_top_dut.timer_int = 'b1; -// end -// -// else if((c_state_apb == S_APB_WR_EXEC) && apb_xfer_end && int_flag) begin -// //Wait for APB flow to be done before toggling generic_input_wires -// generic_input_wires <= {$urandom, $urandom}; //Toggle wires -// end -// -// else if((cycleCnt == cycleCnt_ff + 15000) && int_flag) begin -// force caliptra_top_dut.soft_int = 'b1; -// end -// -// else if (!ras_test_ctrl.error_injection_seen) begin -// release caliptra_top_dut.soft_int; -// release caliptra_top_dut.timer_int; -// generic_input_wires <= 'h0; -// end -// -// else if (ras_test_ctrl.reset_generic_input_wires) begin -// `ifdef VERILATOR -// generic_input_wires <= {32'h72746C76, ERROR_NONE_SET}; /* 32'h72746c76 is the big-endian ASCII representation of 'vltr' (r t l v) */ -// `else -// generic_input_wires <= {32'h0, ERROR_NONE_SET}; -// `endif -// end -// -// else if (c_state_apb == S_APB_WAIT_ERROR_AXS && rv_dma_resp_error) begin -// generic_input_wires <= {32'h0, DMA_ERROR_OBSERVED}; -// end -// -// else if (c_state_apb == S_APB_RD_HW_ERROR_FATAL && apb_xfer_end) begin -// if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_ICCM_ECC_UNC_LOW]) begin -// generic_input_wires <= {32'h0, ICCM_FATAL_OBSERVED}; -// end -// else if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_DCCM_ECC_UNC_LOW]) begin -// generic_input_wires <= {32'h0, DCCM_FATAL_OBSERVED}; -// end -// else if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_NMI_PIN_LOW]) begin -// generic_input_wires <= {32'h0, NMI_FATAL_OBSERVED}; -// end -// else if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_CRYPTO_ERR_LOW]) begin -// generic_input_wires <= {32'h0, CRYPTO_ERROR_OBSERVED}; -// end -// else begin -// generic_input_wires <= {32'h0, ERROR_NONE_SET}; -// end -// end -// -// else if (c_state_apb == S_APB_RD_HW_ERROR_NON_FATAL && apb_xfer_end) begin -// if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_PROT_NO_LOCK_LOW]) begin -// generic_input_wires <= {32'h0, PROT_NO_LOCK_NON_FATAL_OBSERVED}; -// end -// else if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_PROT_OOO_LOW]) begin -// generic_input_wires <= {32'h0, PROT_OOO_NON_FATAL_OBSERVED}; -// end -// else if (PRDATA[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_ECC_UNC_LOW]) begin -// generic_input_wires <= {32'h0, MBOX_NON_FATAL_OBSERVED}; -// end -// else begin -// generic_input_wires <= {32'h0, ERROR_NONE_SET}; -// end -// end -// -// end - -// always@(negedge core_clk or negedge cptra_pwrgood) begin -// // This persists across soft reset -// if (!cptra_pwrgood) begin -// soc_ifc_hw_error_wdata <= '0; -// end -// else if (c_state_apb inside {S_APB_RD_HW_ERROR_FATAL, S_APB_RD_HW_ERROR_NON_FATAL} && apb_xfer_end) begin -// // HW ERROR registers are W1C, capture the set bits -// soc_ifc_hw_error_wdata <= PRDATA; -// end -// else if (c_state_apb inside {S_APB_WR_HW_ERROR_FATAL, S_APB_WR_HW_ERROR_NON_FATAL} && apb_xfer_end) begin -// // Clear after completing the write -// soc_ifc_hw_error_wdata <= 0; -// end -// end - always@(negedge core_clk or negedge cptra_rst_b) begin if (!cptra_rst_b) begin cptra_error_fatal_counter <= 16'h0; @@ -324,7 +189,6 @@ module caliptra_top_tb ( always_comb cptra_error_fatal_dly_p = cptra_error_fatal_counter == 16'h0040; always_comb cptra_error_non_fatal_dly_p = cptra_error_non_fatal_counter == 16'h0040; -// always_comb assert_rst_flag_from_fatal = c_state_apb == S_APB_ERROR; always@(negedge core_clk) begin if (!cptra_pwrgood) begin count_deassert_rst_flag_from_fatal <= 0; @@ -341,78 +205,6 @@ module caliptra_top_tb ( // Leave reset asserted for 32 clock cycles always_comb deassert_rst_flag_from_fatal = count_deassert_rst_flag_from_fatal == 31; -// assert property (@(posedge core_clk) c_state_apb == S_APB_WR_FUSE_DONE |-> !cptra_error_non_fatal) else begin -// $error("cptra_error_non_fatal observed during boot up"); -// $finish; -// end -// assert property (@(posedge core_clk) c_state_apb == S_APB_WR_FUSE_DONE |-> !cptra_error_fatal) else begin -// $error("cptra_error_fatal observed during boot up"); -// $finish; -// end - -// // ==================================================== FIXME ===================================================== // -// always@(negedge core_clk or negedge cptra_rst_b) begin // -// if(!cptra_rst_b) begin // -// mbox_apb_dataout_read_ooo <= 1'b0; // -// end // -// else if(ras_test_ctrl.do_ooo_access) begin // -// mbox_apb_dataout_read_ooo <= 1'b1; // -// end // -// else if (mbox_apb_dataout_read_ooo && (c_state_apb == S_APB_RD_DATAOUT) && (apb_rd_count == dlen)) begin // -// mbox_apb_dataout_read_ooo <= 1'b0; // -// end // -// end // -// // -// always@(negedge core_clk or negedge cptra_rst_b) begin // -// if(!cptra_rst_b) begin // -// mbox_apb_dataout_read_no_lock <= 1'b0; // -// end // -// else if(ras_test_ctrl.do_no_lock_access) begin // -// mbox_apb_dataout_read_no_lock <= 1'b1; // -// end // -// else if (mbox_apb_dataout_read_no_lock && (c_state_apb == S_APB_RD_DATAOUT) && (apb_rd_count == dlen)) begin // -// mbox_apb_dataout_read_no_lock <= 1'b0; // -// end // -// end // -// // -// always@(negedge core_clk or negedge cptra_rst_b) begin // -// if (!cptra_rst_b) begin // -// mbox_ooo_read_done <= 1'b0; // -// end // -// else if (mbox_apb_dataout_read_ooo && (c_state_apb == S_APB_RD_DATAOUT) && (apb_rd_count == dlen)) begin // -// mbox_ooo_read_done <= 1'b1; // -// end // -// else if (c_state_apb == S_APB_WR_HW_ERROR_NON_FATAL) // -// mbox_ooo_read_done <= 1'b0; // -// else if (ras_test_ctrl.reset_ooo_done_flag) // -// mbox_ooo_read_done <= 1'b0; // -// end // -// // -// always@(negedge core_clk or negedge cptra_rst_b) begin // -// if (!cptra_rst_b) begin // -// mbox_no_lock_read_done <= 1'b0; // -// end // -// else if (mbox_apb_dataout_read_no_lock && (c_state_apb == S_APB_RD_DATAOUT) && (apb_rd_count == dlen)) begin // -// mbox_no_lock_read_done <= 1'b1; // -// end // -// else if (c_state_apb == S_APB_WR_HW_ERROR_NON_FATAL) // -// mbox_no_lock_read_done <= 1'b0; // -// else if (ras_test_ctrl.reset_no_lock_done_flag) // -// mbox_no_lock_read_done <= 1'b0; // -// end // -// // -// always@(negedge core_clk or negedge cptra_rst_b) begin // -// if (!cptra_rst_b) begin // -// execute_mbox_rx_protocol <= 'b0; // -// end // -// else if (c_state_apb == S_APB_WR_EXEC) begin // -// execute_mbox_rx_protocol <= 'b1; // -// end // -// else if (execute_mbox_rx_protocol && ((c_state_apb == S_APB_RST_EXEC) && apb_xfer_end)) begin // -// execute_mbox_rx_protocol <= 'b0; // -// end // -// end // -// // ================================================================================================================ // initial begin cptra_pwrgood = 1'b0; BootFSM_BrkPoint = 1'b1; //Set to 1 even before anything starts @@ -455,7 +247,8 @@ module caliptra_top_tb ( // Run the test stimulus - generic_input_wires = 'h0; // FIXME + soc_ifc_hw_error_wdata = 'h0; + generic_input_wires = 'h0; $display ("\n\n\n\n\n\n"); repeat(15) @(posedge core_clk); $display("CLP: Waiting for cptra_rst_b deassertion\n"); @@ -464,12 +257,12 @@ module caliptra_top_tb ( fork begin: BOOT_AND_CMD_FLOW boot_and_cmd_flow = process::self(); + // Repeat this flow after every warm reset @(posedge cptra_rst_b) $display("CLP: Observed cptra_rst_b deassertion\n"); - @(posedge caliptra_top_dut.cptra_noncore_rst_b) - $display("CLP: Observed cptra_noncore_rst_b deassertion\n"); + // Fuse download sequence wait(ready_for_fuses == 1); $display ("CLP: Ready for fuse download\n"); @@ -477,27 +270,19 @@ module caliptra_top_tb ( $display ("SoC: Writing obfuscated UDS to fuse bank\n"); for (int dw=0; dw < `CLP_OBF_UDS_DWORDS; dw++) begin - wdata = new[1]('{cptra_uds_tb[dw]}); - wstrb = new[1]('{{`CALIPTRA_AXI_DATA_WIDTH{1'b1}}}); - s_axi_if.axi_write(.addr(`CLP_SOC_IFC_REG_FUSE_UDS_SEED_0 + 4 * dw), .data(wdata), .strb(wstrb), .resp(wresp)); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_FUSE_UDS_SEED_0 + 4 * dw), .data(cptra_uds_tb[dw]), .resp(wresp)); end $display ("SoC: Writing obfuscated Field Entropy to fuse bank\n"); for (int dw=0; dw < `CLP_OBF_FE_DWORDS; dw++) begin - wdata = new[1]('{cptra_fe_tb[dw]}); - wstrb = new[1]('{{`CALIPTRA_AXI_DATA_WIDTH{1'b1}}}); - s_axi_if.axi_write(.addr(`CLP_SOC_IFC_REG_FUSE_FIELD_ENTROPY_0 + 4 * dw), .data(wdata), .strb(wstrb), .resp(wresp)); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_FUSE_FIELD_ENTROPY_0 + 4 * dw), .data(cptra_fe_tb[dw]), .resp(wresp)); end $display ("SoC: Writing SOC Stepping ID to fuse bank\n"); - wdata = new[1]('{$urandom()}); - wstrb = new[1]('{{`CALIPTRA_AXI_DATA_WIDTH{1'b1}}}); - s_axi_if.axi_write(.addr(`CLP_SOC_IFC_REG_FUSE_SOC_STEPPING_ID), .data(wdata), .strb(wstrb), .resp(wresp)); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_FUSE_SOC_STEPPING_ID), .data($urandom()), .resp(wresp)); $display ("SoC: Writing fuse done register\n"); - wdata = new[1]('{32'h00000001}); - wstrb = new[1]('{{`CALIPTRA_AXI_DATA_WIDTH{1'b1}}}); - s_axi_if.axi_write(.addr(`CLP_SOC_IFC_REG_CPTRA_FUSE_WR_DONE), .data(wdata), .strb(wstrb), .resp(wresp)); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_CPTRA_FUSE_WR_DONE), .data(32'h00000001), .resp(wresp)); assert (!cptra_error_non_fatal) else begin $error("cptra_error_non_fatal observed during boot up"); @@ -509,65 +294,252 @@ module caliptra_top_tb ( end if (BootFSM_BrkPoint) begin - $display ("SoC: Polling Flow Status\n"); - rdata = new[1]('{default:0}); - rresp = new[1]; + $write ("SoC: Polling Flow Status..."); + poll_count = 0; do begin - s_axi_if.axi_read(.addr(`CLP_SOC_IFC_REG_CPTRA_FLOW_STATUS), .data(rdata), .resp(rresp)); - end while(rdata[0][`SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_LOW] == 1); + s_axi_if.axi_read_single(.addr(`CLP_SOC_IFC_REG_CPTRA_FLOW_STATUS), .data(rdata), .resp(rresp)); + poll_count++; + end while(rdata[`SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_LOW] == 1); + $display("\n >>> SoC: Ready for Fuses deasserted after polling %d times\n", poll_count); $display ("SoC: Writing BootGo register\n"); - wdata = new[1]('{32'h00000001}); - wstrb = new[1]('{{`CALIPTRA_AXI_DATA_WIDTH{1'b1}}}); - s_axi_if.axi_write(.addr(`CLP_SOC_IFC_REG_CPTRA_BOOTFSM_GO), .data(wdata), .strb(wstrb), .resp(wresp)); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_CPTRA_BOOTFSM_GO), .data(32'h00000001), .resp(wresp)); + end + + // Test sequence (Mailbox or error handling) + wait(ready_for_fw_push || ras_test_ctrl.error_injection_seen); + + // Mailbox flow + if (ready_for_fw_push) begin + $display ("CLP: ROM Flow in progress...\n"); + repeat(5) @(posedge core_clk); + + $display ("CLP: Ready for firmware push\n"); + $write ("SoC: Requesting mailbox lock..."); + poll_count = 0; + do begin + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_LOCK), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + poll_count++; + end while (rdata[`MBOX_CSR_MBOX_LOCK_LOCK_LOW] == 1); + $display ("\n >>> SoC: Lock granted after polling %d times\n", poll_count); + + $display ("SoC: Writing the Command Register\n"); + s_axi_if.axi_write_single(.addr(`CLP_MBOX_CSR_MBOX_CMD), .id(32'hFFFF_FFFF), .data(32'hBA5EBA11), .resp(wresp)); + + $display ("SoC: Writing the Data Length Register\n"); + s_axi_if.axi_write_single(.addr(`CLP_MBOX_CSR_MBOX_DLEN), .id(32'hFFFF_FFFF), .data(FW_NUM_DWORDS*4), .resp(wresp)); + + $display ("SoC: Writing the Firmware into Data-in Register\n"); + fw_blob = new[FW_NUM_DWORDS]; + wstrb_array = new[FW_NUM_DWORDS]('{default: {`CALIPTRA_AXI_DATA_WIDTH/8{1'b1}}}); + for (int dw=0; dw < FW_NUM_DWORDS; dw++) + fw_blob[dw] = $urandom(); + s_axi_if.axi_write(.addr(`CLP_MBOX_CSR_MBOX_DATAIN), + .burst(AXI_BURST_FIXED), + .len (FW_NUM_DWORDS-1), + .id (32'hFFFF_FFFF), + .data (fw_blob), + .strb (wstrb_array), + .resp (wresp)); + + $display ("SoC: Setting the Execute Register\n"); + s_axi_if.axi_write_single(.addr(`CLP_MBOX_CSR_MBOX_EXECUTE), .id(32'hFFFF_FFFF), .data(32'h00000001), .resp(wresp)); + + $display("SoC: Waiting for Response Data availability\n"); + wait(mailbox_data_avail); + + $display("SoC: Reading the Status Register...\n"); + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_STATUS), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + + if (((rdata & `MBOX_CSR_MBOX_STATUS_STATUS_MASK) >> `MBOX_CSR_MBOX_STATUS_STATUS_LOW) == DATA_READY) begin: READ_RESP_DATA + $display("SoC: Reading the Data Length Register...\n"); + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_DLEN), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + + $display("SoC: Reading the Data Out Register\n"); + for (int xfer4k = 0; xfer4k < rdata; xfer4k += 4096) begin + byte_count = (rdata - xfer4k) > 4096 ? 4096 : (rdata - xfer4k); + dw_count = byte_count/(`CALIPTRA_AXI_DATA_WIDTH/8) + |byte_count[$clog2(`CALIPTRA_AXI_DATA_WIDTH/8)-1:0]; + rdata_array = new[dw_count]; + rresp_array = new[dw_count]; + s_axi_if.axi_read(.addr(`CLP_MBOX_CSR_MBOX_DATAOUT), + .burst(AXI_BURST_FIXED), + .len(dw_count-1), + .id (32'hFFFF_FFFF), + .data(rdata_array), + .resp(rresp_array)); + end + end: READ_RESP_DATA + + $display("SoC: Resetting the Execute Register\n"); + s_axi_if.axi_write_single(.addr(`CLP_MBOX_CSR_MBOX_EXECUTE), .id(32'hFFFF_FFFF), .data(32'h0), .resp(wresp)); + + //Wait for Mailbox flow to be done before toggling generic_input_wires + @(negedge core_clk); + generic_input_wires = {$urandom, $urandom}; //Toggle wires end - @(posedge caliptra_top_dut.cptra_uc_rst_b) - $display("CLP: Observed cptra_uc_rst_b deassertion\n"); - - $display ("CLP: ROM Flow in progress...\n"); -// //stuff -// if (fixme_demo) begin -// $display ("CLP: Ready for firmware push\n"); -// $display ("SoC: Requesting mailbox lock\n"); -// //stuff -// $display ("SoC: Lock granted\n"); -// //stuff -// $display ("SoC: Writing the Command Register\n"); -// //stuff -// $display ("SoC: Writing the Data Length Register\n"); -// //stuff -// $display ("SoC: Writing the Firmware into Data-in Register\n"); -// //stuff -// $display ("SoC: Setting the Execute Register\n"); -// //stuff -// // TODO wait for mailbox_data_avail -// $display("SoC: Reading the Data Length Register\n"); -// //stuff -// $display("SoC: Reading the Data Out Register\n"); -// //stuff -// $display("SoC: Resetting the Execute Register\n"); -// //stuff -// end -// forever begin -// if (mailbox_data_avail) begin -// $display ("SoC: Writing the Mbox Status Register\n"); -// //stuff -// end -// if (fixme_ras) begin -// $display("SoC: Waiting to see cptra_error_fatal/non_fatal\n"); -// //stuff -// $display("SoC: Observed cptra_error_fatal; reading Caliptra register\n"); -// assert_rst_flag_from_fatal = 1; -// //stuff -// $display("SoC: Observed cptra_error_fatal; writing to clear Caliptra register\n"); -// //stuff -// $display("SoC: Observed cptra_error_non_fatal; reading Caliptra register\n"); -// //stuff -// $display("SoC: Observed cptra_error_non_fatal; writing to clear Caliptra register\n"); -// //stuff -// end - forever @(posedge core_clk); + if (ras_test_ctrl.error_injection_seen) begin + $display("SoC: Waiting to see cptra_error_fatal/non_fatal\n"); + rv_dma_resp_error = 1'b0; + end + + // Mailbox response flow and RAS functionality + forever begin + if (cptra_error_fatal_dly_p) begin + $display("SoC: Observed cptra_error_fatal; reading Caliptra register\n"); + s_axi_if.axi_read_single(.addr(`CLP_SOC_IFC_REG_CPTRA_HW_ERROR_FATAL), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_ICCM_ECC_UNC_LOW]) begin + generic_input_wires = {32'h0, ICCM_FATAL_OBSERVED}; + end + else if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_DCCM_ECC_UNC_LOW]) begin + generic_input_wires = {32'h0, DCCM_FATAL_OBSERVED}; + end + else if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_NMI_PIN_LOW]) begin + generic_input_wires = {32'h0, NMI_FATAL_OBSERVED}; + end + else if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_FATAL_CRYPTO_ERR_LOW]) begin + generic_input_wires = {32'h0, CRYPTO_ERROR_OBSERVED}; + end + else begin + generic_input_wires = {32'h0, ERROR_NONE_SET}; + end + // HW ERROR registers are W1C, capture the set bits + soc_ifc_hw_error_wdata = rdata; + //wait for reset stuff + assert_rst_flag_from_fatal = 1; + wait(cptra_rst_b == 0); + end + else if (cptra_error_non_fatal_dly_p) begin + $display("SoC: Observed cptra_error_non_fatal; reading Caliptra register\n"); + s_axi_if.axi_read_single(.addr(`CLP_SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_PROT_NO_LOCK_LOW]) begin + generic_input_wires = {32'h0, PROT_NO_LOCK_NON_FATAL_OBSERVED}; + end + else if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_PROT_OOO_LOW]) begin + generic_input_wires = {32'h0, PROT_OOO_NON_FATAL_OBSERVED}; + end + else if (rdata[`SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL_MBOX_ECC_UNC_LOW]) begin + generic_input_wires = {32'h0, MBOX_NON_FATAL_OBSERVED}; + end + else begin + generic_input_wires = {32'h0, ERROR_NONE_SET}; + end + $display("SoC: Observed cptra_error_non_fatal; writing to clear Caliptra register\n"); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL), .id(32'hFFFF_FFFF), .data(rdata), .resp(wresp)); + end + else if (soc_ifc_hw_error_wdata) begin + $display("SoC: Observed cptra_error_fatal; writing to clear Caliptra register\n"); + s_axi_if.axi_write_single(.addr(`CLP_SOC_IFC_REG_CPTRA_HW_ERROR_FATAL), .id(32'hFFFF_FFFF), .data(soc_ifc_hw_error_wdata), .resp(wresp)); + soc_ifc_hw_error_wdata = '0; + end + else if (ras_test_ctrl.do_no_lock_access) begin + fork + begin + $display("SoC: Reading the Data Out Register without lock\n"); + dw_count = 1; + rdata_array = new[dw_count]; + rresp_array = new[dw_count]; + s_axi_if.axi_read(.addr(`CLP_MBOX_CSR_MBOX_DATAOUT), + .burst(AXI_BURST_FIXED), + .len(dw_count-1), + .id (32'hFFFF_FFFF), + .data(rdata_array), + .resp(rresp_array)); + end + join + end + else if (ras_test_ctrl.do_ooo_access) begin + fork + begin + $write ("SoC: Requesting mailbox lock..."); + poll_count = 0; + do begin + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_LOCK), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + poll_count++; + end while (rdata[`MBOX_CSR_MBOX_LOCK_LOCK_LOW] == 1); + $display ("\n >>> SoC: Lock granted after polling %d times\n", poll_count); + + $display("SoC: Reading the Data Length Register...\n"); + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_DLEN), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + + $display("SoC: Reading the Data Out Register\n"); + dw_count = 1; + rdata_array = new[dw_count]; + rresp_array = new[dw_count]; + s_axi_if.axi_read(.addr(`CLP_MBOX_CSR_MBOX_DATAOUT), + .burst(AXI_BURST_FIXED), + .len(dw_count-1), + .id (32'hFFFF_FFFF), + .data(rdata_array), + .resp(rresp_array)); + end + join + end + else if (ras_test_ctrl.reset_generic_input_wires) begin + `ifdef VERILATOR + generic_input_wires = {32'h72746C76, ERROR_NONE_SET}; /* 32'h72746c76 is the big-endian ASCII representation of 'vltr' (r t l v) */ + `else + generic_input_wires = {32'h0, ERROR_NONE_SET}; + `endif + end + else if (rv_dma_resp_error) begin + generic_input_wires = {32'h0, DMA_ERROR_OBSERVED}; + rv_dma_resp_error = 1'b0; + end + else if (mailbox_data_avail) begin + $display("SoC: Reading the Data Length Register\n"); + s_axi_if.axi_read_single(.addr(`CLP_MBOX_CSR_MBOX_DLEN), .id(32'hFFFF_FFFF), .data(rdata), .resp(rresp)); + + $display("SoC: Reading the Data Out Register\n"); + for (int xfer4k = 0; xfer4k < rdata; xfer4k += 4096) begin + byte_count = (rdata - xfer4k) > 4096 ? 4096 : (rdata - xfer4k); + dw_count = byte_count/(`CALIPTRA_AXI_DATA_WIDTH/8) + |byte_count[$clog2(`CALIPTRA_AXI_DATA_WIDTH/8)-1:0]; + rdata_array = new[dw_count]; + rresp_array = new[dw_count]; + s_axi_if.axi_read(.addr(`CLP_MBOX_CSR_MBOX_DATAOUT), + .burst(AXI_BURST_FIXED), + .len(dw_count-1), + .id (32'hFFFF_FFFF), + .data(rdata_array), + .resp(rresp_array)); + end + + $display ("SoC: Writing the Mbox Status Register\n"); + s_axi_if.axi_write_single(.addr(`CLP_MBOX_CSR_MBOX_STATUS), .id(32'hFFFF_FFFF), .data(32'h1), .resp(wresp)); + end + @(posedge core_clk); + end end: BOOT_AND_CMD_FLOW + begin: CLK_GATE_FLOW + wait(cycleCnt_smpl_en); + repeat(2000) @(negedge core_clk); + + if (int_flag) + $display("SoC (clk_gate_flow): Forcing soft_int = 1. cycleCnt [%d]\n", cycleCnt); + force caliptra_top_dut.soft_int = 1'b1; + repeat(2) @(negedge core_clk); + $display("SoC (clk_gate_flow): Releasing soft_int = 1. cycleCnt [%d]\n", cycleCnt); + release caliptra_top_dut.soft_int; + + repeat(5000) @(negedge core_clk); + + if (int_flag) + $display("SoC (clk_gate_flow): Forcing timer_int = 1. cycleCnt [%d]\n", cycleCnt); + force caliptra_top_dut.timer_int = 1'b1; + repeat(2) @(negedge core_clk); + $display("SoC (clk_gate_flow): Releasing timer_int = 1. cycleCnt [%d]\n", cycleCnt); + release caliptra_top_dut.timer_int; + + repeat(8000) @(negedge core_clk); + + if (int_flag) + $display("SoC (clk_gate_flow): Forcing soft_int = 1. cycleCnt [%d]\n", cycleCnt); + force caliptra_top_dut.soft_int = 1'b1; + repeat(2) @(negedge core_clk); + $display("SoC (clk_gate_flow): Releasing soft_int = 1. cycleCnt [%d]\n", cycleCnt); + release caliptra_top_dut.soft_int; + + wait(cptra_rst_b == 0); + end: CLK_GATE_FLOW begin: RESET_FLOW @(negedge cptra_rst_b); $display("CLP: Observed cptra_rst_b assertion\n"); @@ -603,583 +575,7 @@ module caliptra_top_tb ( end end -// always@(negedge core_clk or negedge cptra_rst_b) begin -// if (!cptra_rst_b) begin -// dlen <= '0; -// end -// else if ((c_state_apb == S_APB_RD_DLEN) && apb_xfer_end) begin -// dlen <= PRDATA; -// end -// end - -// always@(posedge core_clk or negedge cptra_rst_b) begin -// if (!cptra_rst_b) begin -// c_state_apb <= S_APB_IDLE; -// apb_wr_count <= '0; -// apb_rd_count <= '0; -// apb_enable_ph <= 0; -// end -// else begin -// c_state_apb <= n_state_apb; -// apb_wr_count <= apb_wr_count_nxt; -// apb_rd_count <= apb_rd_count_nxt; -// //next phase is an access phase if this is setup phase OR it's access and responder isn't ready -// apb_enable_ph <= (PSEL & ~PENABLE) | (PSEL & PENABLE & ~PREADY); -// end -// if (c_state_apb != n_state_apb) begin -// case (n_state_apb) -// S_APB_WR_UDS: begin -//// $display ("CLP: Ready for fuse download\n"); -//// $display ("SoC: Writing obfuscated UDS to fuse bank\n"); -// end -// S_APB_WR_FE: begin -//// $display ("SoC: Writing obfuscated Field Entropy to fuse bank\n"); -// end -// S_APB_WR_SOC_STEPPING_ID: begin -//// $display ("SoC: Writing SOC Stepping ID to fuse bank\n"); -// end -// S_APB_WR_FUSE_DONE: begin -//// $display ("SoC: Writing fuse done register\n"); -// end -// S_APB_POLL_FLOW_ST: begin -//// $display ("SoC: Polling Flow Status\n"); -// end -// S_APB_WR_BOOT_GO: begin -//// $display ("SoC: Writing BootGo register\n"); -// end -// S_APB_WAIT_FW_TEST: begin -//// $display ("CLP: ROM Flow in progress...\n"); -// end -// S_APB_POLL_LOCK: begin -//// $display ("CLP: Ready for firmware push\n"); -//// $display ("SoC: Requesting mailbox lock\n"); -// end -// S_APB_PRE_WR_CMD: begin -//// $display ("SoC: Lock granted\n"); -// end -// S_APB_WR_CMD: begin -//// $display ("SoC: Writing the Command Register\n"); -// end -// S_APB_WR_DLEN: begin -//// $display ("SoC: Writing the Data Length Register\n"); -// end -// S_APB_WR_DATAIN: begin -//// $display ("SoC: Writing the Firmware into Data-in Register\n"); -// end -// S_APB_WR_EXEC: begin -//// $display ("SoC: Setting the Execute Register\n"); -// end -// S_APB_WR_STATUS: begin -//// $display ("SoC: Writing the Mbox Status Register\n"); -// end -// S_APB_WAIT_ERROR_AXS: begin -//// $display("SoC: Waiting to see cptra_error_fatal/non_fatal\n"); -// end -// S_APB_RD_HW_ERROR_FATAL: begin -//// $display("SoC: Observed cptra_error_fatal; reading Caliptra register\n"); -// end -// S_APB_WR_HW_ERROR_FATAL: begin -//// $display("SoC: Observed cptra_error_fatal; writing to clear Caliptra register\n"); -// end -// S_APB_RD_HW_ERROR_NON_FATAL: begin -//// $display("SoC: Observed cptra_error_non_fatal; reading Caliptra register\n"); -// end -// S_APB_WR_HW_ERROR_NON_FATAL: begin -//// $display("SoC: Observed cptra_error_non_fatal; writing to clear Caliptra register\n"); -// end -// S_APB_DONE: begin -// end -// S_APB_RD_DLEN: begin -//// $display("SoC: Reading the Data Length Register\n"); -// end -// S_APB_RD_DATAOUT: begin -//// $display("SoC: Reading the Data Out Register\n"); -// end -// S_APB_RST_EXEC: begin -//// $display("SoC: Resetting the Execute Register\n"); -// end -// default: begin -// $display("Entering unexpected APB state: %p", n_state_apb); -// end -// endcase -// end -// end - -// always_comb begin -// apb_wr_count_nxt = 0; -// apb_rd_count_nxt = 0; -// case (c_state_apb) inside -// S_APB_IDLE: begin -// if (start_apb_fuse_sequence) -// n_state_apb = S_APB_WR_UDS; -// else -// n_state_apb = S_APB_IDLE; -// end -// //load fuses -// S_APB_WR_UDS: begin -// if (apb_xfer_end && apb_wr_count == (`CLP_OBF_UDS_DWORDS-1)) begin -// n_state_apb = S_APB_WR_FE; -// apb_wr_count_nxt = '0; -// end -// else if (apb_xfer_end) begin -// n_state_apb = S_APB_WR_UDS; -// apb_wr_count_nxt = apb_wr_count + 1; -// end -// else begin -// n_state_apb = S_APB_WR_UDS; -// apb_wr_count_nxt = apb_wr_count; -// end -// end -// S_APB_WR_FE: begin -// if (apb_xfer_end && apb_wr_count == (`CLP_OBF_FE_DWORDS-1)) begin -// n_state_apb = S_APB_WR_SOC_STEPPING_ID; -// apb_wr_count_nxt = '0; -// end -// else if (apb_xfer_end) begin -// n_state_apb = S_APB_WR_FE; -// apb_wr_count_nxt = apb_wr_count + 1; -// end -// else begin -// n_state_apb = S_APB_WR_FE; -// apb_wr_count_nxt = apb_wr_count; -// end -// end -// S_APB_WR_SOC_STEPPING_ID: begin -// if (apb_xfer_end) begin -// n_state_apb = S_APB_WR_FUSE_DONE; -// end -// else begin -// n_state_apb = S_APB_WR_SOC_STEPPING_ID; -// end -// end -// //set fuse done -// S_APB_WR_FUSE_DONE: begin -// if (apb_xfer_end) begin -// if(BootFSM_BrkPoint) begin -// n_state_apb = S_APB_POLL_FLOW_ST; -// end -// else begin -// n_state_apb = S_APB_WAIT_FW_TEST; -// end -// end -// else begin -// n_state_apb = S_APB_WR_FUSE_DONE; -// end -// end -// S_APB_POLL_FLOW_ST: begin -// if (apb_xfer_end && (PRDATA[`SOC_IFC_REG_CPTRA_FLOW_STATUS_READY_FOR_FUSES_LOW] == 0)) begin -// n_state_apb = S_APB_WR_BOOT_GO; -// end -// else begin -// n_state_apb = S_APB_POLL_FLOW_ST; -// end -// end -// //Write BootGo register -// S_APB_WR_BOOT_GO: begin -// if(apb_xfer_end) begin -// n_state_apb = S_APB_WAIT_FW_TEST; -// end -// else begin -// n_state_apb = S_APB_WR_BOOT_GO; -// end -// end -// -// //This is for Caliptra Demo, smoke tests will stop here since they don't set ready for fw -// //wait for fw req -// S_APB_WAIT_FW_TEST: begin -// if (ready_for_fw_push & (apb_wr_count == 5)) begin -// n_state_apb = S_APB_POLL_LOCK; -// apb_wr_count_nxt = 0; -// end -// else if (ready_for_fw_push) begin -// n_state_apb = S_APB_WAIT_FW_TEST; -// apb_wr_count_nxt = apb_wr_count + 1; -// end -// else if (ras_test_ctrl.error_injection_seen) begin -// n_state_apb = S_APB_WAIT_ERROR_AXS; -// end -// else begin -// n_state_apb = S_APB_WAIT_FW_TEST; -// apb_wr_count_nxt = 0; -// end -// end -// // poll for lock register -// S_APB_POLL_LOCK: begin -// if (apb_xfer_end && (PRDATA != 0)) begin -// n_state_apb = mbox_apb_dataout_read_ooo ? S_APB_RD_DLEN : S_APB_WR_CMD; -// end -// else begin -// n_state_apb = S_APB_POLL_LOCK; -// end -// end -// S_APB_PRE_WR_CMD: begin -// if (apb_wr_count == 5) begin -// n_state_apb = S_APB_WR_CMD; -// apb_wr_count_nxt = 0; -// end -// else begin -// n_state_apb = S_APB_PRE_WR_CMD; -// apb_wr_count_nxt = apb_wr_count + 1; -// end -// end -// //write to MBOX_ADDR_CMD -// S_APB_WR_CMD: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_WR_DLEN; -// else -// n_state_apb = S_APB_WR_CMD; -// end -// // write to MBOX_ADDR_DLEN -// S_APB_WR_DLEN: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_WR_DATAIN; -// else -// n_state_apb = S_APB_WR_DLEN; -// end -// // write a random block in -// S_APB_WR_DATAIN: begin -// if (apb_xfer_end && apb_wr_count == (FW_NUM_DWORDS-1)) begin -// n_state_apb = S_APB_WR_EXEC; -// apb_wr_count_nxt = '0; -// end -// else if (apb_xfer_end) begin -// n_state_apb = S_APB_WR_DATAIN; -// apb_wr_count_nxt = apb_wr_count + 1; -// end -// else begin -// n_state_apb = S_APB_WR_DATAIN; -// apb_wr_count_nxt = apb_wr_count; -// end -// end -// // execute -// S_APB_WR_EXEC: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_DONE; -// else -// n_state_apb = S_APB_WR_EXEC; -// end -// // status -// S_APB_WR_STATUS: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_DONE; -// else -// n_state_apb = S_APB_WR_STATUS; -// end -// S_APB_WAIT_ERROR_AXS: begin -// if (cptra_error_fatal_dly_p) begin -// n_state_apb = S_APB_RD_HW_ERROR_FATAL; -// end -// else if (cptra_error_non_fatal_dly_p) begin -// n_state_apb = S_APB_RD_HW_ERROR_NON_FATAL; -// end -// else if (soc_ifc_hw_error_wdata) begin -// n_state_apb = S_APB_WR_HW_ERROR_FATAL; -// end -// else if (ras_test_ctrl.do_no_lock_access) begin -// n_state_apb = S_APB_RD_DLEN; -// end -// else if (mbox_apb_dataout_read_ooo && !mbox_ooo_read_done) begin -// n_state_apb = S_APB_POLL_LOCK; -// end -// else begin -// n_state_apb = S_APB_WAIT_ERROR_AXS; -// end -// end -// S_APB_RD_HW_ERROR_FATAL: begin -// // Go to ERROR state to wait for cptra_rst_b to assert -// if (apb_xfer_end) begin -// n_state_apb = S_APB_ERROR; -// end -// else begin -// n_state_apb = S_APB_RD_HW_ERROR_FATAL; -// end -// end -// S_APB_WR_HW_ERROR_FATAL: begin -// if (apb_xfer_end) begin -// n_state_apb = S_APB_WAIT_ERROR_AXS; -// end -// else begin -// n_state_apb = S_APB_WR_HW_ERROR_FATAL; -// end -// end -// S_APB_RD_HW_ERROR_NON_FATAL: begin -// if (apb_xfer_end) begin -// n_state_apb = S_APB_WR_HW_ERROR_NON_FATAL; -// end -// else begin -// n_state_apb = S_APB_RD_HW_ERROR_NON_FATAL; -// end -// end -// S_APB_WR_HW_ERROR_NON_FATAL: begin -// if (apb_xfer_end) begin -// n_state_apb = S_APB_WAIT_ERROR_AXS; -// end -// else begin -// n_state_apb = S_APB_WR_HW_ERROR_NON_FATAL; -// end -// end -// S_APB_DONE: begin -// apb_wr_count_nxt = '0; -// apb_rd_count_nxt = '0; -// if (mailbox_data_avail && execute_mbox_rx_protocol) -// n_state_apb = S_APB_RD_DLEN; -// else if (mailbox_data_avail && ~status_set && ~execute_mbox_rx_protocol) -// n_state_apb = S_APB_WR_STATUS; -// else -// n_state_apb = S_APB_DONE; -// end -// S_APB_RD_DLEN: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_RD_DATAOUT; -// else -// n_state_apb = S_APB_RD_DLEN; -// end -// S_APB_RD_DATAOUT: begin -// if (apb_xfer_end && (apb_rd_count == dlen)) begin -// n_state_apb = (mbox_no_lock_read_done || mbox_ooo_read_done) ? S_APB_WAIT_ERROR_AXS : S_APB_RST_EXEC; -// apb_rd_count_nxt = '0; -// end -// else if (apb_xfer_end) begin -// n_state_apb = S_APB_RD_DATAOUT; -// apb_rd_count_nxt = apb_rd_count + 1; -// end -// else begin -// n_state_apb = S_APB_RD_DATAOUT; -// apb_rd_count_nxt = apb_rd_count; -// end -// end -// S_APB_RST_EXEC: begin -// if (apb_xfer_end) -// n_state_apb = S_APB_DONE; -// else -// n_state_apb = S_APB_RST_EXEC; -// end -// default: begin -// apb_wr_count_nxt = apb_wr_count; -// apb_rd_count_nxt = apb_rd_count; -// n_state_apb = S_APB_ERROR; -// end -// endcase -// end -// always@(posedge core_clk or negedge cptra_rst_b) begin -// if (!cptra_rst_b) begin -// status_set <= '0; -// end else begin -// status_set <= ~mailbox_data_avail ? '0 : -// (c_state_apb == S_APB_WR_STATUS) ? '1 : status_set; -// end -// end - -//// assign apb_xfer_end = PSEL && PENABLE && PREADY; -// always@(posedge core_clk) begin -// if ((n_state_apb == S_APB_WR_DATAIN) && apb_xfer_end) -// fw_blob[apb_wr_count_nxt] <= $urandom; -// end -// always_comb begin -// case (c_state_apb) inside -// S_APB_WR_UDS: begin -// PADDR = `CLP_SOC_IFC_REG_FUSE_UDS_SEED_0 + 4 * apb_wr_count; -// PWDATA = cptra_uds_tb[apb_wr_count]; -// end -// S_APB_WR_FE: begin -// PADDR = `CLP_SOC_IFC_REG_FUSE_FIELD_ENTROPY_0 + 4 * apb_wr_count; -// PWDATA = cptra_fe_tb[apb_wr_count]; -// end -// S_APB_WR_SOC_STEPPING_ID: begin -// PADDR = `CLP_SOC_IFC_REG_FUSE_SOC_STEPPING_ID; -// PWDATA = $urandom(); -// end -// S_APB_WR_FUSE_DONE: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_FUSE_WR_DONE; -// PWDATA = 32'h00000001; -// end -// S_APB_POLL_FLOW_ST: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_FLOW_STATUS; -// PWDATA = '0; -// end -// S_APB_WR_BOOT_GO: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_BOOTFSM_GO; -// PWDATA = 32'h00000001; -// end -// S_APB_POLL_LOCK: begin -// PADDR = `CLP_MBOX_CSR_MBOX_LOCK; -// PWDATA = '0; -// end -// S_APB_WR_CMD: begin -// PADDR = `CLP_MBOX_CSR_MBOX_CMD; -// PWDATA = 32'hBA5EBA11; -// end -// S_APB_WR_DLEN: begin -// PADDR = `CLP_MBOX_CSR_MBOX_DLEN; -// PWDATA = FW_NUM_DWORDS*4; -// end -// S_APB_WR_DATAIN: begin -// PADDR = `CLP_MBOX_CSR_MBOX_DATAIN; -// PWDATA = fw_blob[apb_wr_count]; -// end -// S_APB_WR_EXEC: begin -// PADDR = `CLP_MBOX_CSR_MBOX_EXECUTE; -// PWDATA = 32'h00000001; -// end -// S_APB_WR_STATUS: begin -// PADDR = `CLP_MBOX_CSR_MBOX_STATUS; -// PWDATA = 32'h00000001; -// end -// S_APB_RD_HW_ERROR_FATAL: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_HW_ERROR_FATAL; -// PWDATA = soc_ifc_hw_error_wdata; -// end -// S_APB_WR_HW_ERROR_FATAL: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_HW_ERROR_FATAL; -// PWDATA = soc_ifc_hw_error_wdata; -// end -// S_APB_RD_HW_ERROR_NON_FATAL: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL; -// PWDATA = soc_ifc_hw_error_wdata; -// end -// S_APB_WR_HW_ERROR_NON_FATAL: begin -// PADDR = `CLP_SOC_IFC_REG_CPTRA_HW_ERROR_NON_FATAL; -// PWDATA = soc_ifc_hw_error_wdata; -// end -// S_APB_DONE: begin -// PADDR = '0; -// PWDATA = '0; -// end -// S_APB_RD_DLEN: begin -// PADDR = `CLP_MBOX_CSR_MBOX_DLEN; -// PWDATA = dlen; -// end -// S_APB_RD_DATAOUT: begin -// PADDR = `CLP_MBOX_CSR_MBOX_DATAOUT; -// PWDATA = '0; -// end -// S_APB_RST_EXEC: begin -// PADDR = `CLP_MBOX_CSR_MBOX_EXECUTE; -// PWDATA = '0; -// end -// default: begin -// PADDR = '0; -// PWDATA = '0; -// end -// endcase -// end -// always_comb begin -// PENABLE = apb_enable_ph; -// case (c_state_apb) inside -// S_APB_IDLE: begin -// PSEL = 0; -// PWRITE = 0; -// PAUSER = 0; -// end -// S_APB_WR_UDS: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = 0; -// end -// S_APB_WR_FE: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = 0; -// end -// S_APB_WR_SOC_STEPPING_ID: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = 0; -// end -// S_APB_WR_FUSE_DONE: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = 0; -// end -// S_APB_POLL_FLOW_ST: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = 0; -// end -// S_APB_WR_BOOT_GO: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = 0; -// end -// S_APB_POLL_LOCK: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = '1; -// end -// S_APB_WR_CMD: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_WR_DLEN: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_WR_DATAIN: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_WR_EXEC: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_WR_STATUS: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_RD_HW_ERROR_FATAL: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = '1; -// end -// S_APB_WR_HW_ERROR_FATAL: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_RD_HW_ERROR_NON_FATAL: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = '1; -// end -// S_APB_WR_HW_ERROR_NON_FATAL: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// S_APB_DONE: begin -// PSEL = 0; -// PWRITE = 0; -// PAUSER = 0; -// end -// S_APB_RD_DLEN: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = '1; //TODO - which value? -// end -// S_APB_RD_DATAOUT: begin -// PSEL = 1; -// PWRITE = 0; -// PAUSER = '1; -// end -// S_APB_RST_EXEC: begin -// PSEL = 1; -// PWRITE = 1; -// PAUSER = '1; -// end -// default: begin -// PSEL = 0; -// PWRITE = 0; -// PAUSER = 0; -// end -// endcase -// end - // JTAG DPI jtagdpi #( .Name ("jtag0"), @@ -1216,6 +612,10 @@ caliptra_top caliptra_top_dut ( .s_axi_w_if(s_axi_if.w_sub), .s_axi_r_if(s_axi_if.r_sub), + //AXI DMA Interface + .m_axi_w_if(m_axi_if.w_mgr), + .m_axi_r_if(m_axi_if.r_mgr), + .qspi_clk_o (qspi_clk), .qspi_cs_no (qspi_cs_n), .qspi_d_i (qspi_data_device_to_host), @@ -1247,6 +647,8 @@ caliptra_top caliptra_top_dut ( .mailbox_flow_done(), .BootFSM_BrkPoint(BootFSM_BrkPoint), + .recovery_data_avail(1'b1/*TODO*/), + //SoC Interrupts .cptra_error_fatal (cptra_error_fatal ), .cptra_error_non_fatal(cptra_error_non_fatal), @@ -1369,6 +771,67 @@ caliptra_top_tb_services #( ); +always_comb begin + // AXI AR + axi_sram_if.araddr = m_axi_if.araddr[AXI_SRAM_ADDR_WIDTH-1:0]; + axi_sram_if.arburst = m_axi_if.arburst; + axi_sram_if.arsize = m_axi_if.arsize ; + axi_sram_if.arlen = m_axi_if.arlen ; + axi_sram_if.aruser = m_axi_if.aruser ; + axi_sram_if.arid = m_axi_if.arid ; + axi_sram_if.arlock = m_axi_if.arlock ; + axi_sram_if.arvalid = m_axi_if.arvalid && m_axi_if.araddr[`CALIPTRA_AXI_DMA_ADDR_WIDTH-1:AXI_SRAM_ADDR_WIDTH] == AXI_SRAM_BASE_ADDR[`CALIPTRA_AXI_DMA_ADDR_WIDTH-1:AXI_SRAM_ADDR_WIDTH]; + m_axi_if.arready = axi_sram_if.arready; + + // AXI R + m_axi_if.rdata = axi_sram_if.rdata ; + m_axi_if.rresp = axi_sram_if.rresp ; + m_axi_if.rid = axi_sram_if.rid ; + m_axi_if.rlast = axi_sram_if.rlast ; + m_axi_if.rvalid = axi_sram_if.rvalid; + axi_sram_if.rready = m_axi_if.rready ; + + // AXI AW + axi_sram_if.awaddr = m_axi_if.awaddr[AXI_SRAM_ADDR_WIDTH-1:0]; + axi_sram_if.awburst = m_axi_if.awburst; + axi_sram_if.awsize = m_axi_if.awsize ; + axi_sram_if.awlen = m_axi_if.awlen ; + axi_sram_if.awuser = m_axi_if.awuser ; + axi_sram_if.awid = m_axi_if.awid ; + axi_sram_if.awlock = m_axi_if.awlock ; + axi_sram_if.awvalid = m_axi_if.awvalid && m_axi_if.awaddr[`CALIPTRA_AXI_DMA_ADDR_WIDTH-1:AXI_SRAM_ADDR_WIDTH] == AXI_SRAM_BASE_ADDR[`CALIPTRA_AXI_DMA_ADDR_WIDTH-1:AXI_SRAM_ADDR_WIDTH]; + m_axi_if.awready = axi_sram_if.awready; + + // AXI W + axi_sram_if.wdata = m_axi_if.wdata ; + axi_sram_if.wstrb = m_axi_if.wstrb ; + axi_sram_if.wvalid = m_axi_if.wvalid ; + axi_sram_if.wlast = m_axi_if.wlast ; + m_axi_if.wready = axi_sram_if.wready ; + + // AXI B + m_axi_if.bresp = axi_sram_if.bresp ; + m_axi_if.bid = axi_sram_if.bid ; + m_axi_if.bvalid = axi_sram_if.bvalid ; + axi_sram_if.bready = m_axi_if.bready ; +end + +caliptra_axi_sram #( + .AW(AXI_SRAM_ADDR_WIDTH), + .DW(CPTRA_AXI_DMA_DATA_WIDTH), + .UW(CPTRA_AXI_DMA_USER_WIDTH), + .IW(CPTRA_AXI_DMA_ID_WIDTH), + .EX_EN(0) +) i_axi_sram ( + .clk(core_clk), + .rst_n(cptra_rst_b), + + // AXI INF + .s_axi_w_if(axi_sram_if.w_sub), + .s_axi_r_if(axi_sram_if.r_sub) +); +initial i_axi_sram.i_sram.ram = '{default:'{default:8'h00}}; + `define RV_INST caliptra_top_dut.rvtop `define RV_IDMA_RESP_INST caliptra_top_dut.responder_inst[`CALIPTRA_SLAVE_SEL_IDMA] `define RV_DDMA_RESP_INST caliptra_top_dut.responder_inst[`CALIPTRA_SLAVE_SEL_DDMA] @@ -1418,18 +881,12 @@ task force_ahb_dma_loop_read(input logic [31:0] start_addr, input logic [19:0] c endtask initial begin - fork forever @(posedge core_clk) begin if (ras_test_ctrl.dccm_read_burst.start) force_ahb_dma_loop_read(ras_test_ctrl.dccm_read_burst.addr, ras_test_ctrl.dccm_read_burst.count); if (ras_test_ctrl.iccm_read_burst.start) force_ahb_dma_loop_read(ras_test_ctrl.iccm_read_burst.addr, ras_test_ctrl.iccm_read_burst.count); end -// forever @(posedge core_clk) begin -// if (c_state_apb != S_APB_WAIT_ERROR_AXS) -// rv_dma_resp_error = 1'b0; -// end - join end caliptra_top_sva sva(); diff --git a/src/integration/tb/caliptra_top_tb_pkg.sv b/src/integration/tb/caliptra_top_tb_pkg.sv index 3dc9a58f6..d98ff8899 100644 --- a/src/integration/tb/caliptra_top_tb_pkg.sv +++ b/src/integration/tb/caliptra_top_tb_pkg.sv @@ -14,6 +14,7 @@ // package caliptra_top_tb_pkg; +import soc_ifc_pkg::*; `ifndef VERILATOR class bitflip_mask_generator #(int MBOX_DATA_AND_ECC_W = 39); @@ -69,8 +70,6 @@ typedef struct packed { logic reset_generic_input_wires; logic do_no_lock_access; logic do_ooo_access; - logic reset_ooo_done_flag; - logic reset_no_lock_done_flag; } ras_test_ctrl_t; // Values to drive onto GENERIC INPUT WIRES in response to RAS testing @@ -84,4 +83,10 @@ localparam CRYPTO_ERROR_OBSERVED = 32'hdeadface; localparam DMA_ERROR_OBSERVED = 32'hfadebadd; localparam ERROR_NONE_SET = 32'hba5eba11; /* default value for a test with no activity observed by TB */ +// AXI SRAM config +localparam AXI_SRAM_SIZE_BYTES = 65536; +localparam AXI_SRAM_ADDR_WIDTH = $clog2(AXI_SRAM_SIZE_BYTES); +localparam AXI_SRAM_DEPTH = AXI_SRAM_SIZE_BYTES / (CPTRA_AXI_DMA_DATA_WIDTH/8); +localparam logic [`CALIPTRA_AXI_DMA_ADDR_WIDTH-1:0] AXI_SRAM_BASE_ADDR = `CALIPTRA_AXI_DMA_ADDR_WIDTH'h0001_2345_0000; + endpackage diff --git a/src/integration/tb/caliptra_top_tb_services.sv b/src/integration/tb/caliptra_top_tb_services.sv index 5eaf68bd6..a0111b7a5 100644 --- a/src/integration/tb/caliptra_top_tb_services.sv +++ b/src/integration/tb/caliptra_top_tb_services.sv @@ -260,7 +260,7 @@ module caliptra_top_tb_services // 8'he4 - Disable all SRAM error injection (Mailbox, ICCM, DCCM) // 8'he5 - Request TB to initiate Mailbox flow without lock (violation) // 8'he6 - Request TB to initiate Mailbox flow with out-of-order accesses (violation) - // 8'he7 - Reset mailbox out-of-order flag when non-fatal error is masked (allows the test to continue) + // 8'he7 - Reset mailbox out-of-order flag when non-fatal error is masked (allows the test to continue) [Deprecated] // 8'he8 - Enable scan mode when DOE fsm transitions to done state // 8'he9 - Force dmi_reg_en input to clk gate to emulate JTAG accesses // 8'hea - Set random values to WDT timer1 and timer2 @@ -323,32 +323,22 @@ module caliptra_top_tb_services if (!cptra_rst_b) begin ras_test_ctrl.do_no_lock_access <= 1'b0; ras_test_ctrl.do_ooo_access <= 1'b0; - ras_test_ctrl.reset_ooo_done_flag <= 1'b0; - ras_test_ctrl.reset_no_lock_done_flag <= 1'b0; end else if((WriteData[7:0] == 8'he5) && mailbox_write) begin ras_test_ctrl.do_no_lock_access <= 1'b1; ras_test_ctrl.do_ooo_access <= 1'b0; - ras_test_ctrl.reset_ooo_done_flag <= 1'b0; - ras_test_ctrl.reset_no_lock_done_flag <= 1'b0; end else if((WriteData[7:0] == 8'he6) && mailbox_write) begin ras_test_ctrl.do_no_lock_access <= 1'b0; ras_test_ctrl.do_ooo_access <= 1'b1; - ras_test_ctrl.reset_ooo_done_flag <= 1'b0; - ras_test_ctrl.reset_no_lock_done_flag <= 1'b0; end else if ((WriteData[7:0] == 8'he7) && mailbox_write) begin ras_test_ctrl.do_no_lock_access <= 1'b0; ras_test_ctrl.do_ooo_access <= 1'b0; - ras_test_ctrl.reset_ooo_done_flag <= 1'b1; - ras_test_ctrl.reset_no_lock_done_flag <= 1'b1; end else begin ras_test_ctrl.do_no_lock_access <= 1'b0; ras_test_ctrl.do_ooo_access <= 1'b0; - ras_test_ctrl.reset_ooo_done_flag <= 1'b0; - ras_test_ctrl.reset_no_lock_done_flag <= 1'b0; end end diff --git a/src/integration/tb/test_caliptra_top_tb.cpp b/src/integration/tb/test_caliptra_top_tb.cpp index 05b7f47db..3665ae00e 100644 --- a/src/integration/tb/test_caliptra_top_tb.cpp +++ b/src/integration/tb/test_caliptra_top_tb.cpp @@ -57,8 +57,9 @@ int main(int argc, char** argv) { #if VM_TRACE tfp->dump (main_time); #endif - main_time += 5; - tb->core_clk = !tb->core_clk; + main_time += 1; + // Toggle every 5ns (timescale precision is 100ps) + if (main_time % 50 == 0) tb->core_clk = !tb->core_clk; tb->eval(); } diff --git a/src/integration/test_suites/iccm_lock/caliptra_isr.h b/src/integration/test_suites/iccm_lock/caliptra_isr.h index 0bdef173f..07a5b39e8 100644 --- a/src/integration/test_suites/iccm_lock/caliptra_isr.h +++ b/src/integration/test_suites/iccm_lock/caliptra_isr.h @@ -54,6 +54,8 @@ typedef struct { uint32_t soc_ifc_notif; uint32_t sha512_acc_error; uint32_t sha512_acc_notif; + uint32_t axi_dma_error; + uint32_t axi_dma_notif; } caliptra_intr_received_s; extern volatile caliptra_intr_received_s cptra_intr_rcv; @@ -241,5 +243,8 @@ inline void service_sha512_acc_notif_intr() { } } +inline void service_axi_dma_error_intr() {return;} +inline void service_axi_dma_notif_intr() {return;} + #endif //CALIPTRA_ISR_H diff --git a/src/integration/test_suites/iccm_lock/iccm_lock.c b/src/integration/test_suites/iccm_lock/iccm_lock.c index 416c449fc..aa73a748b 100644 --- a/src/integration/test_suites/iccm_lock/iccm_lock.c +++ b/src/integration/test_suites/iccm_lock/iccm_lock.c @@ -57,6 +57,8 @@ volatile caliptra_intr_received_s cptra_intr_rcv = { .soc_ifc_notif = 0, .sha512_acc_error = 0, .sha512_acc_notif = 0, + .axi_dma_notif = 0, + .axi_dma_notif = 0, }; extern uintptr_t iccm_code0_start, iccm_code0_end; diff --git a/src/integration/test_suites/includes/caliptra_defines.h b/src/integration/test_suites/includes/caliptra_defines.h index 4214fdd3b..0249f48c7 100644 --- a/src/integration/test_suites/includes/caliptra_defines.h +++ b/src/integration/test_suites/includes/caliptra_defines.h @@ -79,6 +79,10 @@ #define STATUS_READY_BIT 0x0 #define STATUS_VALID_BIT 0x1 +/* ---- AXI SRAM ---- */ +#define AXI_SRAM_BASE_ADDR (uint64_t) 0x000123450000ULL +#define AXI_SRAM_SIZE_BYTES 65536 + /* ---- Interrupts ---- */ #define VEER_INTR_VEC_DOE_ERROR 1 #define VEER_INTR_VEC_DOE_NOTIF 2 @@ -102,8 +106,10 @@ #define VEER_INTR_VEC_SOC_IFC_NOTIF 20 #define VEER_INTR_VEC_SHA512_ACC_ERROR 21 #define VEER_INTR_VEC_SHA512_ACC_NOTIF 22 +#define VEER_INTR_VEC_AXI_DMA_ERROR 23 +#define VEER_INTR_VEC_AXI_DMA_NOTIF 24 // Used to tie-off unused upper intr bits -#define VEER_INTR_VEC_MAX_ASSIGNED VEER_INTR_VEC_SHA512_ACC_NOTIF +#define VEER_INTR_VEC_MAX_ASSIGNED VEER_INTR_VEC_AXI_DMA_NOTIF #define VEER_INTR_PRIO_DOE_ERROR 8 #define VEER_INTR_PRIO_DOE_NOTIF 7 @@ -127,6 +133,8 @@ #define VEER_INTR_PRIO_I3C_NOTIF 3 #define VEER_INTR_PRIO_SOC_IFC_ERROR 8 #define VEER_INTR_PRIO_SOC_IFC_NOTIF 7 +#define VEER_INTR_PRIO_AXI_DMA_ERROR 8 +#define VEER_INTR_PRIO_AXI_DMA_NOTIF 7 #endif // CALIPTRA_DEFINES_H diff --git a/src/integration/test_suites/libs/caliptra_isr/caliptra_isr.c b/src/integration/test_suites/libs/caliptra_isr/caliptra_isr.c index 459b00eea..11acd94e3 100644 --- a/src/integration/test_suites/libs/caliptra_isr/caliptra_isr.c +++ b/src/integration/test_suites/libs/caliptra_isr/caliptra_isr.c @@ -76,6 +76,8 @@ static void nonstd_veer_isr_soc_ifc_error (void) __attribute__ ((interrupt ("mac static void nonstd_veer_isr_soc_ifc_notif (void) __attribute__ ((interrupt ("machine"))); static void nonstd_veer_isr_sha512_acc_error (void) __attribute__ ((interrupt ("machine"))); static void nonstd_veer_isr_sha512_acc_notif (void) __attribute__ ((interrupt ("machine"))); +static void nonstd_veer_isr_axi_dma_error (void) __attribute__ ((interrupt ("machine"))); +static void nonstd_veer_isr_axi_dma_notif (void) __attribute__ ((interrupt ("machine"))); // Could be much more fancy with C preprocessing to pair up the ISR with Vector // numbers as defined in caliptra_defines.h.... TODO @@ -101,13 +103,13 @@ static void (* const nonstd_veer_isr_18) (void) = std_rv_nop_machine ; static void (* const nonstd_veer_isr_19) (void) = nonstd_veer_isr_soc_ifc_error; // | static void (* const nonstd_veer_isr_20) (void) = nonstd_veer_isr_soc_ifc_notif; // | static void (* const nonstd_veer_isr_21) (void) = nonstd_veer_isr_sha512_acc_error;// | -static void (* const nonstd_veer_isr_22) (void) = nonstd_veer_isr_sha512_acc_notif;// -------' -static void (* const nonstd_veer_isr_23) (void) = std_rv_nop_machine; // --------| -static void (* const nonstd_veer_isr_24) (void) = std_rv_nop_machine; // | -static void (* const nonstd_veer_isr_25) (void) = std_rv_nop_machine; // | -static void (* const nonstd_veer_isr_26) (void) = std_rv_nop_machine; // Unimplemented ISR +static void (* const nonstd_veer_isr_22) (void) = nonstd_veer_isr_sha512_acc_notif;// | +static void (* const nonstd_veer_isr_23) (void) = nonstd_veer_isr_axi_dma_error; // | +static void (* const nonstd_veer_isr_24) (void) = nonstd_veer_isr_axi_dma_notif; // -------' +static void (* const nonstd_veer_isr_25) (void) = std_rv_nop_machine; // --------| +static void (* const nonstd_veer_isr_26) (void) = std_rv_nop_machine; // | static void (* const nonstd_veer_isr_27) (void) = std_rv_nop_machine; // | -static void (* const nonstd_veer_isr_28) (void) = std_rv_nop_machine; // | +static void (* const nonstd_veer_isr_28) (void) = std_rv_nop_machine; // Unimplemented ISR static void (* const nonstd_veer_isr_29) (void) = std_rv_nop_machine; // | static void (* const nonstd_veer_isr_30) (void) = std_rv_nop_machine; // | static void (* const nonstd_veer_isr_31) (void) = std_rv_nop_machine; // --------' @@ -177,6 +179,7 @@ void init_interrupts(void) { volatile uint32_t * const sha512_reg = (uint32_t*) CLP_SHA512_REG_BASE_ADDR; volatile uint32_t * const sha256_reg = (uint32_t*) CLP_SHA256_REG_BASE_ADDR; volatile uint32_t * const sha512_acc_csr = (uint32_t*) CLP_SHA512_ACC_CSR_BASE_ADDR; + volatile uint32_t * const axi_dma_reg = (uint32_t*) CLP_AXI_DMA_REG_BASE_ADDR; volatile uint32_t * const mtime_l = (uint32_t*) CLP_SOC_IFC_REG_INTERNAL_RV_MTIME_L; volatile uint32_t * const mtime_h = (uint32_t*) CLP_SOC_IFC_REG_INTERNAL_RV_MTIME_H; volatile uint32_t * const mtimecmp_l = (uint32_t*) CLP_SOC_IFC_REG_INTERNAL_RV_MTIMECMP_L; @@ -240,6 +243,8 @@ void init_interrupts(void) { meipls[VEER_INTR_VEC_SOC_IFC_NOTIF ] = VEER_INTR_PRIO_SOC_IFC_NOTIF ; __asm__ volatile ("fence"); meipls[VEER_INTR_VEC_SHA512_ACC_ERROR] = VEER_INTR_PRIO_SHA512_ACC_ERROR; __asm__ volatile ("fence"); meipls[VEER_INTR_VEC_SHA512_ACC_NOTIF] = VEER_INTR_PRIO_SHA512_ACC_NOTIF; __asm__ volatile ("fence"); + meipls[VEER_INTR_VEC_AXI_DMA_ERROR ] = VEER_INTR_PRIO_AXI_DMA_ERROR ; __asm__ volatile ("fence"); + meipls[VEER_INTR_VEC_AXI_DMA_NOTIF ] = VEER_INTR_PRIO_AXI_DMA_NOTIF ; __asm__ volatile ("fence"); for (uint8_t undef = VEER_INTR_VEC_MAX_ASSIGNED+1; undef <= RV_PIC_TOTAL_INT; undef++) { meipls[undef] = 0; __asm__ volatile ("fence"); // Set to 0 meaning NEVER interrupt } @@ -336,6 +341,23 @@ void init_interrupts(void) { sha512_acc_csr[SHA512_ACC_CSR_INTR_BLOCK_RF_GLOBAL_INTR_EN_R/sizeof(uint32_t)] = SHA512_ACC_CSR_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_MASK | SHA512_ACC_CSR_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_MASK; + // AXI DMA + // TODO + axi_dma_reg[AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R /sizeof(uint32_t)] = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_CMD_DEC_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_AXI_RD_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_AXI_WR_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_MBOX_LOCK_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_SHA_LOCK_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_FIFO_OFLOW_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR_FIFO_UFLOW_EN_MASK; + axi_dma_reg[AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R /sizeof(uint32_t)] = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_TXN_DONE_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_EMPTY_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_NOT_EMPTY_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_FULL_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_NOT_FULL_EN_MASK; + axi_dma_reg[AXI_DMA_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R/sizeof(uint32_t)] = AXI_DMA_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_MASK; + // Set mtimecmp to max value to avoid spurious timer interrupts *mtimecmp_l = 0xFFFFFFFF; *mtimecmp_h = 0xFFFFFFFF; @@ -704,6 +726,8 @@ static void nonstd_veer_isr_0 (void) { * service_soc_ifc_notif_intr \ * service_sha512_acc_error_intr \ * service_sha512_acc_notif_intr \ + * service_axi_dma_error_intr \ + * service_axi_dma_notif_intr \ */ \ service_##name##_intr(); \ \ @@ -774,4 +798,8 @@ nonstd_veer_isr(soc_ifc_notif) nonstd_veer_isr(sha512_acc_error) // Non-Standard Vectored Interrupt Handler (SHA Notification = vector 22) nonstd_veer_isr(sha512_acc_notif) +// Non-Standard Vectored Interrupt Handler (AXI DMA Error = vector 23) +nonstd_veer_isr(axi_dma_error) +// Non-Standard Vectored Interrupt Handler (AXI DMA Notification = vector 24) +nonstd_veer_isr(axi_dma_notif) diff --git a/src/integration/test_suites/libs/soc_ifc/soc_ifc.c b/src/integration/test_suites/libs/soc_ifc/soc_ifc.c index bd890a7bb..2a7edd321 100644 --- a/src/integration/test_suites/libs/soc_ifc/soc_ifc.c +++ b/src/integration/test_suites/libs/soc_ifc/soc_ifc.c @@ -295,3 +295,116 @@ void soc_ifc_sha_accel_clr_lock() { //Write one to clear lsu_write_32((CLP_SHA512_ACC_CSR_LOCK), SHA512_ACC_CSR_LOCK_LOCK_MASK); } + +// AXI DMA Functions +uint8_t soc_ifc_axi_dma_send_ahb_payload(uint64_t dst_addr, uint8_t fixed, uint32_t * payload, uint32_t byte_count, uint16_t block_size) { + uint32_t reg; + uint16_t mdepth; + + // Arm the command + while (lsu_read_32(CLP_AXI_DMA_REG_STATUS0) & AXI_DMA_REG_STATUS0_BUSY_MASK); + lsu_write_32(CLP_AXI_DMA_REG_DST_ADDR_L, dst_addr & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_DST_ADDR_H, (dst_addr >> 32) & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_BYTE_COUNT, byte_count); + lsu_write_32(CLP_AXI_DMA_REG_BLOCK_SIZE, (uint32_t) block_size); + reg |= AXI_DMA_REG_CTRL_GO_MASK; + reg |= axi_dma_rd_route_DISABLE << AXI_DMA_REG_CTRL_RD_ROUTE_LOW; + reg |= axi_dma_wr_route_AHB_FIFO << AXI_DMA_REG_CTRL_WR_ROUTE_LOW; + reg |= fixed ? AXI_DMA_REG_CTRL_WR_FIXED_MASK : 0; + lsu_write_32(CLP_AXI_DMA_REG_CTRL, reg); + + // Send data + mdepth = (lsu_read_32(CLP_AXI_DMA_REG_CAP) & AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_MASK) >> AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_LOW; + for (uint32_t dw_sent = 0; dw_sent < (byte_count>>2); dw_sent++) { + // Wait for there to be available space in the FIFO + while(((lsu_read_32(CLP_AXI_DMA_REG_STATUS0) & AXI_DMA_REG_STATUS0_FIFO_DEPTH_MASK) >> AXI_DMA_REG_STATUS0_FIFO_DEPTH_LOW) == mdepth); + lsu_write_32(CLP_AXI_DMA_REG_WRITE_DATA, payload[dw_sent]); + } + + // Check completion + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + while ((reg & AXI_DMA_REG_STATUS0_BUSY_MASK) && !(reg & AXI_DMA_REG_STATUS0_ERROR_MASK)) { + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + } + + if (reg & AXI_DMA_REG_STATUS0_ERROR_MASK) { + VPRINTF(FATAL, "FATAL: AXI DMA reports error status for FIFO-to-AXI xfer\n"); + lsu_write_32(CLP_AXI_DMA_REG_CTRL, AXI_DMA_REG_CTRL_FLUSH_MASK); + SEND_STDOUT_CTRL(0x1); + } +} + +uint8_t soc_ifc_axi_dma_read_ahb_payload(uint64_t src_addr, uint8_t fixed, uint32_t * payload, uint32_t byte_count, uint16_t block_size) { + uint32_t reg; + uint16_t mdepth; + + // Arm the command + while (lsu_read_32(CLP_AXI_DMA_REG_STATUS0) & AXI_DMA_REG_STATUS0_BUSY_MASK); + lsu_write_32(CLP_AXI_DMA_REG_SRC_ADDR_L, src_addr & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_SRC_ADDR_H, (src_addr >> 32) & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_BYTE_COUNT, byte_count); + lsu_write_32(CLP_AXI_DMA_REG_BLOCK_SIZE, (uint32_t) block_size); + reg |= AXI_DMA_REG_CTRL_GO_MASK; + reg |= axi_dma_rd_route_AHB_FIFO << AXI_DMA_REG_CTRL_RD_ROUTE_LOW; + reg |= axi_dma_wr_route_DISABLE << AXI_DMA_REG_CTRL_WR_ROUTE_LOW; + reg |= fixed ? AXI_DMA_REG_CTRL_RD_FIXED_MASK : 0; + lsu_write_32(CLP_AXI_DMA_REG_CTRL, reg); + + // Read data + mdepth = (lsu_read_32(CLP_AXI_DMA_REG_CAP) & AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_MASK) >> AXI_DMA_REG_CAP_FIFO_MAX_DEPTH_LOW; + for (uint32_t dw_rcv = 0; dw_rcv < (byte_count>>2); dw_rcv++) { + // Wait for there to be available data in the FIFO + while(((lsu_read_32(CLP_AXI_DMA_REG_STATUS0) & AXI_DMA_REG_STATUS0_FIFO_DEPTH_MASK) >> AXI_DMA_REG_STATUS0_FIFO_DEPTH_LOW) == 0); + payload[dw_rcv] = lsu_read_32(CLP_AXI_DMA_REG_READ_DATA); + } + + // Check completion + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + while ((reg & AXI_DMA_REG_STATUS0_BUSY_MASK) && !(reg & AXI_DMA_REG_STATUS0_ERROR_MASK)) { + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + } + + if (reg & AXI_DMA_REG_STATUS0_ERROR_MASK) { + VPRINTF(FATAL, "FATAL: AXI DMA reports error status for AXI-to-FIFO xfer\n"); + lsu_write_32(CLP_AXI_DMA_REG_CTRL, AXI_DMA_REG_CTRL_FLUSH_MASK); + SEND_STDOUT_CTRL(0x1); + } +} + +uint8_t soc_ifc_axi_dma_send_mbox_payload(uint64_t src_addr, uint64_t dst_addr, uint8_t fixed, uint32_t byte_count, uint16_t block_size) { +} + +uint8_t soc_ifc_axi_dma_read_mbox_payload(uint64_t src_addr, uint64_t dst_addr, uint8_t fixed, uint32_t byte_count, uint16_t block_size) { +} + +uint8_t soc_ifc_axi_dma_send_axi_to_axi(uint64_t src_addr, uint8_t src_fixed, uint64_t dst_addr, uint8_t dst_fixed, uint32_t byte_count, uint16_t block_size) { + uint32_t reg; + + // Arm the command + while (lsu_read_32(CLP_AXI_DMA_REG_STATUS0) & AXI_DMA_REG_STATUS0_BUSY_MASK); + lsu_write_32(CLP_AXI_DMA_REG_SRC_ADDR_L, src_addr & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_SRC_ADDR_H, (src_addr >> 32) & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_DST_ADDR_L, dst_addr & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_DST_ADDR_H, (dst_addr >> 32) & 0xffffffff); + lsu_write_32(CLP_AXI_DMA_REG_BYTE_COUNT, byte_count); + lsu_write_32(CLP_AXI_DMA_REG_BLOCK_SIZE, (uint32_t) block_size); + reg |= AXI_DMA_REG_CTRL_GO_MASK; + reg |= axi_dma_rd_route_AXI_WR << AXI_DMA_REG_CTRL_RD_ROUTE_LOW; + reg |= axi_dma_wr_route_AXI_RD << AXI_DMA_REG_CTRL_WR_ROUTE_LOW; + reg |= src_fixed ? AXI_DMA_REG_CTRL_RD_FIXED_MASK : 0; + reg |= dst_fixed ? AXI_DMA_REG_CTRL_WR_FIXED_MASK : 0; + lsu_write_32(CLP_AXI_DMA_REG_CTRL, reg); + + // Check completion + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + while ((reg & AXI_DMA_REG_STATUS0_BUSY_MASK) && !(reg & AXI_DMA_REG_STATUS0_ERROR_MASK)) { + reg = lsu_read_32(CLP_AXI_DMA_REG_STATUS0); + } + + // Report any errors + if (reg & AXI_DMA_REG_STATUS0_ERROR_MASK) { + VPRINTF(FATAL, "FATAL: AXI DMA reports error status for AXI-to-AXI xfer\n"); + lsu_write_32(CLP_AXI_DMA_REG_CTRL, AXI_DMA_REG_CTRL_FLUSH_MASK); + SEND_STDOUT_CTRL(0x1); + } +} diff --git a/src/integration/test_suites/libs/soc_ifc/soc_ifc.h b/src/integration/test_suites/libs/soc_ifc/soc_ifc.h index 84f6ad365..c32277b2a 100644 --- a/src/integration/test_suites/libs/soc_ifc/soc_ifc.h +++ b/src/integration/test_suites/libs/soc_ifc/soc_ifc.h @@ -38,6 +38,27 @@ enum mbox_fsm_e { MBOX_ERROR = 0x7 }; +enum axi_dma_rd_route_e { + axi_dma_rd_route_DISABLE = 0x0, + axi_dma_rd_route_MBOX = 0x1, + axi_dma_rd_route_AHB_FIFO = 0x2, + axi_dma_rd_route_AXI_WR = 0x3 +}; + +enum axi_dma_wr_route_e { + axi_dma_wr_route_DISABLE = 0x0, + axi_dma_wr_route_MBOX = 0x1, + axi_dma_wr_route_AHB_FIFO = 0x2, + axi_dma_wr_route_AXI_RD = 0x3 +}; + +enum axi_dma_fsm_e { + axi_dma_fsm_DMA_IDLE = 0x0, + axi_dma_fsm_DMA_WAIT_DATA = 0x1, + axi_dma_fsm_DMA_DONE = 0x2, + axi_dma_fsm_DMA_ERROR = 0x3 +}; + /** * Decode: * [31]: Firmware command @@ -128,4 +149,11 @@ void soc_ifc_sha_accel_poll_status(); void soc_ifc_sha_accel_clr_lock(); void soc_ifc_w1clr_sha_lock_field(); +// AXI DMA Functions +uint8_t soc_ifc_axi_dma_send_ahb_payload(uint64_t dst_addr, uint8_t fixed, uint32_t * payload, uint32_t byte_count, uint16_t block_size); +uint8_t soc_ifc_axi_dma_read_ahb_payload(uint64_t src_addr, uint8_t fixed, uint32_t * payload, uint32_t byte_count, uint16_t block_size); +uint8_t soc_ifc_axi_dma_send_mbox_payload(uint64_t src_addr, uint64_t dst_addr, uint8_t fixed, uint32_t byte_count, uint16_t block_size); +uint8_t soc_ifc_axi_dma_read_mbox_payload(uint64_t src_addr, uint64_t dst_addr, uint8_t fixed, uint32_t byte_count, uint16_t block_size); +uint8_t soc_ifc_axi_dma_send_axi_to_axi(uint64_t src_addr, uint8_t src_fixed, uint64_t dst_addr, uint8_t dst_fixed, uint32_t byte_count, uint16_t block_size); + #endif diff --git a/src/integration/test_suites/smoke_test_dma/caliptra_isr.h b/src/integration/test_suites/smoke_test_dma/caliptra_isr.h new file mode 100644 index 000000000..eeca30e9b --- /dev/null +++ b/src/integration/test_suites/smoke_test_dma/caliptra_isr.h @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// --------------------------------------------------------------------- +// File: caliptra_isr.h +// Description: +// Provides function declarations for use by external test files, so +// that the ISR functionality may behave like a library. +// TODO: +// This header file includes inline function definitions for event and +// test specific interrupt service behavior, so it should be copied and +// modified for each test. +// --------------------------------------------------------------------- + +#ifndef CALIPTRA_ISR_H + #define CALIPTRA_ISR_H + +#include "caliptra_defines.h" +#include +#include "printf.h" + +/* --------------- symbols/typedefs --------------- */ +typedef struct { + uint32_t doe_error; + uint32_t doe_notif; + uint32_t ecc_error; + uint32_t ecc_notif; + uint32_t hmac_error; + uint32_t hmac_notif; + uint32_t kv_error; + uint32_t kv_notif; + uint32_t sha512_error; + uint32_t sha512_notif; + uint32_t sha256_error; + uint32_t sha256_notif; + uint32_t qspi_error; + uint32_t qspi_notif; + uint32_t uart_error; + uint32_t uart_notif; + uint32_t i3c_error; + uint32_t i3c_notif; + uint32_t soc_ifc_error; + uint32_t soc_ifc_notif; + uint32_t sha512_acc_error; + uint32_t sha512_acc_notif; + uint32_t axi_dma_error; + uint32_t axi_dma_notif; +} caliptra_intr_received_s; +extern volatile caliptra_intr_received_s cptra_intr_rcv; + +////////////////////////////////////////////////////////////////////////////// +// Function Declarations +// + +// Performs all the CSR setup to configure and enable vectored external interrupts +void init_interrupts(void); + +// These inline functions are used to insert event-specific functionality into the +// otherwise generic ISR that gets laid down by the parameterized macro "nonstd_veer_isr" +inline void service_doe_error_intr() {return;} +inline void service_doe_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.doe_notif |= DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad doe_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_ecc_error_intr() {return;} +inline void service_ecc_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.ecc_notif |= ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad ecc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_hmac_error_intr() {return;} +inline void service_hmac_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.hmac_notif |= HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad hmac_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_kv_error_intr() {return;} +inline void service_kv_notif_intr() {return;} +inline void service_sha512_error_intr() {return;} +inline void service_sha512_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha512_notif |= SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha512_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_sha256_error_intr() {return;} +inline void service_sha256_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha256_notif |= SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha256_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_qspi_error_intr() {return;} +inline void service_qspi_notif_intr() {return;} +inline void service_uart_error_intr() {return;} +inline void service_uart_notif_intr() {return;} +inline void service_i3c_error_intr() {return;} +inline void service_i3c_notif_intr() {return;} + +inline void service_soc_ifc_error_intr() { + uint32_t * reg = (uint32_t *) (CLP_SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad soc_ifc_error_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_soc_ifc_notif_intr () { + uint32_t * reg = (uint32_t *) (CLP_SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad soc_ifc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_sha512_acc_error_intr() {return;} +inline void service_sha512_acc_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha512_acc_notif |= SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha512_acc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_axi_dma_error_intr() { + uint32_t * reg = (uint32_t *) (CLP_AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_DEC_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_DEC_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_DEC_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_RD_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_RD_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_RD_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_WR_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_WR_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_AXI_WR_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_LOCK_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_LOCK_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_LOCK_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_SHA_LOCK_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_SHA_LOCK_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_SHA_LOCK_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_OFLOW_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_OFLOW_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_OFLOW_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_UFLOW_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_UFLOW_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= AXI_DMA_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_FIFO_UFLOW_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad axi_dma_error_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} +inline void service_axi_dma_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; +// VPRINTF(LOW, "ntf\n"); + /* Write 1 to Clear the pending interrupt */ + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_TXN_DONE_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_TXN_DONE_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_TXN_DONE_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_EMPTY_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_EMPTY_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_EMPTY_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_EMPTY_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_EMPTY_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_EMPTY_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_FULL_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_FULL_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_FULL_STS_MASK; + } + if (sts & AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_FULL_STS_MASK) { + *reg = AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_FULL_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_FIFO_NOT_FULL_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad axi_dma_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + + +#endif //CALIPTRA_ISR_H diff --git a/src/integration/test_suites/smoke_test_dma/smoke_test_dma.c b/src/integration/test_suites/smoke_test_dma/smoke_test_dma.c new file mode 100644 index 000000000..07f7ee02a --- /dev/null +++ b/src/integration/test_suites/smoke_test_dma/smoke_test_dma.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "caliptra_defines.h" +#include "caliptra_isr.h" +#include "riscv-csr.h" +#include "veer-csr.h" +#include "riscv_hw_if.h" +#include +#include +#include "printf.h" +#include "soc_ifc.h" + + +//int whisperPrintf(const char* format, ...); +//#define ee_printf whisperPrintf + + +volatile char* stdout = (char *)STDOUT; +volatile uint32_t intr_count = 0; +#ifdef CPT_VERBOSITY + enum printf_verbosity verbosity_g = CPT_VERBOSITY; +#else + enum printf_verbosity verbosity_g = LOW; +#endif + +volatile caliptra_intr_received_s cptra_intr_rcv = { + .doe_error = 0, + .doe_notif = 0, + .ecc_error = 0, + .ecc_notif = 0, + .hmac_error = 0, + .hmac_notif = 0, + .kv_error = 0, + .kv_notif = 0, + .sha512_error = 0, + .sha512_notif = 0, + .sha256_error = 0, + .sha256_notif = 0, + .qspi_error = 0, + .qspi_notif = 0, + .uart_error = 0, + .uart_notif = 0, + .i3c_error = 0, + .i3c_notif = 0, + .soc_ifc_error = 0, + .soc_ifc_notif = 0, + .sha512_acc_error = 0, + .sha512_acc_notif = 0, + .axi_dma_notif = 0, + .axi_dma_notif = 0, +}; + +void main(void) { + int argc=0; + char *argv[1]; + uint32_t reg; + uint8_t fail = 0; + uint32_t send_payload[16] = { + 0xabadface, + 0xba5eba11, + 0xcafebabe, + 0xdeadbeef, + 0xebbf1000, + 0xfadefee1, + 0x12344321, + 0xa5a5a5a5, + 0x14351375, + 0x8afdbe82, + 0xafb832ba, + 0x8843151a, + 0xbad831b1, + 0xf831ba83, + 0xad813451, + 0x67120ad3 + }; + uint32_t read_payload[16]; + + VPRINTF(LOW, "----------------------------------\nSmoke Test AXI DMA !!\n----------------------------------\n"); + + // Setup the interrupt CSR configuration + init_interrupts(); + reg = lsu_read_32(CLP_AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R); + lsu_write_32(CLP_AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R, reg & ~(AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_EMPTY_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_NOT_EMPTY_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_FULL_EN_MASK | + AXI_DMA_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_FIFO_NOT_FULL_EN_MASK)); + + // Test each malformed command check + // TODO + + // Send data through AHB interface to AXI_DMA, target the AXI SRAM + VPRINTF(LOW, "Sending payload via AHB i/f\n"); + soc_ifc_axi_dma_send_ahb_payload(AXI_SRAM_BASE_ADDR, 0, send_payload, 16*4, 0); + + // Move data from one address to another in AXI SRAM + // Use the block-size feature + VPRINTF(LOW, "Moving payload at SRAM via axi-to-axi xfer\n"); + soc_ifc_axi_dma_send_axi_to_axi(AXI_SRAM_BASE_ADDR, 0, AXI_SRAM_BASE_ADDR + AXI_SRAM_SIZE_BYTES/2, 0, 16*4, 16*2); + + // Read data back from AXI SRAM and confirm it matches + VPRINTF(LOW, "Reading payload via AHB i/f\n"); + soc_ifc_axi_dma_read_ahb_payload(AXI_SRAM_BASE_ADDR + AXI_SRAM_SIZE_BYTES/2, 0, read_payload, 16*4, 0); + for (uint8_t ii = 0; ii < 16; ii++) { + if (read_payload[ii] != send_payload[ii]) { + fail = 1; + VPRINTF(ERROR, "read_payload[%d] (0x%x) does not match send_payload[%d] (0x%x)\n", ii, read_payload[ii], ii, send_payload[ii]); + } + } + + if (fail) { + VPRINTF(FATAL, "smoke_test_dma failed!\n"); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} diff --git a/src/integration/test_suites/smoke_test_dma/smoke_test_dma.yml b/src/integration/test_suites/smoke_test_dma/smoke_test_dma.yml new file mode 100755 index 000000000..e4385609e --- /dev/null +++ b/src/integration/test_suites/smoke_test_dma/smoke_test_dma.yml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +--- +seed: 1 +testname: smoke_test_dma diff --git a/src/integration/test_suites/smoke_test_mbox/caliptra_isr.h b/src/integration/test_suites/smoke_test_mbox/caliptra_isr.h index 8f5779e04..3b28f5e23 100644 --- a/src/integration/test_suites/smoke_test_mbox/caliptra_isr.h +++ b/src/integration/test_suites/smoke_test_mbox/caliptra_isr.h @@ -56,6 +56,8 @@ typedef struct { uint32_t soc_ifc_notif; uint32_t sha512_acc_error; uint32_t sha512_acc_notif; + uint32_t axi_dma_error; + uint32_t axi_dma_notif; } caliptra_intr_received_s; extern volatile caliptra_intr_received_s cptra_intr_rcv; @@ -243,5 +245,8 @@ inline void service_sha512_acc_notif_intr() { } } +inline void service_axi_dma_error_intr() {return;} +inline void service_axi_dma_notif_intr() {return;} + #endif //CALIPTRA_ISR_H diff --git a/src/integration/test_suites/smoke_test_mbox/smoke_test_mbox.c b/src/integration/test_suites/smoke_test_mbox/smoke_test_mbox.c index 1ad31280c..ab0997714 100644 --- a/src/integration/test_suites/smoke_test_mbox/smoke_test_mbox.c +++ b/src/integration/test_suites/smoke_test_mbox/smoke_test_mbox.c @@ -52,6 +52,8 @@ volatile caliptra_intr_received_s cptra_intr_rcv = { .soc_ifc_notif = 0, .sha512_acc_error = 0, .sha512_acc_notif = 0, + .axi_dma_error = 0, + .axi_dma_notif = 0, }; void main () { diff --git a/tools/scripts/Makefile b/tools/scripts/Makefile index 658fd6d87..e303d3a5a 100644 --- a/tools/scripts/Makefile +++ b/tools/scripts/Makefile @@ -245,14 +245,14 @@ clean_fw: verilator-build: $(TBFILES) $(INCLUDES_DIR)/defines.h $(TB_VERILATOR_SRCS) $(TBDIR)/../config/caliptra_top_tb.vf set -eo pipefail; $(VERILATOR) $(TB_VERILATOR_SRCS) --cc -CFLAGS "$(CFLAGS)" \ +libext+.v+.sv +define+RV_OPENSOURCE \ - --timescale 1ns/1ps \ - --timing \ + --timescale 1ns/100ps \ + --timing \ $(includes) \ $(suppress) \ -f $(TBDIR)/../config/caliptra_top_tb.vf --top-module caliptra_top_tb \ -f $(TBDIR)/../config/caliptra_top_tb.vlt \ -exe test_caliptra_top_tb.cpp --autoflush $(VERILATOR_DEBUG) \ - $(TB_DEFS) 2>&1 | tee verilate.log + $(TB_DEFS) 2>&1 | tee verilator_build.log set -eo pipefail; $(MAKE) -j`nproc` -e -C obj_dir/ -f Vcaliptra_top_tb.mk $(VERILATOR_MAKE_FLAGS) VM_PARALLEL_BUILDS=1 2>&1 | tee verilator_make.log touch verilator-build @@ -266,7 +266,7 @@ vcs-build: $(TBFILES) $(INCLUDES_DIR)/defines.h $(TB_DPI_SRCS) ############ TEST Simulation ############################### verilator: program.hex verilator-build - set -eo pipefail; ./obj_dir/Vcaliptra_top_tb $(VERILATOR_RUN_ARGS) 2>&1 | tee verilator_run.log + set -eo pipefail; ./obj_dir/Vcaliptra_top_tb $(VERILATOR_RUN_ARGS) 2>&1 | tee verilator_sim.log vcs: program.hex vcs-build cp $(TEST_GEN_FILES) $(BUILD_DIR)