diff --git a/verification/block/common.mk b/verification/block/common.mk index 361bb55a75f..efa29b2b79b 100644 --- a/verification/block/common.mk +++ b/verification/block/common.mk @@ -60,5 +60,5 @@ include $(shell cocotb-config --makefiles)/Makefile.sim # Rules for generating VeeR config $(CFGDIR)/common_defines.vh: - cd $(CURDIR) && $(CONFIG)/veer.config -fpga_optimize=0 + cd $(CURDIR) && $(CONFIG)/veer.config -fpga_optimize=0 $(EXTRA_VEER_CONFIG) diff --git a/verification/block/dcls/Makefile b/verification/block/dcls/Makefile index 94eb749f8c4..c7be9896fb2 100644 --- a/verification/block/dcls/Makefile +++ b/verification/block/dcls/Makefile @@ -8,13 +8,17 @@ SRCDIR := $(abspath $(CURDIR)../../../../design) TEST_FILES = $(sort $(wildcard test_*.py)) MODULE ?= $(subst $(space),$(comma),$(subst .py,,$(TEST_FILES))) -TOPLEVEL = el2_veer_lockstep +TOPLEVEL = el2_veer_lockstep_wrapper + +EXTRA_VEER_CONFIG = -set lockstep_enable=1 -set lockstep_regfile_enable=1 VERILOG_INCLUDE_DIRS += \ ${RV_ROOT}/testbench \ ${RV_ROOT}/design/include VERILOG_SOURCES = \ + ${SRCDIR}/lib/el2_mem_if.sv \ + ${SRCDIR}/lib/el2_regfile_if.sv \ ${SRCDIR}/el2_veer_wrapper.sv \ ${SRCDIR}/el2_mem.sv \ ${SRCDIR}/el2_pic_ctrl.sv \ @@ -57,6 +61,7 @@ VERILOG_SOURCES = \ ${SRCDIR}/dmi/dmi_jtag_to_core_sync.v \ ${SRCDIR}/dmi/rvjtag_tap.v \ ${SRCDIR}/lib/el2_lib.sv \ - $(SRCDIR)/el2_veer_lockstep.sv + $(SRCDIR)/el2_veer_lockstep.sv \ + $(CURDIR)/dcls/el2_veer_lockstep_wrapper.sv include $(CURDIR)/../common.mk diff --git a/verification/block/dcls/el2_veer_lockstep_wrapper.sv b/verification/block/dcls/el2_veer_lockstep_wrapper.sv new file mode 100644 index 00000000000..ebd09c6e724 --- /dev/null +++ b/verification/block/dcls/el2_veer_lockstep_wrapper.sv @@ -0,0 +1,400 @@ +// Copyright (c) 2024 Antmicro +// SPDX-License-Identifier: Apache-2.0 + +module el2_veer_lockstep_wrapper + import el2_pkg::*; +#( + `include "el2_param.vh" +) ( + input logic clk, + input logic rst_l, + input logic dbg_rst_l, + + output logic shadow_reset, + output logic shadow_dbg_reset, + + // Equivalency Checker + output logic corruption_detected +); + logic core_rst_l; // This is "rst_l | dbg_rst_l" + + logic [31:1] rst_vec; + logic [31:1] nmi_vec; + + logic nmi_int; + logic timer_int; + logic soft_int; + + logic [pt.PIC_TOTAL_INT:1] extintsrc_req; + + logic active_l2clk; + logic free_l2clk; + + logic [31:0] trace_rv_i_insn_ip; + logic [31:0] trace_rv_i_address_ip; + logic trace_rv_i_valid_ip; + logic trace_rv_i_exception_ip; + logic [ 4:0] trace_rv_i_ecause_ip; + logic trace_rv_i_interrupt_ip; + logic [31:0] trace_rv_i_tval_ip; + + + logic dccm_clk_override; + logic icm_clk_override; + logic dec_tlu_core_ecc_disable; + + // external halt/run interface + logic i_cpu_halt_req; // Asynchronous Halt request to CPU + logic i_cpu_run_req; // Asynchronous Restart request to CPU + logic o_cpu_halt_ack; // Core Acknowledge to Halt request + logic o_cpu_halt_status; // 1'b1 indicates processor is halted + logic o_cpu_run_ack; // Core Acknowledge to run request + logic o_debug_mode_status; // Core to the PMU that core is in debug mode. When core is in debug mode; the PMU should refrain from sendng a halt or run request + + logic [31:4] core_id; // CORE ID + + // external MPC halt/run interface + logic mpc_debug_halt_req; // Async halt request + logic mpc_debug_run_req; // Async run request + logic mpc_reset_run_req; // Run/halt after reset + logic mpc_debug_halt_ack; // Halt ack + logic mpc_debug_run_ack; // Run ack + logic debug_brkpt_status; // debug breakpoint + + logic dec_tlu_perfcnt0; // toggles when slot0 perf counter 0 has an event inc + logic dec_tlu_perfcnt1; + logic dec_tlu_perfcnt2; + logic dec_tlu_perfcnt3; + + // DCCM ports + logic dccm_wren; + logic dccm_rden; + logic [ pt.DCCM_BITS-1:0] dccm_wr_addr_lo; + logic [ pt.DCCM_BITS-1:0] dccm_wr_addr_hi; + logic [ pt.DCCM_BITS-1:0] dccm_rd_addr_lo; + logic [ pt.DCCM_BITS-1:0] dccm_rd_addr_hi; + logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo; + logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi; + + logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo; + logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi; + + // ICCM ports + logic [pt.ICCM_BITS-1:1] iccm_rw_addr; + logic iccm_wren; + logic iccm_rden; + logic [ 2:0] iccm_wr_size; + logic [ 77:0] iccm_wr_data; + logic iccm_buf_correct_ecc; + logic iccm_correction_state; + + logic [63:0] iccm_rd_data; + logic [77:0] iccm_rd_data_ecc; + + // ICache ; ITAG ports + logic [ 31:1] ic_rw_addr; + logic [pt.ICACHE_NUM_WAYS-1:0] ic_tag_valid; + logic [pt.ICACHE_NUM_WAYS-1:0] ic_wr_en; + logic ic_rd_en; + + logic [pt.ICACHE_BANKS_WAY-1:0][70:0] ic_wr_data; // Data to fill to the Icache. With ECC + logic [ 63:0] ic_rd_data ; // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC + logic [ 70:0] ic_debug_rd_data ; // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC + logic [ 25:0] ictag_debug_rd_data;// Debug icache tag. + logic [ 70:0] ic_debug_wr_data; // Debug wr cache. + + logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr; + logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr; + logic [ 63:0] ic_premux_data; // Premux data to be muxed with each way of the Icache. + logic ic_sel_premux_data; // Select premux data + + + logic [ pt.ICACHE_INDEX_HI:3] ic_debug_addr; // Read/Write addresss to the Icache. + logic ic_debug_rd_en; // Icache debug rd + logic ic_debug_wr_en; // Icache debug wr + logic ic_debug_tag_array; // Debug tag array + logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_way; // Debug way. Rd or Wr. + + + + logic [pt.ICACHE_NUM_WAYS-1:0] ic_rd_hit; + logic ic_tag_perr; // Icache Tag parity error + + //-------------------------- LSU AXI signals-------------------------- + // AXI Write Channels + logic lsu_axi_awvalid; + logic lsu_axi_awready; + logic [pt.LSU_BUS_TAG-1:0] lsu_axi_awid; + logic [ 31:0] lsu_axi_awaddr; + logic [ 3:0] lsu_axi_awregion; + logic [ 7:0] lsu_axi_awlen; + logic [ 2:0] lsu_axi_awsize; + logic [ 1:0] lsu_axi_awburst; + logic lsu_axi_awlock; + logic [ 3:0] lsu_axi_awcache; + logic [ 2:0] lsu_axi_awprot; + logic [ 3:0] lsu_axi_awqos; + + logic lsu_axi_wvalid; + logic lsu_axi_wready; + logic [63:0] lsu_axi_wdata; + logic [ 7:0] lsu_axi_wstrb; + logic lsu_axi_wlast; + + logic lsu_axi_bvalid; + logic lsu_axi_bready; + logic [ 1:0] lsu_axi_bresp; + logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid; + + // AXI Read Channels + logic lsu_axi_arvalid; + logic lsu_axi_arready; + logic [pt.LSU_BUS_TAG-1:0] lsu_axi_arid; + logic [ 31:0] lsu_axi_araddr; + logic [ 3:0] lsu_axi_arregion; + logic [ 7:0] lsu_axi_arlen; + logic [ 2:0] lsu_axi_arsize; + logic [ 1:0] lsu_axi_arburst; + logic lsu_axi_arlock; + logic [ 3:0] lsu_axi_arcache; + logic [ 2:0] lsu_axi_arprot; + logic [ 3:0] lsu_axi_arqos; + + logic lsu_axi_rvalid; + logic lsu_axi_rready; + logic [pt.LSU_BUS_TAG-1:0] lsu_axi_rid; + logic [ 63:0] lsu_axi_rdata; + logic [ 1:0] lsu_axi_rresp; + logic lsu_axi_rlast; + + //-------------------------- IFU AXI signals-------------------------- + // AXI Write Channels + logic ifu_axi_awvalid; + logic ifu_axi_awready; + logic [pt.IFU_BUS_TAG-1:0] ifu_axi_awid; + logic [ 31:0] ifu_axi_awaddr; + logic [ 3:0] ifu_axi_awregion; + logic [ 7:0] ifu_axi_awlen; + logic [ 2:0] ifu_axi_awsize; + logic [ 1:0] ifu_axi_awburst; + logic ifu_axi_awlock; + logic [ 3:0] ifu_axi_awcache; + logic [ 2:0] ifu_axi_awprot; + logic [ 3:0] ifu_axi_awqos; + + logic ifu_axi_wvalid; + logic ifu_axi_wready; + logic [63:0] ifu_axi_wdata; + logic [ 7:0] ifu_axi_wstrb; + logic ifu_axi_wlast; + + logic ifu_axi_bvalid; + logic ifu_axi_bready; + logic [ 1:0] ifu_axi_bresp; + logic [pt.IFU_BUS_TAG-1:0] ifu_axi_bid; + + // AXI Read Channels + logic ifu_axi_arvalid; + logic ifu_axi_arready; + logic [pt.IFU_BUS_TAG-1:0] ifu_axi_arid; + logic [ 31:0] ifu_axi_araddr; + logic [ 3:0] ifu_axi_arregion; + logic [ 7:0] ifu_axi_arlen; + logic [ 2:0] ifu_axi_arsize; + logic [ 1:0] ifu_axi_arburst; + logic ifu_axi_arlock; + logic [ 3:0] ifu_axi_arcache; + logic [ 2:0] ifu_axi_arprot; + logic [ 3:0] ifu_axi_arqos; + + logic ifu_axi_rvalid; + logic ifu_axi_rready; + logic [pt.IFU_BUS_TAG-1:0] ifu_axi_rid; + logic [ 63:0] ifu_axi_rdata; + logic [ 1:0] ifu_axi_rresp; + logic ifu_axi_rlast; + + //-------------------------- SB AXI signals-------------------------- + // AXI Write Channels + logic sb_axi_awvalid; + logic sb_axi_awready; + logic [pt.SB_BUS_TAG-1:0] sb_axi_awid; + logic [ 31:0] sb_axi_awaddr; + logic [ 3:0] sb_axi_awregion; + logic [ 7:0] sb_axi_awlen; + logic [ 2:0] sb_axi_awsize; + logic [ 1:0] sb_axi_awburst; + logic sb_axi_awlock; + logic [ 3:0] sb_axi_awcache; + logic [ 2:0] sb_axi_awprot; + logic [ 3:0] sb_axi_awqos; + + logic sb_axi_wvalid; + logic sb_axi_wready; + logic [63:0] sb_axi_wdata; + logic [ 7:0] sb_axi_wstrb; + logic sb_axi_wlast; + + logic sb_axi_bvalid; + logic sb_axi_bready; + logic [ 1:0] sb_axi_bresp; + logic [pt.SB_BUS_TAG-1:0] sb_axi_bid; + + // AXI Read Channels + logic sb_axi_arvalid; + logic sb_axi_arready; + logic [pt.SB_BUS_TAG-1:0] sb_axi_arid; + logic [ 31:0] sb_axi_araddr; + logic [ 3:0] sb_axi_arregion; + logic [ 7:0] sb_axi_arlen; + logic [ 2:0] sb_axi_arsize; + logic [ 1:0] sb_axi_arburst; + logic sb_axi_arlock; + logic [ 3:0] sb_axi_arcache; + logic [ 2:0] sb_axi_arprot; + logic [ 3:0] sb_axi_arqos; + + logic sb_axi_rvalid; + logic sb_axi_rready; + logic [pt.SB_BUS_TAG-1:0] sb_axi_rid; + logic [ 63:0] sb_axi_rdata; + logic [ 1:0] sb_axi_rresp; + logic sb_axi_rlast; + + //-------------------------- DMA AXI signals-------------------------- + // AXI Write Channels + logic dma_axi_awvalid; + logic dma_axi_awready; + logic [pt.DMA_BUS_TAG-1:0] dma_axi_awid; + logic [ 31:0] dma_axi_awaddr; + logic [ 2:0] dma_axi_awsize; + logic [ 2:0] dma_axi_awprot; + logic [ 7:0] dma_axi_awlen; + logic [ 1:0] dma_axi_awburst; + + + logic dma_axi_wvalid; + logic dma_axi_wready; + logic [63:0] dma_axi_wdata; + logic [ 7:0] dma_axi_wstrb; + logic dma_axi_wlast; + + logic dma_axi_bvalid; + logic dma_axi_bready; + logic [ 1:0] dma_axi_bresp; + logic [pt.DMA_BUS_TAG-1:0] dma_axi_bid; + + // AXI Read Channels + logic dma_axi_arvalid; + logic dma_axi_arready; + logic [pt.DMA_BUS_TAG-1:0] dma_axi_arid; + logic [ 31:0] dma_axi_araddr; + logic [ 2:0] dma_axi_arsize; + logic [ 2:0] dma_axi_arprot; + logic [ 7:0] dma_axi_arlen; + logic [ 1:0] dma_axi_arburst; + + logic dma_axi_rvalid; + logic dma_axi_rready; + logic [pt.DMA_BUS_TAG-1:0] dma_axi_rid; + logic [ 63:0] dma_axi_rdata; + logic [ 1:0] dma_axi_rresp; + logic dma_axi_rlast; + + + //// AHB LITE BUS + logic [31:0] haddr; + logic [ 2:0] hburst; + logic hmastlock; + logic [ 3:0] hprot; + logic [ 2:0] hsize; + logic [ 1:0] htrans; + logic hwrite; + + logic [63:0] hrdata; + logic hready; + logic hresp; + + // LSU AHB Master + logic [31:0] lsu_haddr; + logic [ 2:0] lsu_hburst; + logic lsu_hmastlock; + logic [ 3:0] lsu_hprot; + logic [ 2:0] lsu_hsize; + logic [ 1:0] lsu_htrans; + logic lsu_hwrite; + logic [63:0] lsu_hwdata; + + logic [63:0] lsu_hrdata; + logic lsu_hready; + logic lsu_hresp; + + //System Bus Debug Master + logic [31:0] sb_haddr; + logic [ 2:0] sb_hburst; + logic sb_hmastlock; + logic [ 3:0] sb_hprot; + logic [ 2:0] sb_hsize; + logic [ 1:0] sb_htrans; + logic sb_hwrite; + logic [63:0] sb_hwdata; + + logic [63:0] sb_hrdata; + logic sb_hready; + logic sb_hresp; + + // DMA Slave + logic dma_hsel; + logic [31:0] dma_haddr; + logic [ 2:0] dma_hburst; + logic dma_hmastlock; + logic [ 3:0] dma_hprot; + logic [ 2:0] dma_hsize; + logic [ 1:0] dma_htrans; + logic dma_hwrite; + logic [63:0] dma_hwdata; + logic dma_hreadyin; + + logic [63:0] dma_hrdata; + logic dma_hreadyout; + logic dma_hresp; + + logic lsu_bus_clk_en; + logic ifu_bus_clk_en; + logic dbg_bus_clk_en; + logic dma_bus_clk_en; + + logic dmi_reg_en; // read or write + logic [ 6:0] dmi_reg_addr; // address of DM register + logic dmi_reg_wr_en; // write instruction + logic [31:0] dmi_reg_wdata; // write data + logic [31:0] dmi_reg_rdata; + + // ICCM/DCCM ECC status + logic iccm_ecc_single_error; + logic iccm_ecc_double_error; + logic dccm_ecc_single_error; + logic dccm_ecc_double_error; + + logic scan_mode; + + el2_regfile_if regfile (); + + el2_veer #(.pt(pt)) veer ( +`ifdef RV_LOCKSTEP_REGFILE_ENABLE + .regfile(regfile.veer_rf_src), +`endif // `ifdef RV_LOCKSTEP_REGFILE_ENABLE + .* + ); + + el2_veer_lockstep #(.pt(pt)) lockstep ( +`ifdef RV_LOCKSTEP_REGFILE_ENABLE + .main_core_regfile(regfile.veer_rf_sink), +`endif // `ifdef RV_LOCKSTEP_REGFILE_ENABLE + .corruption_detected(corruption_detected), + .* + ); + + assign shadow_reset = lockstep.rst_shadow; + assign shadow_dbg_reset = lockstep.rst_dbg_shadow; +endmodule diff --git a/verification/block/dcls/test_lockstep.py b/verification/block/dcls/test_lockstep.py new file mode 100644 index 00000000000..3960f385be6 --- /dev/null +++ b/verification/block/dcls/test_lockstep.py @@ -0,0 +1,54 @@ +# Copyright (c) 2024 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +from random import randrange + +import pyuvm +from cocotb.triggers import ReadOnly, RisingEdge +from cocotb.utils import get_sim_time +from pyuvm import ConfigDB +from testbench import BaseTest + +# ============================================================================= + + +@pyuvm.test() +class TestReset(BaseTest): + """ + A basic test that resets the DUT and ensures shadow core gets out of reset + after the configured delay + """ + + def assert_signals(self, signals): + time = get_sim_time(units="ns") + self.logger.info(f"Validating signals at {time}") + for name, value in signals.items(): + try: + sig = getattr(self.dut, name) + except AttributeError: + print(f"DUT does not contain signal named {name}") + exit(1) + self.logger.info(f"Assert that {name}={value}") + assert sig.value == value + + async def test_reset(self): + lockstep_delay = ConfigDB().get(None, "", "LOCKSTEP_DELAY") + signals = { + "shadow_reset": 0, + "shadow_dbg_reset": 0, + "corruption_detected": 0, + } + # The shadow core should go into the reset regardless of the delay + for _ in range(lockstep_delay): + await ReadOnly() + self.assert_signals(signals) + await RisingEdge(self.clk) + + # After the delay shadow core should be out of reset without corruption detected + signals.update({"shadow_reset": 1, "shadow_dbg_reset": 1}) + await ReadOnly() + self.assert_signals(signals) + await RisingEdge(self.clk) + + async def run(self): + await self.test_reset() diff --git a/verification/block/dcls/test_reset.py b/verification/block/dcls/test_reset.py deleted file mode 100644 index d78f790eb8f..00000000000 --- a/verification/block/dcls/test_reset.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2024 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -import cocotb -import pyuvm -from cocotb.triggers import ClockCycles -from testbench import BaseTest - -# ============================================================================= - - -@pyuvm.test() -class TestReset(BaseTest): - """ - A basic test that resets the DUT - """ - - # TODO: Change me once `el2_veer_lockstep` outputs only `panic` signal - async def run(self): - # The shadow core should go into the reset regardless of the delay - state = { - "corruption_detected": 0, - } - - for name, value in state.items(): - signal = getattr(cocotb.top, name) - assert signal.value == value, "{}={}, should be {}".format(name, signal.value, value) diff --git a/verification/block/dcls/testbench.py b/verification/block/dcls/testbench.py index 577aa0df07d..216812c442a 100644 --- a/verification/block/dcls/testbench.py +++ b/verification/block/dcls/testbench.py @@ -5,7 +5,7 @@ import cocotb from cocotb.clock import Clock -from cocotb.triggers import ClockCycles, FallingEdge +from cocotb.triggers import ClockCycles, FallingEdge, RisingEdge from pyuvm import ConfigDB, uvm_env, uvm_report_object, uvm_test @@ -16,13 +16,8 @@ class BaseEnv(uvm_env): def build_phase(self): # Config - pmp_entries = 16 - ConfigDB().set(None, "*", "PMP_ENTRIES", pmp_entries) - ConfigDB().set(None, "*", "PMP_CHANNELS", 3) - ConfigDB().set(None, "*", "PMP_GRANULARITY", 0) - ConfigDB().set(None, "*", "TEST_CLK_PERIOD", 1) - ConfigDB().set(None, "*", "TEST_ITERATIONS", 100) + ConfigDB().set(None, "*", "LOCKSTEP_DELAY", 3) def connect_phase(self): pass @@ -39,6 +34,8 @@ class BaseTest(uvm_test): def __init__(self, name, parent, env_class=BaseEnv): super().__init__(name, parent) self.env_class = env_class + self.dut = cocotb.top + self.clk = self.dut.clk # Synchronize pyuvm logging level with cocotb logging level. Unclear # why it does not happen automatically. @@ -50,15 +47,17 @@ def build_phase(self): def start_clock(self, name): period = ConfigDB().get(None, "", "TEST_CLK_PERIOD") - sig = getattr(cocotb.top, name) + sig = getattr(self.dut, name) clock = Clock(sig, period, units="ns") cocotb.start_soon(clock.start(start_high=False)) async def do_reset(self): - cocotb.top.rst_l.value = 0 - await ClockCycles(cocotb.top.clk, 2) - await FallingEdge(cocotb.top.clk) - cocotb.top.rst_l.value = 1 + self.dut.rst_l.value = 0 + self.dut.dbg_rst_l.value = 0 + await ClockCycles(self.dut.clk, 2) + await FallingEdge(self.dut.clk) + self.dut.rst_l.value = 1 + self.dut.dbg_rst_l.value = 1 async def run_phase(self): self.raise_objection() @@ -68,15 +67,13 @@ async def run_phase(self): # Issue reset await self.do_reset() - - # Wait some cycles - await ClockCycles(cocotb.top.clk, 2) + await RisingEdge(self.clk) # Run the actual test await self.run() # Wait some cycles - await ClockCycles(cocotb.top.clk, 10) + await ClockCycles(self.clk, 10) self.drop_objection() diff --git a/verification/block/noxfile.py b/verification/block/noxfile.py index d375cbcb472..faa89b08303 100644 --- a/verification/block/noxfile.py +++ b/verification/block/noxfile.py @@ -275,7 +275,7 @@ def dccm_verify(session, blockName, testName, coverage): @nox.parametrize( "testName", [ - "test_reset", + "test_lockstep", ], ) @nox.parametrize("coverage", coverageTypes)