diff --git a/.clang-format-ignore b/.clang-format-ignore index b09ee4eaf..0bfe35ead 100644 --- a/.clang-format-ignore +++ b/.clang-format-ignore @@ -4,6 +4,7 @@ # Exclude files from formatting requirement # External dependencies +*/software/runtime/control_registers.h */software/runtime/encoding.h */software/riscv-tests */toolchain diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 457df0654..fd0be25b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -239,6 +239,20 @@ jobs: make -C hardware src/bootrom.sv git diff --exit-code + check-control-registers: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + - name: Install Python requirements + run: pip install -r python-requirements.txt + - name: Build Control Registers + run: | + git submodule update --init --recursive -- hardware/deps/register_interface + git apply hardware/deps/patches/register_interface.patch + make -C hardware/src/control_registers clean + make -C hardware/src/control_registers all + git diff --ignore-submodules=dirty --exit-code + check-opcodes: runs-on: ubuntu-20.04 steps: diff --git a/.gitlab/.gitlab-ci.yml b/.gitlab/.gitlab-ci.yml index 1bb6e54e2..a49145bc6 100644 --- a/.gitlab/.gitlab-ci.yml +++ b/.gitlab/.gitlab-ci.yml @@ -128,6 +128,13 @@ check-bootrom: - make -C hardware src/bootrom.sv - git diff --exit-code +check-control-registers: + stage: test + script: + - make -C hardware/src/control_registers clean + - make -C hardware/src/control_registers all + - git diff --exit-code + check-opcodes: stage: test script: diff --git a/Bender.yml b/Bender.yml index 438492b87..8d6913a8e 100644 --- a/Bender.yml +++ b/Bender.yml @@ -35,6 +35,8 @@ sources: - hardware/src/address_scrambler.sv - hardware/src/axi2mem.sv - hardware/src/bootrom.sv + - hardware/src/control_registers/control_registers_reg_pkg.sv + - hardware/src/control_registers/control_registers_reg_top.sv # Level 1 - hardware/src/mempool_tile.sv # Level 2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4f0945b..76793e524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Update `register_interface` to 0.4.3 - Updated Halide to version 15 - Move instruction cache into its own dependency +- Use automatically generated control registers ### Fixed - Fix type issue in `snitch_addr_demux` diff --git a/hardware/Makefile b/hardware/Makefile index 6de18eb4f..1a78620c7 100644 --- a/hardware/Makefile +++ b/hardware/Makefile @@ -413,6 +413,11 @@ src/bootrom.sv: $(MEMPOOL_DIR)/software/runtime/bootrom.img $(config_mk) Makefil $(MEMPOOL_DIR)/software/runtime/bootrom.img: make -C $(MEMPOOL_DIR)/software runtime/bootrom.img +# Control Register +CONTROL_REG_DIR := src/control_registers +$(CONTROL_REG_DIR)/control_registers_reg_top.sv: $(CONTROL_REG_DIR)/control_registers.hjson + make -C $(CONTROL_REG_DIR) all + # Clean targets .PHONY: clean clean-dasm clean-trace update_opcodes diff --git a/hardware/deps/patches/register_interface.patch b/hardware/deps/patches/register_interface.patch new file mode 100644 index 000000000..04bea1d5f --- /dev/null +++ b/hardware/deps/patches/register_interface.patch @@ -0,0 +1,98 @@ +diff --git a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_pkg.sv.tpl b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_pkg.sv.tpl +index 1c5520a..77619d9 100644 +--- a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_pkg.sv.tpl ++++ b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_pkg.sv.tpl +@@ -1,6 +1,6 @@ +-// Copyright lowRISC contributors. +-// Licensed under the Apache License, Version 2.0, see LICENSE for details. +-// SPDX-License-Identifier: Apache-2.0 ++// Copyright 2024 ETH Zurich and University of Bologna. ++// Solderpad Hardware License, Version 0.51, see LICENSE for details. ++// SPDX-License-Identifier: SHL-0.51 + // + // Register Package auto-generated by `reggen` containing data structure + <% +@@ -344,4 +344,3 @@ ${reg_data_for_iface(iface_name, iface_desc, for_iface, rb)}\ + % endfor + + endpackage +- +diff --git a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_top.sv.tpl b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_top.sv.tpl +index bfab87f..2b2764e 100644 +--- a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_top.sv.tpl ++++ b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/reggen/reg_top.sv.tpl +@@ -1,6 +1,6 @@ +-// Copyright lowRISC contributors. +-// Licensed under the Apache License, Version 2.0, see LICENSE for details. +-// SPDX-License-Identifier: Apache-2.0 ++// Copyright 2024 ETH Zurich and University of Bologna. ++// Solderpad Hardware License, Version 0.51, see LICENSE for details. ++// SPDX-License-Identifier: SHL-0.51 + // + // Register Top module auto-generated by `reggen` + <% +@@ -534,6 +534,7 @@ ${rdata_gen(f, r.name.lower() + "_" + f.name.lower())}\ + endmodule + + % if use_reg_iface: ++/* verilator lint_off DECLFILENAME */ + module ${mod_name}_intf + #( + parameter int AW = ${addr_width}, +@@ -568,7 +569,7 @@ module ${mod_name}_intf + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; +- ++ + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) +@@ -580,9 +581,9 @@ module ${mod_name}_intf + `REG_BUS_ASSIGN_TO_REQ(s_reg_win_req[i], regbus_win_mst[i]) + `REG_BUS_ASSIGN_FROM_RSP(regbus_win_mst[i], s_reg_win_rsp[i]) + end +- ++ + % endif +- ++ + + ${mod_name} #( + .reg_req_t(reg_bus_req_t), +@@ -605,11 +606,10 @@ module ${mod_name}_intf + % endif + .devmode_i + ); +- +-endmodule + ++endmodule ++/* verilator lint_on DECLFILENAME */ + % endif +- + <%def name="str_bits_sv(bits)">\ + % if bits.msb != bits.lsb: + ${bits.msb}:${bits.lsb}\ +diff --git a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/regtool.py b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/regtool.py +index f7e117a..767c839 100755 +--- a/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/regtool.py ++++ b/hardware/deps/register_interface/vendor/lowrisc_opentitan/util/regtool.py +@@ -210,7 +210,7 @@ def main(): + found_lunder = None + copy = re.compile(r'.*(copyright.*)|(.*\(c\).*)', re.IGNORECASE) + spdx = re.compile(r'.*(SPDX-License-Identifier:.+)') +- lunder = re.compile(r'.*(Licensed under.+)', re.IGNORECASE) ++ lunder = re.compile(r'.*(Solderpad.*)|(Apache.*)', re.IGNORECASE) + for line in srcfull.splitlines(): + mat = copy.match(line) + if mat is not None: +@@ -225,7 +225,7 @@ def main(): + src_lic = found_lunder + if found_spdx: + if src_lic is None: +- src_lic = '\n' + found_spdx ++ src_lic = found_spdx + else: + src_lic += '\n' + found_spdx + diff --git a/hardware/src/control_registers/Makefile b/hardware/src/control_registers/Makefile new file mode 100644 index 000000000..84d1d6319 --- /dev/null +++ b/hardware/src/control_registers/Makefile @@ -0,0 +1,32 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +# Samuel Riedel + +SHELL = /usr/bin/env bash +ROOT_DIR := $(patsubst %/,%, $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) +RUNTIME_DIR := $(abspath $(ROOT_DIR)/../../../software/runtime) + +regtool ?= $(abspath $(ROOT_DIR)/../../deps/register_interface/vendor/lowrisc_opentitan/util/regtool.py) + +RTL := $(patsubst $(ROOT_DIR)/%.hjson,%,$(shell find $(ROOT_DIR) -name "*.hjson")) + +all: $(RTL)_reg_top.sv $(RUNTIME_DIR)/$(RTL).h + +$(RTL)_reg_top.sv: %_reg_top.sv: %.hjson + $(regtool) $^ -r -t $(ROOT_DIR) + +$(RUNTIME_DIR)/$(RTL).h: $(RUNTIME_DIR)/%.h: %.hjson + $(regtool) $^ -D -o $@ + +$(RTL).html: %.html: %.hjson + $(regtool) $^ -d -o $@ + +clean: + @rm -fv $(RTL)_reg_pkg.sv + @rm -fv $(RTL)_reg_top.sv + @rm -fv $(RTL).html + @rm -fv $(RUNTIME_DIR)/$(RTL).h + +.EXTRA_PREREQS:= $(abspath $(lastword $(MAKEFILE_LIST))) diff --git a/hardware/src/control_registers/control_registers.hjson b/hardware/src/control_registers/control_registers.hjson new file mode 100644 index 000000000..dc1aebe42 --- /dev/null +++ b/hardware/src/control_registers/control_registers.hjson @@ -0,0 +1,126 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +{ + name: "control_registers" + clock_primary: "clk_i" + reset_primary: "rst_ni" + bus_interfaces: [ + { protocol: "reg_iface" + direction: "device" + } + ] + param_list: [ + { name: "ROCacheNumAddrRules", + desc: "Number of programmable address regions for the read-only cache", + type: "int", + default: "4" + }, + { name: "MAX_NumGroups", + desc: "Maximum number of groups that we support in any configuration", + type: "int", + default: "8" + } + ], + regwidth: 32 + registers: [ + { name: "eoc" + desc: "End-of-Computation Register" + swaccess: "rw" + hwaccess: "hro" + fields: [{ bits: "31:0" }] + }, + { name: "wake_up" + desc: "Wake Up Register" + swaccess: "wo" + hwaccess: "hro" + hwqe: "true" + fields: [{ bits: "31:0" }] + }, + { multireg: + { + name: "wake_up_tile" + desc: "Wake Up Tile Register" + swaccess: "wo" + hwaccess: "hro" + hwqe: "true" + count: "MAX_NumGroups" + cname: "wake_up_tile" + fields: [{ bits: "31:0" }] + }, + }, + { name: "wake_up_group" + desc: "Wake Up Group Register" + swaccess: "wo" + hwaccess: "hro" + hwqe: "true" + fields: [{ bits: "31:0" }] + }, + { name: "tcdm_start_address" + desc: "TCDM Start Address Register" + swaccess: "ro" + hwaccess: "hwo" + // External because we want to define the reset from a parameter + hwext: "true" + fields: [{ bits: "31:0" }] + }, + { name: "tcdm_end_address" + desc: "TCDM End Address Register" + swaccess: "ro" + hwaccess: "hwo" + // External because we want to define the reset from a parameter + hwext: "true" + fields: [{ bits: "31:0" }] + }, + { name: "nr_cores_reg" + desc: "Number of Cores Register" + swaccess: "ro" + hwaccess: "hwo" + // External because we want to define the reset from a parameter + hwext: "true" + fields: [{ bits: "31:0" }] + }, + { name: "ro_cache_enable" + desc: "Read-only cache Enable" + swaccess: "rw" + hwaccess: "hro" + resval: "1" + fields: [{ bits: "31:0" }] + }, + { name: "ro_cache_flush" + desc: "Read-only cache Flush" + swaccess: "rw" + hwaccess: "hro" + fields: [{ bits: "31:0" }] + }, + { multireg: + { + name: "ro_cache_start" + desc: "Read-only cache Region Start" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + // External because we want to define the reset from a parameter + hwext: "true" + count: "ROCacheNumAddrRules" + cname: "ro_cache_start" + fields: [{ bits: "31:0" }] + }, + }, + { multireg: + { + name: "ro_cache_end" + desc: "Read-only cache Region End" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + // External because we want to define the reset from a parameter + hwext: "true" + count: "ROCacheNumAddrRules" + cname: "ro_cache_end" + fields: [{ bits: "31:0" }] + } + } + ] +} diff --git a/hardware/src/control_registers/control_registers_reg_pkg.sv b/hardware/src/control_registers/control_registers_reg_pkg.sv new file mode 100644 index 000000000..3a44033a3 --- /dev/null +++ b/hardware/src/control_registers/control_registers_reg_pkg.sv @@ -0,0 +1,193 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Register Package auto-generated by `reggen` containing data structure + +package control_registers_reg_pkg; + + // Param list + parameter int ROCacheNumAddrRules = 4; + parameter int MAX_NumGroups = 8; + + // Address widths within the block + parameter int BlockAw = 7; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic [31:0] q; + } control_registers_reg2hw_eoc_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } control_registers_reg2hw_wake_up_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } control_registers_reg2hw_wake_up_tile_mreg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } control_registers_reg2hw_wake_up_group_reg_t; + + typedef struct packed { + logic [31:0] q; + } control_registers_reg2hw_ro_cache_enable_reg_t; + + typedef struct packed { + logic [31:0] q; + } control_registers_reg2hw_ro_cache_flush_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } control_registers_reg2hw_ro_cache_start_mreg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } control_registers_reg2hw_ro_cache_end_mreg_t; + + typedef struct packed { + logic [31:0] d; + } control_registers_hw2reg_tcdm_start_address_reg_t; + + typedef struct packed { + logic [31:0] d; + } control_registers_hw2reg_tcdm_end_address_reg_t; + + typedef struct packed { + logic [31:0] d; + } control_registers_hw2reg_nr_cores_reg_reg_t; + + typedef struct packed { + logic [31:0] d; + } control_registers_hw2reg_ro_cache_start_mreg_t; + + typedef struct packed { + logic [31:0] d; + } control_registers_hw2reg_ro_cache_end_mreg_t; + + // Register -> HW type + typedef struct packed { + control_registers_reg2hw_eoc_reg_t eoc; // [689:658] + control_registers_reg2hw_wake_up_reg_t wake_up; // [657:625] + control_registers_reg2hw_wake_up_tile_mreg_t [7:0] wake_up_tile; // [624:361] + control_registers_reg2hw_wake_up_group_reg_t wake_up_group; // [360:328] + control_registers_reg2hw_ro_cache_enable_reg_t ro_cache_enable; // [327:296] + control_registers_reg2hw_ro_cache_flush_reg_t ro_cache_flush; // [295:264] + control_registers_reg2hw_ro_cache_start_mreg_t [3:0] ro_cache_start; // [263:132] + control_registers_reg2hw_ro_cache_end_mreg_t [3:0] ro_cache_end; // [131:0] + } control_registers_reg2hw_t; + + // HW -> register type + typedef struct packed { + control_registers_hw2reg_tcdm_start_address_reg_t tcdm_start_address; // [351:320] + control_registers_hw2reg_tcdm_end_address_reg_t tcdm_end_address; // [319:288] + control_registers_hw2reg_nr_cores_reg_reg_t nr_cores_reg; // [287:256] + control_registers_hw2reg_ro_cache_start_mreg_t [3:0] ro_cache_start; // [255:128] + control_registers_hw2reg_ro_cache_end_mreg_t [3:0] ro_cache_end; // [127:0] + } control_registers_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_EOC_OFFSET = 7'h 0; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_OFFSET = 7'h 4; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_0_OFFSET = 7'h 8; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_1_OFFSET = 7'h c; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_2_OFFSET = 7'h 10; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_3_OFFSET = 7'h 14; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_4_OFFSET = 7'h 18; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_5_OFFSET = 7'h 1c; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_6_OFFSET = 7'h 20; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_TILE_7_OFFSET = 7'h 24; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_WAKE_UP_GROUP_OFFSET = 7'h 28; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_TCDM_START_ADDRESS_OFFSET = 7'h 2c; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_TCDM_END_ADDRESS_OFFSET = 7'h 30; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_NR_CORES_REG_OFFSET = 7'h 34; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_ENABLE_OFFSET = 7'h 38; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_FLUSH_OFFSET = 7'h 3c; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_START_0_OFFSET = 7'h 40; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_START_1_OFFSET = 7'h 44; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_START_2_OFFSET = 7'h 48; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_START_3_OFFSET = 7'h 4c; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_END_0_OFFSET = 7'h 50; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_END_1_OFFSET = 7'h 54; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_END_2_OFFSET = 7'h 58; + parameter logic [BlockAw-1:0] CONTROL_REGISTERS_RO_CACHE_END_3_OFFSET = 7'h 5c; + + // Reset values for hwext registers and their fields + parameter logic [31:0] CONTROL_REGISTERS_TCDM_START_ADDRESS_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_TCDM_END_ADDRESS_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_NR_CORES_REG_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_START_0_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_START_1_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_START_2_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_START_3_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_END_0_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_END_1_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_END_2_RESVAL = 32'h 0; + parameter logic [31:0] CONTROL_REGISTERS_RO_CACHE_END_3_RESVAL = 32'h 0; + + // Register index + typedef enum int { + CONTROL_REGISTERS_EOC, + CONTROL_REGISTERS_WAKE_UP, + CONTROL_REGISTERS_WAKE_UP_TILE_0, + CONTROL_REGISTERS_WAKE_UP_TILE_1, + CONTROL_REGISTERS_WAKE_UP_TILE_2, + CONTROL_REGISTERS_WAKE_UP_TILE_3, + CONTROL_REGISTERS_WAKE_UP_TILE_4, + CONTROL_REGISTERS_WAKE_UP_TILE_5, + CONTROL_REGISTERS_WAKE_UP_TILE_6, + CONTROL_REGISTERS_WAKE_UP_TILE_7, + CONTROL_REGISTERS_WAKE_UP_GROUP, + CONTROL_REGISTERS_TCDM_START_ADDRESS, + CONTROL_REGISTERS_TCDM_END_ADDRESS, + CONTROL_REGISTERS_NR_CORES_REG, + CONTROL_REGISTERS_RO_CACHE_ENABLE, + CONTROL_REGISTERS_RO_CACHE_FLUSH, + CONTROL_REGISTERS_RO_CACHE_START_0, + CONTROL_REGISTERS_RO_CACHE_START_1, + CONTROL_REGISTERS_RO_CACHE_START_2, + CONTROL_REGISTERS_RO_CACHE_START_3, + CONTROL_REGISTERS_RO_CACHE_END_0, + CONTROL_REGISTERS_RO_CACHE_END_1, + CONTROL_REGISTERS_RO_CACHE_END_2, + CONTROL_REGISTERS_RO_CACHE_END_3 + } control_registers_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] CONTROL_REGISTERS_PERMIT [24] = '{ + 4'b 1111, // index[ 0] CONTROL_REGISTERS_EOC + 4'b 1111, // index[ 1] CONTROL_REGISTERS_WAKE_UP + 4'b 1111, // index[ 2] CONTROL_REGISTERS_WAKE_UP_TILE_0 + 4'b 1111, // index[ 3] CONTROL_REGISTERS_WAKE_UP_TILE_1 + 4'b 1111, // index[ 4] CONTROL_REGISTERS_WAKE_UP_TILE_2 + 4'b 1111, // index[ 5] CONTROL_REGISTERS_WAKE_UP_TILE_3 + 4'b 1111, // index[ 6] CONTROL_REGISTERS_WAKE_UP_TILE_4 + 4'b 1111, // index[ 7] CONTROL_REGISTERS_WAKE_UP_TILE_5 + 4'b 1111, // index[ 8] CONTROL_REGISTERS_WAKE_UP_TILE_6 + 4'b 1111, // index[ 9] CONTROL_REGISTERS_WAKE_UP_TILE_7 + 4'b 1111, // index[10] CONTROL_REGISTERS_WAKE_UP_GROUP + 4'b 1111, // index[11] CONTROL_REGISTERS_TCDM_START_ADDRESS + 4'b 1111, // index[12] CONTROL_REGISTERS_TCDM_END_ADDRESS + 4'b 1111, // index[13] CONTROL_REGISTERS_NR_CORES_REG + 4'b 1111, // index[14] CONTROL_REGISTERS_RO_CACHE_ENABLE + 4'b 1111, // index[15] CONTROL_REGISTERS_RO_CACHE_FLUSH + 4'b 1111, // index[16] CONTROL_REGISTERS_RO_CACHE_START_0 + 4'b 1111, // index[17] CONTROL_REGISTERS_RO_CACHE_START_1 + 4'b 1111, // index[18] CONTROL_REGISTERS_RO_CACHE_START_2 + 4'b 1111, // index[19] CONTROL_REGISTERS_RO_CACHE_START_3 + 4'b 1111, // index[20] CONTROL_REGISTERS_RO_CACHE_END_0 + 4'b 1111, // index[21] CONTROL_REGISTERS_RO_CACHE_END_1 + 4'b 1111, // index[22] CONTROL_REGISTERS_RO_CACHE_END_2 + 4'b 1111 // index[23] CONTROL_REGISTERS_RO_CACHE_END_3 + }; + +endpackage diff --git a/hardware/src/control_registers/control_registers_reg_top.sv b/hardware/src/control_registers/control_registers_reg_top.sv new file mode 100644 index 000000000..76e9e07cb --- /dev/null +++ b/hardware/src/control_registers/control_registers_reg_top.sv @@ -0,0 +1,972 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module control_registers_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 7 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output control_registers_reg_pkg::control_registers_reg2hw_t reg2hw, // Write + input control_registers_reg_pkg::control_registers_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import control_registers_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [31:0] eoc_qs; + logic [31:0] eoc_wd; + logic eoc_we; + logic [31:0] wake_up_wd; + logic wake_up_we; + logic [31:0] wake_up_tile_0_wd; + logic wake_up_tile_0_we; + logic [31:0] wake_up_tile_1_wd; + logic wake_up_tile_1_we; + logic [31:0] wake_up_tile_2_wd; + logic wake_up_tile_2_we; + logic [31:0] wake_up_tile_3_wd; + logic wake_up_tile_3_we; + logic [31:0] wake_up_tile_4_wd; + logic wake_up_tile_4_we; + logic [31:0] wake_up_tile_5_wd; + logic wake_up_tile_5_we; + logic [31:0] wake_up_tile_6_wd; + logic wake_up_tile_6_we; + logic [31:0] wake_up_tile_7_wd; + logic wake_up_tile_7_we; + logic [31:0] wake_up_group_wd; + logic wake_up_group_we; + logic [31:0] tcdm_start_address_qs; + logic tcdm_start_address_re; + logic [31:0] tcdm_end_address_qs; + logic tcdm_end_address_re; + logic [31:0] nr_cores_reg_qs; + logic nr_cores_reg_re; + logic [31:0] ro_cache_enable_qs; + logic [31:0] ro_cache_enable_wd; + logic ro_cache_enable_we; + logic [31:0] ro_cache_flush_qs; + logic [31:0] ro_cache_flush_wd; + logic ro_cache_flush_we; + logic [31:0] ro_cache_start_0_qs; + logic [31:0] ro_cache_start_0_wd; + logic ro_cache_start_0_we; + logic ro_cache_start_0_re; + logic [31:0] ro_cache_start_1_qs; + logic [31:0] ro_cache_start_1_wd; + logic ro_cache_start_1_we; + logic ro_cache_start_1_re; + logic [31:0] ro_cache_start_2_qs; + logic [31:0] ro_cache_start_2_wd; + logic ro_cache_start_2_we; + logic ro_cache_start_2_re; + logic [31:0] ro_cache_start_3_qs; + logic [31:0] ro_cache_start_3_wd; + logic ro_cache_start_3_we; + logic ro_cache_start_3_re; + logic [31:0] ro_cache_end_0_qs; + logic [31:0] ro_cache_end_0_wd; + logic ro_cache_end_0_we; + logic ro_cache_end_0_re; + logic [31:0] ro_cache_end_1_qs; + logic [31:0] ro_cache_end_1_wd; + logic ro_cache_end_1_we; + logic ro_cache_end_1_re; + logic [31:0] ro_cache_end_2_qs; + logic [31:0] ro_cache_end_2_wd; + logic ro_cache_end_2_we; + logic ro_cache_end_2_re; + logic [31:0] ro_cache_end_3_qs; + logic [31:0] ro_cache_end_3_wd; + logic ro_cache_end_3_we; + logic ro_cache_end_3_re; + + // Register instances + // R[eoc]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_eoc ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (eoc_we), + .wd (eoc_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.eoc.q ), + + // to register interface (read) + .qs (eoc_qs) + ); + + + // R[wake_up]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_we), + .wd (wake_up_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up.qe), + .q (reg2hw.wake_up.q ), + + .qs () + ); + + + + // Subregister 0 of Multireg wake_up_tile + // R[wake_up_tile_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_0_we), + .wd (wake_up_tile_0_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[0].qe), + .q (reg2hw.wake_up_tile[0].q ), + + .qs () + ); + + // Subregister 1 of Multireg wake_up_tile + // R[wake_up_tile_1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_1_we), + .wd (wake_up_tile_1_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[1].qe), + .q (reg2hw.wake_up_tile[1].q ), + + .qs () + ); + + // Subregister 2 of Multireg wake_up_tile + // R[wake_up_tile_2]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_2 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_2_we), + .wd (wake_up_tile_2_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[2].qe), + .q (reg2hw.wake_up_tile[2].q ), + + .qs () + ); + + // Subregister 3 of Multireg wake_up_tile + // R[wake_up_tile_3]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_3 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_3_we), + .wd (wake_up_tile_3_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[3].qe), + .q (reg2hw.wake_up_tile[3].q ), + + .qs () + ); + + // Subregister 4 of Multireg wake_up_tile + // R[wake_up_tile_4]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_4 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_4_we), + .wd (wake_up_tile_4_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[4].qe), + .q (reg2hw.wake_up_tile[4].q ), + + .qs () + ); + + // Subregister 5 of Multireg wake_up_tile + // R[wake_up_tile_5]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_5 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_5_we), + .wd (wake_up_tile_5_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[5].qe), + .q (reg2hw.wake_up_tile[5].q ), + + .qs () + ); + + // Subregister 6 of Multireg wake_up_tile + // R[wake_up_tile_6]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_6 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_6_we), + .wd (wake_up_tile_6_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[6].qe), + .q (reg2hw.wake_up_tile[6].q ), + + .qs () + ); + + // Subregister 7 of Multireg wake_up_tile + // R[wake_up_tile_7]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_tile_7 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_tile_7_we), + .wd (wake_up_tile_7_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_tile[7].qe), + .q (reg2hw.wake_up_tile[7].q ), + + .qs () + ); + + + // R[wake_up_group]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("WO"), + .RESVAL (32'h0) + ) u_wake_up_group ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (wake_up_group_we), + .wd (wake_up_group_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.wake_up_group.qe), + .q (reg2hw.wake_up_group.q ), + + .qs () + ); + + + // R[tcdm_start_address]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_tcdm_start_address ( + .re (tcdm_start_address_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.tcdm_start_address.d), + .qre (), + .qe (), + .q (), + .qs (tcdm_start_address_qs) + ); + + + // R[tcdm_end_address]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_tcdm_end_address ( + .re (tcdm_end_address_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.tcdm_end_address.d), + .qre (), + .qe (), + .q (), + .qs (tcdm_end_address_qs) + ); + + + // R[nr_cores_reg]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_nr_cores_reg ( + .re (nr_cores_reg_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.nr_cores_reg.d), + .qre (), + .qe (), + .q (), + .qs (nr_cores_reg_qs) + ); + + + // R[ro_cache_enable]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h1) + ) u_ro_cache_enable ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (ro_cache_enable_we), + .wd (ro_cache_enable_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.ro_cache_enable.q ), + + // to register interface (read) + .qs (ro_cache_enable_qs) + ); + + + // R[ro_cache_flush]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_ro_cache_flush ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (ro_cache_flush_we), + .wd (ro_cache_flush_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.ro_cache_flush.q ), + + // to register interface (read) + .qs (ro_cache_flush_qs) + ); + + + + // Subregister 0 of Multireg ro_cache_start + // R[ro_cache_start_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_start_0 ( + .re (ro_cache_start_0_re), + .we (ro_cache_start_0_we), + .wd (ro_cache_start_0_wd), + .d (hw2reg.ro_cache_start[0].d), + .qre (), + .qe (reg2hw.ro_cache_start[0].qe), + .q (reg2hw.ro_cache_start[0].q ), + .qs (ro_cache_start_0_qs) + ); + + // Subregister 1 of Multireg ro_cache_start + // R[ro_cache_start_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_start_1 ( + .re (ro_cache_start_1_re), + .we (ro_cache_start_1_we), + .wd (ro_cache_start_1_wd), + .d (hw2reg.ro_cache_start[1].d), + .qre (), + .qe (reg2hw.ro_cache_start[1].qe), + .q (reg2hw.ro_cache_start[1].q ), + .qs (ro_cache_start_1_qs) + ); + + // Subregister 2 of Multireg ro_cache_start + // R[ro_cache_start_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_start_2 ( + .re (ro_cache_start_2_re), + .we (ro_cache_start_2_we), + .wd (ro_cache_start_2_wd), + .d (hw2reg.ro_cache_start[2].d), + .qre (), + .qe (reg2hw.ro_cache_start[2].qe), + .q (reg2hw.ro_cache_start[2].q ), + .qs (ro_cache_start_2_qs) + ); + + // Subregister 3 of Multireg ro_cache_start + // R[ro_cache_start_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_start_3 ( + .re (ro_cache_start_3_re), + .we (ro_cache_start_3_we), + .wd (ro_cache_start_3_wd), + .d (hw2reg.ro_cache_start[3].d), + .qre (), + .qe (reg2hw.ro_cache_start[3].qe), + .q (reg2hw.ro_cache_start[3].q ), + .qs (ro_cache_start_3_qs) + ); + + + + // Subregister 0 of Multireg ro_cache_end + // R[ro_cache_end_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_end_0 ( + .re (ro_cache_end_0_re), + .we (ro_cache_end_0_we), + .wd (ro_cache_end_0_wd), + .d (hw2reg.ro_cache_end[0].d), + .qre (), + .qe (reg2hw.ro_cache_end[0].qe), + .q (reg2hw.ro_cache_end[0].q ), + .qs (ro_cache_end_0_qs) + ); + + // Subregister 1 of Multireg ro_cache_end + // R[ro_cache_end_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_end_1 ( + .re (ro_cache_end_1_re), + .we (ro_cache_end_1_we), + .wd (ro_cache_end_1_wd), + .d (hw2reg.ro_cache_end[1].d), + .qre (), + .qe (reg2hw.ro_cache_end[1].qe), + .q (reg2hw.ro_cache_end[1].q ), + .qs (ro_cache_end_1_qs) + ); + + // Subregister 2 of Multireg ro_cache_end + // R[ro_cache_end_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_end_2 ( + .re (ro_cache_end_2_re), + .we (ro_cache_end_2_we), + .wd (ro_cache_end_2_wd), + .d (hw2reg.ro_cache_end[2].d), + .qre (), + .qe (reg2hw.ro_cache_end[2].qe), + .q (reg2hw.ro_cache_end[2].q ), + .qs (ro_cache_end_2_qs) + ); + + // Subregister 3 of Multireg ro_cache_end + // R[ro_cache_end_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_ro_cache_end_3 ( + .re (ro_cache_end_3_re), + .we (ro_cache_end_3_we), + .wd (ro_cache_end_3_wd), + .d (hw2reg.ro_cache_end[3].d), + .qre (), + .qe (reg2hw.ro_cache_end[3].qe), + .q (reg2hw.ro_cache_end[3].q ), + .qs (ro_cache_end_3_qs) + ); + + + + + logic [23:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == CONTROL_REGISTERS_EOC_OFFSET); + addr_hit[ 1] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_OFFSET); + addr_hit[ 2] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_0_OFFSET); + addr_hit[ 3] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_1_OFFSET); + addr_hit[ 4] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_2_OFFSET); + addr_hit[ 5] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_3_OFFSET); + addr_hit[ 6] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_4_OFFSET); + addr_hit[ 7] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_5_OFFSET); + addr_hit[ 8] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_6_OFFSET); + addr_hit[ 9] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_TILE_7_OFFSET); + addr_hit[10] = (reg_addr == CONTROL_REGISTERS_WAKE_UP_GROUP_OFFSET); + addr_hit[11] = (reg_addr == CONTROL_REGISTERS_TCDM_START_ADDRESS_OFFSET); + addr_hit[12] = (reg_addr == CONTROL_REGISTERS_TCDM_END_ADDRESS_OFFSET); + addr_hit[13] = (reg_addr == CONTROL_REGISTERS_NR_CORES_REG_OFFSET); + addr_hit[14] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_ENABLE_OFFSET); + addr_hit[15] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_FLUSH_OFFSET); + addr_hit[16] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_START_0_OFFSET); + addr_hit[17] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_START_1_OFFSET); + addr_hit[18] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_START_2_OFFSET); + addr_hit[19] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_START_3_OFFSET); + addr_hit[20] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_END_0_OFFSET); + addr_hit[21] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_END_1_OFFSET); + addr_hit[22] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_END_2_OFFSET); + addr_hit[23] = (reg_addr == CONTROL_REGISTERS_RO_CACHE_END_3_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(CONTROL_REGISTERS_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(CONTROL_REGISTERS_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(CONTROL_REGISTERS_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(CONTROL_REGISTERS_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(CONTROL_REGISTERS_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(CONTROL_REGISTERS_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(CONTROL_REGISTERS_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(CONTROL_REGISTERS_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(CONTROL_REGISTERS_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(CONTROL_REGISTERS_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(CONTROL_REGISTERS_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(CONTROL_REGISTERS_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(CONTROL_REGISTERS_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(CONTROL_REGISTERS_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(CONTROL_REGISTERS_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(CONTROL_REGISTERS_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(CONTROL_REGISTERS_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(CONTROL_REGISTERS_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(CONTROL_REGISTERS_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(CONTROL_REGISTERS_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(CONTROL_REGISTERS_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(CONTROL_REGISTERS_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(CONTROL_REGISTERS_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(CONTROL_REGISTERS_PERMIT[23] & ~reg_be))))); + end + + assign eoc_we = addr_hit[0] & reg_we & !reg_error; + assign eoc_wd = reg_wdata[31:0]; + + assign wake_up_we = addr_hit[1] & reg_we & !reg_error; + assign wake_up_wd = reg_wdata[31:0]; + + assign wake_up_tile_0_we = addr_hit[2] & reg_we & !reg_error; + assign wake_up_tile_0_wd = reg_wdata[31:0]; + + assign wake_up_tile_1_we = addr_hit[3] & reg_we & !reg_error; + assign wake_up_tile_1_wd = reg_wdata[31:0]; + + assign wake_up_tile_2_we = addr_hit[4] & reg_we & !reg_error; + assign wake_up_tile_2_wd = reg_wdata[31:0]; + + assign wake_up_tile_3_we = addr_hit[5] & reg_we & !reg_error; + assign wake_up_tile_3_wd = reg_wdata[31:0]; + + assign wake_up_tile_4_we = addr_hit[6] & reg_we & !reg_error; + assign wake_up_tile_4_wd = reg_wdata[31:0]; + + assign wake_up_tile_5_we = addr_hit[7] & reg_we & !reg_error; + assign wake_up_tile_5_wd = reg_wdata[31:0]; + + assign wake_up_tile_6_we = addr_hit[8] & reg_we & !reg_error; + assign wake_up_tile_6_wd = reg_wdata[31:0]; + + assign wake_up_tile_7_we = addr_hit[9] & reg_we & !reg_error; + assign wake_up_tile_7_wd = reg_wdata[31:0]; + + assign wake_up_group_we = addr_hit[10] & reg_we & !reg_error; + assign wake_up_group_wd = reg_wdata[31:0]; + + assign tcdm_start_address_re = addr_hit[11] & reg_re & !reg_error; + + assign tcdm_end_address_re = addr_hit[12] & reg_re & !reg_error; + + assign nr_cores_reg_re = addr_hit[13] & reg_re & !reg_error; + + assign ro_cache_enable_we = addr_hit[14] & reg_we & !reg_error; + assign ro_cache_enable_wd = reg_wdata[31:0]; + + assign ro_cache_flush_we = addr_hit[15] & reg_we & !reg_error; + assign ro_cache_flush_wd = reg_wdata[31:0]; + + assign ro_cache_start_0_we = addr_hit[16] & reg_we & !reg_error; + assign ro_cache_start_0_wd = reg_wdata[31:0]; + assign ro_cache_start_0_re = addr_hit[16] & reg_re & !reg_error; + + assign ro_cache_start_1_we = addr_hit[17] & reg_we & !reg_error; + assign ro_cache_start_1_wd = reg_wdata[31:0]; + assign ro_cache_start_1_re = addr_hit[17] & reg_re & !reg_error; + + assign ro_cache_start_2_we = addr_hit[18] & reg_we & !reg_error; + assign ro_cache_start_2_wd = reg_wdata[31:0]; + assign ro_cache_start_2_re = addr_hit[18] & reg_re & !reg_error; + + assign ro_cache_start_3_we = addr_hit[19] & reg_we & !reg_error; + assign ro_cache_start_3_wd = reg_wdata[31:0]; + assign ro_cache_start_3_re = addr_hit[19] & reg_re & !reg_error; + + assign ro_cache_end_0_we = addr_hit[20] & reg_we & !reg_error; + assign ro_cache_end_0_wd = reg_wdata[31:0]; + assign ro_cache_end_0_re = addr_hit[20] & reg_re & !reg_error; + + assign ro_cache_end_1_we = addr_hit[21] & reg_we & !reg_error; + assign ro_cache_end_1_wd = reg_wdata[31:0]; + assign ro_cache_end_1_re = addr_hit[21] & reg_re & !reg_error; + + assign ro_cache_end_2_we = addr_hit[22] & reg_we & !reg_error; + assign ro_cache_end_2_wd = reg_wdata[31:0]; + assign ro_cache_end_2_re = addr_hit[22] & reg_re & !reg_error; + + assign ro_cache_end_3_we = addr_hit[23] & reg_we & !reg_error; + assign ro_cache_end_3_wd = reg_wdata[31:0]; + assign ro_cache_end_3_re = addr_hit[23] & reg_re & !reg_error; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[31:0] = eoc_qs; + end + + addr_hit[1]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[2]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[3]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[4]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[5]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[6]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[7]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[8]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[9]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[10]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[11]: begin + reg_rdata_next[31:0] = tcdm_start_address_qs; + end + + addr_hit[12]: begin + reg_rdata_next[31:0] = tcdm_end_address_qs; + end + + addr_hit[13]: begin + reg_rdata_next[31:0] = nr_cores_reg_qs; + end + + addr_hit[14]: begin + reg_rdata_next[31:0] = ro_cache_enable_qs; + end + + addr_hit[15]: begin + reg_rdata_next[31:0] = ro_cache_flush_qs; + end + + addr_hit[16]: begin + reg_rdata_next[31:0] = ro_cache_start_0_qs; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = ro_cache_start_1_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = ro_cache_start_2_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = ro_cache_start_3_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = ro_cache_end_0_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = ro_cache_end_1_qs; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = ro_cache_end_2_qs; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = ro_cache_end_3_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +/* verilator lint_off DECLFILENAME */ +module control_registers_reg_top_intf +#( + parameter int AW = 7, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output control_registers_reg_pkg::control_registers_reg2hw_t reg2hw, // Write + input control_registers_reg_pkg::control_registers_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + control_registers_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule +/* verilator lint_on DECLFILENAME */ diff --git a/hardware/src/ctrl_registers.sv b/hardware/src/ctrl_registers.sv index 189c76fc0..3e35434a4 100644 --- a/hardware/src/ctrl_registers.sv +++ b/hardware/src/ctrl_registers.sv @@ -3,12 +3,12 @@ // SPDX-License-Identifier: SHL-0.51 `include "common_cells/registers.svh" +`include "register_interface/typedef.svh" module ctrl_registers import mempool_pkg::ro_cache_ctrl_t; #( parameter int DataWidth = 32, - parameter int NumRegs = 0, // Parameters parameter logic [DataWidth-1:0] TCDMBaseAddr = 0, parameter logic [DataWidth-1:0] TCDMSize = 0, @@ -26,195 +26,142 @@ module ctrl_registers output logic [DataWidth-1:0] eoc_o, output logic eoc_valid_o, output logic [NumCores-1:0] wake_up_o, - output logic [DataWidth-1:0] tcdm_start_address_o, - output logic [DataWidth-1:0] tcdm_end_address_o, - output logic [DataWidth-1:0] num_cores_o, output ro_cache_ctrl_t ro_cache_ctrl_o ); - import mempool_pkg::*; - - /***************** - * Definitions * - *****************/ - - localparam int unsigned DataWidthInBytes = (DataWidth + 7) / 8; - localparam int unsigned RegNumBytes = NumRegs * DataWidthInBytes; - localparam int unsigned RegDataWidth = NumRegs * DataWidth; - - localparam logic [DataWidthInBytes-1:0] ReadOnlyReg = {DataWidthInBytes{1'b1}}; - localparam logic [DataWidthInBytes-1:0] ReadWriteReg = {DataWidthInBytes{1'b0}}; - - // Memory map - // [3 :0 ]:eoc_reg (rw) - // [7 :4 ]:wake_up_reg (rw) - // [11:8 ]:wake_up_group_reg (rw) - // [15:12]:tcdm_start_adress_reg (ro) - // [19:16]:tcdm_end_address_reg (ro) - // [23:20]:nr_cores_address_reg (ro) - // [27:24]:ro_cache_enable (rw) - // [31:28]:ro_cache_flush (rw) - // [35:32]:ro_cache_start_0 (rw) - // [39:36]:ro_cache_end_0 (rw) - // [43:40]:ro_cache_start_1 (rw) - // [47:44]:ro_cache_end_1 (rw) - // [51:48]:ro_cache_start_2 (rw) - // [55:52]:ro_cache_end_2 (rw) - // [59:56]:ro_cache_start_3 (rw) - // [63:60]:ro_cache_end_3 (rw) - - // [95:64]:wake_up_tile[7:0] (rw) - - localparam logic [MAX_NumGroups*DataWidth-1:0] RegRstVal_TileWakeUp = '{MAX_NumGroups*DataWidth{1'b0}}; - localparam logic [NumRegs-MAX_NumGroups-1:0][DataWidth-1:0] RegRstVal = '{ - 32'h0000_0010, - 32'h0000_000C, - 32'h0000_000C, - 32'h0000_0008, - 32'hA000_1000, - 32'hA000_0000, - 32'h8000_1000, - 32'h8000_0000, - {DataWidth{1'b0}}, - 32'h1, - NumCores, - TCDMBaseAddr + TCDMSize, - TCDMBaseAddr, - {DataWidth{1'b0}}, - {DataWidth{1'b0}}, - {DataWidth{1'b0}} - }; - - localparam logic [MAX_NumGroups-1:0][DataWidthInBytes-1:0] AxiReadOnly_TileWakeUp = '{MAX_NumGroups{ReadWriteReg}}; - localparam logic [NumRegs-MAX_NumGroups-1:0][DataWidthInBytes-1:0] AxiReadOnly = '{ - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg, - ReadOnlyReg, - ReadOnlyReg, - ReadOnlyReg, - ReadWriteReg, - ReadWriteReg, - ReadWriteReg - }; + import mempool_pkg::AddrWidth; + import control_registers_reg_pkg::*; /*************** * Registers * ***************/ - logic [DataWidth-1:0] eoc; - logic [DataWidth-1:0] wake_up; - logic [DataWidth-1:0] wake_up_group; - logic [DataWidth-1:0] tcdm_start_address; - logic [DataWidth-1:0] tcdm_end_address; - logic [DataWidth-1:0] num_cores; - logic [DataWidth-1:0] ro_cache_enable; - logic [DataWidth-1:0] ro_cache_flush; - logic [DataWidth-1:0] ro_cache_start_0; - logic [DataWidth-1:0] ro_cache_end_0; - logic [DataWidth-1:0] ro_cache_start_1; - logic [DataWidth-1:0] ro_cache_end_1; - logic [DataWidth-1:0] ro_cache_start_2; - logic [DataWidth-1:0] ro_cache_end_2; - logic [DataWidth-1:0] ro_cache_start_3; - logic [DataWidth-1:0] ro_cache_end_3; - logic [MAX_NumGroups*DataWidth-1:0] wake_up_tile; - - logic [RegNumBytes-1:0] wr_active_d; - logic [RegNumBytes-1:0] wr_active_q; - - axi_lite_regs #( - .RegNumBytes (RegNumBytes ), - .AxiAddrWidth(AddrWidth ), - .AxiDataWidth(AxiLiteDataWidth ), - .AxiReadOnly ({AxiReadOnly_TileWakeUp, AxiReadOnly} ), - .RegRstVal ({RegRstVal_TileWakeUp, RegRstVal} ), - .req_lite_t (axi_lite_req_t ), - .resp_lite_t (axi_lite_resp_t ) - ) i_axi_lite_regs ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - .axi_req_i (axi_lite_slave_req_i ), - .axi_resp_o (axi_lite_slave_resp_o ), - .wr_active_o(wr_active_d ), - .rd_active_o(/* Unused */ ), - .reg_d_i ('0 ), - .reg_load_i ('0 ), - .reg_q_o ({ wake_up_tile, - ro_cache_end_3, ro_cache_start_3, - ro_cache_end_2, ro_cache_start_2, - ro_cache_end_1, ro_cache_start_1, - ro_cache_end_0, ro_cache_start_0, - ro_cache_flush, ro_cache_enable, - num_cores, tcdm_end_address, tcdm_start_address, wake_up_group, wake_up, eoc }) + `REG_BUS_TYPEDEF_ALL(ctrl_reg, logic[AddrWidth-1:0], logic[DataWidth-1:0], logic[DataWidth/8-1:0]); + ctrl_reg_req_t ctrl_reg_req; + ctrl_reg_rsp_t ctrl_reg_rsp; + control_registers_reg2hw_t ctrl_reg2hw; + control_registers_hw2reg_t ctrl_hw2reg; + + axi_lite_to_reg #( + .ADDR_WIDTH (AddrWidth ), + .DATA_WIDTH (DataWidth ), + .BUFFER_DEPTH (1 ), + .DECOUPLE_W (0 ), + .axi_lite_req_t(axi_lite_req_t ), + .axi_lite_rsp_t(axi_lite_resp_t), + .reg_req_t (ctrl_reg_req_t ), + .reg_rsp_t (ctrl_reg_rsp_t ) + ) i_axi_lite_to_reg ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .axi_lite_req_i(axi_lite_slave_req_i ), + .axi_lite_rsp_o(axi_lite_slave_resp_o), + .reg_req_o (ctrl_reg_req ), + .reg_rsp_i (ctrl_reg_rsp ) ); - /*************** - * Signals * - ***************/ + control_registers_reg_top #( + .reg_req_t(ctrl_reg_req_t), + .reg_rsp_t(ctrl_reg_rsp_t) + ) i_control_registers_reg_top ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + .reg_req_i(ctrl_reg_req), + .reg_rsp_o(ctrl_reg_rsp), + .reg2hw (ctrl_reg2hw ), + .hw2reg (ctrl_hw2reg ), + .devmode_i(1'b0 ) + ); - assign eoc_o = eoc >> 1; - assign tcdm_start_address_o = tcdm_start_address; - assign tcdm_end_address_o = tcdm_end_address; - assign num_cores_o = num_cores; - - assign ro_cache_ctrl_o.enable = ro_cache_enable[0]; - assign ro_cache_ctrl_o.flush_valid = ro_cache_flush[0]; - assign ro_cache_ctrl_o.start_addr[0] = ro_cache_start_0; - assign ro_cache_ctrl_o.start_addr[1] = ro_cache_start_1; - assign ro_cache_ctrl_o.start_addr[2] = ro_cache_start_2; - assign ro_cache_ctrl_o.start_addr[3] = ro_cache_start_3; - assign ro_cache_ctrl_o.end_addr[0] = ro_cache_end_0; - assign ro_cache_ctrl_o.end_addr[1] = ro_cache_end_1; - assign ro_cache_ctrl_o.end_addr[2] = ro_cache_end_2; - assign ro_cache_ctrl_o.end_addr[3] = ro_cache_end_3; + /************************ + * External Registers * + ************************/ + // These registers have hardcoded values (read-only) + assign ctrl_hw2reg.nr_cores_reg.d = NumCores; + assign ctrl_hw2reg.tcdm_start_address.d = TCDMBaseAddr; + assign ctrl_hw2reg.tcdm_end_address.d = TCDMBaseAddr + TCDMSize; + + // These registers are external because they have special reset values. But they are read and + // write so we need to instantiate an actual register + typedef struct packed { + logic [AddrWidth-1:0] start_addr; + logic [AddrWidth-1:0] end_addr; + } ro_cache_region_t; + ro_cache_region_t [ROCacheNumAddrRules-1:0] ro_cache_regions; + assign ro_cache_regions = '{ + '{start_addr: 32'h0000_000C, end_addr: 32'h0000_0010}, + '{start_addr: 32'h0000_0008, end_addr: 32'h0000_000C}, + '{start_addr: 32'hA000_0000, end_addr: 32'hA000_1000}, + '{start_addr: 32'h8000_0000, end_addr: 32'h8000_1000} + }; + for (genvar i = 0; i < ROCacheNumAddrRules; i++) begin : gen_ro_cache_reg + `FFL(ctrl_hw2reg.ro_cache_start[i].d, ctrl_reg2hw.ro_cache_start[i].q, ctrl_reg2hw.ro_cache_start[i].qe, ro_cache_regions[i].start_addr) + `FFL(ctrl_hw2reg.ro_cache_end[i].d, ctrl_reg2hw.ro_cache_end[i].q, ctrl_reg2hw.ro_cache_end[i].qe, ro_cache_regions[i].end_addr) + end + + /************************ + * Wakeup Pulse Logic * + ************************/ + import mempool_pkg::NumCoresPerGroup; + import mempool_pkg::NumCoresPerTile; + import mempool_pkg::NumTilesPerGroup; + import mempool_pkg::NumGroups; + + // Delay the write-enable signal by one cycle so it arrives + // simultaneously with the registered values + logic wake_up_pulse; + logic [MAX_NumGroups-1:0] wake_up_tile_pulse; + logic wake_up_group_pulse; + + `FF(wake_up_pulse, ctrl_reg2hw.wake_up.qe, '0) + for (genvar i = 0; i < MAX_NumGroups; i++) begin : gen_wake_up_tile_reg + `FF(wake_up_tile_pulse[i], ctrl_reg2hw.wake_up_tile[i].qe, '0) + end + `FF(wake_up_group_pulse, ctrl_reg2hw.wake_up_group.qe, '0) always_comb begin wake_up_o = '0; - // converts 32 bit wake up to 256 bit - if (wr_active_q[7:4]) begin - if (wake_up < NumCores) begin - wake_up_o = 1 << wake_up; - end else if (wake_up == {DataWidth{1'b1}}) begin + // converts 32-bit core wake-up into a 'NumCores'-bit mask + if (wake_up_pulse) begin + if (ctrl_reg2hw.wake_up.q < NumCores) begin + wake_up_o = 1 << ctrl_reg2hw.wake_up.q; + end else begin wake_up_o = {NumCores{1'b1}}; end end - // converts 32 bit group wake up mask to 256 bit core wake up mask - if (wr_active_q[11:8]) begin - if (wake_up_group <= {NumGroups{1'b1}}) begin - for(int i = 0; i < NumGroups; i = i + 1) begin - wake_up_o[NumCoresPerGroup * i +: NumCoresPerGroup] = {NumCoresPerGroup{wake_up_group[i]}}; + // converts 32-bit tile wake-up mask into a 'NumCores'-bit mask + for(int g = 0; g < NumGroups; g = g + 1) begin + if (wake_up_tile_pulse[g]) begin + if (ctrl_reg2hw.wake_up_tile[g].q <= {NumTilesPerGroup{1'b1}}) begin + for (int t = 0; t < NumTilesPerGroup; t = t + 1) begin + wake_up_o[NumCoresPerGroup * g + NumCoresPerTile * t +: NumCoresPerTile] = {NumCoresPerTile{ctrl_reg2hw.wake_up_tile[g].q[t]}}; + end end - end else if (wake_up_group == {DataWidth{1'b1}}) begin - wake_up_o = {NumCores{1'b1}}; end end - - // converts 32 bit tile wake up mask to 256 bit core wake up mask - for(int i_g = 0; i_g < NumGroups; i_g = i_g + 1) begin - - if (wr_active_q[64 + 4 * i_g +: 4]) begin - if (wake_up_tile[i_g * DataWidth +: DataWidth] <= {NumTilesPerGroup{1'b1}}) begin - for (int i = 0; i < NumTilesPerGroup; i = i + 1) begin - wake_up_o[NumCoresPerGroup * i_g + NumCoresPerTile * i +: NumCoresPerTile] = {NumCoresPerTile{wake_up_tile[i_g * DataWidth + i]}}; - end + // converts 32-bit group wake-up mask into a 'NumCores'-bit mask + if (wake_up_group_pulse) begin + if (ctrl_reg2hw.wake_up_group.q <= {NumGroups{1'b1}}) begin + for(int i = 0; i < NumGroups; i = i + 1) begin + wake_up_o[NumCoresPerGroup * i +: NumCoresPerGroup] = {NumCoresPerGroup{ctrl_reg2hw.wake_up_group.q[i]}}; end + end else if (ctrl_reg2hw.wake_up_group.q == {DataWidth{1'b1}}) begin + wake_up_o = {NumCores{1'b1}}; end - end - end - assign eoc_valid_o = eoc[0]; - - // register to add +1 latency to the wr_active signal - `FF(wr_active_q, wr_active_d, '0, clk_i, rst_ni) + /*********************** + * Output Assignment * + ***********************/ + assign eoc_o = ctrl_reg2hw.eoc.q >> 1; + assign eoc_valid_o = ctrl_reg2hw.eoc.q[0]; + + assign ro_cache_ctrl_o.enable = ctrl_reg2hw.ro_cache_enable.q[0]; + assign ro_cache_ctrl_o.flush_valid = ctrl_reg2hw.ro_cache_flush.q[0]; + for (genvar i = 0; i < ROCacheNumAddrRules; i++) begin : gen_ro_cache_out + assign ro_cache_ctrl_o.start_addr[i] = ctrl_hw2reg.ro_cache_start[i].d; + assign ro_cache_ctrl_o.end_addr[i] = ctrl_hw2reg.ro_cache_end[i].d; + end /****************** * Assertions * @@ -222,4 +169,10 @@ module ctrl_registers if (NumGroups > MAX_NumGroups) $error("[ctrl_registers] Number of groups exceeds the maximum supported."); + if (MAX_NumGroups != mempool_pkg::MAX_NumGroups) + $error("[ctrl_registers] MAX_NumGroups parameter does not match the one from mempool_pkg."); + + if (ROCacheNumAddrRules != mempool_pkg::ROCacheNumAddrRules) + $error("[ctrl_registers] ROCacheNumAddrRules parameter does not match the one from mempool_pkg."); + endmodule : ctrl_registers diff --git a/hardware/src/mempool_system.sv b/hardware/src/mempool_system.sv index 7bddbe17e..b7fbb00d0 100644 --- a/hardware/src/mempool_system.sv +++ b/hardware/src/mempool_system.sv @@ -718,7 +718,6 @@ module mempool_system ); ctrl_registers #( - .NumRegs (16 + 8 ), .TCDMBaseAddr (TCDMBaseAddr ), .TCDMSize (TCDMSize ), .NumCores (NumCores ), @@ -729,13 +728,10 @@ module mempool_system .rst_ni (rst_ni ), .axi_lite_slave_req_i (axi_lite_slv_req[CtrlRegisters] ), .axi_lite_slave_resp_o(axi_lite_slv_resp[CtrlRegisters]), - .ro_cache_ctrl_o (ro_cache_ctrl ), - .tcdm_start_address_o (/* Unused */ ), - .tcdm_end_address_o (/* Unused */ ), - .num_cores_o (/* Unused */ ), - .wake_up_o (wake_up ), .eoc_o (/* Unused */ ), - .eoc_valid_o (eoc_valid_o ) + .eoc_valid_o (eoc_valid_o ), + .wake_up_o (wake_up ), + .ro_cache_ctrl_o (ro_cache_ctrl ) ); mempool_dma #( diff --git a/hardware/tb/verilator/waiver.vlt b/hardware/tb/verilator/waiver.vlt index e52cedca5..2b2b4be24 100644 --- a/hardware/tb/verilator/waiver.vlt +++ b/hardware/tb/verilator/waiver.vlt @@ -25,6 +25,9 @@ lint_off -rule PINCONNECTEMPTY -file "*/deps/*" -match "*" lint_off -rule DECLFILENAME -file "*/deps/*" -match "*" lint_off -rule LITENDIAN -file "*/deps/fpnew/*" -match "*" +// Ignore unused register ports in lowRISC's prims +lint_off -rule PINCONNECTEMPTY -file "*/src/control_registers/*" -match "*" + // Ignore unused RISCV instruction encoding parameters lint_off -rule UNUSED -file "*/deps/snitch/src/riscv_instr.sv" -match "*" diff --git a/scripts/license-checker.hjson b/scripts/license-checker.hjson index eea7ec365..8666e0955 100644 --- a/scripts/license-checker.hjson +++ b/scripts/license-checker.hjson @@ -13,6 +13,7 @@ match_regex: 'true' exclude_paths: [ # Exclude anything that is explicitly mentioned in the README + 'software/runtime/control_registers.h' 'software/runtime/printf*' 'software/runtime/encoding.h' 'software/runtime/mempool_dma_frontend.h' diff --git a/scripts/lint.sh b/scripts/lint.sh index b313feb11..5b321dbe3 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -39,6 +39,7 @@ echo "Checking for trailing whitespaces and tabs in unstaged files" git --no-pager diff --check -- \ ':(exclude)**.def' \ ':(exclude)**.patch' \ + ':(exclude)hardware/src/control_registers/*.sv' \ ':(exclude)toolchain/**' \ ':(exclude)software/riscv-tests/**' \ || EXIT_STATUS=$? @@ -47,6 +48,7 @@ echo "Checking for trailing whitespaces and tabs between HEAD and $base" git --no-pager diff --check $base HEAD -- \ ':(exclude)**.def' \ ':(exclude)**.patch' \ + ':(exclude)hardware/src/control_registers/*.sv' \ ':(exclude)toolchain/**' \ ':(exclude)software/riscv-tests/**' \ || EXIT_STATUS=$? diff --git a/software/runtime/addrmap.h b/software/runtime/addrmap.h new file mode 100644 index 000000000..2c6029169 --- /dev/null +++ b/software/runtime/addrmap.h @@ -0,0 +1,14 @@ +// 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 + +// Author: Samuel Riedel, ETH Zurich + +#ifndef _ADDRMAP_H_ +#define _ADDRMAP_H_ + +#define CONTROL_REGISTER_OFFSET (0x40000000) + +#include "control_registers.h" + +#endif // _DMA_H_ diff --git a/software/runtime/arch.ld.c b/software/runtime/arch.ld.c index 8d003388b..1d8de5e57 100644 --- a/software/runtime/arch.ld.c +++ b/software/runtime/arch.ld.c @@ -31,32 +31,5 @@ SECTIONS { __heap_start = __l1_start; __heap_end = __l1_end; - // Hardware register location - eoc_reg = 0x40000000; - wake_up_reg = 0x40000004; - wake_up_group_reg = 0x40000008; - tcdm_start_address_reg = 0x4000000C; - tcdm_end_address_reg = 0x40000010; - nr_cores_address_reg = 0x40000014; - ro_cache_enable = 0x40000018; - ro_cache_flush = 0x4000001C; - ro_cache_start_0 = 0x40000020; - ro_cache_end_0 = 0x40000024; - ro_cache_start_1 = 0x40000028; - ro_cache_end_1 = 0x4000002C; - ro_cache_start_2 = 0x40000030; - ro_cache_end_2 = 0x40000034; - ro_cache_start_3 = 0x40000038; - ro_cache_end_3 = 0x4000003C; - - wake_up_tile_g0_reg = 0x40000040; - wake_up_tile_g1_reg = 0x40000044; - wake_up_tile_g2_reg = 0x40000048; - wake_up_tile_g3_reg = 0x4000004C; - wake_up_tile_g4_reg = 0x40000050; - wake_up_tile_g5_reg = 0x40000054; - wake_up_tile_g6_reg = 0x40000058; - wake_up_tile_g7_reg = 0x4000005C; - fake_uart = 0xC0000000; } diff --git a/software/runtime/control_registers.h b/software/runtime/control_registers.h new file mode 100644 index 000000000..95bd21e45 --- /dev/null +++ b/software/runtime/control_registers.h @@ -0,0 +1,116 @@ +// Generated register defines for control_registers + +// Copyright information found in source file: +// Copyright 2024 ETH Zurich and University of Bologna. + +// Licensing information found in source file: +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +#ifndef _CONTROL_REGISTERS_REG_DEFS_ +#define _CONTROL_REGISTERS_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Number of programmable address regions for the read-only cache +#define CONTROL_REGISTERS_PARAM_R_O_CACHE_NUM_ADDR_RULES 4 + +// Maximum number of groups that we support in any configuration +#define CONTROL_REGISTERS_PARAM_MAX_NUMGROUPS 8 + +// Register width +#define CONTROL_REGISTERS_PARAM_REG_WIDTH 32 + +// End-of-Computation Register +#define CONTROL_REGISTERS_EOC_REG_OFFSET 0x0 + +// Wake Up Register +#define CONTROL_REGISTERS_WAKE_UP_REG_OFFSET 0x4 + +// Wake Up Tile Register (common parameters) +#define CONTROL_REGISTERS_WAKE_UP_TILE_WAKE_UP_TILE_FIELD_WIDTH 32 +#define CONTROL_REGISTERS_WAKE_UP_TILE_WAKE_UP_TILE_FIELDS_PER_REG 1 +#define CONTROL_REGISTERS_WAKE_UP_TILE_MULTIREG_COUNT 8 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_0_REG_OFFSET 0x8 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_1_REG_OFFSET 0xc + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_2_REG_OFFSET 0x10 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_3_REG_OFFSET 0x14 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_4_REG_OFFSET 0x18 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_5_REG_OFFSET 0x1c + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_6_REG_OFFSET 0x20 + +// Wake Up Tile Register +#define CONTROL_REGISTERS_WAKE_UP_TILE_7_REG_OFFSET 0x24 + +// Wake Up Group Register +#define CONTROL_REGISTERS_WAKE_UP_GROUP_REG_OFFSET 0x28 + +// TCDM Start Address Register +#define CONTROL_REGISTERS_TCDM_START_ADDRESS_REG_OFFSET 0x2c + +// TCDM End Address Register +#define CONTROL_REGISTERS_TCDM_END_ADDRESS_REG_OFFSET 0x30 + +// Number of Cores Register +#define CONTROL_REGISTERS_NR_CORES_REG_REG_OFFSET 0x34 + +// Read-only cache Enable +#define CONTROL_REGISTERS_RO_CACHE_ENABLE_REG_OFFSET 0x38 + +// Read-only cache Flush +#define CONTROL_REGISTERS_RO_CACHE_FLUSH_REG_OFFSET 0x3c + +// Read-only cache Region Start (common parameters) +#define CONTROL_REGISTERS_RO_CACHE_START_RO_CACHE_START_FIELD_WIDTH 32 +#define CONTROL_REGISTERS_RO_CACHE_START_RO_CACHE_START_FIELDS_PER_REG 1 +#define CONTROL_REGISTERS_RO_CACHE_START_MULTIREG_COUNT 4 + +// Read-only cache Region Start +#define CONTROL_REGISTERS_RO_CACHE_START_0_REG_OFFSET 0x40 + +// Read-only cache Region Start +#define CONTROL_REGISTERS_RO_CACHE_START_1_REG_OFFSET 0x44 + +// Read-only cache Region Start +#define CONTROL_REGISTERS_RO_CACHE_START_2_REG_OFFSET 0x48 + +// Read-only cache Region Start +#define CONTROL_REGISTERS_RO_CACHE_START_3_REG_OFFSET 0x4c + +// Read-only cache Region End (common parameters) +#define CONTROL_REGISTERS_RO_CACHE_END_RO_CACHE_END_FIELD_WIDTH 32 +#define CONTROL_REGISTERS_RO_CACHE_END_RO_CACHE_END_FIELDS_PER_REG 1 +#define CONTROL_REGISTERS_RO_CACHE_END_MULTIREG_COUNT 4 + +// Read-only cache Region End +#define CONTROL_REGISTERS_RO_CACHE_END_0_REG_OFFSET 0x50 + +// Read-only cache Region End +#define CONTROL_REGISTERS_RO_CACHE_END_1_REG_OFFSET 0x54 + +// Read-only cache Region End +#define CONTROL_REGISTERS_RO_CACHE_END_2_REG_OFFSET 0x58 + +// Read-only cache Region End +#define CONTROL_REGISTERS_RO_CACHE_END_3_REG_OFFSET 0x5c + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _CONTROL_REGISTERS_REG_DEFS_ +// End generated register defines for control_registers \ No newline at end of file diff --git a/software/runtime/crt0.S b/software/runtime/crt0.S index 1cc1905c6..4de3d2b70 100644 --- a/software/runtime/crt0.S +++ b/software/runtime/crt0.S @@ -7,6 +7,8 @@ // #define TOP4_STACK +#include "addrmap.h" + .globl _start .globl _eoc .section .text; @@ -77,14 +79,14 @@ _reset_vector: csrw stacklimit, t0 // write stack limit into CSR // Configure the RO cache or directly jump to main bnez a0, _jump_main - la t0, ro_cache_end_0 // Get peripheral register to set cacheable region + li t0, (CONTROL_REGISTER_OFFSET + CONTROL_REGISTERS_RO_CACHE_END_0_REG_OFFSET) // Get peripheral register to set cacheable region la t1, _erodata // Write the end of the read-only data to be cacheable sw t1, 0(t0) _jump_main: call main _eoc: - la t0, eoc_reg + li t0, (CONTROL_REGISTER_OFFSET + CONTROL_REGISTERS_EOC_REG_OFFSET) slli t1, a0, 1 addi t1, t1, 1 sw t1, 0(t0) diff --git a/software/runtime/riscv_test.h b/software/runtime/riscv_test.h index 31882d421..1bf169534 100644 --- a/software/runtime/riscv_test.h +++ b/software/runtime/riscv_test.h @@ -8,6 +8,7 @@ #define _ENV_PHYSICAL_SINGLE_CORE_H #include "encoding.h" +#include "addrmap.h" //----------------------------------------------------------------------- // Begin Macro @@ -95,7 +96,7 @@ reset_vector: \ #define RVTEST_CODE_END \ _eoc: \ - la t0, eoc_reg; \ + li t0, (CONTROL_REGISTER_OFFSET + CONTROL_REGISTERS_EOC_REG_OFFSET); \ slli t1, a0, 1; \ addi t1, t1, 1; \ sw t1, 0(t0); \ diff --git a/software/runtime/runtime.h b/software/runtime/runtime.h index 4abdbd682..958d6775d 100644 --- a/software/runtime/runtime.h +++ b/software/runtime/runtime.h @@ -6,6 +6,7 @@ // Matheus Cavalcante, ETH Zurich #pragma once +#include "addrmap.h" #include "alloc.h" #include "encoding.h" #include @@ -14,18 +15,37 @@ #define NUM_BANKS_PER_TILE NUM_CORES_PER_TILE *BANKING_FACTOR extern char l1_alloc_base; -extern uint32_t atomic_barrier; -extern volatile uint32_t wake_up_reg; -extern volatile uint32_t wake_up_group_reg; - -extern volatile uint32_t wake_up_tile_g0_reg; -extern volatile uint32_t wake_up_tile_g1_reg; -extern volatile uint32_t wake_up_tile_g2_reg; -extern volatile uint32_t wake_up_tile_g3_reg; -extern volatile uint32_t wake_up_tile_g4_reg; -extern volatile uint32_t wake_up_tile_g5_reg; -extern volatile uint32_t wake_up_tile_g6_reg; -extern volatile uint32_t wake_up_tile_g7_reg; +static uint32_t volatile *wake_up_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_REG_OFFSET); +static uint32_t volatile *wake_up_group_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_GROUP_REG_OFFSET); + +static uint32_t volatile *wake_up_tile_g0_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_0_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g1_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_1_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g2_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_2_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g3_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_3_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g4_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_4_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g5_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_5_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g6_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_6_REG_OFFSET); +static uint32_t volatile *wake_up_tile_g7_reg = + (uint32_t volatile *)(CONTROL_REGISTER_OFFSET + + CONTROL_REGISTERS_WAKE_UP_TILE_7_REG_OFFSET); typedef uint32_t mempool_id_t; typedef uint32_t mempool_timer_t; @@ -127,10 +147,10 @@ static inline void mempool_wfi() { asm volatile("wfi"); } // Wake up core with given core_id by writing in the wake up control register. // If core_id equals -1, wake up all cores. -static inline void wake_up(uint32_t core_id) { wake_up_reg = core_id; } +static inline void wake_up(uint32_t core_id) { *wake_up_reg = core_id; } static inline void wake_up_all() { wake_up((uint32_t)-1); } static inline void wake_up_group(uint32_t group_mask) { - wake_up_group_reg = group_mask; + *wake_up_group_reg = group_mask; } static inline void wake_up_all_group() { wake_up_group((uint32_t)-1); } @@ -138,31 +158,31 @@ static inline void wake_up_tile(uint32_t group_id, uint32_t tile_mask) { switch (group_id) { case 0: - wake_up_tile_g0_reg = tile_mask; + *wake_up_tile_g0_reg = tile_mask; break; case 1: - wake_up_tile_g1_reg = tile_mask; + *wake_up_tile_g1_reg = tile_mask; break; case 2: - wake_up_tile_g2_reg = tile_mask; + *wake_up_tile_g2_reg = tile_mask; break; case 3: - wake_up_tile_g3_reg = tile_mask; + *wake_up_tile_g3_reg = tile_mask; break; case 4: - wake_up_tile_g4_reg = tile_mask; + *wake_up_tile_g4_reg = tile_mask; break; case 5: - wake_up_tile_g5_reg = tile_mask; + *wake_up_tile_g5_reg = tile_mask; break; case 6: - wake_up_tile_g6_reg = tile_mask; + *wake_up_tile_g6_reg = tile_mask; break; case 7: - wake_up_tile_g7_reg = tile_mask; + *wake_up_tile_g7_reg = tile_mask; break; default: - wake_up_tile_g0_reg = tile_mask; + *wake_up_tile_g0_reg = tile_mask; break; } }