diff --git a/Bender.yml b/Bender.yml index 29fc783b5..26b238277 100644 --- a/Bender.yml +++ b/Bender.yml @@ -159,6 +159,7 @@ sources: - hw/snitch_cluster/src/snitch_fpu.sv - hw/snitch_cluster/src/snitch_sequencer.sv - hw/snitch_cluster/src/snitch_tcdm_interconnect.sv + - target/snitch_cluster/test/snitch_bootrom.sv # Level 1 - hw/snitch_cluster/src/snitch_barrier.sv - hw/snitch_cluster/src/snitch_fp_ss.sv diff --git a/docs/schema/snitch_cluster.schema.json b/docs/schema/snitch_cluster.schema.json index f9d5831ca..6da52b15a 100644 --- a/docs/schema/snitch_cluster.schema.json +++ b/docs/schema/snitch_cluster.schema.json @@ -16,7 +16,7 @@ }, "boot_addr": { "type": "number", - "description": "Address from which all harts of the cluster start to boot. The default setting is `0x8000_0000`.", + "description": "Address from which all harts of the cluster start to boot. The default setting is `0x8000_0000`. Unused if `alias_region_enable` is set.", "default": 2147483648 }, "cluster_base_addr": { @@ -89,6 +89,14 @@ 64 ] }, + "bootrom_size": { + "type": "number", + "description": "Address region size reserved for the Bootrom-Memory in KiByte.", + "examples": [ + 128, + 64 + ] + }, "alias_region_enable": { "type": "boolean", "description": "Whether to provide a hardwired alias region for the TCDM (and cluster) address space.", diff --git a/hw/snitch/src/snitch_pkg.sv b/hw/snitch/src/snitch_pkg.sv index e70325b71..6918a0a77 100644 --- a/hw/snitch/src/snitch_pkg.sv +++ b/hw/snitch/src/snitch_pkg.sv @@ -139,7 +139,8 @@ package snitch_pkg; typedef enum int unsigned { TCDMDMA = 0, SoCDMAOut = 1, - ZeroMemory = 2 + ZeroMemory = 2, + BootRom = 3 } cluster_slave_dma_e; typedef enum int unsigned { diff --git a/hw/snitch_cluster/src/snitch_cluster.sv b/hw/snitch_cluster/src/snitch_cluster.sv index 9d68831f3..745ad52f3 100644 --- a/hw/snitch_cluster/src/snitch_cluster.sv +++ b/hw/snitch_cluster/src/snitch_cluster.sv @@ -37,7 +37,8 @@ module snitch_cluster parameter int unsigned NarrowUserWidth = 1, /// AXI: dma user width. parameter int unsigned WideUserWidth = 1, - /// Address from which to fetch the first instructions. + /// Boot Address from which to fetch the first instructions. + /// Only used if `AliasRegionEnable` is not set. parameter logic [31:0] BootAddr = 32'h0, /// Number of Hives. Each Hive can hold 1-many cores. parameter int unsigned NrHives = 1, @@ -47,6 +48,8 @@ module snitch_cluster parameter int unsigned TCDMDepth = 1024, /// Zero memory address region size (in kB). parameter int unsigned ZeroMemorySize = 64, + /// Bootrom memory address region size (in kB). + parameter int unsigned BootRomSize = 4, /// Cluster peripheral address region size (in kB). parameter int unsigned ClusterPeriphSize = 64, /// Number of TCDM Banks. It is recommended to have twice the number of banks @@ -280,7 +283,7 @@ module snitch_cluster localparam int unsigned NrWideMasters = 1 + DMANumChannels + NrHives; localparam int unsigned WideIdWidthOut = $clog2(NrWideMasters) + WideIdWidthIn; // DMA X-BAR configuration - localparam int unsigned NrWideSlaves = 3; + localparam int unsigned NrWideSlaves = 4; localparam int unsigned NrWideRuleIdcs = NrWideSlaves - 1; localparam int unsigned NrWideRules = (1 + AliasRegionEnable) * NrWideRuleIdcs; @@ -463,6 +466,10 @@ module snitch_cluster assign cluster_periph_start_address = tcdm_end_address; assign cluster_periph_end_address = tcdm_end_address + ClusterPeriphSize * 1024; + addr_t bootrom_start_address, bootrom_end_address; + assign bootrom_start_address = cluster_periph_start_address + 4 * 1024; + assign bootrom_end_address = cluster_periph_end_address; + addr_t zero_mem_start_address, zero_mem_end_address; assign zero_mem_start_address = cluster_periph_end_address; assign zero_mem_end_address = cluster_periph_end_address + ZeroMemorySize * 1024; @@ -473,9 +480,13 @@ module snitch_cluster localparam addr_t PeriphAliasStart = TCDMAliasEnd; localparam addr_t PeriphAliasEnd = TCDMAliasEnd + ClusterPeriphSize * 1024; + localparam addr_t BootRomAliasStart = PeriphAliasStart + 4 * 1024; + localparam addr_t BootRomAliasEnd = PeriphAliasEnd; + localparam addr_t ZeroMemAliasStart = PeriphAliasEnd; localparam addr_t ZeroMemAliasEnd = PeriphAliasEnd + ZeroMemorySize * 1024; + // ---------------- // Wire Definitions // ---------------- @@ -585,6 +596,11 @@ module snitch_cluster idx: ZeroMemory, start_addr: zero_mem_start_address, end_addr: zero_mem_end_address + }, + '{ + idx: BootRom, + start_addr: bootrom_start_address, + end_addr: bootrom_end_address } }; if (AliasRegionEnable) begin : gen_dma_xbar_alias @@ -598,6 +614,11 @@ module snitch_cluster idx: ZeroMemory, start_addr: ZeroMemAliasStart, end_addr: ZeroMemAliasEnd + }, + '{ + idx: BootRom, + start_addr: BootRomAliasStart, + end_addr: BootRomAliasEnd } }; end @@ -857,6 +878,8 @@ module snitch_cluster tcdm_req_t [TcdmPorts-1:0] tcdm_req_wo_user; + parameter logic [31:0] BootAddrInternal = AliasRegionEnable ? BootRomAliasStart : BootAddr; + snitch_cc #( .AddrWidth (PhysicalAddrWidth), .DataWidth (NarrowDataWidth), @@ -881,7 +904,7 @@ module snitch_cluster .acc_req_t (acc_req_t), .acc_resp_t (acc_resp_t), .dma_events_t (dma_events_t), - .BootAddr (BootAddr), + .BootAddr (BootAddrInternal), .RVE (RVE[i]), .RVF (RVF[i]), .RVD (RVD[i]), @@ -1236,6 +1259,37 @@ module snitch_cluster .reg_rsp_i (reg_rsp) ); + addr_t bootrom_addr; + data_dma_t bootrom_data, bootrom_data_q; + logic bootrom_req, bootrom_req_q; + + `FF(bootrom_data_q, bootrom_data, '0, clk_i, rst_ni) + `FF(bootrom_req_q, bootrom_req, '0, clk_i, rst_ni) + + axi_to_mem #( + .axi_req_t (axi_slv_dma_req_t), + .axi_resp_t (axi_slv_dma_resp_t), + .AddrWidth (PhysicalAddrWidth), + .DataWidth (WideDataWidth), + .IdWidth (WideIdWidthOut), + .NumBanks (1) + ) i_axi_to_mem ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .busy_o (), + .axi_req_i (wide_axi_slv_req[BootRom]), + .axi_resp_o (wide_axi_slv_rsp[BootRom]), + .mem_req_o (bootrom_req), + .mem_gnt_i (bootrom_req), + .mem_addr_o (bootrom_addr), + .mem_wdata_o (), + .mem_strb_o (), + .mem_atop_o (), + .mem_we_o (), + .mem_rvalid_i (bootrom_req_q), + .mem_rdata_i (bootrom_data_q) + ); + snitch_cluster_peripheral #( .reg_req_t (reg_req_t), .reg_rsp_t (reg_rsp_t), @@ -1256,6 +1310,17 @@ module snitch_cluster .icache_events_i (icache_events) ); + snitch_bootrom #( + .AddrWidth (PhysicalAddrWidth), + .DataWidth (WideDataWidth), + .BootromSize (BootRomSize * 1024) + ) i_bootrom ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .addr_i (bootrom_addr), + .data_o (bootrom_data) + ); + // Optionally decouple the external narrow AXI master ports. axi_cut #( .Bypass ( !RegisterExtNarrow ), diff --git a/hw/snitch_cluster/src/snitch_cluster_peripheral/Makefile b/hw/snitch_cluster/src/snitch_cluster_peripheral/Makefile new file mode 100644 index 000000000..712b63bd9 --- /dev/null +++ b/hw/snitch_cluster/src/snitch_cluster_peripheral/Makefile @@ -0,0 +1,27 @@ +# Copyright 2021 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# +# Noah Huetter + +BENDER=$(shell which bender) +REGTOOL=$(shell $(BENDER) path register_interface)/vendor/lowrisc_opentitan/util/regtool.py +PYTHON3=$(shell which python) +CLANG_FORMAT=$(shell which clang-format-12.0.1) + +SCHEMA=snitch_cluster_peripheral_reg.hjson + +PKG=snitch_cluster_peripheral_reg_pkg.sv +TOP=snitch_cluster_peripheral_reg_top.sv +CDEF=../../../../target/snitch_cluster/sw/runtime/common/snitch_cluster_peripheral.h + +all: $(PKG) $(TOP) $(CDEF) + +$(PKG): $(SCHEMA) + $(PYTHON3) $(REGTOOL) -r -t $(dir $@) $< +$(TOP): $(SCHEMA) + $(PYTHON3) $(REGTOOL) -r -t $(dir $@) $< + +%.h: $(SCHEMA) + $(PYTHON3) $(REGTOOL) -D -o $@ $< + $(CLANG_FORMAT) -i $@ diff --git a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson index 8831aa089..aa31b74b6 100644 --- a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson +++ b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg.hjson @@ -4,11 +4,18 @@ // Licensed under Solderpad Hardware License, Version 0.51, see LICENSE for details. { param_list: [ - { name: "NumPerfCounters", + { + name: "NumPerfCounters", desc: "Number of performance counters", type: "int", default: "16" }, + { + name: "NumCtrlScratch", + desc: "Number of scratch registers", + type: "int", + default: "4" + }, ], name: "snitch_cluster_peripheral", clock_primary: "clk_i", @@ -303,6 +310,22 @@ }] } }, + { + multireg: { + name: "SCRATCH", + desc: '''Scratch registers. Used in the bootrom for various purposes.''' + swaccess: "rw", + hwaccess: "none", + count: "NumCtrlScratch", + cname: "ctrl_scratch", + compact: "false", + fields: [{ + bits: "31:0", + name: "SCRATCH", + desc: "Scratch register" + }] + } + }, { name: "CL_CLINT_SET", desc: ''' diff --git a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_pkg.sv b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_pkg.sv index 3795d8013..50b789c34 100644 --- a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_pkg.sv +++ b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_pkg.sv @@ -8,6 +8,7 @@ package snitch_cluster_peripheral_reg_pkg; // Param list parameter int NumPerfCounters = 16; + parameter int NumCtrlScratch = 4; // Address widths within the block parameter int BlockAw = 9; @@ -128,9 +129,13 @@ package snitch_cluster_peripheral_reg_pkg; parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_13_OFFSET = 9'h 168; parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_14_OFFSET = 9'h 170; parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_15_OFFSET = 9'h 178; - parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET_OFFSET = 9'h 180; - parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR_OFFSET = 9'h 188; - parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE_OFFSET = 9'h 190; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_0_OFFSET = 9'h 180; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_1_OFFSET = 9'h 188; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_2_OFFSET = 9'h 190; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_3_OFFSET = 9'h 198; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET_OFFSET = 9'h 1a0; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR_OFFSET = 9'h 1a8; + parameter logic [BlockAw-1:0] SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE_OFFSET = 9'h 1b0; // Reset values for hwext registers and their fields parameter logic [31:0] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_SEL_0_RESVAL = 32'h 0; @@ -218,13 +223,17 @@ package snitch_cluster_peripheral_reg_pkg; SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_13, SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_14, SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_15, + SNITCH_CLUSTER_PERIPHERAL_SCRATCH_0, + SNITCH_CLUSTER_PERIPHERAL_SCRATCH_1, + SNITCH_CLUSTER_PERIPHERAL_SCRATCH_2, + SNITCH_CLUSTER_PERIPHERAL_SCRATCH_3, SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET, SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR, SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE } snitch_cluster_peripheral_id_e; // Register width information to check illegal writes - parameter logic [3:0] SNITCH_CLUSTER_PERIPHERAL_PERMIT [51] = '{ + parameter logic [3:0] SNITCH_CLUSTER_PERIPHERAL_PERMIT [55] = '{ 4'b 0001, // index[ 0] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_EN_0 4'b 0001, // index[ 1] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_EN_1 4'b 0001, // index[ 2] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_EN_2 @@ -273,9 +282,13 @@ package snitch_cluster_peripheral_reg_pkg; 4'b 1111, // index[45] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_13 4'b 1111, // index[46] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_14 4'b 1111, // index[47] SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_15 - 4'b 1111, // index[48] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET - 4'b 1111, // index[49] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR - 4'b 0001 // index[50] SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE + 4'b 1111, // index[48] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_0 + 4'b 1111, // index[49] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_1 + 4'b 1111, // index[50] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_2 + 4'b 1111, // index[51] SNITCH_CLUSTER_PERIPHERAL_SCRATCH_3 + 4'b 1111, // index[52] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET + 4'b 1111, // index[53] SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR + 4'b 0001 // index[54] SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE }; endpackage diff --git a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_top.sv b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_top.sv index fb6cdb86d..62781fda6 100644 --- a/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_top.sv +++ b/hw/snitch_cluster/src/snitch_cluster_peripheral/snitch_cluster_peripheral_reg_top.sv @@ -308,6 +308,18 @@ module snitch_cluster_peripheral_reg_top #( logic [47:0] perf_cnt_15_wd; logic perf_cnt_15_we; logic perf_cnt_15_re; + logic [31:0] scratch_0_qs; + logic [31:0] scratch_0_wd; + logic scratch_0_we; + logic [31:0] scratch_1_qs; + logic [31:0] scratch_1_wd; + logic scratch_1_we; + logic [31:0] scratch_2_qs; + logic [31:0] scratch_2_wd; + logic scratch_2_we; + logic [31:0] scratch_3_qs; + logic [31:0] scratch_3_wd; + logic scratch_3_we; logic [31:0] cl_clint_set_wd; logic cl_clint_set_we; logic [31:0] cl_clint_clear_wd; @@ -1538,6 +1550,116 @@ module snitch_cluster_peripheral_reg_top #( ); + + // Subregister 0 of Multireg scratch + // R[scratch_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_scratch_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (scratch_0_we), + .wd (scratch_0_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (scratch_0_qs) + ); + + // Subregister 1 of Multireg scratch + // R[scratch_1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_scratch_1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (scratch_1_we), + .wd (scratch_1_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (scratch_1_qs) + ); + + // Subregister 2 of Multireg scratch + // R[scratch_2]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_scratch_2 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (scratch_2_we), + .wd (scratch_2_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (scratch_2_qs) + ); + + // Subregister 3 of Multireg scratch + // R[scratch_3]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_scratch_3 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (scratch_3_we), + .wd (scratch_3_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (scratch_3_qs) + ); + + // R[cl_clint_set]: V(True) prim_subreg_ext #( @@ -1598,7 +1720,7 @@ module snitch_cluster_peripheral_reg_top #( - logic [50:0] addr_hit; + logic [54:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[ 0] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_EN_0_OFFSET); @@ -1649,9 +1771,13 @@ module snitch_cluster_peripheral_reg_top #( addr_hit[45] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_13_OFFSET); addr_hit[46] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_14_OFFSET); addr_hit[47] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_PERF_CNT_15_OFFSET); - addr_hit[48] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET_OFFSET); - addr_hit[49] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR_OFFSET); - addr_hit[50] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE_OFFSET); + addr_hit[48] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_SCRATCH_0_OFFSET); + addr_hit[49] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_SCRATCH_1_OFFSET); + addr_hit[50] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_SCRATCH_2_OFFSET); + addr_hit[51] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_SCRATCH_3_OFFSET); + addr_hit[52] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_SET_OFFSET); + addr_hit[53] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_CL_CLINT_CLEAR_OFFSET); + addr_hit[54] = (reg_addr == SNITCH_CLUSTER_PERIPHERAL_ICACHE_PREFETCH_ENABLE_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -1709,7 +1835,11 @@ module snitch_cluster_peripheral_reg_top #( (addr_hit[47] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[47] & ~reg_be))) | (addr_hit[48] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[48] & ~reg_be))) | (addr_hit[49] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[49] & ~reg_be))) | - (addr_hit[50] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[50] & ~reg_be))))); + (addr_hit[50] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[50] & ~reg_be))) | + (addr_hit[51] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[51] & ~reg_be))) | + (addr_hit[52] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[52] & ~reg_be))) | + (addr_hit[53] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[53] & ~reg_be))) | + (addr_hit[54] & (|(SNITCH_CLUSTER_PERIPHERAL_PERMIT[54] & ~reg_be))))); end assign perf_cnt_en_0_we = addr_hit[0] & reg_we & !reg_error; @@ -1952,13 +2082,25 @@ module snitch_cluster_peripheral_reg_top #( assign perf_cnt_15_wd = reg_wdata[47:0]; assign perf_cnt_15_re = addr_hit[47] & reg_re & !reg_error; - assign cl_clint_set_we = addr_hit[48] & reg_we & !reg_error; + assign scratch_0_we = addr_hit[48] & reg_we & !reg_error; + assign scratch_0_wd = reg_wdata[31:0]; + + assign scratch_1_we = addr_hit[49] & reg_we & !reg_error; + assign scratch_1_wd = reg_wdata[31:0]; + + assign scratch_2_we = addr_hit[50] & reg_we & !reg_error; + assign scratch_2_wd = reg_wdata[31:0]; + + assign scratch_3_we = addr_hit[51] & reg_we & !reg_error; + assign scratch_3_wd = reg_wdata[31:0]; + + assign cl_clint_set_we = addr_hit[52] & reg_we & !reg_error; assign cl_clint_set_wd = reg_wdata[31:0]; - assign cl_clint_clear_we = addr_hit[49] & reg_we & !reg_error; + assign cl_clint_clear_we = addr_hit[53] & reg_we & !reg_error; assign cl_clint_clear_wd = reg_wdata[31:0]; - assign icache_prefetch_enable_we = addr_hit[50] & reg_we & !reg_error; + assign icache_prefetch_enable_we = addr_hit[54] & reg_we & !reg_error; assign icache_prefetch_enable_wd = reg_wdata[0]; // Read data return @@ -2174,14 +2316,30 @@ module snitch_cluster_peripheral_reg_top #( end addr_hit[48]: begin - reg_rdata_next[31:0] = '0; + reg_rdata_next[31:0] = scratch_0_qs; end addr_hit[49]: begin - reg_rdata_next[31:0] = '0; + reg_rdata_next[31:0] = scratch_1_qs; end addr_hit[50]: begin + reg_rdata_next[31:0] = scratch_2_qs; + end + + addr_hit[51]: begin + reg_rdata_next[31:0] = scratch_3_qs; + end + + addr_hit[52]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[53]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[54]: begin reg_rdata_next[0] = '0; end diff --git a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl index b3c35d9ac..e9c290d96 100644 --- a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +++ b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl @@ -271,6 +271,7 @@ module ${cfg['name']}_wrapper ( .TCDMDepth (${cfg['tcdm']['depth']}), .ZeroMemorySize (${cfg['zero_mem_size']}), .ClusterPeriphSize (${cfg['cluster_periph_size']}), + .BootRomSize (${cfg['bootrom_size']}), .NrBanks (${cfg['tcdm']['banks']}), .DMANumAxInFlight (${cfg['dma_axi_req_fifo_depth']}), .DMAReqFifoDepth (${cfg['dma_req_fifo_depth']}), diff --git a/target/common/test/bootrom.cc b/target/common/test/bootrom.cc deleted file mode 100644 index c35518eae..000000000 --- a/target/common/test/bootrom.cc +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -asm(".global tb_bootrom_start \n" - ".global tb_bootrom_end \n" - "tb_bootrom_start: .incbin \"bootrom.bin\" \n" - "tb_bootrom_end: \n"); diff --git a/target/common/test/common_lib.cc b/target/common/test/common_lib.cc index f8e50ce07..4e8fc1152 100644 --- a/target/common/test/common_lib.cc +++ b/target/common/test/common_lib.cc @@ -20,32 +20,7 @@ GlobalMemory MEM; // Override HTIF to populate bootloader with system specification and entry // symbol. -void Sim::start() { - htif_t::start(); - - // Write the bootloader into memory. - size_t bllen = (&tb_bootrom_end - &tb_bootrom_start); - MEM.write(BOOTDATA.boot_addr, bllen, &tb_bootrom_start, nullptr); - std::cout << "[fesvr] Wrote " << bllen << " bytes of bootrom to 0x" - << std::hex << BOOTDATA.boot_addr << "\n"; - - // Write the entry point of the binary to the last word in the bootloader - // (which is a placeholder for this data). - uint32_t e = get_entry_point(); - size_t ep = BOOTDATA.boot_addr + bllen - 4; - MEM.write(ep, 4, reinterpret_cast(&e), nullptr); - std::cout << "[fesvr] Wrote entry point 0x" << std::hex << e - << " to bootloader slot 0x" << ep << "\n"; - - // Write the boot data to the end of the bootloader. This address will be - // passed to the binary in register a1. - size_t bdlen = sizeof(BootData); - size_t bdp = BOOTDATA.boot_addr + bllen; - MEM.write(bdp, bdlen, reinterpret_cast(&BOOTDATA), - nullptr); - std::cout << "[fesvr] Wrote " << bdlen << " bytes of bootdata to 0x" - << std::hex << bdp << "\n"; -} +void Sim::start() { htif_t::start(); } void Sim::read_chunk(addr_t taddr, size_t len, void *dst) { MEM.read(taddr, len, reinterpret_cast(dst)); diff --git a/target/snitch_cluster/.rtlbinary b/target/snitch_cluster/.rtlbinary new file mode 100644 index 000000000..e69de29bb diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 1a5ab2388..80220be08 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -84,7 +84,6 @@ VLOG_FLAGS += ${VLOG_64BIT} ############### TB_CC_SOURCES += \ - ${TB_DIR}/bootrom.cc \ ${TB_DIR}/ipc.cc \ ${TB_DIR}/common_lib.cc \ $(GENERATED_DIR)/bootdata.cc @@ -136,11 +135,6 @@ $(CFG): FORCE fi FORCE: -test/bootrom.elf test/bootrom.dump test/bootrom.bin: test/bootrom.S test/bootrom.ld - riscv64-unknown-elf-gcc -mabi=ilp32d -march=rv32imafd -static -nostartfiles -Ttest/bootrom.ld $< -o test/bootrom.elf - riscv64-unknown-elf-objdump -d test/bootrom.elf > test/bootrom.dump - riscv64-unknown-elf-objcopy -j .text -O binary test/bootrom.elf test/bootrom.bin - ############ # Software # ############ @@ -154,6 +148,7 @@ include $(ROOT)/target/snitch_cluster/sw.mk GENERATED_RTL_SOURCES = $(PERIPH_DIR)/snitch_cluster_peripheral_reg_top.sv GENERATED_RTL_SOURCES += $(PERIPH_DIR)/snitch_cluster_peripheral_reg_pkg.sv GENERATED_RTL_SOURCES += $(GENERATED_DIR)/snitch_cluster_wrapper.sv +GENERATED_RTL_SOURCES += test/snitch_bootrom.sv .PHONY: rtl clean-rtl @@ -183,6 +178,15 @@ $(PERIPH_DIR)/snitch_cluster_peripheral_reg_top.sv: $(PERIPH_DIR)/snitch_cluster @echo "[REGGEN] Generating peripheral regfile" $(REGGEN) -r -t $(PERIPH_DIR) $< +# Bootrom +.PHONY: bootrom +bootrom: test/snitch_bootrom.sv +test/bootrom.elf test/bootrom.dump test/bootrom.bin test/snitch_bootrom.sv: test/bootrom.S test/bootrom.ld util/gen_bootrom.py + $(RISCV_CC) -mabi=ilp32d -march=rv32imafd -static -nostartfiles -fuse-ld=$(RISCV_LD) -Lsw/runtime -Ttest/bootrom.ld $< -o $@ + $(RISCV_OBJDUMP) -d test/bootrom.elf > test/bootrom.dump + $(RISCV_OBJCOPY) -j .text -O binary test/bootrom.elf test/bootrom.bin + util/gen_bootrom.py --sv-module snitch_bootrom test/bootrom.bin > test/snitch_bootrom.sv + ############# # Verilator # ############# diff --git a/target/snitch_cluster/cfg/default.hjson b/target/snitch_cluster/cfg/default.hjson index 93cb2dbec..d332c7270 100644 --- a/target/snitch_cluster/cfg/default.hjson +++ b/target/snitch_cluster/cfg/default.hjson @@ -5,7 +5,6 @@ // Cluster configuration for a simple testbench system. { cluster: { - boot_addr: 4096, // 0x1000 cluster_base_addr: 268435456, // 0x1000_0000 cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, @@ -18,6 +17,7 @@ }, cluster_periph_size: 64, // kB zero_mem_size: 64, // kB + bootrom_size: 4, // kB alias_region_enable: true, dma_data_width: 512, dma_axi_req_fifo_depth: 24, diff --git a/target/snitch_cluster/cfg/dma_mchan.hjson b/target/snitch_cluster/cfg/dma_mchan.hjson index ef551a2d2..9d31f34ba 100644 --- a/target/snitch_cluster/cfg/dma_mchan.hjson +++ b/target/snitch_cluster/cfg/dma_mchan.hjson @@ -4,13 +4,7 @@ // Cluster configuration for a simple testbench system. { - nr_s1_quadrant: 1, - s1_quadrant: { - nr_clusters: 1, - }, - cluster: { - boot_addr: 4096, // 0x1000 cluster_base_addr: 268435456, // 0x1000_0000 cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, @@ -23,6 +17,7 @@ }, cluster_periph_size: 64, // kB zero_mem_size: 64, // kB + bootrom_size: 4, // kB alias_region_enable: true, dma_data_width: 512, dma_nr_channels: 4, diff --git a/target/snitch_cluster/cfg/fdiv.hjson b/target/snitch_cluster/cfg/fdiv.hjson index c58409ef7..9f9e49569 100644 --- a/target/snitch_cluster/cfg/fdiv.hjson +++ b/target/snitch_cluster/cfg/fdiv.hjson @@ -5,7 +5,6 @@ // Cluster configuration for a simple testbench system. { cluster: { - boot_addr: 4096, // 0x1000 cluster_base_addr: 268435456, // 0x1000_0000 cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, @@ -18,6 +17,7 @@ }, cluster_periph_size: 64, // kB zero_mem_size: 64, // kB + bootrom_size: 4, // kB alias_region_enable: true, dma_data_width: 512, dma_axi_req_fifo_depth: 24, diff --git a/target/snitch_cluster/cfg/github-ci.hjson b/target/snitch_cluster/cfg/github-ci.hjson index 3b788754c..568405cce 100644 --- a/target/snitch_cluster/cfg/github-ci.hjson +++ b/target/snitch_cluster/cfg/github-ci.hjson @@ -4,13 +4,7 @@ // Cluster configuration for a simple testbench system. { - nr_s1_quadrant: 1, - s1_quadrant: { - nr_clusters: 1, - }, - cluster: { - boot_addr: 4096, // 0x1000 cluster_base_addr: 268435456, // 0x1000_0000 cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, @@ -23,6 +17,7 @@ }, cluster_periph_size: 64, // kB zero_mem_size: 64, // kB + bootrom_size: 4, // kB alias_region_enable: true, dma_data_width: 512, dma_axi_req_fifo_depth: 24, diff --git a/target/snitch_cluster/cfg/omega.hjson b/target/snitch_cluster/cfg/omega.hjson index 65655936a..06a068c56 100644 --- a/target/snitch_cluster/cfg/omega.hjson +++ b/target/snitch_cluster/cfg/omega.hjson @@ -5,7 +5,6 @@ // Cluster configuration for a simple testbench system. { cluster: { - boot_addr: 4096, // 0x1000 cluster_base_addr: 268435456, // 0x1000_0000 cluster_base_offset: 0, // 0x0 cluster_base_hartid: 0, @@ -19,6 +18,7 @@ }, cluster_periph_size: 64, // kB zero_mem_size: 64, // kB + bootrom_size: 4, // kB alias_region_enable: true, dma_data_width: 512, dma_axi_req_fifo_depth: 24, diff --git a/target/snitch_cluster/src/banshee.yaml b/target/snitch_cluster/src/banshee.yaml index ba8045683..c888c1d07 100644 --- a/target/snitch_cluster/src/banshee.yaml +++ b/target/snitch_cluster/src/banshee.yaml @@ -6,9 +6,9 @@ --- address: - # Snitch: cl_peripherals + 0x190 + # Snitch: cl_peripherals + 0x1b0 barrier_reg: - start: 0x10020190 + start: 0x100201b0 offset: 0x40000 # Snitch/Occamy: SOC_CTRL + 0x14 # in Banshee also used as exit code location @@ -16,8 +16,8 @@ address: uart: 0xF00B8000 # Snitch: Bootdata.clint_base clint: 0xFFFF0000 - # Snitch: cl_peripherals + 0x180 - cl_clint: 0x10020180 + # Snitch: cl_peripherals + 0x1a0 + cl_clint: 0x100201a0 ## These parameters are not used, but Banshee requires them being defined tcdm_end: 0x00000000 tcdm_start: 0x00000000 diff --git a/target/snitch_cluster/test/bootrom.S b/target/snitch_cluster/test/bootrom.S index 10fccfda2..864685f44 100644 --- a/target/snitch_cluster/test/bootrom.S +++ b/target/snitch_cluster/test/bootrom.S @@ -1,16 +1,14 @@ -# Copyright 2020 ETH Zurich and University of Bologna. +# Copyright 2024 ETH Zurich and University of Bologna. # Solderpad Hardware License, Version 0.51, see LICENSE for details. # SPDX-License-Identifier: SHL-0.51 .global _start +.extern _l3_base + _start: - csrr a0, mhartid - la a1, device_tree - lw t0, entry_addr - jalr t0 -no_payload: + lui t0, %hi(_l3_base) // Load the L3 base address + addi t0, t0, %lo(_l3_base) + jalr zero, t0, 0 // Jump to the L3 base address +wfi_loop: wfi - j no_payload -entry_addr: - .word no_payload -device_tree: + j wfi_loop diff --git a/target/snitch_cluster/test/bootrom.bin b/target/snitch_cluster/test/bootrom.bin index 7bfb65be5..971506862 100755 Binary files a/target/snitch_cluster/test/bootrom.bin and b/target/snitch_cluster/test/bootrom.bin differ diff --git a/target/snitch_cluster/test/bootrom.dump b/target/snitch_cluster/test/bootrom.dump index a16b8f2f4..c099da420 100644 --- a/target/snitch_cluster/test/bootrom.dump +++ b/target/snitch_cluster/test/bootrom.dump @@ -1,21 +1,14 @@ -test/bootrom.elf: file format elf32-littleriscv +test/bootrom.elf: file format elf32-littleriscv Disassembly of section .text: -00001000 <_start>: - 1000: f1402573 csrr a0,mhartid - 1004: 00000597 auipc a1,0x0 - 1008: 02058593 addi a1,a1,32 # 1024 - 100c: 00000297 auipc t0,0x0 - 1010: 0142a283 lw t0,20(t0) # 1020 - 1014: 000280e7 jalr t0 +80000000 <_start>: +80000000: b7 02 00 80 lui t0, 524288 +80000004: 93 82 02 00 mv t0, t0 +80000008: 67 80 02 00 jr t0 -00001018 : - 1018: 10500073 wfi - 101c: ffdff06f j 1018 - -00001020 : - 1020: 1018 addi a4,sp,32 - ... +8000000c : +8000000c: 73 00 50 10 wfi +80000010: 6f f0 df ff j 0x8000000c diff --git a/target/snitch_cluster/test/bootrom.elf b/target/snitch_cluster/test/bootrom.elf index 2a6a0dd80..cdb1c18c2 100755 Binary files a/target/snitch_cluster/test/bootrom.elf and b/target/snitch_cluster/test/bootrom.elf differ diff --git a/target/snitch_cluster/test/bootrom.ld b/target/snitch_cluster/test/bootrom.ld index 6b144ee07..a5e79d242 100644 --- a/target/snitch_cluster/test/bootrom.ld +++ b/target/snitch_cluster/test/bootrom.ld @@ -1,9 +1,12 @@ /* Copyright 2020 ETH Zurich and University of Bologna. */ /* Solderpad Hardware License, Version 0.51, see LICENSE for details. */ /* SPDX-License-Identifier: SHL-0.51 */ + +INCLUDE "memory.ld" ENTRY(_start) + SECTIONS { - . = 0x1000; .text : { *(.text) } + _l3_base = ORIGIN(L3); } diff --git a/target/snitch_cluster/test/snitch_bootrom.sv b/target/snitch_cluster/test/snitch_bootrom.sv new file mode 100755 index 000000000..a556f3eb5 --- /dev/null +++ b/target/snitch_cluster/test/snitch_bootrom.sv @@ -0,0 +1,35 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// AUTOMATICALLY GENERATED by gen_bootrom.py; edit the script instead. + +module snitch_bootrom #( + parameter int unsigned AddrWidth = 32, + parameter int unsigned DataWidth = 32, + parameter int unsigned BootromSize = 65536 +)( + input logic clk_i, + input logic rst_ni, + input logic [AddrWidth-1:0] addr_i, + output logic [DataWidth-1:0] data_o +); + + // The bootrom is stored as 32-bit instruction words. + // However, the data bus can have a different width. + logic [BootromSize/4-1:0][31:0] bootrom; + logic [BootromSize/DataWidth*8-1:0][DataWidth-1:0] bootrom_aligned; + + assign bootrom_aligned = bootrom; + assign data_o = bootrom_aligned[addr_i[$clog2(BootromSize)-1:$clog2(DataWidth/8)]]; + + always_comb begin : gen_bootrom + bootrom = '0; + bootrom[0] = 32'h800002b7; /* 0x0000 */ + bootrom[1] = 32'h00028293; /* 0x0004 */ + bootrom[2] = 32'h00028067; /* 0x0008 */ + bootrom[3] = 32'h10500073; /* 0x000c */ + bootrom[4] = 32'hffdff06f; /* 0x0010 */ + end + +endmodule diff --git a/target/snitch_cluster/util/gen_bootrom.py b/target/snitch_cluster/util/gen_bootrom.py new file mode 100755 index 000000000..3936fccef --- /dev/null +++ b/target/snitch_cluster/util/gen_bootrom.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Fabian Schuiki +# Florian Zaruba +# Stefan Mach +# Thomas Benz +# Paul Scheffler +# Wolfgang Roenninger +# Gianna Paulin +# Tim Fischer + +import os +import argparse +import struct + +# Parse arguments. +parser = argparse.ArgumentParser(description="Generate bootrom.sv") +parser.add_argument("BINARY", help="Binary image for which to create a bootrom") +parser.add_argument( + "--sv-module", + "-m", + metavar="BINARY", + help="Name of the combinatorial SystemVerilog bootrom module", +) +args = parser.parse_args() + +# Read the bootrom binary. +with open(args.BINARY, "rb") as file: + binary = file.read() + + +def format_binary(binary): + num_words = len(binary) // 4 + sv_code = "" + for i in range(num_words): + # Extract each 32-bit word as little-endian and unpack it as an unsigned integer + word = struct.unpack_from("