diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 043732ed..babd1190 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,11 @@ jobs: run: make bender - name: Python Requirements run: pip install -r requirements.txt + - name: Checkout dependencies + run: ./bender checkout - name: Check clean make targets run: | - make -B gen_ODRG gen_TCLS gen_ecc_registers gen_ECC + make -B gen_ODRG gen_TCLS gen_ecc_registers gen_ECC gen_HMR git status && test -z "$(git status --porcelain)" lint-verilog: runs-on: ubuntu-latest @@ -59,6 +61,7 @@ jobs: ./rtl/HMR/hmr_registers_reg_top.sv ./rtl/HMR/hmr_tmr_regs_reg_pkg.sv ./rtl/HMR/hmr_tmr_regs_reg_top.sv + ./rtl/HMR/hmr_registers_reg_addr_pkg.sv ./rtl/pulpissimo_tcls/tcls_manager_reg_pkg.sv ./rtl/pulpissimo_tcls/tcls_manager_reg_top.sv extra_args: "--rules=-interface-name-style --lint_fatal --parse_fatal --waiver_files .github/waiver.verible" diff --git a/Bender.yml b/Bender.yml index ea8f550b..b28acae2 100644 --- a/Bender.yml +++ b/Bender.yml @@ -8,7 +8,8 @@ dependencies: common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.0 } register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 } common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.35.0 } - + apb: { git: "https://github.com/pulp-platform/apb.git", version: 0.2.4 } + export_include_dirs: - include @@ -139,7 +140,7 @@ sources: - rtl/HMR/hmr_dmr_ctrl.sv - rtl/HMR/hmr_tmr_regs_reg_top.sv - rtl/HMR/hmr_tmr_ctrl.sv - - rtl/HMR/HMR_wrap.sv + # - rtl/HMR/HMR_wrap.sv # Legacy, plase use hmr_unit instead - rtl/HMR/hmr_unit.sv vendor_package: diff --git a/Makefile b/Makefile index 153a1446..558fa819 100644 --- a/Makefile +++ b/Makefile @@ -19,13 +19,20 @@ REG_PATH = $(shell $(BENDER) path register_interface) # use if you need to hardcode location of regtool # REG_PATH = ../register_interface REG_TOOL = $(REG_PATH)/vendor/lowrisc_opentitan/util/regtool.py +PEAKRDL ?= peakrdl HJSON_ODRG = rtl/ODRG_unit/ODRG_unit.hjson HJSON_TCLS = rtl/pulpissimo_tcls/TCLS_unit.hjson -HJSON_HMR = rtl/HMR/HMR_regs.hjson -HJSON_HMR_core = rtl/HMR/HMR_core_regs.hjson -HJSON_HMR_dmr = rtl/HMR/HMR_dmr_regs.hjson -HJSON_HMR_tmr = rtl/HMR/HMR_tmr_regs.hjson +RDL_HMR_TOP = rtl/HMR/hmr_all.rdl +RDL_HMR = rtl/HMR/hmr_regs.rdl +RDL_HMR_core = rtl/HMR/hmr_core_regs.rdl +RDL_HMR_dmr = rtl/HMR/hmr_dmr_regs.rdl +RDL_HMR_tmr = rtl/HMR/hmr_tmr_regs.rdl +HMR_NUM_CORES ?= 12 +HMR_NUM_DMR_GROUPS ?= $(HMR_NUM_CORES)/2 +HMR_NUM_TMR_GROUPS ?= $(HMR_NUM_CORES)/3 +HMR_DMR_AVAILABLE ?= 1 +HMR_TMR_AVAILABLE ?= 1 HJSON_ECC = rtl/ecc_wrap/ecc_sram_wrapper.hjson TARGET_DIR_ODRG = rtl/ODRG_unit @@ -33,49 +40,6 @@ TARGET_DIR_TCLS = rtl/pulpissimo_tcls TARGET_DIR_HMR = rtl/HMR TARGET_DIR_ECC = rtl/ecc_wrap -define HMR_H_HEADER_STRING -/* - * Copyright (C) 2023 ETH Zurich and University of Bologna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ARCHI_HMR_HMR_V1_H__ -#define __ARCHI_HMR_HMR_V1_H__ - -#define HMR_IN_INTERLEAVED 1 - -#define HMR_TOP_OFFSET 0x000 -#define HMR_CORE_OFFSET 0x100 -#define HMR_DMR_OFFSET 0x200 -#define HMR_TMR_OFFSET 0x300 - -#define HMR_CORE_INCREMENT 0x010 -#define HMR_CORE_SLL 0x004 -#define HMR_DMR_INCREMENT 0x010 -#define HMR_DMR_SLL 0x004 -#define HMR_TMR_INCREMENT 0x010 -#define HMR_TMR_SLL 0x004 -\n -endef -define HMR_H_FINAL_STRING -\n\n -#endif // __ARCHI_HMR_HMR_V1_H__ - -endef -export HMR_H_HEADER_STRING -export HMR_H_FINAL_STRING - .PHONY: gen_ODRG gen_TCLS gen_ecc_registers gen_ECC gen_ODRG: python $(REG_TOOL) $(HJSON_ODRG) -t $(TARGET_DIR_ODRG) -r @@ -87,23 +51,22 @@ gen_TCLS: python $(REG_TOOL) $(HJSON_TCLS) -d > $(TARGET_DIR_TCLS)/doc.md python $(REG_TOOL) $(HJSON_TCLS) -D > $(TARGET_DIR_TCLS)/TCLS.h -gen_HMR: - python $(REG_TOOL) $(HJSON_HMR) -t $(TARGET_DIR_HMR) -r - python $(REG_TOOL) $(HJSON_HMR) -d > $(TARGET_DIR_HMR)/doc.html - python $(REG_TOOL) $(HJSON_HMR) --doc > $(TARGET_DIR_HMR)/doc.md - python $(REG_TOOL) $(HJSON_HMR_core) -t $(TARGET_DIR_HMR) -r - python $(REG_TOOL) $(HJSON_HMR_dmr) -t $(TARGET_DIR_HMR) -r - python $(REG_TOOL) $(HJSON_HMR_tmr) -t $(TARGET_DIR_HMR) -r - - @printf "$$HMR_H_HEADER_STRING" > $(TARGET_DIR_HMR)/hmr_v1.h - python $(REG_TOOL) $(HJSON_HMR) -D >> $(TARGET_DIR_HMR)/hmr_v1.h - @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h - python $(REG_TOOL) $(HJSON_HMR_core) -D >> $(TARGET_DIR_HMR)/hmr_v1.h - @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h - python $(REG_TOOL) $(HJSON_HMR_dmr) -D >> $(TARGET_DIR_HMR)/hmr_v1.h - @printf "\n\n" >> $(TARGET_DIR_HMR)/hmr_v1.h - python $(REG_TOOL) $(HJSON_HMR_tmr) -D >> $(TARGET_DIR_HMR)/hmr_v1.h - @printf "$$HMR_H_FINAL_STRING" >> $(TARGET_DIR_HMR)/hmr_v1.h +gen_HMR: $(RDL_HMR_TOP) $(RDL_HMR) $(RDL_HMR_core) $(RDL_HMR_dmr) $(RDL_HMR_tmr) + $(PEAKRDL) regblock $(RDL_HMR) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \ + --module-name hmr_registers_reg_top --package-name hmr_registers_reg_pkg \ + -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS) + $(PEAKRDL) regblock $(RDL_HMR_core) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \ + --module-name hmr_core_regs_reg_top --package-name hmr_core_regs_reg_pkg + $(PEAKRDL) regblock $(RDL_HMR_dmr) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \ + --module-name hmr_dmr_regs_reg_top --package-name hmr_dmr_regs_reg_pkg + $(PEAKRDL) regblock $(RDL_HMR_tmr) -o $(TARGET_DIR_HMR) --cpuif apb4-flat --default-reset arst_n \ + --module-name hmr_tmr_regs_reg_top --package-name hmr_tmr_regs_reg_pkg + $(PEAKRDL) raw-header $(RDL_HMR_TOP) -I $(TARGET_DIR_HMR) -o $(TARGET_DIR_HMR)/hmr_registers_reg_addr_pkg.sv --format svpkg \ + -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS) \ + -P DMRAvailable=$(HMR_DMR_AVAILABLE) -P TMRAvailable=$(HMR_TMR_AVAILABLE) + $(PEAKRDL) c-header $(RDL_HMR_TOP) -I $(TARGET_DIR_HMR) -o $(TARGET_DIR_HMR)/hmr_registers.h \ + -P NumCores=$(HMR_NUM_CORES) -P NumDMRGroups=$(HMR_NUM_DMR_GROUPS) -P NumTMRGroups=$(HMR_NUM_TMR_GROUPS) \ + -P DMRAvailable=$(HMR_DMR_AVAILABLE) -P TMRAvailable=$(HMR_TMR_AVAILABLE) gen_ecc_registers: python $(REG_TOOL) $(HJSON_ECC) -t $(TARGET_DIR_ECC) -r diff --git a/README.md b/README.md index 63dff9f5..50a2df8c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,105 @@ This repository contains various modules used to add redundancy. +## Hybrid Modular Redundancy (HMR) + +The HMR unit (contained in `rtl/HMR/hmr_unit.sv`) is designed as a configurable bridge between the system and multiple cores. This bridge allows to configure the cores to run independently, run in a dual/DMR/DCLS mode, or run in a triple/TMR/TCLS mode. These configurations can be switched at runtime (given the availability at design time), or fixed with a parameter at design time. + +### System integration + +### Instantiation + +This module should be placed between all signals connecting the processor cores to the rest of the system. Some additional modules are required to support certain features: +- To allow runtime switching between independent, DMR, and TMR modes, logic should be implemented to signal when the cores are ready to group together and synchronize. If in `DMRFixed` or `TMRFixed` configuration, this is not needed. + +#### Parameters + +To integrate this module into a system, the following parameters *require* configuration: +- `NumCores`: The number of physical cores within the system +- `all_inputs_t`: A custom struct type containing all inputs required for the implemented core +- `nominal_outputs_t`: A custom struct type containing all normal output signals from the implemented core +- `apb_req_t/apb_resp_t`: APB types (see [apb](https://github.com/pulp-platform/apb)) to access configuration registers + +The following parameters are optional for custom configurations: +- `DMRSupported`: Enables support for DMR mode (default: `1'b1`). +- `DMRFixed`: Enforces permanent DMR mode. Cannot be used with `TMRSupported` or `TMRFixed` (default: `1'b0`). +- `TMRSupported`: Enables support for TMR mode (default: `1'b1`). +- `TMRFixed`: Enforces permanent TMR mode. Cannot be used with `DMRSupported` or `DMRFixed` (default: `1'b0`). +- `InterleaveGrps`: Uses interleaved cores for groups instead of sequential cores for groups (e.g., for 6 cores TMR, interleaved groups 0,2,4 and 1,3,5 together vs. sequential groups 0,1,2 and 3,4,5 together) (default: `1'b1`). +- `DefaultNominalOutputs`: Sets a custom default value the core outputs should have towards the system when disabled (i.e., part of a DMR/TMR group) (default: `'{default: '0}`). +- `SeparateData`: Have separate error signalling for data buses, disabling error notification when the bus is disabled (default: `1'b0`). Requires `NumBusVoters` and `bus_outputs_t` to be set. +- `bus_outputs_t`: A custom struct type containing output signals from the implemented core for a separated bus (default: `logic`). +- `DefaultBusOutputs`: Sets a custom default value the bus outptus should have towards the system when disabled (i.e., part of a DMR/TMR group) (default: `'{default: '0}`). +- `RapidRecovery`: Enables the *rapid recovery* feature. Requires `RfAddrWidth`, `SysDataWidth`, `core_backup_t`, and `rapid_recovery_t` to be set. Please check the HMR paper and the code for more information (default: `1'b0`). + +When using a non-standard configuration, it may be beneficial to regenerate the configuration registers with the desired values. The `Makefile` sets up a target for this with variables to configure: + +```sh +make gen_HMR HMR_NUM_CORES=[12|your desired core number] HMR_DMR_AVAILABLE=[1|your DMRSupported/Fixed config] HMR_TMR_AVAILABLE=[1|your TMRSupported/Fixed config] +``` + +#### Signals + +The following signals are required for baseline functionality: +- `clk_i`: The clock. +- `rst_ni`: The reset. +- `apb_req_i`: An APB request struct input (see [apb](https://github.com/pulp-platform/apb)). +- `apb_resp_o`: An APB response struct output (see [apb](https://github.com/pulp-platform/apb)). + +All signals with a `sys_` prefix connect to the system: +- `sys_bootaddress_i`: Default boot address (required for *checkpoint* feature in DMR, otherwise can be tied to `'0`). +- `sys_inputs_i`: All inputs to the cores from the system. +- `sys_nominal_outputs_o`: All normal outputs from the cores to the system. +- `sys_bus_outputs_o`: Bus outputs from the system. Can be left unconnected if `SeparateData` is disabled. +- `sys_fetch_en_i`: Allows configuration switching prior to coer startup. +- `enable_bus_vote_i`: Signals bus outputs are enabled. Can be tied to `'0` if `SeparateData` is disabled. + +All signals with a `core_` prefix connect to the core: +- `core_bootaddress_o`: Connect to the cores' boot address input signal (if *checkpoint* feature in DMR is desired, otherwise can be unconnected). +- `core_setback_o`: Reset signal to the processor cores (may need FF if aynchronous reset is used internally). +- `core_inputs_o`: All inputs to the cores. +- `core_nominal_output_i`: All normal outputs from the cores. +- `core_bus_outputs_i`: Bus outputs from the cores. Can be tied to `'0` if `SeparateData` is disabled. + +Both DMR and TMR feature some indicator signals: +- `?mr_failure_o`: Indicates an unrecoverable mismatch detected. +- `tmr_error_o`: Indicates a mismatch of a single core. +- `?mr_resynch_req_o`: Interrupt to cores to trigger software resynchronization routine. +- `?mr_sw_synch_req_o`: Interrupt to cores to trigger a software routine to synchronize independent cores. Can be left unconnected for ?MRFixed configurations. +- `?mr_cores_synch_i`: Signal indicating independent cores for a group are synchronized and ready to lock together. +- `redundancy_enable_o`: Signal indicating any redundancy currently is enabled. + +To support the *rapid recovery* feature, additional signals are required connecting to a rapid recovery capable core. Please check the HMR paper and the code for more information. If unused, these signals can be left unconnected (outputs) or tied to '0 (inputs). + +### Citing + +If you are using HMR in your academic work you can cite us: +```BibTeX +@article{10.1145/3635161, +author = {Rogenmoser, Michael and Tortorella, Yvan and Rossi, Davide and Conti, Francesco and Benini, Luca}, +title = {Hybrid Modular Redundancy: Exploring Modular Redundancy Approaches in RISC-V Multi-core Computing Clusters for Reliable Processing in Space}, +year = {2025}, +issue_date = {January 2025}, +publisher = {Association for Computing Machinery}, +address = {New York, NY, USA}, +volume = {9}, +number = {1}, +issn = {2378-962X}, +url = {https://doi.org/10.1145/3635161}, +doi = {10.1145/3635161}, +abstract = {Space Cyber-Physical Systems such as spacecraft and satellites strongly rely on the reliability of onboard computers to guarantee the success of their missions. Relying solely on radiation-hardened technologies is extremely expensive, and developing inflexible architectural and microarchitectural modifications to introduce modular redundancy within a system leads to significant area increase and performance degradation. To mitigate the overheads of traditional radiation hardening and modular redundancy approaches, we present a novel Hybrid Modular Redundancy approach, a redundancy scheme that features a cluster of RISC-V processors with a flexible on-demand dual-core and triple-core lockstep grouping of computing cores with runtime split-lock capabilities. Further, we propose two recovery approaches, software-based and hardware-based, trading off performance and area overhead. Running at 430 MHz, our fault-tolerant cluster achieves up to 1,160 MOPS on a matrix multiplication benchmark when configured in non-redundant mode and 617 and 414 MOPS in dual and triple mode, respectively. A software-based recovery in triple mode requires 363 clock cycles and occupies 0.612 mm2, representing a 1.3\% area overhead over a non-redundant 12-core RISC-V cluster. As a high-performance alternative, a new hardware-based method provides rapid fault recovery in just 24 clock cycles and occupies 0.660 mm2, namely, ∼9.4\% area overhead over the baseline non-redundant RISC-V cluster. The cluster is also enhanced with split-lock capabilities to enter one of the available redundant modes with minimum performance loss, allowing execution of a mission-critical portion of code when in independent mode, or a performance section when in a reliability mode, with <400 clock cycles overhead for entry and exit. The proposed system is the first to integrate these functionalities on an open-source RISC-V-based compute device, enabling finely tunable reliability versus performance trade-offs.}, +journal = {ACM Trans. Cyber-Phys. Syst.}, +month = jan, +articleno = {8}, +numpages = {29}, +keywords = {RISC-V, adaptive fault tolerance, space vehicle computer, reliable computing} +} +``` + ## On-Demand Redundancy Grouping (ODRG_unit) +> [!NOTE] +> This module has been superceeded by HMR above. ODRG functionality is supported within certain configurations of HMR. + The `ODRG_unit` is designed as a configurable bridge between three ibex cores, allowing for independent operation or lock-step operation with majority voting, triggering an interrupt in case a mismatch is detected. It uses lowrisc's reggen tool to generate the required configuration registers. ### Testing @@ -13,8 +111,8 @@ If you are using ODRG in your academic work you can cite us: ```BibTeX @INPROCEEDINGS{9912026, author={Rogenmoser, Michael and Wistoff, Nils and Vogel, Pirmin and Gürkaynak, Frank and Benini, Luca}, - booktitle={2022 IEEE Computer Society Annual Symposium on VLSI (ISVLSI)}, - title={On-Demand Redundancy Grouping: Selectable Soft-Error Tolerance for a Multicore Cluster}, + booktitle={2022 IEEE Computer Society Annual Symposium on VLSI (ISVLSI)}, + title={On-Demand Redundancy Grouping: Selectable Soft-Error Tolerance for a Multicore Cluster}, year={2022}, volume={}, number={}, diff --git a/requirements.txt b/requirements.txt index c87c92a8..deb228b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ hjson mako pyyaml tabulate +peakrdl +peakrdl-rawheader @ git+https://github.com/micprog/PeakRDL-rawheader.git diff --git a/rtl/HMR/HMR_core_regs.hjson b/rtl/HMR/HMR_core_regs.hjson deleted file mode 100644 index c55f5ede..00000000 --- a/rtl/HMR/HMR_core_regs.hjson +++ /dev/null @@ -1,60 +0,0 @@ -{ name: "HMR_core_regs", - clock_primary: "clk_i", - reset_primary: "rst_ni", - bus_interfaces: [ - { protocol: "reg_iface", - direction: "device" - } - ], - - regwidth: "32", - registers: [ - { name: "Current_mode", - desc: "Value to determine wich redundancy mode the core with that ID is in.", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "0", - name: "independent", - resval: "1", - desc: "" - }, - { bits: "1", - name: "dual", - resval: "0", - desc: "" - }, - { bits: "2", - name: "triple", - resval: "0", - desc: "" - } - ] - - }, - { name: "mismatches", - desc: "Mismatches of the core", - swaccess: "rw0c", - hwaccess: "hrw", - fields: [ - { bits: "31:0", - name: "mismatches", - desc: "mismatch counter of the core" - } - ] - }, - { name: "sp_store", - desc: "Stack Pointer storage register", - swaccess: "rw", - hwaccess: "hro", - hwqe: "true", - fields: [ - { bits: "31:0", - name: "SP", - desc: "Stack Pointer" - } - ] - } - ] -} diff --git a/rtl/HMR/HMR_dmr_regs.hjson b/rtl/HMR/HMR_dmr_regs.hjson deleted file mode 100644 index 12e16d44..00000000 --- a/rtl/HMR/HMR_dmr_regs.hjson +++ /dev/null @@ -1,56 +0,0 @@ -{ - name: "HMR_dmr_regs", - clock_primary: "clk_i", - reset_primary: "rst_ni", - bus_interfaces: [ - { protocol: "reg_iface", - direction: "device" - } - ], - - regwidth: "32", - - registers: [ - { name: "DMR_enable", - desc: "DMR configuration enable.", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - resval: "0", - fields: [ - { bits: "0", - name: "DMR_enable", - desc: "DMR configuration enable." - } - ] - }, - { name: "DMR_config", - desc: "DMR configuration bits." - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - fields: [ - { bits: "0", - name: "rapid_recovery", - desc: "Enable rapid recovery using an additional register file." - }, - { bits: "1" - name: "force_recovery", - desc: "Forces recovery routine (if rapid_recovery is available)." - } - ] - }, - { name: "checkpoint_addr", - desc: "Address for the last checkpoint.", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - fields: [ - { bits: "31:0", - name: "checkpoint_addr", - desc: "Address for the last checkpoint." - } - ] - } - ] -} diff --git a/rtl/HMR/HMR_regs.hjson b/rtl/HMR/HMR_regs.hjson deleted file mode 100644 index c6a10cbc..00000000 --- a/rtl/HMR/HMR_regs.hjson +++ /dev/null @@ -1,141 +0,0 @@ -{ - name: "HMR_registers", - clock_primary: "clk_i", - reset_primary: "rst_ni", - bus_interfaces: [ - { protocol: "reg_iface", - direction: "device" - } - ], - - regwidth: "32", - - param_list: [ - { name: "NumCores", - default: "12" # Supports up to 16 cores - }, - { name: "NumDMRGroups", - default: "6" - }, - { name: "NumTMRGroups", - default: "4" - } - ], - - registers: [ - { name: "avail_config", - desc: "Available Configurations from implemented hardware.", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "0", - name: "independent", - desc: "Independent mode is available." - }, - { bits: "1", - name: "dual", - desc: "Dual Modular Redundancy (DMR) is available." - }, - { bits: "2", - name: "triple", - desc: "Triple Modular Redundancy (TMR) is available." - }, - { bits: "8", - name: "rapid_recovery", - desc: "Rapid Recovery is available." - } - ] - }, - { name: "cores_en", - desc: "Enabled cores, based on the configuration. Can be used for barriers.", - swaccess: "ro", - hwaccess: "hwo", - hwext: "true", - fields: [ - { bits: "NumCores-1:0" - name: "cores_en", - desc: "Enabled cores." - } - ] - }, - { name: "DMR_enable", - desc: "DMR configuration enable, on bit per DMR group.", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - hwext: "true", - resval: "0", - fields: [ - { bits: "NumDMRGroups-1:0", - name: "DMR_enable", - desc: "DMR configuration enable." - } - ] - }, - { name: "TMR_enable", - desc: "TMR configuration enable, one bit per TMR group.", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - hwext: "true", - resval: "0", - fields: [ - { bits: "NumTMRGroups-1:0", - name: "TMR_enable", - desc: "TMR configuration enable." - } - ] - }, - { name: "DMR_config", - desc: "DMR configuration bits." - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - hwext: "true", - fields: [ - { bits: "0", - name: "rapid_recovery", - desc: "Enable rapid recovery using an additional register file." - }, - { bits: "1" - name: "force_recovery", - desc: "Forces recovery routine (if rapid_recovery is available)." - } - ] - }, - { name: "TMR_config", - desc: "TMR configuration bits." - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - hwext: "true", - fields: [ - { bits: "0", - name: "delay_resynch", - resval: "0", - desc: "Enable wait-for-restoration" - }, - { bits: "1", - name: "setback", - resval: "1", - desc: "Enable setback (synchronous reset) during re-synch." - }, - { bits: "2", - name: "reload_setback", - resval: "1", - desc: "Enable setback on mismatch during reload section of re-synch (only possible with `setback`)" - }, - { bits: "3", - name: "rapid_recovery", - desc: "Enable rapid recovery using additional register file." - }, - { bits: "4", - name: "force_resynch", - resval: "0", - desc: "Forces a resynchronization routine" - } - ] - } - ] -} diff --git a/rtl/HMR/HMR_tmr_regs.hjson b/rtl/HMR/HMR_tmr_regs.hjson deleted file mode 100644 index 8d6dab90..00000000 --- a/rtl/HMR/HMR_tmr_regs.hjson +++ /dev/null @@ -1,60 +0,0 @@ -{ - name: "HMR_tmr_regs", - clock_primary: "clk_i", - reset_primary: "rst_ni", - bus_interfaces: [ - { protocol: "reg_iface", - direction: "device" - } - ], - - regwidth: "32", - - registers: [ - { name: "TMR_enable", - desc: "TMR configuration enable.", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - resval: "0", - fields: [ - { bits: "0", - name: "TMR_enable", - desc: "TMR configuration enable." - } - ] - }, - { name: "TMR_config", - desc: "TMR configuration bits." - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - fields: [ - { bits: "0", - name: "delay_resynch", - resval: "0", - desc: "Enable wait-for-restoration" - }, - { bits: "1", - name: "setback", - resval: "1", - desc: "Enable setback (synchronous reset) during re-synch." - }, - { bits: "2", - name: "reload_setback", - resval: "1", - desc: "Enable setback on mismatch during reload section of re-synch (only possible with `setback`)" - }, - { bits: "3", - name: "rapid_recovery", - desc: "Enable rapid recovery using additional register file." - }, - { bits: "4", - name: "force_resynch", - resval: "0", - desc: "Forces a resynchronization routine" - } - ] - } - ] -} diff --git a/rtl/HMR/doc.html b/rtl/HMR/doc.html deleted file mode 100644 index ab3898ef..00000000 --- a/rtl/HMR/doc.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - -
-
HMR_registers.avail_config @ 0x0
-

Available Configurations from implemented hardware.

-
Reset default = 0x0, mask 0x107
-
- - - - - - - -
31302928272625242322212019181716
 
1514131211109876543210
 rapid_recovery tripledualindependent
BitsTypeResetNameDescription
0roxindependent

Independent mode is available.

1roxdual

Dual Modular Redundancy (DMR) is available.

2roxtriple

Triple Modular Redundancy (TMR) is available.

7:3Reserved
8roxrapid_recovery

Rapid Recovery is available.

-
- - - - - -
-
HMR_registers.cores_en @ 0x4
-

Enabled cores, based on the configuration. Can be used for barriers.

-
Reset default = 0x0, mask 0xfff
-
- - - -
31302928272625242322212019181716
 
1514131211109876543210
 cores_en
BitsTypeResetNameDescription
11:0roxcores_en

Enabled cores.

-
- - - - - -
-
HMR_registers.DMR_enable @ 0x8
-

DMR configuration enable, on bit per DMR group.

-
Reset default = 0x0, mask 0x3f
-
- - - -
31302928272625242322212019181716
 
1514131211109876543210
 DMR_enable
BitsTypeResetNameDescription
5:0rw0x0DMR_enable

DMR configuration enable.

-
- - - - - -
-
HMR_registers.TMR_enable @ 0xc
-

TMR configuration enable, one bit per TMR group.

-
Reset default = 0x0, mask 0xf
-
- - - -
31302928272625242322212019181716
 
1514131211109876543210
 TMR_enable
BitsTypeResetNameDescription
3:0rw0x0TMR_enable

TMR configuration enable.

-
- - - - - -
-
HMR_registers.DMR_config @ 0x10
-

DMR configuration bits.

-
Reset default = 0x0, mask 0x3
-
- - - - -
31302928272625242322212019181716
 
1514131211109876543210
 force_recoveryrapid_recovery
BitsTypeResetNameDescription
0rwxrapid_recovery

Enable rapid recovery using an additional register file.

1rwxforce_recovery

Forces recovery routine (if rapid_recovery is available).

-
- - - - - -
-
HMR_registers.TMR_config @ 0x14
-

TMR configuration bits.

-
Reset default = 0x6, mask 0x1f
-
- - - - - - - -
31302928272625242322212019181716
 
1514131211109876543210
 force_resynchrapid_recoveryreload_setbacksetbackdelay_resynch
BitsTypeResetNameDescription
0rw0x0delay_resynch

Enable wait-for-restoration

1rw0x1setback

Enable setback (synchronous reset) during re-synch.

2rw0x1reload_setback

Enable setback on mismatch during reload section of re-synch (only possible with setback)

3rwxrapid_recovery

Enable rapid recovery using additional register file.

4rw0x0force_resynch

Forces a resynchronization routine

-
diff --git a/rtl/HMR/doc.md b/rtl/HMR/doc.md deleted file mode 100644 index 892ab665..00000000 --- a/rtl/HMR/doc.md +++ /dev/null @@ -1,312 +0,0 @@ - - - - -The tables describe each key and the type of the value. The following -types are used: - -Type | Description ----- | ----------- -int | integer (binary 0b, octal 0o, decimal, hex 0x) -xint | x for undefined otherwise int -bitrange | bit number as decimal integer, or bit-range as decimal integers msb:lsb -list | comma separated list enclosed in `[]` -name list | comma separated list enclosed in `[]` of one or more groups that have just name and dscr keys. e.g. `{ name: "name", desc: "description"}` -name list+ | name list that optionally contains a width -parameter list | parameter list having default value optionally -group | comma separated group of key:value enclosed in `{}` -list of group | comma separated group of key:value enclosed in `{}` the second entry of the list is the sub group format -string | string, typically short -text | string, may be multi-line enclosed in `'''` may use `**bold**`, `*italic*` or `!!Reg` markup -tuple | tuple enclosed in () -python int | Native Python type int (generated) -python Bool | Native Python type Bool (generated) -python list | Native Python type list (generated) -python enum | Native Python type enum (generated) - - -Register fields are tagged using the swaccess key to describe the -permitted access and side-effects. This key must have one of these -values: - - -Key | Description ---- | ----------- -none | No access -ro | Read Only -rc | Read Only, reading clears -rw | Read/Write -r0w1c | Read zero, Write with 1 clears -rw1s | Read, Write with 1 sets -rw1c | Read, Write with 1 clears -rw0c | Read, Write with 0 clears -wo | Write Only - - -Register fields are tagged using the hwaccess key to describe the -permitted access from hardware logic and side-effects. This key must -have one of these values: - - -Key | Description ---- | ----------- -hro | Read Only -hrw | Read/Write -hwo | Write Only -none | No Access Needed - - -The top level of the JSON is a group containing the following keys: - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -name | required | string | name of the component -clock_primary | required | string | name of the primary clock -bus_interfaces | required | list | bus interfaces for the device -registers | required | list | list of register definition groups and offset control groups -alert_list | optional | name list+ | list of peripheral alerts -available_inout_list | optional | name list+ | list of available peripheral inouts -available_input_list | optional | name list+ | list of available peripheral inputs -available_output_list | optional | name list+ | list of available peripheral outputs -hier_path | additional hierarchy path before the reg block instance -interrupt_list | optional | name list+ | list of peripheral interrupts -inter_signal_list | optional | list | list of inter-module signals -no_auto_alert_regs | optional | string | Set to true to suppress automatic generation of alert test registers. Defaults to true if no alert_list is present. Otherwise this defaults to false. -no_auto_intr_regs | optional | string | Set to true to suppress automatic generation of interrupt registers. Defaults to true if no interrupt_list is present. Otherwise this defaults to false. -other_clock_list | optional | list | list of other chip clocks needed -other_reset_list | optional | list | list of other resets -param_list | optional | parameter list | list of parameters of the IP -regwidth | optional | int | width of registers in bits (default 32) -reset_primary | optional | string | primary reset used by the module -reset_request_list | optional | list | list of signals requesting reset -scan | optional | python Bool | Indicates the module have `scanmode_i` -scan_reset | optional | python Bool | Indicates the module have `scan_rst_ni` -scan_en | optional | python Bool | Indicates the module has `scan_en_i` -SPDX-License-Identifier | optional | string | License ientifier (if using pure json) Only use this if unable to put this information in a comment at the top of the file. -wakeup_list | optional | name list+ | list of peripheral wakeups - -The basic structure of a register definition file is thus: - -```hjson -{ - name: "GP", - regwidth: "32", - registers: [ - // register definitions... - ] -} - -``` - - - -The list of registers includes register definition groups containing the following keys: - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -name | required | string | name of the register -desc | required | text | description of the register -fields | required | list | list of register field description groups -swaccess | optional | string | software access permission to use for fields that don't specify swaccess -hwaccess | optional | string | hardware access permission to use for fields that don't specify hwaccess -hwext | optional | string | 'true' if the register is stored outside of the register module -hwqe | optional | string | 'true' if hardware uses 'q' enable signal, which is latched signal of software write pulse. -hwre | optional | string | 'true' if hardware uses 're' signal, which is latched signal of software read pulse. -regwen | optional | string | if register is write-protected by another register, that register name should be given here. empty-string for no register write protection -resval | optional | int | reset value of full register (default 0) -tags | optional | string | tags for the register, following the format 'tag_name:item1:item2...' -shadowed | optional | string | 'true' if the register is shadowed -update_err_alert | optional | string | alert that will be triggered if this shadowed register has update error -storage_err_alert | optional | string | alert that will be triggered if this shadowed register has storage error - - -The basic register definition group will follow this pattern: - -```hjson - { name: "REGA", - desc: "Description of register", - swaccess: "rw", - resval: "42", - fields: [ - // bit field definitions... - ] - } -``` - -The name and brief description are required. If the swaccess key is -provided it describes the access pattern that will be used by all -bitfields in the register that do not override with their own swaccess -key. This is a useful shortcut because in most cases a register will -have the same access restrictions for all fields. The reset value of -the register may also be provided here or in the individual fields. If -it is provided in both places then they must match, if it is provided -in neither place then the reset value defaults to zero for all except -write-only fields when it defaults to x. - - - -In the fields list each field definition is a group itself containing the following keys: - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -bits | required | bitrange | bit or bit range (msb:lsb) -name | optional | string | name of the field -desc | optional | text | description of field (required if the field has a name) -swaccess | optional | string | software access permission, copied from register if not provided in field. (Tool adds if not provided.) -hwaccess | optional | string | hardware access permission, copied from register if not prvided in field. (Tool adds if not provided.) -resval | optional | xint | reset value, comes from register resval if not provided in field. Zero if neither are provided and the field is readable, x if neither are provided and the field is wo. Must match if both are provided. -enum | optional | list | list of permitted enumeration groups -tags | optional | string | tags for the field, followed by the format 'tag_name:item1:item2...' - - -Field names should be relatively short because they will be used -frequently (and need to fit in the register layout picture!) The field -description is expected to be longer and will most likely make use of -the Hjson ability to include multi-line strings. An example with three -fields: - -```hjson - fields: [ - { bits: "15:0", - name: "RXS", - desc: ''' - Last 16 oversampled values of RX. These are captured at 16x the baud - rate clock. This is a shift register with the most recent bit in - bit 0 and the oldest in bit 15. Only valid when ENRXS is set. - ''' - } - { bits: "16", - name: "ENRXS", - desc: ''' - If this bit is set the receive oversampled data is collected - in the RXS field. - ''' - } - {bits: "20:19", name: "TXILVL", - desc: "Trigger level for TX interrupts", - resval: "2", - enum: [ - { value: "0", name: "txlvl1", desc: "1 character" }, - { value: "1", name: "txlvl4", desc: "4 characters" }, - { value: "2", name: "txlvl8", desc: "8 characters" }, - { value: "3", name: "txlvl16", desc: "16 characters" } - ] - } - ] -``` - -In all of these the swaccess parameter is inherited from the register -level, and will be added so this key is always available to the -backend. The RXS and ENRXS will default to zero reset value (unless -something different is provided for the register) and will have the -key added, but TXILVL expicitly sets its reset value as 2. - -The missing bits 17 and 18 will be treated as reserved by the tool, as -will any bits between 21 and the maximum in the register. - -The TXILVL is an example using an enumeration to specify all valid -values for the field. In this case all possible values are described, -if the list is incomplete then the field is marked with the rsvdenum -key so the backend can take appropriate action. (If the enum field is -more than 7 bits then the checking is not done.) - - - -Definitions in an enumeration group contain: - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -name | required | string | name of the member of the enum -desc | required | text | description when field has this value -value | required | int | value of this member of the enum - - -The list of registers may include single entry groups to control the offset, open a window or generate registers: - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -reserved | optional | int | number of registers to reserve space for -skipto | optional | int | set next register offset to value -window | optional | group | group defining an address range for something other than standard registers -multireg | optional | group | group defining registers generated from a base instance. - - - - -Registers can protect themselves from software writes by using the -register attribute regwen. When not an emptry string (the default -value), regwen indicates that another register must be true in order -to allow writes to this register. This is useful for the prevention -of software modification. The register-enable register (call it -REGWEN) must be one bit in width, and should default to 1 and be rw1c -for preferred security control. This allows all writes to proceed -until at some point software disables future modifications by clearing -REGWEN. An error is reported if REGWEN does not exist, contains more -than one bit, is not `rw1c` or does not default to 1. One REGWEN can -protect multiple registers. The REGWEN register must precede those -registers that refer to it in the .hjson register list. An example: - -```hjson - { name: "REGWEN", - desc: "Register write enable for a bank of registers", - swaccess: "rw1c", - fields: [ { bits: "0", resval: "1" } ] - } - { name: "REGA", - swaccess: "rw", - regwen: "REGWEN", - ... - } - { name: "REGB", - swaccess: "rw", - regwen: "REGWEN", - ... - } -``` - - -A window defines an open region of the register space that can be used -for things that are not registers (for example access to a buffer ram). - - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -name | required | string | name of the window -desc | required | text | description of the window -items | required | int | size in fieldaccess width words of the window -swaccess | required | string | software access permitted -data-intg-passthru | optional | string | True if the window has data integrity pass through. Defaults to false if not present. -byte-write | optional | string | True if byte writes are supported. Defaults to false if not present. -validbits | optional | int | Number of valid data bits within regwidth sized word. Defaults to regwidth. If smaller than the regwidth then in each word of the window bits [regwidth-1:validbits] are unused and bits [validbits-1:0] are valid. -unusual | optional | string | True if window has unusual parameters (set to prevent Unusual: errors).Defaults to false if not present. - - -The multireg expands on the register required fields and will generate -a list of the generated registers (that contain all required and -generated keys for an actual register). - - -Key | Kind | Type | Description of Value ---- | ---- | ---- | -------------------- -name | required | string | base name of the registers -desc | required | text | description of the registers -count | required | string | number of instances to generate. This field can be integer or string matching from param_list. -cname | required | string | base name for each instance, mostly useful for referring to instance in messages. -fields | required | list | list of register field description groups. Describes bit positions used for base instance. -swaccess | optional | string | software access permission to use for fields that don't specify swaccess -hwaccess | optional | string | hardware access permission to use for fields that don't specify hwaccess -hwext | optional | string | 'true' if the register is stored outside of the register module -hwqe | optional | string | 'true' if hardware uses 'q' enable signal, which is latched signal of software write pulse. -hwre | optional | string | 'true' if hardware uses 're' signal, which is latched signal of software read pulse. -regwen | optional | string | if register is write-protected by another register, that register name should be given here. empty-string for no register write protection -resval | optional | int | reset value of full register (default 0) -tags | optional | string | tags for the register, following the format 'tag_name:item1:item2...' -shadowed | optional | string | 'true' if the register is shadowed -update_err_alert | optional | string | alert that will be triggered if this shadowed register has update error -storage_err_alert | optional | string | alert that will be triggered if this shadowed register has storage error -regwen_multi | optional | python Bool | If true, regwen term increments along with current multireg count. -compact | optional | python Bool | If true, allow multireg compacting.If false, do not compact. - - -(end of output generated by `regtool.py --doc`) - diff --git a/rtl/HMR/hmr_all.rdl b/rtl/HMR/hmr_all.rdl new file mode 100644 index 00000000..a9ed329d --- /dev/null +++ b/rtl/HMR/hmr_all.rdl @@ -0,0 +1,29 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +addrmap hmr_all #( + longint unsigned NumCores = 12, + longint unsigned NumDMRGroups = 6, + longint unsigned NumTMRGroups = 4, + bit DMRAvailable = 1, + bit TMRAvailable = 1 +) { + `include "hmr_regs.rdl" + `include "hmr_core_regs.rdl" + `include "hmr_dmr_regs.rdl" + `include "hmr_tmr_regs.rdl" + + hmr hmr @0x0; + hmr_core hmr_core[NumCores] @0x100 += 0x10; + hmr_dmr hmr_dmr[NumDMRGroups] @0x200 += 0x10; + hmr_tmr hmr_tmr[NumTMRGroups] @0x300 += 0x10; + hmr_dmr->ispresent = DMRAvailable; + hmr_tmr->ispresent = TMRAvailable; +}; diff --git a/rtl/HMR/hmr_core_regs.rdl b/rtl/HMR/hmr_core_regs.rdl new file mode 100644 index 00000000..d2527d0b --- /dev/null +++ b/rtl/HMR/hmr_core_regs.rdl @@ -0,0 +1,63 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +addrmap hmr_core { + reg current_mode { + name = "current_mode"; + desc = "Value to determine wich redundancy mode the core with that ID is in."; + field { + name = "independent"; + desc = "1 if in independent mode"; + sw = r; + hw = rw; + } independent[0:0] = 0x1; + field { + name = "dual"; + desc = "1 if in dual/DMR mode"; + sw = r; + hw = rw; + } dual[1:1] = 0x0; + field { + name = "triple"; + desc = "1 if in triple/TMR mode"; + sw = r; + hw = rw; + } triple[2:2] = 0x0; + }; + + reg mismatches { + name = "mismatches"; + desc = "Number of mismatches detected in the core."; + field { + name = "mismatches"; + desc = "Number of mismatches detected in the core."; + sw = rw; + hw = rw; + woclr; + we = true; + } mismatches[31:0] = 0x0; + }; + + reg sp_store { + name = "sp_store"; + desc = "Stack pointer storage register."; + field { + name = "sp_store"; + desc = "Stack Pointer"; + sw = rw; + hw = r; + swmod = true; + } sp_store[31:0] = 0x0; + }; + + external current_mode current_mode; + mismatches mismatches; + sp_store sp_store; +}; diff --git a/rtl/HMR/hmr_core_regs_reg_pkg.sv b/rtl/HMR/hmr_core_regs_reg_pkg.sv index 602bd91a..3dc97194 100644 --- a/rtl/HMR/hmr_core_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_core_regs_reg_pkg.sv @@ -1,80 +1,63 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock package hmr_core_regs_reg_pkg; - // Address widths within the block - parameter int BlockAw = 4; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic [31:0] q; - } hmr_core_regs_reg2hw_mismatches_reg_t; - - typedef struct packed { - logic [31:0] q; - logic qe; - } hmr_core_regs_reg2hw_sp_store_reg_t; - - typedef struct packed { - struct packed { - logic d; - } independent; - struct packed { - logic d; - } dual; - struct packed { - logic d; - } triple; - } hmr_core_regs_hw2reg_current_mode_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } hmr_core_regs_hw2reg_mismatches_reg_t; - - // Register -> HW type - typedef struct packed { - hmr_core_regs_reg2hw_mismatches_reg_t mismatches; // [64:33] - hmr_core_regs_reg2hw_sp_store_reg_t sp_store; // [32:0] - } hmr_core_regs_reg2hw_t; - - // HW -> register type - typedef struct packed { - hmr_core_regs_hw2reg_current_mode_reg_t current_mode; // [35:33] - hmr_core_regs_hw2reg_mismatches_reg_t mismatches; // [32:0] - } hmr_core_regs_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] HMR_CORE_REGS_CURRENT_MODE_OFFSET = 4'h 0; - parameter logic [BlockAw-1:0] HMR_CORE_REGS_MISMATCHES_OFFSET = 4'h 4; - parameter logic [BlockAw-1:0] HMR_CORE_REGS_SP_STORE_OFFSET = 4'h 8; - - // Reset values for hwext registers and their fields - parameter logic [2:0] HMR_CORE_REGS_CURRENT_MODE_RESVAL = 3'h 1; - parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_INDEPENDENT_RESVAL = 1'h 1; - parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_DUAL_RESVAL = 1'h 0; - parameter logic [0:0] HMR_CORE_REGS_CURRENT_MODE_TRIPLE_RESVAL = 1'h 0; - - // Register index - typedef enum int { - HMR_CORE_REGS_CURRENT_MODE, - HMR_CORE_REGS_MISMATCHES, - HMR_CORE_REGS_SP_STORE - } hmr_core_regs_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] HMR_CORE_REGS_PERMIT [3] = '{ - 4'b 0001, // index[0] HMR_CORE_REGS_CURRENT_MODE - 4'b 1111, // index[1] HMR_CORE_REGS_MISMATCHES - 4'b 1111 // index[2] HMR_CORE_REGS_SP_STORE - }; - + localparam HMR_CORE_REGS_REG_TOP_DATA_WIDTH = 32; + localparam HMR_CORE_REGS_REG_TOP_MIN_ADDR_WIDTH = 4; + localparam HMR_CORE_REGS_REG_TOP_SIZE = 'hc; + + typedef struct packed { + logic [28:0] _reserved_31_3; + logic triple; + logic dual; + logic independent; + } hmr_core__current_mode__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr_core__current_mode__external__fields__in_t rd_data; + } hmr_core__current_mode__external__in_t; + + typedef struct { + logic [31:0] next; + logic we; + } hmr_core__mismatches__mismatches__in_t; + + typedef struct { + hmr_core__mismatches__mismatches__in_t mismatches; + } hmr_core__mismatches__in_t; + + typedef struct { + hmr_core__current_mode__external__in_t current_mode; + hmr_core__mismatches__in_t mismatches; + } hmr_core__in_t; + + typedef struct { + logic req; + logic req_is_wr; + } hmr_core__current_mode__external__out_t; + + typedef struct { + logic [31:0] value; + } hmr_core__mismatches__mismatches__out_t; + + typedef struct { + hmr_core__mismatches__mismatches__out_t mismatches; + } hmr_core__mismatches__out_t; + + typedef struct { + logic [31:0] value; + logic swmod; + } hmr_core__sp_store__sp_store__out_t; + + typedef struct { + hmr_core__sp_store__sp_store__out_t sp_store; + } hmr_core__sp_store__out_t; + + typedef struct { + hmr_core__current_mode__external__out_t current_mode; + hmr_core__mismatches__out_t mismatches; + hmr_core__sp_store__out_t sp_store; + } hmr_core__out_t; endpackage - diff --git a/rtl/HMR/hmr_core_regs_reg_top.sv b/rtl/HMR/hmr_core_regs_reg_top.sv index d9cf8ceb..47a58eac 100644 --- a/rtl/HMR/hmr_core_regs_reg_top.sv +++ b/rtl/HMR/hmr_core_regs_reg_top.sv @@ -1,306 +1,277 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module hmr_core_regs_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 4 -) ( - 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 hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t reg2hw, // Write - input hmr_core_regs_reg_pkg::hmr_core_regs_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import hmr_core_regs_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-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; - 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 current_mode_independent_qs; - logic current_mode_independent_re; - logic current_mode_dual_qs; - logic current_mode_dual_re; - logic current_mode_triple_qs; - logic current_mode_triple_re; - logic [31:0] mismatches_qs; - logic [31:0] mismatches_wd; - logic mismatches_we; - logic [31:0] sp_store_qs; - logic [31:0] sp_store_wd; - logic sp_store_we; - - // Register instances - // R[current_mode]: V(True) - - // F[independent]: 0:0 - prim_subreg_ext #( - .DW (1) - ) u_current_mode_independent ( - .re (current_mode_independent_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.current_mode.independent.d), - .qre (), - .qe (), - .q (), - .qs (current_mode_independent_qs) - ); - - - // F[dual]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_current_mode_dual ( - .re (current_mode_dual_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.current_mode.dual.d), - .qre (), - .qe (), - .q (), - .qs (current_mode_dual_qs) - ); - - - // F[triple]: 2:2 - prim_subreg_ext #( - .DW (1) - ) u_current_mode_triple ( - .re (current_mode_triple_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.current_mode.triple.d), - .qre (), - .qe (), - .q (), - .qs (current_mode_triple_qs) - ); - - - // R[mismatches]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("W0C"), - .RESVAL (32'h0) - ) u_mismatches ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (mismatches_we), - .wd (mismatches_wd), - - // from internal hardware - .de (hw2reg.mismatches.de), - .d (hw2reg.mismatches.d ), - - // to internal hardware - .qe (), - .q (reg2hw.mismatches.q ), - - // to register interface (read) - .qs (mismatches_qs) - ); - - - // R[sp_store]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_sp_store ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (sp_store_we), - .wd (sp_store_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (reg2hw.sp_store.qe), - .q (reg2hw.sp_store.q ), - - // to register interface (read) - .qs (sp_store_qs) - ); - - - - - logic [2:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == HMR_CORE_REGS_CURRENT_MODE_OFFSET); - addr_hit[1] = (reg_addr == HMR_CORE_REGS_MISMATCHES_OFFSET); - addr_hit[2] = (reg_addr == HMR_CORE_REGS_SP_STORE_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] & (|(HMR_CORE_REGS_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(HMR_CORE_REGS_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(HMR_CORE_REGS_PERMIT[2] & ~reg_be))))); - end - - assign current_mode_independent_re = addr_hit[0] & reg_re & !reg_error; - - assign current_mode_dual_re = addr_hit[0] & reg_re & !reg_error; - - assign current_mode_triple_re = addr_hit[0] & reg_re & !reg_error; - - assign mismatches_we = addr_hit[1] & reg_we & !reg_error; - assign mismatches_wd = reg_wdata[31:0]; - - assign sp_store_we = addr_hit[2] & reg_we & !reg_error; - assign sp_store_wd = reg_wdata[31:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = current_mode_independent_qs; - reg_rdata_next[1] = current_mode_dual_qs; - reg_rdata_next[2] = current_mode_triple_qs; - end - - addr_hit[1]: begin - reg_rdata_next[31:0] = mismatches_qs; - end - - addr_hit[2]: begin - reg_rdata_next[31:0] = sp_store_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 - -module hmr_core_regs_reg_top_intf -#( - parameter int AW = 4, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t reg2hw, // Write - input hmr_core_regs_reg_pkg::hmr_core_regs_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) - - - - hmr_core_regs_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 - ); - +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module hmr_core_regs_reg_top ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [3:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + input hmr_core_regs_reg_pkg::hmr_core__in_t hwif_in, + output hmr_core_regs_reg_pkg::hmr_core__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [3:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[3:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + logic external_req; + logic external_pending; + logic external_wr_ack; + logic external_rd_ack; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + external_pending <= '0; + end else begin + if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1; + else if(external_wr_ack | external_rd_ack) external_pending <= '0; + `ifndef SYNTHESIS + assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req)) + else $error("An external wr_ack strobe was asserted when no external request was active"); + assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req)) + else $error("An external rd_ack strobe was asserted when no external request was active"); + `endif + end + end + + // Read & write latencies are balanced. Stalls not required + // except if external + assign cpuif_req_stall_rd = external_pending; + assign cpuif_req_stall_wr = external_pending; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic current_mode; + logic mismatches; + logic sp_store; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_strb_is_external; + + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + automatic logic is_external; + is_external = '0; + decoded_reg_strb.current_mode = cpuif_req_masked & (cpuif_addr == 4'h0); + is_external |= cpuif_req_masked & (cpuif_addr == 4'h0) & !cpuif_req_is_wr; + decoded_reg_strb.mismatches = cpuif_req_masked & (cpuif_addr == 4'h4); + decoded_reg_strb.sp_store = cpuif_req_masked & (cpuif_addr == 4'h8); + decoded_strb_is_external = is_external; + external_req = is_external; + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + typedef struct { + struct { + struct { + logic [31:0] next; + logic load_next; + } mismatches; + } mismatches; + struct { + struct { + logic [31:0] next; + logic load_next; + } sp_store; + } sp_store; + } field_combo_t; + field_combo_t field_combo; + + typedef struct { + struct { + struct { + logic [31:0] value; + } mismatches; + } mismatches; + struct { + struct { + logic [31:0] value; + } sp_store; + } sp_store; + } field_storage_t; + field_storage_t field_storage; + + + assign hwif_out.current_mode.req = !decoded_req_is_wr ? decoded_reg_strb.current_mode : '0; + assign hwif_out.current_mode.req_is_wr = decoded_req_is_wr; + // Field: hmr_core.mismatches.mismatches + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.mismatches.mismatches.value; + load_next_c = '0; + if(decoded_reg_strb.mismatches && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.mismatches.mismatches.value & ~(decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end else if(hwif_in.mismatches.mismatches.we) begin // HW Write - we + next_c = hwif_in.mismatches.mismatches.next; + load_next_c = '1; + end + field_combo.mismatches.mismatches.next = next_c; + field_combo.mismatches.mismatches.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.mismatches.mismatches.value <= 32'h0; + end else begin + if(field_combo.mismatches.mismatches.load_next) begin + field_storage.mismatches.mismatches.value <= field_combo.mismatches.mismatches.next; + end + end + end + assign hwif_out.mismatches.mismatches.value = field_storage.mismatches.mismatches.value; + // Field: hmr_core.sp_store.sp_store + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.sp_store.sp_store.value; + load_next_c = '0; + if(decoded_reg_strb.sp_store && decoded_req_is_wr) begin // SW write + next_c = (field_storage.sp_store.sp_store.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.sp_store.sp_store.next = next_c; + field_combo.sp_store.sp_store.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.sp_store.sp_store.value <= 32'h0; + end else begin + if(field_combo.sp_store.sp_store.load_next) begin + field_storage.sp_store.sp_store.value <= field_combo.sp_store.sp_store.next; + end + end + end + assign hwif_out.sp_store.sp_store.value = field_storage.sp_store.sp_store.value; + assign hwif_out.sp_store.sp_store.swmod = decoded_reg_strb.sp_store && decoded_req_is_wr && |(decoded_wr_biten[31:0]); + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + always_comb begin + automatic logic wr_ack; + wr_ack = '0; + + external_wr_ack = wr_ack; + end + assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external); + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + logic readback_external_rd_ack_c; + always_comb begin + automatic logic rd_ack; + rd_ack = '0; + rd_ack |= hwif_in.current_mode.rd_ack; + readback_external_rd_ack_c = rd_ack; + end + + logic readback_external_rd_ack; + + assign readback_external_rd_ack = readback_external_rd_ack_c; + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [31:0] readback_array[3]; + assign readback_array[0] = hwif_in.current_mode.rd_ack ? hwif_in.current_mode.rd_data : '0; + assign readback_array[1][31:0] = (decoded_reg_strb.mismatches && !decoded_req_is_wr) ? field_storage.mismatches.mismatches.value : '0; + assign readback_array[2][31:0] = (decoded_reg_strb.sp_store && !decoded_req_is_wr) ? field_storage.sp_store.sp_store.value : '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<3; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign external_rd_ack = readback_external_rd_ack; + assign cpuif_rd_ack = readback_done | readback_external_rd_ack; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; endmodule - - diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index ad74eab0..244aecd5 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -18,16 +18,16 @@ module hmr_dmr_ctrl parameter bit DMRFixed = 1'b0, parameter bit DefaultInDMR = DMRFixed ? 1'b1 : 1'b0, parameter bit RapidRecovery = 1'b0, - parameter type reg_req_t = logic, - parameter type reg_resp_t = logic + parameter type apb_req_t = logic, + parameter type apb_resp_t = logic ) ( input logic clk_i, input logic rst_ni, // input logic test_enable_i, // Register interface - input reg_req_t reg_req_i, - output reg_resp_t reg_resp_o, + input apb_req_t reg_req_i, + output apb_resp_t reg_resp_o, // CTRL from external (e.g. HMR ctrl regs) input logic dmr_enable_q_i, @@ -60,39 +60,45 @@ module hmr_dmr_ctrl typedef enum logic [2:0] {NON_DMR, DMR_RUN, DMR_RESTORE} dmr_mode_e; localparam dmr_mode_e DefaultDMRMode = DefaultInDMR || DMRFixed ? DMR_RUN : NON_DMR; - hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t dmr_reg2hw; - hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t dmr_hw2reg; + hmr_dmr_regs_reg_pkg::hmr_dmr__out_t dmr_reg2hw; + hmr_dmr_regs_reg_pkg::hmr_dmr__in_t dmr_hw2reg; dmr_mode_e dmr_red_mode_d, dmr_red_mode_q; assign grp_in_independent_o = dmr_red_mode_q == NON_DMR; - assign rapid_recovery_en_o = dmr_reg2hw.dmr_config.rapid_recovery.q && RapidRecovery; + assign rapid_recovery_en_o = dmr_reg2hw.dmr_config.rapid_recovery.value && RapidRecovery; assign sw_synch_req_o = synch_req & ~synch_req_sent_q; assign synch_req_sent_d = synch_req; assign sw_resynch_req_o = resynch_req & ~resynch_req_sent_q; assign resynch_req_sent_d = resynch_req; - assign checkpoint_o = dmr_reg2hw.checkpoint_addr.q; - - hmr_dmr_regs_reg_top #( - .reg_req_t(reg_req_t), - .reg_rsp_t(reg_resp_t) - ) i_dmr_regs ( - .clk_i, - .rst_ni, - .reg_req_i(reg_req_i), - .reg_rsp_o(reg_resp_o), - .reg2hw (dmr_reg2hw), - .hw2reg (dmr_hw2reg), - .devmode_i('0) + assign checkpoint_o = dmr_reg2hw.checkpoint_addr.checkpoint_addr.value; + + hmr_dmr_regs_reg_top i_dmr_regs ( + .clk(clk_i), + .arst_n(rst_ni), + .s_apb_psel(reg_req_i.psel), + .s_apb_penable(apb_req_i.penable), + .s_apb_pwrite(apb_req_i.pwrite), + .s_apb_pprot(apb_req_i.pprot), + .s_apb_paddr(apb_req_i.paddr[3:0]), + .s_apb_pwdata(apb_req_i.pwdata), + .s_apb_pstrb(apb_req_i.pstrb), + .s_apb_pready(apb_resp_o.pready), + .s_apb_prdata(apb_resp_o.prdata), + .s_apb_pslverr(apb_resp_o.pslverr), + .hwif_in(dmr_hw2reg), + .hwif_out(dmr_reg2hw) ); // Global config update - assign dmr_hw2reg.dmr_enable.de = dmr_enable_qe_i; - assign dmr_hw2reg.dmr_enable.d = dmr_enable_q_i; - assign dmr_hw2reg.dmr_config.rapid_recovery.de = rapid_recovery_qe_i || ~RapidRecovery; - assign dmr_hw2reg.dmr_config.rapid_recovery.d = rapid_recovery_q_i && RapidRecovery; - assign dmr_hw2reg.dmr_config.force_recovery.d = force_recovery_qe_i ? force_recovery_q_i : 1'b0; + assign dmr_hw2reg.dmr_enable.dmr_enable.we = dmr_enable_qe_i; + assign dmr_hw2reg.dmr_enable.dmr_enable.next = dmr_enable_q_i; + assign dmr_hw2reg.dmr_config.rapid_recovery.we = rapid_recovery_qe_i || ~RapidRecovery; + assign dmr_hw2reg.dmr_config.rapid_recovery.next = rapid_recovery_q_i && RapidRecovery; + assign dmr_hw2reg.dmr_config.force_recovery.next = force_recovery_qe_i ? + force_recovery_q_i : + 1'b0; /************************** * FSM for DMR lockstep * @@ -106,24 +112,24 @@ module hmr_dmr_ctrl resynch_req = 1'b0; synch_req = 1'b0; - dmr_hw2reg.dmr_config.force_recovery.de = force_recovery_qe_i; + dmr_hw2reg.dmr_config.force_recovery.we = force_recovery_qe_i; case (dmr_red_mode_q) DMR_RUN: begin // If forced execute recovery - if (dmr_reg2hw.dmr_config.force_recovery.q && RapidRecovery && - dmr_reg2hw.dmr_config.rapid_recovery.q) begin - dmr_hw2reg.dmr_config.force_recovery.de = 1'b1; + if (dmr_reg2hw.dmr_config.force_recovery.value && RapidRecovery && + dmr_reg2hw.dmr_config.rapid_recovery.value) begin + dmr_hw2reg.dmr_config.force_recovery.we = 1'b1; dmr_red_mode_d = DMR_RESTORE; end // If error detected, restore - if (dmr_error_i && RapidRecovery && dmr_reg2hw.dmr_config.rapid_recovery.q) begin + if (dmr_error_i && RapidRecovery && dmr_reg2hw.dmr_config.rapid_recovery.value) begin $display("[HMR-dual] %t - mismatch detected, rapid recovery starting", $realtime); dmr_red_mode_d = DMR_RESTORE; end - if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.q)) begin + if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.value)) begin $display("[HMR-dual] %t - mismatch detected, SW trigger", $realtime); resynch_req = 1'b1; end @@ -144,10 +150,10 @@ module hmr_dmr_ctrl // Logic to switch in and out of DMR if (!DMRFixed) begin // Set DMR mode on external signal that cores are synchronized - if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.q == 1'b1) begin + if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b1) begin synch_req = 1'b1; if (cores_synch_q == 1'b1) begin - if (dmr_reg2hw.dmr_config.rapid_recovery.q == 1'b1) begin + if (dmr_reg2hw.dmr_config.rapid_recovery.value == 1'b1) begin dmr_red_mode_d = DMR_RESTORE; end else begin dmr_red_mode_d = DMR_RUN; @@ -157,7 +163,7 @@ module hmr_dmr_ctrl end // Before core startup: set DMR mode from reg2hw.dmr_enable if (fetch_en_i == 0) begin - if (dmr_reg2hw.dmr_enable.q == 1'b0) begin + if (dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b0) begin dmr_red_mode_d = NON_DMR; end else begin synch_req = 1'b0; @@ -166,7 +172,7 @@ module hmr_dmr_ctrl end // split tolerant mode to performance mode anytime (but require correct core state) if (dmr_red_mode_q == DMR_RUN) begin - if (dmr_reg2hw.dmr_enable.q == 1'b0) begin + if (dmr_reg2hw.dmr_enable.dmr_enable.value == 1'b0) begin dmr_red_mode_d = NON_DMR; setback_o = 2'b10; end diff --git a/rtl/HMR/hmr_dmr_regs.rdl b/rtl/HMR/hmr_dmr_regs.rdl new file mode 100644 index 00000000..1d17fff2 --- /dev/null +++ b/rtl/HMR/hmr_dmr_regs.rdl @@ -0,0 +1,59 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +addrmap hmr_dmr { + reg dmr_enable { + name = "dmr_enable"; + desc = "DMR Configuration Enable"; + field { + name = "enable"; + desc = "Enable DMR mode"; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } dmr_enable[0:0] = 0x0; + }; + reg dmr_config { + name = "dmr_config"; + desc = "DMR Configuration Register"; + field { + name = "rapid_recovery"; + desc = "Enable rapid recovery using an additional register file."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } rapid_recovery[0:0] = 0x0; + field { + name = "force_recovery"; + desc = "Forces recovery routine (if rapid_recovery is available)."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } force_recovery[1:1] = 0x0; + }; + reg checkpoint_addr { + name = "checkpoint_addr"; + desc = "Address for the last checkpoint."; + field { + name = "checkpoint_addr"; + desc = "Address for the last checkpoint."; + sw = rw; + hw = r; + // swmod = true; + } checkpoint_addr[31:0] = 0x0; + }; + + dmr_enable dmr_enable; + dmr_config dmr_config; + checkpoint_addr checkpoint_addr; +}; diff --git a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv index 95199d4c..9800a335 100644 --- a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv @@ -1,92 +1,73 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock package hmr_dmr_regs_reg_pkg; - // Address widths within the block - parameter int BlockAw = 4; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic q; - logic qe; - } hmr_dmr_regs_reg2hw_dmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic qe; - } rapid_recovery; - struct packed { - logic q; - logic qe; - } force_recovery; - } hmr_dmr_regs_reg2hw_dmr_config_reg_t; - - typedef struct packed { - logic [31:0] q; - logic qe; - } hmr_dmr_regs_reg2hw_checkpoint_addr_reg_t; - - typedef struct packed { - logic d; - logic de; - } hmr_dmr_regs_hw2reg_dmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic d; - logic de; - } rapid_recovery; - struct packed { - logic d; - logic de; - } force_recovery; - } hmr_dmr_regs_hw2reg_dmr_config_reg_t; - - typedef struct packed { - logic [31:0] d; - logic de; - } hmr_dmr_regs_hw2reg_checkpoint_addr_reg_t; - - // Register -> HW type - typedef struct packed { - hmr_dmr_regs_reg2hw_dmr_enable_reg_t dmr_enable; // [38:37] - hmr_dmr_regs_reg2hw_dmr_config_reg_t dmr_config; // [36:33] - hmr_dmr_regs_reg2hw_checkpoint_addr_reg_t checkpoint_addr; // [32:0] - } hmr_dmr_regs_reg2hw_t; - - // HW -> register type - typedef struct packed { - hmr_dmr_regs_hw2reg_dmr_enable_reg_t dmr_enable; // [38:37] - hmr_dmr_regs_hw2reg_dmr_config_reg_t dmr_config; // [36:33] - hmr_dmr_regs_hw2reg_checkpoint_addr_reg_t checkpoint_addr; // [32:0] - } hmr_dmr_regs_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] HMR_DMR_REGS_DMR_ENABLE_OFFSET = 4'h 0; - parameter logic [BlockAw-1:0] HMR_DMR_REGS_DMR_CONFIG_OFFSET = 4'h 4; - parameter logic [BlockAw-1:0] HMR_DMR_REGS_CHECKPOINT_ADDR_OFFSET = 4'h 8; - - // Register index - typedef enum int { - HMR_DMR_REGS_DMR_ENABLE, - HMR_DMR_REGS_DMR_CONFIG, - HMR_DMR_REGS_CHECKPOINT_ADDR - } hmr_dmr_regs_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] HMR_DMR_REGS_PERMIT [3] = '{ - 4'b 0001, // index[0] HMR_DMR_REGS_DMR_ENABLE - 4'b 0001, // index[1] HMR_DMR_REGS_DMR_CONFIG - 4'b 1111 // index[2] HMR_DMR_REGS_CHECKPOINT_ADDR - }; - + localparam HMR_DMR_REGS_REG_TOP_DATA_WIDTH = 32; + localparam HMR_DMR_REGS_REG_TOP_MIN_ADDR_WIDTH = 4; + localparam HMR_DMR_REGS_REG_TOP_SIZE = 'hc; + + typedef struct { + logic next; + logic we; + } hmr_dmr__dmr_enable__dmr_enable__in_t; + + typedef struct { + hmr_dmr__dmr_enable__dmr_enable__in_t dmr_enable; + } hmr_dmr__dmr_enable__in_t; + + typedef struct { + logic next; + logic we; + } hmr_dmr__dmr_config__rapid_recovery__in_t; + + typedef struct { + logic next; + logic we; + } hmr_dmr__dmr_config__force_recovery__in_t; + + typedef struct { + hmr_dmr__dmr_config__rapid_recovery__in_t rapid_recovery; + hmr_dmr__dmr_config__force_recovery__in_t force_recovery; + } hmr_dmr__dmr_config__in_t; + + typedef struct { + hmr_dmr__dmr_enable__in_t dmr_enable; + hmr_dmr__dmr_config__in_t dmr_config; + } hmr_dmr__in_t; + + typedef struct { + logic value; + } hmr_dmr__dmr_enable__dmr_enable__out_t; + + typedef struct { + hmr_dmr__dmr_enable__dmr_enable__out_t dmr_enable; + } hmr_dmr__dmr_enable__out_t; + + typedef struct { + logic value; + } hmr_dmr__dmr_config__rapid_recovery__out_t; + + typedef struct { + logic value; + } hmr_dmr__dmr_config__force_recovery__out_t; + + typedef struct { + hmr_dmr__dmr_config__rapid_recovery__out_t rapid_recovery; + hmr_dmr__dmr_config__force_recovery__out_t force_recovery; + } hmr_dmr__dmr_config__out_t; + + typedef struct { + logic [31:0] value; + } hmr_dmr__checkpoint_addr__checkpoint_addr__out_t; + + typedef struct { + hmr_dmr__checkpoint_addr__checkpoint_addr__out_t checkpoint_addr; + } hmr_dmr__checkpoint_addr__out_t; + + typedef struct { + hmr_dmr__dmr_enable__out_t dmr_enable; + hmr_dmr__dmr_config__out_t dmr_config; + hmr_dmr__checkpoint_addr__out_t checkpoint_addr; + } hmr_dmr__out_t; endpackage - diff --git a/rtl/HMR/hmr_dmr_regs_reg_top.sv b/rtl/HMR/hmr_dmr_regs_reg_top.sv index 209d9348..d2b0c3e5 100644 --- a/rtl/HMR/hmr_dmr_regs_reg_top.sv +++ b/rtl/HMR/hmr_dmr_regs_reg_top.sv @@ -1,312 +1,302 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module hmr_dmr_regs_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 4 -) ( - 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 hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t reg2hw, // Write - input hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import hmr_dmr_regs_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-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; - 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 dmr_enable_qs; - logic dmr_enable_wd; - logic dmr_enable_we; - logic dmr_config_rapid_recovery_qs; - logic dmr_config_rapid_recovery_wd; - logic dmr_config_rapid_recovery_we; - logic dmr_config_force_recovery_qs; - logic dmr_config_force_recovery_wd; - logic dmr_config_force_recovery_we; - logic [31:0] checkpoint_addr_qs; - logic [31:0] checkpoint_addr_wd; - logic checkpoint_addr_we; - - // Register instances - // R[dmr_enable]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_dmr_enable ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dmr_enable_we), - .wd (dmr_enable_wd), - - // from internal hardware - .de (hw2reg.dmr_enable.de), - .d (hw2reg.dmr_enable.d ), - - // to internal hardware - .qe (reg2hw.dmr_enable.qe), - .q (reg2hw.dmr_enable.q ), - - // to register interface (read) - .qs (dmr_enable_qs) - ); - - - // R[dmr_config]: V(False) - - // F[rapid_recovery]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_dmr_config_rapid_recovery ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dmr_config_rapid_recovery_we), - .wd (dmr_config_rapid_recovery_wd), - - // from internal hardware - .de (hw2reg.dmr_config.rapid_recovery.de), - .d (hw2reg.dmr_config.rapid_recovery.d ), - - // to internal hardware - .qe (reg2hw.dmr_config.rapid_recovery.qe), - .q (reg2hw.dmr_config.rapid_recovery.q ), - - // to register interface (read) - .qs (dmr_config_rapid_recovery_qs) - ); - - - // F[force_recovery]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_dmr_config_force_recovery ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dmr_config_force_recovery_we), - .wd (dmr_config_force_recovery_wd), - - // from internal hardware - .de (hw2reg.dmr_config.force_recovery.de), - .d (hw2reg.dmr_config.force_recovery.d ), - - // to internal hardware - .qe (reg2hw.dmr_config.force_recovery.qe), - .q (reg2hw.dmr_config.force_recovery.q ), - - // to register interface (read) - .qs (dmr_config_force_recovery_qs) - ); - - - // R[checkpoint_addr]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_checkpoint_addr ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (checkpoint_addr_we), - .wd (checkpoint_addr_wd), - - // from internal hardware - .de (hw2reg.checkpoint_addr.de), - .d (hw2reg.checkpoint_addr.d ), - - // to internal hardware - .qe (reg2hw.checkpoint_addr.qe), - .q (reg2hw.checkpoint_addr.q ), - - // to register interface (read) - .qs (checkpoint_addr_qs) - ); - - - - - logic [2:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == HMR_DMR_REGS_DMR_ENABLE_OFFSET); - addr_hit[1] = (reg_addr == HMR_DMR_REGS_DMR_CONFIG_OFFSET); - addr_hit[2] = (reg_addr == HMR_DMR_REGS_CHECKPOINT_ADDR_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] & (|(HMR_DMR_REGS_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(HMR_DMR_REGS_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(HMR_DMR_REGS_PERMIT[2] & ~reg_be))))); - end - - assign dmr_enable_we = addr_hit[0] & reg_we & !reg_error; - assign dmr_enable_wd = reg_wdata[0]; - - assign dmr_config_rapid_recovery_we = addr_hit[1] & reg_we & !reg_error; - assign dmr_config_rapid_recovery_wd = reg_wdata[0]; - - assign dmr_config_force_recovery_we = addr_hit[1] & reg_we & !reg_error; - assign dmr_config_force_recovery_wd = reg_wdata[1]; - - assign checkpoint_addr_we = addr_hit[2] & reg_we & !reg_error; - assign checkpoint_addr_wd = reg_wdata[31:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = dmr_enable_qs; - end - - addr_hit[1]: begin - reg_rdata_next[0] = dmr_config_rapid_recovery_qs; - reg_rdata_next[1] = dmr_config_force_recovery_qs; - end - - addr_hit[2]: begin - reg_rdata_next[31:0] = checkpoint_addr_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)) - +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module hmr_dmr_regs_reg_top ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [3:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + input hmr_dmr_regs_reg_pkg::hmr_dmr__in_t hwif_in, + output hmr_dmr_regs_reg_pkg::hmr_dmr__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [3:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[3:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + + // Read & write latencies are balanced. Stalls not required + assign cpuif_req_stall_rd = '0; + assign cpuif_req_stall_wr = '0; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic dmr_enable; + logic dmr_config; + logic checkpoint_addr; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + decoded_reg_strb.dmr_enable = cpuif_req_masked & (cpuif_addr == 4'h0); + decoded_reg_strb.dmr_config = cpuif_req_masked & (cpuif_addr == 4'h4); + decoded_reg_strb.checkpoint_addr = cpuif_req_masked & (cpuif_addr == 4'h8); + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + typedef struct { + struct { + struct { + logic next; + logic load_next; + } dmr_enable; + } dmr_enable; + struct { + struct { + logic next; + logic load_next; + } rapid_recovery; + struct { + logic next; + logic load_next; + } force_recovery; + } dmr_config; + struct { + struct { + logic [31:0] next; + logic load_next; + } checkpoint_addr; + } checkpoint_addr; + } field_combo_t; + field_combo_t field_combo; + + typedef struct { + struct { + struct { + logic value; + } dmr_enable; + } dmr_enable; + struct { + struct { + logic value; + } rapid_recovery; + struct { + logic value; + } force_recovery; + } dmr_config; + struct { + struct { + logic [31:0] value; + } checkpoint_addr; + } checkpoint_addr; + } field_storage_t; + field_storage_t field_storage; + + // Field: hmr_dmr.dmr_enable.dmr_enable + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.dmr_enable.dmr_enable.value; + load_next_c = '0; + if(decoded_reg_strb.dmr_enable && decoded_req_is_wr) begin // SW write + next_c = (field_storage.dmr_enable.dmr_enable.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else if(hwif_in.dmr_enable.dmr_enable.we) begin // HW Write - we + next_c = hwif_in.dmr_enable.dmr_enable.next; + load_next_c = '1; + end + field_combo.dmr_enable.dmr_enable.next = next_c; + field_combo.dmr_enable.dmr_enable.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.dmr_enable.dmr_enable.value <= 1'h0; + end else begin + if(field_combo.dmr_enable.dmr_enable.load_next) begin + field_storage.dmr_enable.dmr_enable.value <= field_combo.dmr_enable.dmr_enable.next; + end + end + end + assign hwif_out.dmr_enable.dmr_enable.value = field_storage.dmr_enable.dmr_enable.value; + // Field: hmr_dmr.dmr_config.rapid_recovery + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.dmr_config.rapid_recovery.value; + load_next_c = '0; + if(decoded_reg_strb.dmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.dmr_config.rapid_recovery.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else if(hwif_in.dmr_config.rapid_recovery.we) begin // HW Write - we + next_c = hwif_in.dmr_config.rapid_recovery.next; + load_next_c = '1; + end + field_combo.dmr_config.rapid_recovery.next = next_c; + field_combo.dmr_config.rapid_recovery.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.dmr_config.rapid_recovery.value <= 1'h0; + end else begin + if(field_combo.dmr_config.rapid_recovery.load_next) begin + field_storage.dmr_config.rapid_recovery.value <= field_combo.dmr_config.rapid_recovery.next; + end + end + end + assign hwif_out.dmr_config.rapid_recovery.value = field_storage.dmr_config.rapid_recovery.value; + // Field: hmr_dmr.dmr_config.force_recovery + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.dmr_config.force_recovery.value; + load_next_c = '0; + if(decoded_reg_strb.dmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.dmr_config.force_recovery.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end else if(hwif_in.dmr_config.force_recovery.we) begin // HW Write - we + next_c = hwif_in.dmr_config.force_recovery.next; + load_next_c = '1; + end + field_combo.dmr_config.force_recovery.next = next_c; + field_combo.dmr_config.force_recovery.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.dmr_config.force_recovery.value <= 1'h0; + end else begin + if(field_combo.dmr_config.force_recovery.load_next) begin + field_storage.dmr_config.force_recovery.value <= field_combo.dmr_config.force_recovery.next; + end + end + end + assign hwif_out.dmr_config.force_recovery.value = field_storage.dmr_config.force_recovery.value; + // Field: hmr_dmr.checkpoint_addr.checkpoint_addr + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.checkpoint_addr.checkpoint_addr.value; + load_next_c = '0; + if(decoded_reg_strb.checkpoint_addr && decoded_req_is_wr) begin // SW write + next_c = (field_storage.checkpoint_addr.checkpoint_addr.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + field_combo.checkpoint_addr.checkpoint_addr.next = next_c; + field_combo.checkpoint_addr.checkpoint_addr.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.checkpoint_addr.checkpoint_addr.value <= 32'h0; + end else begin + if(field_combo.checkpoint_addr.checkpoint_addr.load_next) begin + field_storage.checkpoint_addr.checkpoint_addr.value <= field_combo.checkpoint_addr.checkpoint_addr.next; + end + end + end + assign hwif_out.checkpoint_addr.checkpoint_addr.value = field_storage.checkpoint_addr.checkpoint_addr.value; + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [31:0] readback_array[3]; + assign readback_array[0][0:0] = (decoded_reg_strb.dmr_enable && !decoded_req_is_wr) ? field_storage.dmr_enable.dmr_enable.value : '0; + assign readback_array[0][31:1] = '0; + assign readback_array[1][0:0] = (decoded_reg_strb.dmr_config && !decoded_req_is_wr) ? field_storage.dmr_config.rapid_recovery.value : '0; + assign readback_array[1][1:1] = (decoded_reg_strb.dmr_config && !decoded_req_is_wr) ? field_storage.dmr_config.force_recovery.value : '0; + assign readback_array[1][31:2] = '0; + assign readback_array[2][31:0] = (decoded_reg_strb.checkpoint_addr && !decoded_req_is_wr) ? field_storage.checkpoint_addr.checkpoint_addr.value : '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<3; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign cpuif_rd_ack = readback_done; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; endmodule - -module hmr_dmr_regs_reg_top_intf -#( - parameter int AW = 4, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t reg2hw, // Write - input hmr_dmr_regs_reg_pkg::hmr_dmr_regs_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) - - - - hmr_dmr_regs_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 - - diff --git a/rtl/HMR/hmr_registers.h b/rtl/HMR/hmr_registers.h new file mode 100644 index 00000000..323bec79 --- /dev/null +++ b/rtl/HMR/hmr_registers.h @@ -0,0 +1,209 @@ +// Generated by PeakRDL-cheader - A free and open-source header generator +// https://github.com/SystemRDL/PeakRDL-cheader + +#ifndef HMR_REGISTERS_H +#define HMR_REGISTERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Reg - hmr_all::hmr::avail_config +#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bm 0x1 +#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bp 0 +#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_bw 1 +#define HMR_ALL__HMR__AVAIL_CONFIG__INDEPENDENT_reset 0x1 +#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bm 0x2 +#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bp 1 +#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_bw 1 +#define HMR_ALL__HMR__AVAIL_CONFIG__DUAL_reset 0x1 +#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bm 0x4 +#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bp 2 +#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_bw 1 +#define HMR_ALL__HMR__AVAIL_CONFIG__TRIPLE_reset 0x1 +#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bm 0x100 +#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bp 8 +#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_bw 1 +#define HMR_ALL__HMR__AVAIL_CONFIG__RAPID_RECOVERY_reset 0x1 + +// Reg - hmr_all::hmr::cores_en +#define HMR_ALL__HMR__CORES_EN__CORES_EN_bm 0xfff +#define HMR_ALL__HMR__CORES_EN__CORES_EN_bp 0 +#define HMR_ALL__HMR__CORES_EN__CORES_EN_bw 12 +#define HMR_ALL__HMR__CORES_EN__CORES_EN_reset 0x0 + +// Reg - hmr_all::hmr::dmr_enable +#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bm 0x3f +#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bp 0 +#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_bw 6 +#define HMR_ALL__HMR__DMR_ENABLE__DMR_ENABLE_reset 0x0 + +// Reg - hmr_all::hmr::tmr_enable +#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bm 0xf +#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bp 0 +#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_bw 4 +#define HMR_ALL__HMR__TMR_ENABLE__TMR_ENABLE_reset 0x0 + +// Reg - hmr_all::hmr::dmr_config +#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bm 0x1 +#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bp 0 +#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_bw 1 +#define HMR_ALL__HMR__DMR_CONFIG__RAPID_RECOVERY_reset 0x0 +#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bm 0x2 +#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bp 1 +#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_bw 1 +#define HMR_ALL__HMR__DMR_CONFIG__FORCE_RECOVERY_reset 0x0 + +// Reg - hmr_all::hmr::tmr_config +#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bm 0x1 +#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bp 0 +#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_bw 1 +#define HMR_ALL__HMR__TMR_CONFIG__DELAY_RESYNCH_reset 0x0 +#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bm 0x2 +#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bp 1 +#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_bw 1 +#define HMR_ALL__HMR__TMR_CONFIG__SETBACK_reset 0x1 +#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bm 0x4 +#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bp 2 +#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_bw 1 +#define HMR_ALL__HMR__TMR_CONFIG__RELOAD_SETBACK_reset 0x1 +#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bm 0x8 +#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bp 3 +#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_bw 1 +#define HMR_ALL__HMR__TMR_CONFIG__RAPID_RECOVERY_reset 0x0 +#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bm 0x10 +#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bp 4 +#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_bw 1 +#define HMR_ALL__HMR__TMR_CONFIG__FORCE_RESYNCH_reset 0x0 + +// Addrmap - hmr_all::hmr +typedef struct __attribute__ ((__packed__)) { + uint32_t avail_config; + uint32_t cores_en; + uint32_t dmr_enable; + uint32_t tmr_enable; + uint32_t dmr_config; + uint32_t tmr_config; +} hmr_all__hmr_t; + +// Reg - hmr_all::hmr_core::current_mode +#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bm 0x1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bp 0 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_bw 1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__INDEPENDENT_reset 0x1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bm 0x2 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bp 1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_bw 1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__DUAL_reset 0x0 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bm 0x4 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bp 2 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_bw 1 +#define HMR_ALL__HMR_CORE__CURRENT_MODE__TRIPLE_reset 0x0 + +// Reg - hmr_all::hmr_core::mismatches +#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bm 0xffffffff +#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bp 0 +#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_bw 32 +#define HMR_ALL__HMR_CORE__MISMATCHES__MISMATCHES_reset 0x0 + +// Reg - hmr_all::hmr_core::sp_store +#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bm 0xffffffff +#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bp 0 +#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_bw 32 +#define HMR_ALL__HMR_CORE__SP_STORE__SP_STORE_reset 0x0 + +// Addrmap - hmr_all::hmr_core +typedef struct __attribute__ ((__packed__)) { + uint32_t current_mode; + uint32_t mismatches; + uint32_t sp_store; + uint8_t RESERVED_c_f[0x4]; +} hmr_all__hmr_core__stride10_t; + +// Reg - hmr_all::hmr_dmr_ispresent_t::dmr_enable +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bm 0x1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bp 0 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_bw 1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_ENABLE__DMR_ENABLE_reset 0x0 + +// Reg - hmr_all::hmr_dmr_ispresent_t::dmr_config +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bm 0x1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bp 0 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_bw 1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__RAPID_RECOVERY_reset 0x0 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bm 0x2 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bp 1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_bw 1 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__DMR_CONFIG__FORCE_RECOVERY_reset 0x0 + +// Reg - hmr_all::hmr_dmr_ispresent_t::checkpoint_addr +#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bm 0xffffffff +#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bp 0 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_bw 32 +#define HMR_ALL__HMR_DMR_ISPRESENT_T__CHECKPOINT_ADDR__CHECKPOINT_ADDR_reset 0x0 + +// Addrmap - hmr_all::hmr_dmr_ispresent_t +typedef struct __attribute__ ((__packed__)) { + uint32_t dmr_enable; + uint32_t dmr_config; + uint32_t checkpoint_addr; + uint8_t RESERVED_c_f[0x4]; +} hmr_all__hmr_dmr_ispresent_t__stride10_t; + +// Reg - hmr_all::hmr_tmr_ispresent_t::tmr_enable +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bm 0x1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bp 0 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_ENABLE__TMR_ENABLE_reset 0x0 + +// Reg - hmr_all::hmr_tmr_ispresent_t::tmr_config +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bm 0x1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bp 0 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__DELAY_RESYNCH_reset 0x0 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bm 0x2 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bp 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__SETBACK_reset 0x1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bm 0x4 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bp 2 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RELOAD_SETBACK_reset 0x1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bm 0x8 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bp 3 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__RAPID_RECOVERY_reset 0x0 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bm 0x10 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bp 4 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_bw 1 +#define HMR_ALL__HMR_TMR_ISPRESENT_T__TMR_CONFIG__FORCE_RESYNCH_reset 0x0 + +// Addrmap - hmr_all::hmr_tmr_ispresent_t +typedef struct __attribute__ ((__packed__)) { + uint32_t tmr_enable; + uint32_t tmr_config; + uint8_t RESERVED_8_f[0x8]; +} hmr_all__hmr_tmr_ispresent_t__stride10_t; + +// Addrmap - hmr_all +typedef struct __attribute__ ((__packed__)) { + hmr_all__hmr_t hmr; + uint8_t RESERVED_18_ff[0xe8]; + hmr_all__hmr_core__stride10_t hmr_core[12]; + uint8_t RESERVED_1c0_1ff[0x40]; + hmr_all__hmr_dmr_ispresent_t__stride10_t hmr_dmr[6]; + uint8_t RESERVED_260_2ff[0xa0]; + hmr_all__hmr_tmr_ispresent_t__stride10_t hmr_tmr[4]; +} hmr_all_t; + + +static_assert(sizeof(hmr_all_t) == 0x340, "Packing error"); + +#ifdef __cplusplus +} +#endif + +#endif /* HMR_REGISTERS_H */ diff --git a/rtl/HMR/hmr_registers_reg_addr_pkg.sv b/rtl/HMR/hmr_registers_reg_addr_pkg.sv new file mode 100644 index 00000000..cd3cd5bb --- /dev/null +++ b/rtl/HMR/hmr_registers_reg_addr_pkg.sv @@ -0,0 +1,304 @@ +package hmr_all_addrmap_pkg; + + +localparam longint unsigned HMR_ALL_BASE_ADDR = 64'h00000000; +localparam longint unsigned HMR_ALL_SIZE = 64'h00000340; + + +localparam longint unsigned HMR_ALL_HMR_BASE_ADDR = 64'h00000000; +localparam longint unsigned HMR_ALL_HMR_SIZE = 64'h00000018; + +localparam longint unsigned HMR_ALL_HMR_AVAIL_CONFIG_REG_ADDR = 64'h00000000; +localparam longint unsigned HMR_ALL_HMR_AVAIL_CONFIG_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORES_EN_REG_ADDR = 64'h00000004; +localparam longint unsigned HMR_ALL_HMR_CORES_EN_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_ENABLE_REG_ADDR = 64'h00000008; +localparam longint unsigned HMR_ALL_HMR_DMR_ENABLE_REG_OFFSET = 64'h00000008; + +localparam longint unsigned HMR_ALL_HMR_TMR_ENABLE_REG_ADDR = 64'h0000000C; +localparam longint unsigned HMR_ALL_HMR_TMR_ENABLE_REG_OFFSET = 64'h0000000C; + +localparam longint unsigned HMR_ALL_HMR_DMR_CONFIG_REG_ADDR = 64'h00000010; +localparam longint unsigned HMR_ALL_HMR_DMR_CONFIG_REG_OFFSET = 64'h00000010; + +localparam longint unsigned HMR_ALL_HMR_TMR_CONFIG_REG_ADDR = 64'h00000014; +localparam longint unsigned HMR_ALL_HMR_TMR_CONFIG_REG_OFFSET = 64'h00000014; + + +localparam longint unsigned HMR_ALL_HMR_CORE_0_BASE_ADDR = 64'h00000100; +localparam longint unsigned HMR_ALL_HMR_CORE_0_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_0_CURRENT_MODE_REG_ADDR = 64'h00000100; +localparam longint unsigned HMR_ALL_HMR_CORE_0_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_0_MISMATCHES_REG_ADDR = 64'h00000104; +localparam longint unsigned HMR_ALL_HMR_CORE_0_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_0_SP_STORE_REG_ADDR = 64'h00000108; +localparam longint unsigned HMR_ALL_HMR_CORE_0_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_1_BASE_ADDR = 64'h00000110; +localparam longint unsigned HMR_ALL_HMR_CORE_1_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_1_CURRENT_MODE_REG_ADDR = 64'h00000110; +localparam longint unsigned HMR_ALL_HMR_CORE_1_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_1_MISMATCHES_REG_ADDR = 64'h00000114; +localparam longint unsigned HMR_ALL_HMR_CORE_1_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_1_SP_STORE_REG_ADDR = 64'h00000118; +localparam longint unsigned HMR_ALL_HMR_CORE_1_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_2_BASE_ADDR = 64'h00000120; +localparam longint unsigned HMR_ALL_HMR_CORE_2_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_2_CURRENT_MODE_REG_ADDR = 64'h00000120; +localparam longint unsigned HMR_ALL_HMR_CORE_2_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_2_MISMATCHES_REG_ADDR = 64'h00000124; +localparam longint unsigned HMR_ALL_HMR_CORE_2_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_2_SP_STORE_REG_ADDR = 64'h00000128; +localparam longint unsigned HMR_ALL_HMR_CORE_2_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_3_BASE_ADDR = 64'h00000130; +localparam longint unsigned HMR_ALL_HMR_CORE_3_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_3_CURRENT_MODE_REG_ADDR = 64'h00000130; +localparam longint unsigned HMR_ALL_HMR_CORE_3_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_3_MISMATCHES_REG_ADDR = 64'h00000134; +localparam longint unsigned HMR_ALL_HMR_CORE_3_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_3_SP_STORE_REG_ADDR = 64'h00000138; +localparam longint unsigned HMR_ALL_HMR_CORE_3_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_4_BASE_ADDR = 64'h00000140; +localparam longint unsigned HMR_ALL_HMR_CORE_4_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_4_CURRENT_MODE_REG_ADDR = 64'h00000140; +localparam longint unsigned HMR_ALL_HMR_CORE_4_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_4_MISMATCHES_REG_ADDR = 64'h00000144; +localparam longint unsigned HMR_ALL_HMR_CORE_4_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_4_SP_STORE_REG_ADDR = 64'h00000148; +localparam longint unsigned HMR_ALL_HMR_CORE_4_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_5_BASE_ADDR = 64'h00000150; +localparam longint unsigned HMR_ALL_HMR_CORE_5_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_5_CURRENT_MODE_REG_ADDR = 64'h00000150; +localparam longint unsigned HMR_ALL_HMR_CORE_5_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_5_MISMATCHES_REG_ADDR = 64'h00000154; +localparam longint unsigned HMR_ALL_HMR_CORE_5_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_5_SP_STORE_REG_ADDR = 64'h00000158; +localparam longint unsigned HMR_ALL_HMR_CORE_5_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_6_BASE_ADDR = 64'h00000160; +localparam longint unsigned HMR_ALL_HMR_CORE_6_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_6_CURRENT_MODE_REG_ADDR = 64'h00000160; +localparam longint unsigned HMR_ALL_HMR_CORE_6_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_6_MISMATCHES_REG_ADDR = 64'h00000164; +localparam longint unsigned HMR_ALL_HMR_CORE_6_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_6_SP_STORE_REG_ADDR = 64'h00000168; +localparam longint unsigned HMR_ALL_HMR_CORE_6_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_7_BASE_ADDR = 64'h00000170; +localparam longint unsigned HMR_ALL_HMR_CORE_7_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_7_CURRENT_MODE_REG_ADDR = 64'h00000170; +localparam longint unsigned HMR_ALL_HMR_CORE_7_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_7_MISMATCHES_REG_ADDR = 64'h00000174; +localparam longint unsigned HMR_ALL_HMR_CORE_7_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_7_SP_STORE_REG_ADDR = 64'h00000178; +localparam longint unsigned HMR_ALL_HMR_CORE_7_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_8_BASE_ADDR = 64'h00000180; +localparam longint unsigned HMR_ALL_HMR_CORE_8_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_8_CURRENT_MODE_REG_ADDR = 64'h00000180; +localparam longint unsigned HMR_ALL_HMR_CORE_8_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_8_MISMATCHES_REG_ADDR = 64'h00000184; +localparam longint unsigned HMR_ALL_HMR_CORE_8_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_8_SP_STORE_REG_ADDR = 64'h00000188; +localparam longint unsigned HMR_ALL_HMR_CORE_8_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_9_BASE_ADDR = 64'h00000190; +localparam longint unsigned HMR_ALL_HMR_CORE_9_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_9_CURRENT_MODE_REG_ADDR = 64'h00000190; +localparam longint unsigned HMR_ALL_HMR_CORE_9_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_9_MISMATCHES_REG_ADDR = 64'h00000194; +localparam longint unsigned HMR_ALL_HMR_CORE_9_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_9_SP_STORE_REG_ADDR = 64'h00000198; +localparam longint unsigned HMR_ALL_HMR_CORE_9_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_10_BASE_ADDR = 64'h000001A0; +localparam longint unsigned HMR_ALL_HMR_CORE_10_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_10_CURRENT_MODE_REG_ADDR = 64'h000001A0; +localparam longint unsigned HMR_ALL_HMR_CORE_10_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_10_MISMATCHES_REG_ADDR = 64'h000001A4; +localparam longint unsigned HMR_ALL_HMR_CORE_10_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_10_SP_STORE_REG_ADDR = 64'h000001A8; +localparam longint unsigned HMR_ALL_HMR_CORE_10_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_CORE_11_BASE_ADDR = 64'h000001B0; +localparam longint unsigned HMR_ALL_HMR_CORE_11_SIZE = 64'h000000C0; + +localparam longint unsigned HMR_ALL_HMR_CORE_11_CURRENT_MODE_REG_ADDR = 64'h000001B0; +localparam longint unsigned HMR_ALL_HMR_CORE_11_CURRENT_MODE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_CORE_11_MISMATCHES_REG_ADDR = 64'h000001B4; +localparam longint unsigned HMR_ALL_HMR_CORE_11_MISMATCHES_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_CORE_11_SP_STORE_REG_ADDR = 64'h000001B8; +localparam longint unsigned HMR_ALL_HMR_CORE_11_SP_STORE_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_0_BASE_ADDR = 64'h00000200; +localparam longint unsigned HMR_ALL_HMR_DMR_0_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_ENABLE_REG_ADDR = 64'h00000200; +localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_CONFIG_REG_ADDR = 64'h00000204; +localparam longint unsigned HMR_ALL_HMR_DMR_0_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_0_CHECKPOINT_ADDR_REG_ADDR = 64'h00000208; +localparam longint unsigned HMR_ALL_HMR_DMR_0_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_1_BASE_ADDR = 64'h00000210; +localparam longint unsigned HMR_ALL_HMR_DMR_1_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_ENABLE_REG_ADDR = 64'h00000210; +localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_CONFIG_REG_ADDR = 64'h00000214; +localparam longint unsigned HMR_ALL_HMR_DMR_1_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_1_CHECKPOINT_ADDR_REG_ADDR = 64'h00000218; +localparam longint unsigned HMR_ALL_HMR_DMR_1_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_2_BASE_ADDR = 64'h00000220; +localparam longint unsigned HMR_ALL_HMR_DMR_2_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_ENABLE_REG_ADDR = 64'h00000220; +localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_CONFIG_REG_ADDR = 64'h00000224; +localparam longint unsigned HMR_ALL_HMR_DMR_2_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_2_CHECKPOINT_ADDR_REG_ADDR = 64'h00000228; +localparam longint unsigned HMR_ALL_HMR_DMR_2_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_3_BASE_ADDR = 64'h00000230; +localparam longint unsigned HMR_ALL_HMR_DMR_3_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_ENABLE_REG_ADDR = 64'h00000230; +localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_CONFIG_REG_ADDR = 64'h00000234; +localparam longint unsigned HMR_ALL_HMR_DMR_3_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_3_CHECKPOINT_ADDR_REG_ADDR = 64'h00000238; +localparam longint unsigned HMR_ALL_HMR_DMR_3_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_4_BASE_ADDR = 64'h00000240; +localparam longint unsigned HMR_ALL_HMR_DMR_4_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_ENABLE_REG_ADDR = 64'h00000240; +localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_CONFIG_REG_ADDR = 64'h00000244; +localparam longint unsigned HMR_ALL_HMR_DMR_4_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_4_CHECKPOINT_ADDR_REG_ADDR = 64'h00000248; +localparam longint unsigned HMR_ALL_HMR_DMR_4_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_DMR_5_BASE_ADDR = 64'h00000250; +localparam longint unsigned HMR_ALL_HMR_DMR_5_SIZE = 64'h00000060; + +localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_ENABLE_REG_ADDR = 64'h00000250; +localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_CONFIG_REG_ADDR = 64'h00000254; +localparam longint unsigned HMR_ALL_HMR_DMR_5_DMR_CONFIG_REG_OFFSET = 64'h00000004; + +localparam longint unsigned HMR_ALL_HMR_DMR_5_CHECKPOINT_ADDR_REG_ADDR = 64'h00000258; +localparam longint unsigned HMR_ALL_HMR_DMR_5_CHECKPOINT_ADDR_REG_OFFSET = 64'h00000008; + + +localparam longint unsigned HMR_ALL_HMR_TMR_0_BASE_ADDR = 64'h00000300; +localparam longint unsigned HMR_ALL_HMR_TMR_0_SIZE = 64'h00000040; + +localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_ENABLE_REG_ADDR = 64'h00000300; +localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_CONFIG_REG_ADDR = 64'h00000304; +localparam longint unsigned HMR_ALL_HMR_TMR_0_TMR_CONFIG_REG_OFFSET = 64'h00000004; + + +localparam longint unsigned HMR_ALL_HMR_TMR_1_BASE_ADDR = 64'h00000310; +localparam longint unsigned HMR_ALL_HMR_TMR_1_SIZE = 64'h00000040; + +localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_ENABLE_REG_ADDR = 64'h00000310; +localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_CONFIG_REG_ADDR = 64'h00000314; +localparam longint unsigned HMR_ALL_HMR_TMR_1_TMR_CONFIG_REG_OFFSET = 64'h00000004; + + +localparam longint unsigned HMR_ALL_HMR_TMR_2_BASE_ADDR = 64'h00000320; +localparam longint unsigned HMR_ALL_HMR_TMR_2_SIZE = 64'h00000040; + +localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_ENABLE_REG_ADDR = 64'h00000320; +localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_CONFIG_REG_ADDR = 64'h00000324; +localparam longint unsigned HMR_ALL_HMR_TMR_2_TMR_CONFIG_REG_OFFSET = 64'h00000004; + + +localparam longint unsigned HMR_ALL_HMR_TMR_3_BASE_ADDR = 64'h00000330; +localparam longint unsigned HMR_ALL_HMR_TMR_3_SIZE = 64'h00000040; + +localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_ENABLE_REG_ADDR = 64'h00000330; +localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_ENABLE_REG_OFFSET = 64'h00000000; + +localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_CONFIG_REG_ADDR = 64'h00000334; +localparam longint unsigned HMR_ALL_HMR_TMR_3_TMR_CONFIG_REG_OFFSET = 64'h00000004; + + +endpackage; diff --git a/rtl/HMR/hmr_registers_reg_pkg.sv b/rtl/HMR/hmr_registers_reg_pkg.sv index 1c590cce..8f814e0d 100644 --- a/rtl/HMR/hmr_registers_reg_pkg.sv +++ b/rtl/HMR/hmr_registers_reg_pkg.sv @@ -1,180 +1,166 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock package hmr_registers_reg_pkg; - // Param list - parameter int NumCores = 12; - parameter int NumDMRGroups = 6; - parameter int NumTMRGroups = 4; - - // Address widths within the block - parameter int BlockAw = 5; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic [5:0] q; - logic qe; - } hmr_registers_reg2hw_dmr_enable_reg_t; - - typedef struct packed { - logic [3:0] q; - logic qe; - } hmr_registers_reg2hw_tmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic qe; - } rapid_recovery; - struct packed { - logic q; - logic qe; - } force_recovery; - } hmr_registers_reg2hw_dmr_config_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic qe; - } delay_resynch; - struct packed { - logic q; - logic qe; - } setback; - struct packed { - logic q; - logic qe; - } reload_setback; - struct packed { - logic q; - logic qe; - } rapid_recovery; - struct packed { - logic q; - logic qe; - } force_resynch; - } hmr_registers_reg2hw_tmr_config_reg_t; - - typedef struct packed { - struct packed { - logic d; - } independent; - struct packed { - logic d; - } dual; - struct packed { - logic d; - } triple; - struct packed { - logic d; - } rapid_recovery; - } hmr_registers_hw2reg_avail_config_reg_t; - - typedef struct packed { - logic [11:0] d; - } hmr_registers_hw2reg_cores_en_reg_t; - - typedef struct packed { - logic [5:0] d; - } hmr_registers_hw2reg_dmr_enable_reg_t; - - typedef struct packed { - logic [3:0] d; - } hmr_registers_hw2reg_tmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic d; - } rapid_recovery; - struct packed { - logic d; - } force_recovery; - } hmr_registers_hw2reg_dmr_config_reg_t; - - typedef struct packed { - struct packed { - logic d; - } delay_resynch; - struct packed { - logic d; - } setback; - struct packed { - logic d; - } reload_setback; - struct packed { - logic d; - } rapid_recovery; - struct packed { - logic d; - } force_resynch; - } hmr_registers_hw2reg_tmr_config_reg_t; - - // Register -> HW type - typedef struct packed { - hmr_registers_reg2hw_dmr_enable_reg_t dmr_enable; // [25:19] - hmr_registers_reg2hw_tmr_enable_reg_t tmr_enable; // [18:14] - hmr_registers_reg2hw_dmr_config_reg_t dmr_config; // [13:10] - hmr_registers_reg2hw_tmr_config_reg_t tmr_config; // [9:0] - } hmr_registers_reg2hw_t; - - // HW -> register type - typedef struct packed { - hmr_registers_hw2reg_avail_config_reg_t avail_config; // [32:29] - hmr_registers_hw2reg_cores_en_reg_t cores_en; // [28:17] - hmr_registers_hw2reg_dmr_enable_reg_t dmr_enable; // [16:11] - hmr_registers_hw2reg_tmr_enable_reg_t tmr_enable; // [10:7] - hmr_registers_hw2reg_dmr_config_reg_t dmr_config; // [6:5] - hmr_registers_hw2reg_tmr_config_reg_t tmr_config; // [4:0] - } hmr_registers_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] HMR_REGISTERS_AVAIL_CONFIG_OFFSET = 5'h 0; - parameter logic [BlockAw-1:0] HMR_REGISTERS_CORES_EN_OFFSET = 5'h 4; - parameter logic [BlockAw-1:0] HMR_REGISTERS_DMR_ENABLE_OFFSET = 5'h 8; - parameter logic [BlockAw-1:0] HMR_REGISTERS_TMR_ENABLE_OFFSET = 5'h c; - parameter logic [BlockAw-1:0] HMR_REGISTERS_DMR_CONFIG_OFFSET = 5'h 10; - parameter logic [BlockAw-1:0] HMR_REGISTERS_TMR_CONFIG_OFFSET = 5'h 14; - - // Reset values for hwext registers and their fields - parameter logic [8:0] HMR_REGISTERS_AVAIL_CONFIG_RESVAL = 9'h 0; - parameter logic [11:0] HMR_REGISTERS_CORES_EN_RESVAL = 12'h 0; - parameter logic [5:0] HMR_REGISTERS_DMR_ENABLE_RESVAL = 6'h 0; - parameter logic [5:0] HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_RESVAL = 6'h 0; - parameter logic [3:0] HMR_REGISTERS_TMR_ENABLE_RESVAL = 4'h 0; - parameter logic [3:0] HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_RESVAL = 4'h 0; - parameter logic [1:0] HMR_REGISTERS_DMR_CONFIG_RESVAL = 2'h 0; - parameter logic [4:0] HMR_REGISTERS_TMR_CONFIG_RESVAL = 5'h 6; - parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_DELAY_RESYNCH_RESVAL = 1'h 0; - parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_SETBACK_RESVAL = 1'h 1; - parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_RELOAD_SETBACK_RESVAL = 1'h 1; - parameter logic [0:0] HMR_REGISTERS_TMR_CONFIG_FORCE_RESYNCH_RESVAL = 1'h 0; - - // Register index - typedef enum int { - HMR_REGISTERS_AVAIL_CONFIG, - HMR_REGISTERS_CORES_EN, - HMR_REGISTERS_DMR_ENABLE, - HMR_REGISTERS_TMR_ENABLE, - HMR_REGISTERS_DMR_CONFIG, - HMR_REGISTERS_TMR_CONFIG - } hmr_registers_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] HMR_REGISTERS_PERMIT [6] = '{ - 4'b 0011, // index[0] HMR_REGISTERS_AVAIL_CONFIG - 4'b 0011, // index[1] HMR_REGISTERS_CORES_EN - 4'b 0001, // index[2] HMR_REGISTERS_DMR_ENABLE - 4'b 0001, // index[3] HMR_REGISTERS_TMR_ENABLE - 4'b 0001, // index[4] HMR_REGISTERS_DMR_CONFIG - 4'b 0001 // index[5] HMR_REGISTERS_TMR_CONFIG - }; - + localparam HMR_REGISTERS_REG_TOP_DATA_WIDTH = 32; + localparam HMR_REGISTERS_REG_TOP_MIN_ADDR_WIDTH = 5; + localparam HMR_REGISTERS_REG_TOP_SIZE = 'h18; + localparam NumCores = 'hc; + localparam NumDMRGroups = 'h6; + localparam NumTMRGroups = 'h4; + + typedef struct packed { + logic [22:0] _reserved_31_9; + logic rapid_recovery; + logic [4:0] _reserved_7_3; + logic triple; + logic dual; + logic independent; + } hmr__avail_config__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__avail_config__external__fields__in_t rd_data; + } hmr__avail_config__external__in_t; + + typedef struct packed { + logic [19:0] _reserved_31_12; + logic [11:0] cores_en; + } hmr__cores_en__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__cores_en__external__fields__in_t rd_data; + } hmr__cores_en__external__in_t; + + typedef struct packed { + logic [25:0] _reserved_31_6; + logic [5:0] dmr_enable; + } hmr__dmr_enable__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__dmr_enable__external__fields__in_t rd_data; + logic wr_ack; + } hmr__dmr_enable__external__in_t; + + typedef struct packed { + logic [27:0] _reserved_31_4; + logic [3:0] tmr_enable; + } hmr__tmr_enable__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__tmr_enable__external__fields__in_t rd_data; + logic wr_ack; + } hmr__tmr_enable__external__in_t; + + typedef struct packed { + logic [29:0] _reserved_31_2; + logic force_recovery; + logic rapid_recovery; + } hmr__dmr_config__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__dmr_config__external__fields__in_t rd_data; + logic wr_ack; + } hmr__dmr_config__external__in_t; + + typedef struct packed { + logic [26:0] _reserved_31_5; + logic force_resynch; + logic rapid_recovery; + logic reload_setback; + logic setback; + logic delay_resynch; + } hmr__tmr_config__external__fields__in_t; + + typedef struct { + logic rd_ack; + hmr__tmr_config__external__fields__in_t rd_data; + logic wr_ack; + } hmr__tmr_config__external__in_t; + + typedef struct { + hmr__avail_config__external__in_t avail_config; + hmr__cores_en__external__in_t cores_en; + hmr__dmr_enable__external__in_t dmr_enable; + hmr__tmr_enable__external__in_t tmr_enable; + hmr__dmr_config__external__in_t dmr_config; + hmr__tmr_config__external__in_t tmr_config; + } hmr__in_t; + + typedef struct { + logic req; + logic req_is_wr; + } hmr__avail_config__external__out_t; + + typedef struct { + logic req; + logic req_is_wr; + } hmr__cores_en__external__out_t; + + typedef struct packed { + logic [25:0] _reserved_31_6; + logic [5:0] dmr_enable; + } hmr__dmr_enable__external__fields__out_t; + + typedef struct { + logic req; + logic req_is_wr; + hmr__dmr_enable__external__fields__out_t wr_data; + hmr__dmr_enable__external__fields__out_t wr_biten; + } hmr__dmr_enable__external__out_t; + + typedef struct packed { + logic [27:0] _reserved_31_4; + logic [3:0] tmr_enable; + } hmr__tmr_enable__external__fields__out_t; + + typedef struct { + logic req; + logic req_is_wr; + hmr__tmr_enable__external__fields__out_t wr_data; + hmr__tmr_enable__external__fields__out_t wr_biten; + } hmr__tmr_enable__external__out_t; + + typedef struct packed { + logic [29:0] _reserved_31_2; + logic force_recovery; + logic rapid_recovery; + } hmr__dmr_config__external__fields__out_t; + + typedef struct { + logic req; + logic req_is_wr; + hmr__dmr_config__external__fields__out_t wr_data; + hmr__dmr_config__external__fields__out_t wr_biten; + } hmr__dmr_config__external__out_t; + + typedef struct packed { + logic [26:0] _reserved_31_5; + logic force_resynch; + logic rapid_recovery; + logic reload_setback; + logic setback; + logic delay_resynch; + } hmr__tmr_config__external__fields__out_t; + + typedef struct { + logic req; + logic req_is_wr; + hmr__tmr_config__external__fields__out_t wr_data; + hmr__tmr_config__external__fields__out_t wr_biten; + } hmr__tmr_config__external__out_t; + + typedef struct { + hmr__avail_config__external__out_t avail_config; + hmr__cores_en__external__out_t cores_en; + hmr__dmr_enable__external__out_t dmr_enable; + hmr__tmr_enable__external__out_t tmr_enable; + hmr__dmr_config__external__out_t dmr_config; + hmr__tmr_config__external__out_t tmr_config; + } hmr__out_t; endpackage - diff --git a/rtl/HMR/hmr_registers_reg_top.sv b/rtl/HMR/hmr_registers_reg_top.sv index 9769fed7..52d5d4dd 100644 --- a/rtl/HMR/hmr_registers_reg_top.sv +++ b/rtl/HMR/hmr_registers_reg_top.sv @@ -1,516 +1,246 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module hmr_registers_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 5 -) ( - 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 hmr_registers_reg_pkg::hmr_registers_reg2hw_t reg2hw, // Write - input hmr_registers_reg_pkg::hmr_registers_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import hmr_registers_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-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; - 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 avail_config_independent_qs; - logic avail_config_independent_re; - logic avail_config_dual_qs; - logic avail_config_dual_re; - logic avail_config_triple_qs; - logic avail_config_triple_re; - logic avail_config_rapid_recovery_qs; - logic avail_config_rapid_recovery_re; - logic [11:0] cores_en_qs; - logic cores_en_re; - logic [5:0] dmr_enable_qs; - logic [5:0] dmr_enable_wd; - logic dmr_enable_we; - logic dmr_enable_re; - logic [3:0] tmr_enable_qs; - logic [3:0] tmr_enable_wd; - logic tmr_enable_we; - logic tmr_enable_re; - logic dmr_config_rapid_recovery_qs; - logic dmr_config_rapid_recovery_wd; - logic dmr_config_rapid_recovery_we; - logic dmr_config_rapid_recovery_re; - logic dmr_config_force_recovery_qs; - logic dmr_config_force_recovery_wd; - logic dmr_config_force_recovery_we; - logic dmr_config_force_recovery_re; - logic tmr_config_delay_resynch_qs; - logic tmr_config_delay_resynch_wd; - logic tmr_config_delay_resynch_we; - logic tmr_config_delay_resynch_re; - logic tmr_config_setback_qs; - logic tmr_config_setback_wd; - logic tmr_config_setback_we; - logic tmr_config_setback_re; - logic tmr_config_reload_setback_qs; - logic tmr_config_reload_setback_wd; - logic tmr_config_reload_setback_we; - logic tmr_config_reload_setback_re; - logic tmr_config_rapid_recovery_qs; - logic tmr_config_rapid_recovery_wd; - logic tmr_config_rapid_recovery_we; - logic tmr_config_rapid_recovery_re; - logic tmr_config_force_resynch_qs; - logic tmr_config_force_resynch_wd; - logic tmr_config_force_resynch_we; - logic tmr_config_force_resynch_re; - - // Register instances - // R[avail_config]: V(True) - - // F[independent]: 0:0 - prim_subreg_ext #( - .DW (1) - ) u_avail_config_independent ( - .re (avail_config_independent_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.avail_config.independent.d), - .qre (), - .qe (), - .q (), - .qs (avail_config_independent_qs) - ); - - - // F[dual]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_avail_config_dual ( - .re (avail_config_dual_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.avail_config.dual.d), - .qre (), - .qe (), - .q (), - .qs (avail_config_dual_qs) - ); - - - // F[triple]: 2:2 - prim_subreg_ext #( - .DW (1) - ) u_avail_config_triple ( - .re (avail_config_triple_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.avail_config.triple.d), - .qre (), - .qe (), - .q (), - .qs (avail_config_triple_qs) - ); - - - // F[rapid_recovery]: 8:8 - prim_subreg_ext #( - .DW (1) - ) u_avail_config_rapid_recovery ( - .re (avail_config_rapid_recovery_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.avail_config.rapid_recovery.d), - .qre (), - .qe (), - .q (), - .qs (avail_config_rapid_recovery_qs) - ); - - - // R[cores_en]: V(True) - - prim_subreg_ext #( - .DW (12) - ) u_cores_en ( - .re (cores_en_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.cores_en.d), - .qre (), - .qe (), - .q (), - .qs (cores_en_qs) - ); - - - // R[dmr_enable]: V(True) - - prim_subreg_ext #( - .DW (6) - ) u_dmr_enable ( - .re (dmr_enable_re), - .we (dmr_enable_we), - .wd (dmr_enable_wd), - .d (hw2reg.dmr_enable.d), - .qre (), - .qe (reg2hw.dmr_enable.qe), - .q (reg2hw.dmr_enable.q ), - .qs (dmr_enable_qs) - ); - - - // R[tmr_enable]: V(True) - - prim_subreg_ext #( - .DW (4) - ) u_tmr_enable ( - .re (tmr_enable_re), - .we (tmr_enable_we), - .wd (tmr_enable_wd), - .d (hw2reg.tmr_enable.d), - .qre (), - .qe (reg2hw.tmr_enable.qe), - .q (reg2hw.tmr_enable.q ), - .qs (tmr_enable_qs) - ); - - - // R[dmr_config]: V(True) - - // F[rapid_recovery]: 0:0 - prim_subreg_ext #( - .DW (1) - ) u_dmr_config_rapid_recovery ( - .re (dmr_config_rapid_recovery_re), - .we (dmr_config_rapid_recovery_we), - .wd (dmr_config_rapid_recovery_wd), - .d (hw2reg.dmr_config.rapid_recovery.d), - .qre (), - .qe (reg2hw.dmr_config.rapid_recovery.qe), - .q (reg2hw.dmr_config.rapid_recovery.q ), - .qs (dmr_config_rapid_recovery_qs) - ); - - - // F[force_recovery]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_dmr_config_force_recovery ( - .re (dmr_config_force_recovery_re), - .we (dmr_config_force_recovery_we), - .wd (dmr_config_force_recovery_wd), - .d (hw2reg.dmr_config.force_recovery.d), - .qre (), - .qe (reg2hw.dmr_config.force_recovery.qe), - .q (reg2hw.dmr_config.force_recovery.q ), - .qs (dmr_config_force_recovery_qs) - ); - - - // R[tmr_config]: V(True) - - // F[delay_resynch]: 0:0 - prim_subreg_ext #( - .DW (1) - ) u_tmr_config_delay_resynch ( - .re (tmr_config_delay_resynch_re), - .we (tmr_config_delay_resynch_we), - .wd (tmr_config_delay_resynch_wd), - .d (hw2reg.tmr_config.delay_resynch.d), - .qre (), - .qe (reg2hw.tmr_config.delay_resynch.qe), - .q (reg2hw.tmr_config.delay_resynch.q ), - .qs (tmr_config_delay_resynch_qs) - ); - - - // F[setback]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_tmr_config_setback ( - .re (tmr_config_setback_re), - .we (tmr_config_setback_we), - .wd (tmr_config_setback_wd), - .d (hw2reg.tmr_config.setback.d), - .qre (), - .qe (reg2hw.tmr_config.setback.qe), - .q (reg2hw.tmr_config.setback.q ), - .qs (tmr_config_setback_qs) - ); - - - // F[reload_setback]: 2:2 - prim_subreg_ext #( - .DW (1) - ) u_tmr_config_reload_setback ( - .re (tmr_config_reload_setback_re), - .we (tmr_config_reload_setback_we), - .wd (tmr_config_reload_setback_wd), - .d (hw2reg.tmr_config.reload_setback.d), - .qre (), - .qe (reg2hw.tmr_config.reload_setback.qe), - .q (reg2hw.tmr_config.reload_setback.q ), - .qs (tmr_config_reload_setback_qs) - ); - - - // F[rapid_recovery]: 3:3 - prim_subreg_ext #( - .DW (1) - ) u_tmr_config_rapid_recovery ( - .re (tmr_config_rapid_recovery_re), - .we (tmr_config_rapid_recovery_we), - .wd (tmr_config_rapid_recovery_wd), - .d (hw2reg.tmr_config.rapid_recovery.d), - .qre (), - .qe (reg2hw.tmr_config.rapid_recovery.qe), - .q (reg2hw.tmr_config.rapid_recovery.q ), - .qs (tmr_config_rapid_recovery_qs) - ); - - - // F[force_resynch]: 4:4 - prim_subreg_ext #( - .DW (1) - ) u_tmr_config_force_resynch ( - .re (tmr_config_force_resynch_re), - .we (tmr_config_force_resynch_we), - .wd (tmr_config_force_resynch_wd), - .d (hw2reg.tmr_config.force_resynch.d), - .qre (), - .qe (reg2hw.tmr_config.force_resynch.qe), - .q (reg2hw.tmr_config.force_resynch.q ), - .qs (tmr_config_force_resynch_qs) - ); - - - - - logic [5:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == HMR_REGISTERS_AVAIL_CONFIG_OFFSET); - addr_hit[1] = (reg_addr == HMR_REGISTERS_CORES_EN_OFFSET); - addr_hit[2] = (reg_addr == HMR_REGISTERS_DMR_ENABLE_OFFSET); - addr_hit[3] = (reg_addr == HMR_REGISTERS_TMR_ENABLE_OFFSET); - addr_hit[4] = (reg_addr == HMR_REGISTERS_DMR_CONFIG_OFFSET); - addr_hit[5] = (reg_addr == HMR_REGISTERS_TMR_CONFIG_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] & (|(HMR_REGISTERS_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(HMR_REGISTERS_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(HMR_REGISTERS_PERMIT[2] & ~reg_be))) | - (addr_hit[3] & (|(HMR_REGISTERS_PERMIT[3] & ~reg_be))) | - (addr_hit[4] & (|(HMR_REGISTERS_PERMIT[4] & ~reg_be))) | - (addr_hit[5] & (|(HMR_REGISTERS_PERMIT[5] & ~reg_be))))); - end - - assign avail_config_independent_re = addr_hit[0] & reg_re & !reg_error; - - assign avail_config_dual_re = addr_hit[0] & reg_re & !reg_error; - - assign avail_config_triple_re = addr_hit[0] & reg_re & !reg_error; - - assign avail_config_rapid_recovery_re = addr_hit[0] & reg_re & !reg_error; - - assign cores_en_re = addr_hit[1] & reg_re & !reg_error; - - assign dmr_enable_we = addr_hit[2] & reg_we & !reg_error; - assign dmr_enable_wd = reg_wdata[5:0]; - assign dmr_enable_re = addr_hit[2] & reg_re & !reg_error; - - assign tmr_enable_we = addr_hit[3] & reg_we & !reg_error; - assign tmr_enable_wd = reg_wdata[3:0]; - assign tmr_enable_re = addr_hit[3] & reg_re & !reg_error; - - assign dmr_config_rapid_recovery_we = addr_hit[4] & reg_we & !reg_error; - assign dmr_config_rapid_recovery_wd = reg_wdata[0]; - assign dmr_config_rapid_recovery_re = addr_hit[4] & reg_re & !reg_error; - - assign dmr_config_force_recovery_we = addr_hit[4] & reg_we & !reg_error; - assign dmr_config_force_recovery_wd = reg_wdata[1]; - assign dmr_config_force_recovery_re = addr_hit[4] & reg_re & !reg_error; - - assign tmr_config_delay_resynch_we = addr_hit[5] & reg_we & !reg_error; - assign tmr_config_delay_resynch_wd = reg_wdata[0]; - assign tmr_config_delay_resynch_re = addr_hit[5] & reg_re & !reg_error; - - assign tmr_config_setback_we = addr_hit[5] & reg_we & !reg_error; - assign tmr_config_setback_wd = reg_wdata[1]; - assign tmr_config_setback_re = addr_hit[5] & reg_re & !reg_error; - - assign tmr_config_reload_setback_we = addr_hit[5] & reg_we & !reg_error; - assign tmr_config_reload_setback_wd = reg_wdata[2]; - assign tmr_config_reload_setback_re = addr_hit[5] & reg_re & !reg_error; - - assign tmr_config_rapid_recovery_we = addr_hit[5] & reg_we & !reg_error; - assign tmr_config_rapid_recovery_wd = reg_wdata[3]; - assign tmr_config_rapid_recovery_re = addr_hit[5] & reg_re & !reg_error; - - assign tmr_config_force_resynch_we = addr_hit[5] & reg_we & !reg_error; - assign tmr_config_force_resynch_wd = reg_wdata[4]; - assign tmr_config_force_resynch_re = addr_hit[5] & 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[0] = avail_config_independent_qs; - reg_rdata_next[1] = avail_config_dual_qs; - reg_rdata_next[2] = avail_config_triple_qs; - reg_rdata_next[8] = avail_config_rapid_recovery_qs; - end - - addr_hit[1]: begin - reg_rdata_next[11:0] = cores_en_qs; - end - - addr_hit[2]: begin - reg_rdata_next[5:0] = dmr_enable_qs; - end - - addr_hit[3]: begin - reg_rdata_next[3:0] = tmr_enable_qs; - end - - addr_hit[4]: begin - reg_rdata_next[0] = dmr_config_rapid_recovery_qs; - reg_rdata_next[1] = dmr_config_force_recovery_qs; - end - - addr_hit[5]: begin - reg_rdata_next[0] = tmr_config_delay_resynch_qs; - reg_rdata_next[1] = tmr_config_setback_qs; - reg_rdata_next[2] = tmr_config_reload_setback_qs; - reg_rdata_next[3] = tmr_config_rapid_recovery_qs; - reg_rdata_next[4] = tmr_config_force_resynch_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)) - +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module hmr_registers_reg_top ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [4:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + input hmr_registers_reg_pkg::hmr__in_t hwif_in, + output hmr_registers_reg_pkg::hmr__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [4:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[4:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + logic external_req; + logic external_pending; + logic external_wr_ack; + logic external_rd_ack; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + external_pending <= '0; + end else begin + if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1; + else if(external_wr_ack | external_rd_ack) external_pending <= '0; + `ifndef SYNTHESIS + assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req)) + else $error("An external wr_ack strobe was asserted when no external request was active"); + assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req)) + else $error("An external rd_ack strobe was asserted when no external request was active"); + `endif + end + end + + // Read & write latencies are balanced. Stalls not required + // except if external + assign cpuif_req_stall_rd = external_pending; + assign cpuif_req_stall_wr = external_pending; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic avail_config; + logic cores_en; + logic dmr_enable; + logic tmr_enable; + logic dmr_config; + logic tmr_config; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_strb_is_external; + + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + automatic logic is_external; + is_external = '0; + decoded_reg_strb.avail_config = cpuif_req_masked & (cpuif_addr == 5'h0); + is_external |= cpuif_req_masked & (cpuif_addr == 5'h0) & !cpuif_req_is_wr; + decoded_reg_strb.cores_en = cpuif_req_masked & (cpuif_addr == 5'h4); + is_external |= cpuif_req_masked & (cpuif_addr == 5'h4) & !cpuif_req_is_wr; + decoded_reg_strb.dmr_enable = cpuif_req_masked & (cpuif_addr == 5'h8); + is_external |= cpuif_req_masked & (cpuif_addr == 5'h8); + decoded_reg_strb.tmr_enable = cpuif_req_masked & (cpuif_addr == 5'hc); + is_external |= cpuif_req_masked & (cpuif_addr == 5'hc); + decoded_reg_strb.dmr_config = cpuif_req_masked & (cpuif_addr == 5'h10); + is_external |= cpuif_req_masked & (cpuif_addr == 5'h10); + decoded_reg_strb.tmr_config = cpuif_req_masked & (cpuif_addr == 5'h14); + is_external |= cpuif_req_masked & (cpuif_addr == 5'h14); + decoded_strb_is_external = is_external; + external_req = is_external; + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + + + + + + assign hwif_out.avail_config.req = !decoded_req_is_wr ? decoded_reg_strb.avail_config : '0; + assign hwif_out.avail_config.req_is_wr = decoded_req_is_wr; + + assign hwif_out.cores_en.req = !decoded_req_is_wr ? decoded_reg_strb.cores_en : '0; + assign hwif_out.cores_en.req_is_wr = decoded_req_is_wr; + + assign hwif_out.dmr_enable.req = decoded_reg_strb.dmr_enable; + assign hwif_out.dmr_enable.req_is_wr = decoded_req_is_wr; + assign hwif_out.dmr_enable.wr_data = decoded_wr_data; + assign hwif_out.dmr_enable.wr_biten = decoded_wr_biten; + + assign hwif_out.tmr_enable.req = decoded_reg_strb.tmr_enable; + assign hwif_out.tmr_enable.req_is_wr = decoded_req_is_wr; + assign hwif_out.tmr_enable.wr_data = decoded_wr_data; + assign hwif_out.tmr_enable.wr_biten = decoded_wr_biten; + + assign hwif_out.dmr_config.req = decoded_reg_strb.dmr_config; + assign hwif_out.dmr_config.req_is_wr = decoded_req_is_wr; + assign hwif_out.dmr_config.wr_data = decoded_wr_data; + assign hwif_out.dmr_config.wr_biten = decoded_wr_biten; + + assign hwif_out.tmr_config.req = decoded_reg_strb.tmr_config; + assign hwif_out.tmr_config.req_is_wr = decoded_req_is_wr; + assign hwif_out.tmr_config.wr_data = decoded_wr_data; + assign hwif_out.tmr_config.wr_biten = decoded_wr_biten; + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + always_comb begin + automatic logic wr_ack; + wr_ack = '0; + wr_ack |= hwif_in.dmr_enable.wr_ack; + wr_ack |= hwif_in.tmr_enable.wr_ack; + wr_ack |= hwif_in.dmr_config.wr_ack; + wr_ack |= hwif_in.tmr_config.wr_ack; + external_wr_ack = wr_ack; + end + assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external); + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + logic readback_external_rd_ack_c; + always_comb begin + automatic logic rd_ack; + rd_ack = '0; + rd_ack |= hwif_in.avail_config.rd_ack; + rd_ack |= hwif_in.cores_en.rd_ack; + rd_ack |= hwif_in.dmr_enable.rd_ack; + rd_ack |= hwif_in.tmr_enable.rd_ack; + rd_ack |= hwif_in.dmr_config.rd_ack; + rd_ack |= hwif_in.tmr_config.rd_ack; + readback_external_rd_ack_c = rd_ack; + end + + logic readback_external_rd_ack; + + assign readback_external_rd_ack = readback_external_rd_ack_c; + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [31:0] readback_array[6]; + assign readback_array[0] = hwif_in.avail_config.rd_ack ? hwif_in.avail_config.rd_data : '0; + assign readback_array[1] = hwif_in.cores_en.rd_ack ? hwif_in.cores_en.rd_data : '0; + assign readback_array[2] = hwif_in.dmr_enable.rd_ack ? hwif_in.dmr_enable.rd_data : '0; + assign readback_array[3] = hwif_in.tmr_enable.rd_ack ? hwif_in.tmr_enable.rd_data : '0; + assign readback_array[4] = hwif_in.dmr_config.rd_ack ? hwif_in.dmr_config.rd_data : '0; + assign readback_array[5] = hwif_in.tmr_config.rd_ack ? hwif_in.tmr_config.rd_data : '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<6; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign external_rd_ack = readback_external_rd_ack; + assign cpuif_rd_ack = readback_done | readback_external_rd_ack; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; endmodule - -module hmr_registers_reg_top_intf -#( - parameter int AW = 5, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output hmr_registers_reg_pkg::hmr_registers_reg2hw_t reg2hw, // Write - input hmr_registers_reg_pkg::hmr_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) - - - - hmr_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 - - diff --git a/rtl/HMR/hmr_regs.rdl b/rtl/HMR/hmr_regs.rdl new file mode 100644 index 00000000..a053c0b9 --- /dev/null +++ b/rtl/HMR/hmr_regs.rdl @@ -0,0 +1,145 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +addrmap hmr #( + longint unsigned NumCores = 12, + longint unsigned NumDMRGroups = 6, + longint unsigned NumTMRGroups = 4 +) { + + reg avail_config { + name = "avail_config"; + desc = "Available Configurations from implemented hardware."; + field { + name = "independent"; + desc = "1 if independent mode is available"; + sw = r; + hw = w; + } independent[0:0] = 0x1; + field { + name = "dual"; + desc = "1 if dual/DMR mode is available"; + sw = r; + hw = w; + } dual[1:1] = 0x1; + field { + name = "triple"; + desc = "1 if triple/TMR mode is available"; + sw = r; + hw = w; + } triple[2:2] = 0x1; + field { + name = "rapid_recovery"; + desc = "Number of cores in the system."; + sw = r; + hw = w; + } rapid_recovery[8:8] = 0x1; + }; + + reg cores_en { + name = "cores_en"; + desc = "Enabled cores, based on the configuration. Can be used for barriers."; + field { + name = "cores_en"; + desc = "Enabled cores."; + sw = r; + hw = w; + } cores_en[NumCores-1:0] = 0x0; + }; + + reg dmr_enable { + name = "dmr_enable"; + desc = "DMR configuration enable, on bit per DMR group."; + field { + name = "dmr_enable"; + desc = "Enable DMR mode"; + sw = rw; + hw = rw; + swmod = true; + } dmr_enable[NumDMRGroups-1:0] = 0x0; + }; + + reg tmr_enable { + name = "tmr_enable"; + desc = "TMR configuration enable, on bit per TMR group."; + field { + name = "tmr_enable"; + desc = "Enable TMR mode"; + sw = rw; + hw = rw; + swmod = true; + } tmr_enable[NumTMRGroups-1:0] = 0x0; + }; + reg dmr_config { // From hmr_dmr_regs.rdl + name = "dmr_config"; + desc = "DMR Configuration Register"; + field { + name = "rapid_recovery"; + desc = "Enable rapid recovery using an additional register file."; + sw = rw; + hw = rw; + swmod = true; + } rapid_recovery[0:0] = 0x0; + field { + name = "force_recovery"; + desc = "Forces recovery routine (if rapid_recovery is available)."; + sw = rw; + hw = rw; + swmod = true; + } force_recovery[1:1] = 0x0; + }; + reg tmr_config { // From hmr_tmr_regs.rdl + name = "tmr_config"; + desc = "TMR Configuration Register"; + field { + name = "delay_resynch"; + desc = "Enable wait-for-restoration."; + sw = rw; + hw = rw; + swmod = true; + } delay_resynch[0:0] = 0x0; + field { + name = "setback"; + desc = "Enable setback (synchronous reset) during re-synch."; + sw = rw; + hw = rw; + swmod = true; + } setback[1:1] = 0x1; + field { + name = "reload_setback"; + desc = "Enable reload of the setback value from the register."; + sw = rw; + hw = rw; + swmod = true; + } reload_setback[2:2] = 0x1; + field { + name = "rapid_recovery"; + desc = "Enable rapid recovery using an additional register file."; + sw = rw; + hw = rw; + swmod = true; + } rapid_recovery[3:3] = 0x0; + field { + name = "force_resynch"; + desc = "Forces a resynchronization routine."; + sw = rw; + hw = rw; + swmod = true; + } force_resynch[4:4] = 0x0; + }; + + + external avail_config avail_config; + external cores_en cores_en; + external dmr_enable dmr_enable; + external tmr_enable tmr_enable; + external dmr_config dmr_config; + external tmr_config tmr_config; +}; diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index f23512f3..49fefb4d 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -15,16 +15,16 @@ module hmr_tmr_ctrl #( parameter bit TMRFixed = 1'b0, parameter bit DefaultInTMR = TMRFixed ? 1'b1 : 1'b0, parameter bit RapidRecovery = 1'b0, - parameter type reg_req_t = logic, - parameter type reg_resp_t = logic + parameter type apb_req_t = logic, + parameter type apb_resp_t = logic ) ( input logic clk_i, input logic rst_ni, // input logic test_enable_i, // Register interface - input reg_req_t reg_req_i, - output reg_resp_t reg_resp_o, + input apb_req_t apb_req_i, + output apb_resp_t apb_resp_o, // CTRL from external (e.g. HMR ctrl regs) input logic tmr_enable_q_i, @@ -65,45 +65,49 @@ module hmr_tmr_ctrl #( typedef enum logic [2:0] {NON_TMR, TMR_RUN, TMR_UNLOAD, TMR_RELOAD, TMR_RAPID} tmr_mode_e; localparam tmr_mode_e DefaultTMRMode = DefaultInTMR || TMRFixed ? TMR_RUN : NON_TMR; - hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t tmr_reg2hw; - hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t tmr_hw2reg; + hmr_tmr_regs_reg_pkg::hmr_tmr__out_t tmr_reg2hw; + hmr_tmr_regs_reg_pkg::hmr_tmr__in_t tmr_hw2reg; tmr_mode_e tmr_red_mode_d, tmr_red_mode_q; assign grp_in_independent_o = tmr_red_mode_q == NON_TMR; assign tmr_resynch_req_o = tmr_red_mode_q == TMR_UNLOAD; - assign rapid_recovery_en_o = tmr_reg2hw.tmr_config.rapid_recovery.q & RapidRecovery; + assign rapid_recovery_en_o = tmr_reg2hw.tmr_config.rapid_recovery.value & RapidRecovery; assign sw_synch_req_o = synch_req & ~synch_req_sent_q; assign synch_req_sent_d = synch_req; assign sw_resynch_req_o = resynch_req & ~resynch_req_sent_q; assign resynch_req_sent_d = resynch_req; - hmr_tmr_regs_reg_top #( - .reg_req_t(reg_req_t), - .reg_rsp_t(reg_resp_t) - ) i_tmr_regs ( - .clk_i, - .rst_ni, - .reg_req_i(reg_req_i), - .reg_rsp_o(reg_resp_o), - .reg2hw (tmr_reg2hw), - .hw2reg (tmr_hw2reg), - .devmode_i('0) + hmr_tmr_regs_reg_top i_tmr_regs ( + .clk (clk_i), + .arst_n (rst_ni), + .s_apb_psel (apb_req_i.psel), + .s_apb_penable (apb_req_i.penable), + .s_apb_pwrite (apb_req_i.pwrite), + .s_apb_pprot (apb_req_i.pprot), + .s_apb_paddr (apb_req_i.paddr[2:0]), + .s_apb_pwdata (apb_req_i.pwdata), + .s_apb_pstrb (apb_req_i.pstrb), + .s_apb_pready (apb_resp_o.pready), + .s_apb_prdata (apb_resp_o.prdata), + .s_apb_pslverr (apb_resp_o.pslverr), + .hwif_in (tmr_hw2reg), + .hwif_out (tmr_reg2hw) ); // Global config update - assign tmr_hw2reg.tmr_enable.de = tmr_enable_qe_i; - assign tmr_hw2reg.tmr_enable.d = tmr_enable_q_i; - assign tmr_hw2reg.tmr_config.delay_resynch.de = delay_resynch_qe_i; - assign tmr_hw2reg.tmr_config.delay_resynch.d = delay_resynch_q_i; - assign tmr_hw2reg.tmr_config.setback.de = setback_qe_i; - assign tmr_hw2reg.tmr_config.setback.d = setback_q_i; - assign tmr_hw2reg.tmr_config.reload_setback.de = reload_setback_qe_i; - assign tmr_hw2reg.tmr_config.reload_setback.d = reload_setback_q_i; - assign tmr_hw2reg.tmr_config.rapid_recovery.de = rapid_recovery_qe_i; - assign tmr_hw2reg.tmr_config.rapid_recovery.d = rapid_recovery_q_i; - assign tmr_hw2reg.tmr_config.force_resynch.d = force_resynch_qe_i ? force_resynch_q_i : 1'b0; + assign tmr_hw2reg.tmr_enable.tmr_enable.we = tmr_enable_qe_i; + assign tmr_hw2reg.tmr_enable.tmr_enable.next = tmr_enable_q_i; + assign tmr_hw2reg.tmr_config.delay_resynch.we = delay_resynch_qe_i; + assign tmr_hw2reg.tmr_config.delay_resynch.next = delay_resynch_q_i; + assign tmr_hw2reg.tmr_config.setback.we = setback_qe_i; + assign tmr_hw2reg.tmr_config.setback.next = setback_q_i; + assign tmr_hw2reg.tmr_config.reload_setback.we = reload_setback_qe_i; + assign tmr_hw2reg.tmr_config.reload_setback.next = reload_setback_q_i; + assign tmr_hw2reg.tmr_config.rapid_recovery.we = rapid_recovery_qe_i; + assign tmr_hw2reg.tmr_config.rapid_recovery.next = rapid_recovery_q_i; + assign tmr_hw2reg.tmr_config.force_resynch.next = force_resynch_qe_i ? force_resynch_q_i : 1'b0; /************************** * FSM for TMR lockstep * @@ -116,16 +120,16 @@ module hmr_tmr_ctrl #( resynch_req = 1'b0; synch_req = 1'b0; - tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; + tmr_hw2reg.tmr_config.force_resynch.we = force_resynch_qe_i; case (tmr_red_mode_q) TMR_RUN: begin // If forced execute resynchronization - if (tmr_reg2hw.tmr_config.force_resynch.q) begin - tmr_hw2reg.tmr_config.force_resynch.de = 1'b1; - if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin + if (tmr_reg2hw.tmr_config.force_resynch.value) begin + tmr_hw2reg.tmr_config.force_resynch.we = 1'b1; + if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; - end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin + end else if (tmr_reg2hw.tmr_config.delay_resynch.value == '0) begin tmr_red_mode_d = TMR_UNLOAD; // TODO: buffer the restoration until delay_resynch is disabled end @@ -138,9 +142,9 @@ module hmr_tmr_ctrl #( if (tmr_error_i[1]) tmr_incr_mismatches_o[1] = 1'b1; if (tmr_error_i[2]) tmr_incr_mismatches_o[2] = 1'b1; - if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; - end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin + end else if (tmr_reg2hw.tmr_config.delay_resynch.value == '0) begin tmr_red_mode_d = TMR_UNLOAD; // TODO: buffer the restoration until delay_resynch is disabled end @@ -152,7 +156,7 @@ module hmr_tmr_ctrl #( // If unload complete, go to reload (and reset) if (!sp_store_is_zero) begin tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q) begin + if (tmr_reg2hw.tmr_config.setback.value) begin setback_o = 3'b111; end end @@ -164,8 +168,8 @@ module hmr_tmr_ctrl #( // $display("[HMR-triple] %t - mismatch restored", $realtime); tmr_red_mode_d = TMR_RUN; end else begin - if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.q && - tmr_reg2hw.tmr_config.reload_setback.q && + if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.value && + tmr_reg2hw.tmr_config.reload_setback.value && !sp_store_will_be_zero) begin setback_o = 3'b111; end @@ -188,14 +192,14 @@ module hmr_tmr_ctrl #( // Logic to switch in and out of TMR if (!TMRFixed) begin // Set TMR mode on external signal that cores are synchronized - if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.q == 1'b1) begin + if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b1) begin synch_req = 1'b1; if (cores_synch_q == 1'b1) begin - if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.value == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; end else begin tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin + if (tmr_reg2hw.tmr_config.setback.value == 1'b1) begin setback_o = 3'b111; end end @@ -203,7 +207,7 @@ module hmr_tmr_ctrl #( end // Before core startup: set TMR mode from reg2hw.tmr_enable if (fetch_en_i == 0) begin - if (tmr_reg2hw.tmr_enable.q == 1'b0) begin + if (tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b0) begin tmr_red_mode_d = NON_TMR; end else begin tmr_red_mode_d = TMR_RUN; @@ -212,8 +216,8 @@ module hmr_tmr_ctrl #( end // split tolerant mode to performance mode anytime (but require correct core state) if (tmr_red_mode_q == TMR_RUN) begin - if (tmr_reg2hw.tmr_enable.q == 1'b0) begin - if (tmr_reg2hw.tmr_config.setback.q) begin + if (tmr_reg2hw.tmr_enable.tmr_enable.value == 1'b0) begin + if (tmr_reg2hw.tmr_config.setback.value) begin setback_o = 3'b110; end tmr_red_mode_d = NON_TMR; diff --git a/rtl/HMR/hmr_tmr_regs.rdl b/rtl/HMR/hmr_tmr_regs.rdl new file mode 100644 index 00000000..664dbdf2 --- /dev/null +++ b/rtl/HMR/hmr_tmr_regs.rdl @@ -0,0 +1,71 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +addrmap hmr_tmr { + reg tmr_enable { + name = "tmr_enable"; + desc = "TMR Configuration Enable"; + field { + name = "enable"; + desc = "Enable TMR mode"; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } tmr_enable[0:0] = 0x0; + }; + reg tmr_config { + name = "tmr_config"; + desc = "TMR Configuration Register"; + field { + name = "delay_resynch"; + desc = "Enable wait-for-restoration."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } delay_resynch[0:0] = 0x0; + field { + name = "setback"; + desc = "Enable setback (synchronous reset) during re-synch."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } setback[1:1] = 0x1; + field { + name = "reload_setback"; + desc = "Enable reload of the setback value from the register."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } reload_setback[2:2] = 0x1; + field { + name = "rapid_recovery"; + desc = "Enable rapid recovery using an additional register file."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } rapid_recovery[3:3] = 0x0; + field { + name = "force_resynch"; + desc = "Forces a resynchronization routine."; + sw = rw; + hw = rw; + // swmod = true; + we = true; + } force_resynch[4:4] = 0x0; + }; + + tmr_enable tmr_enable; + tmr_config tmr_config; +}; diff --git a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv index 89eeca99..c9d18a35 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv @@ -1,101 +1,97 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock package hmr_tmr_regs_reg_pkg; - // Address widths within the block - parameter int BlockAw = 3; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic q; - logic qe; - } hmr_tmr_regs_reg2hw_tmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic q; - logic qe; - } delay_resynch; - struct packed { - logic q; - logic qe; - } setback; - struct packed { - logic q; - logic qe; - } reload_setback; - struct packed { - logic q; - logic qe; - } rapid_recovery; - struct packed { - logic q; - logic qe; - } force_resynch; - } hmr_tmr_regs_reg2hw_tmr_config_reg_t; - - typedef struct packed { - logic d; - logic de; - } hmr_tmr_regs_hw2reg_tmr_enable_reg_t; - - typedef struct packed { - struct packed { - logic d; - logic de; - } delay_resynch; - struct packed { - logic d; - logic de; - } setback; - struct packed { - logic d; - logic de; - } reload_setback; - struct packed { - logic d; - logic de; - } rapid_recovery; - struct packed { - logic d; - logic de; - } force_resynch; - } hmr_tmr_regs_hw2reg_tmr_config_reg_t; - - // Register -> HW type - typedef struct packed { - hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [11:10] - hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [9:0] - } hmr_tmr_regs_reg2hw_t; - - // HW -> register type - typedef struct packed { - hmr_tmr_regs_hw2reg_tmr_enable_reg_t tmr_enable; // [11:10] - hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [9:0] - } hmr_tmr_regs_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_ENABLE_OFFSET = 3'h 0; - parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_CONFIG_OFFSET = 3'h 4; - - // Register index - typedef enum int { - HMR_TMR_REGS_TMR_ENABLE, - HMR_TMR_REGS_TMR_CONFIG - } hmr_tmr_regs_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] HMR_TMR_REGS_PERMIT [2] = '{ - 4'b 0001, // index[0] HMR_TMR_REGS_TMR_ENABLE - 4'b 0001 // index[1] HMR_TMR_REGS_TMR_CONFIG - }; + localparam HMR_TMR_REGS_REG_TOP_DATA_WIDTH = 32; + localparam HMR_TMR_REGS_REG_TOP_MIN_ADDR_WIDTH = 3; + localparam HMR_TMR_REGS_REG_TOP_SIZE = 'h8; -endpackage + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_enable__tmr_enable__in_t; + + typedef struct { + hmr_tmr__tmr_enable__tmr_enable__in_t tmr_enable; + } hmr_tmr__tmr_enable__in_t; + + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_config__delay_resynch__in_t; + + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_config__setback__in_t; + + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_config__reload_setback__in_t; + + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_config__rapid_recovery__in_t; + + typedef struct { + logic next; + logic we; + } hmr_tmr__tmr_config__force_resynch__in_t; + + typedef struct { + hmr_tmr__tmr_config__delay_resynch__in_t delay_resynch; + hmr_tmr__tmr_config__setback__in_t setback; + hmr_tmr__tmr_config__reload_setback__in_t reload_setback; + hmr_tmr__tmr_config__rapid_recovery__in_t rapid_recovery; + hmr_tmr__tmr_config__force_resynch__in_t force_resynch; + } hmr_tmr__tmr_config__in_t; + + typedef struct { + hmr_tmr__tmr_enable__in_t tmr_enable; + hmr_tmr__tmr_config__in_t tmr_config; + } hmr_tmr__in_t; + typedef struct { + logic value; + } hmr_tmr__tmr_enable__tmr_enable__out_t; + + typedef struct { + hmr_tmr__tmr_enable__tmr_enable__out_t tmr_enable; + } hmr_tmr__tmr_enable__out_t; + + typedef struct { + logic value; + } hmr_tmr__tmr_config__delay_resynch__out_t; + + typedef struct { + logic value; + } hmr_tmr__tmr_config__setback__out_t; + + typedef struct { + logic value; + } hmr_tmr__tmr_config__reload_setback__out_t; + + typedef struct { + logic value; + } hmr_tmr__tmr_config__rapid_recovery__out_t; + + typedef struct { + logic value; + } hmr_tmr__tmr_config__force_resynch__out_t; + + typedef struct { + hmr_tmr__tmr_config__delay_resynch__out_t delay_resynch; + hmr_tmr__tmr_config__setback__out_t setback; + hmr_tmr__tmr_config__reload_setback__out_t reload_setback; + hmr_tmr__tmr_config__rapid_recovery__out_t rapid_recovery; + hmr_tmr__tmr_config__force_resynch__out_t force_resynch; + } hmr_tmr__tmr_config__out_t; + + typedef struct { + hmr_tmr__tmr_enable__out_t tmr_enable; + hmr_tmr__tmr_config__out_t tmr_config; + } hmr_tmr__out_t; +endpackage diff --git a/rtl/HMR/hmr_tmr_regs_reg_top.sv b/rtl/HMR/hmr_tmr_regs_reg_top.sv index 1249580e..4a846355 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_top.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_top.sv @@ -1,372 +1,367 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module hmr_tmr_regs_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 3 -) ( - 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 hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t reg2hw, // Write - input hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import hmr_tmr_regs_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-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; - 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 tmr_enable_qs; - logic tmr_enable_wd; - logic tmr_enable_we; - logic tmr_config_delay_resynch_qs; - logic tmr_config_delay_resynch_wd; - logic tmr_config_delay_resynch_we; - logic tmr_config_setback_qs; - logic tmr_config_setback_wd; - logic tmr_config_setback_we; - logic tmr_config_reload_setback_qs; - logic tmr_config_reload_setback_wd; - logic tmr_config_reload_setback_we; - logic tmr_config_rapid_recovery_qs; - logic tmr_config_rapid_recovery_wd; - logic tmr_config_rapid_recovery_we; - logic tmr_config_force_resynch_qs; - logic tmr_config_force_resynch_wd; - logic tmr_config_force_resynch_we; - - // Register instances - // R[tmr_enable]: V(False) - - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_tmr_enable ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_enable_we), - .wd (tmr_enable_wd), - - // from internal hardware - .de (hw2reg.tmr_enable.de), - .d (hw2reg.tmr_enable.d ), - - // to internal hardware - .qe (reg2hw.tmr_enable.qe), - .q (reg2hw.tmr_enable.q ), - - // to register interface (read) - .qs (tmr_enable_qs) - ); - - - // R[tmr_config]: V(False) - - // F[delay_resynch]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_tmr_config_delay_resynch ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_config_delay_resynch_we), - .wd (tmr_config_delay_resynch_wd), - - // from internal hardware - .de (hw2reg.tmr_config.delay_resynch.de), - .d (hw2reg.tmr_config.delay_resynch.d ), - - // to internal hardware - .qe (reg2hw.tmr_config.delay_resynch.qe), - .q (reg2hw.tmr_config.delay_resynch.q ), - - // to register interface (read) - .qs (tmr_config_delay_resynch_qs) - ); - - - // F[setback]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h1) - ) u_tmr_config_setback ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_config_setback_we), - .wd (tmr_config_setback_wd), - - // from internal hardware - .de (hw2reg.tmr_config.setback.de), - .d (hw2reg.tmr_config.setback.d ), - - // to internal hardware - .qe (reg2hw.tmr_config.setback.qe), - .q (reg2hw.tmr_config.setback.q ), - - // to register interface (read) - .qs (tmr_config_setback_qs) - ); - - - // F[reload_setback]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h1) - ) u_tmr_config_reload_setback ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_config_reload_setback_we), - .wd (tmr_config_reload_setback_wd), - - // from internal hardware - .de (hw2reg.tmr_config.reload_setback.de), - .d (hw2reg.tmr_config.reload_setback.d ), - - // to internal hardware - .qe (reg2hw.tmr_config.reload_setback.qe), - .q (reg2hw.tmr_config.reload_setback.q ), - - // to register interface (read) - .qs (tmr_config_reload_setback_qs) - ); - - - // F[rapid_recovery]: 3:3 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_tmr_config_rapid_recovery ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_config_rapid_recovery_we), - .wd (tmr_config_rapid_recovery_wd), - - // from internal hardware - .de (hw2reg.tmr_config.rapid_recovery.de), - .d (hw2reg.tmr_config.rapid_recovery.d ), - - // to internal hardware - .qe (reg2hw.tmr_config.rapid_recovery.qe), - .q (reg2hw.tmr_config.rapid_recovery.q ), - - // to register interface (read) - .qs (tmr_config_rapid_recovery_qs) - ); - - - // F[force_resynch]: 4:4 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_tmr_config_force_resynch ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (tmr_config_force_resynch_we), - .wd (tmr_config_force_resynch_wd), - - // from internal hardware - .de (hw2reg.tmr_config.force_resynch.de), - .d (hw2reg.tmr_config.force_resynch.d ), - - // to internal hardware - .qe (reg2hw.tmr_config.force_resynch.qe), - .q (reg2hw.tmr_config.force_resynch.q ), - - // to register interface (read) - .qs (tmr_config_force_resynch_qs) - ); - - - - - logic [1:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == HMR_TMR_REGS_TMR_ENABLE_OFFSET); - addr_hit[1] = (reg_addr == HMR_TMR_REGS_TMR_CONFIG_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] & (|(HMR_TMR_REGS_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(HMR_TMR_REGS_PERMIT[1] & ~reg_be))))); - end - - assign tmr_enable_we = addr_hit[0] & reg_we & !reg_error; - assign tmr_enable_wd = reg_wdata[0]; - - assign tmr_config_delay_resynch_we = addr_hit[1] & reg_we & !reg_error; - assign tmr_config_delay_resynch_wd = reg_wdata[0]; - - assign tmr_config_setback_we = addr_hit[1] & reg_we & !reg_error; - assign tmr_config_setback_wd = reg_wdata[1]; - - assign tmr_config_reload_setback_we = addr_hit[1] & reg_we & !reg_error; - assign tmr_config_reload_setback_wd = reg_wdata[2]; - - assign tmr_config_rapid_recovery_we = addr_hit[1] & reg_we & !reg_error; - assign tmr_config_rapid_recovery_wd = reg_wdata[3]; - - assign tmr_config_force_resynch_we = addr_hit[1] & reg_we & !reg_error; - assign tmr_config_force_resynch_wd = reg_wdata[4]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = tmr_enable_qs; - end - - addr_hit[1]: begin - reg_rdata_next[0] = tmr_config_delay_resynch_qs; - reg_rdata_next[1] = tmr_config_setback_qs; - reg_rdata_next[2] = tmr_config_reload_setback_qs; - reg_rdata_next[3] = tmr_config_rapid_recovery_qs; - reg_rdata_next[4] = tmr_config_force_resynch_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 - -module hmr_tmr_regs_reg_top_intf -#( - parameter int AW = 3, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t reg2hw, // Write - input hmr_tmr_regs_reg_pkg::hmr_tmr_regs_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) - - - - hmr_tmr_regs_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 - ); - +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module hmr_tmr_regs_reg_top ( + input wire clk, + input wire arst_n, + + input wire s_apb_psel, + input wire s_apb_penable, + input wire s_apb_pwrite, + input wire [2:0] s_apb_pprot, + input wire [2:0] s_apb_paddr, + input wire [31:0] s_apb_pwdata, + input wire [3:0] s_apb_pstrb, + output logic s_apb_pready, + output logic [31:0] s_apb_prdata, + output logic s_apb_pslverr, + + input hmr_tmr_regs_reg_pkg::hmr_tmr__in_t hwif_in, + output hmr_tmr_regs_reg_pkg::hmr_tmr__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [2:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + // Request + logic is_active; + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + is_active <= '0; + cpuif_req <= '0; + cpuif_req_is_wr <= '0; + cpuif_addr <= '0; + cpuif_wr_data <= '0; + cpuif_wr_biten <= '0; + end else begin + if(~is_active) begin + if(s_apb_psel) begin + is_active <= '1; + cpuif_req <= '1; + cpuif_req_is_wr <= s_apb_pwrite; + cpuif_addr <= {s_apb_paddr[2:2], 2'b0}; + cpuif_wr_data <= s_apb_pwdata; + for(int i=0; i<4; i++) begin + cpuif_wr_biten[i*8 +: 8] <= {8{s_apb_pstrb[i]}}; + end + end + end else begin + cpuif_req <= '0; + if(cpuif_rd_ack || cpuif_wr_ack) begin + is_active <= '0; + end + end + end + end + + // Response + assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack; + assign s_apb_prdata = cpuif_rd_data; + assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err; + + logic cpuif_req_masked; + + // Read & write latencies are balanced. Stalls not required + assign cpuif_req_stall_rd = '0; + assign cpuif_req_stall_wr = '0; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct { + logic tmr_enable; + logic tmr_config; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + decoded_reg_strb.tmr_enable = cpuif_req_masked & (cpuif_addr == 3'h0); + decoded_reg_strb.tmr_config = cpuif_req_masked & (cpuif_addr == 3'h4); + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + typedef struct { + struct { + struct { + logic next; + logic load_next; + } tmr_enable; + } tmr_enable; + struct { + struct { + logic next; + logic load_next; + } delay_resynch; + struct { + logic next; + logic load_next; + } setback; + struct { + logic next; + logic load_next; + } reload_setback; + struct { + logic next; + logic load_next; + } rapid_recovery; + struct { + logic next; + logic load_next; + } force_resynch; + } tmr_config; + } field_combo_t; + field_combo_t field_combo; + + typedef struct { + struct { + struct { + logic value; + } tmr_enable; + } tmr_enable; + struct { + struct { + logic value; + } delay_resynch; + struct { + logic value; + } setback; + struct { + logic value; + } reload_setback; + struct { + logic value; + } rapid_recovery; + struct { + logic value; + } force_resynch; + } tmr_config; + } field_storage_t; + field_storage_t field_storage; + + // Field: hmr_tmr.tmr_enable.tmr_enable + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_enable.tmr_enable.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_enable && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_enable.tmr_enable.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else if(hwif_in.tmr_enable.tmr_enable.we) begin // HW Write - we + next_c = hwif_in.tmr_enable.tmr_enable.next; + load_next_c = '1; + end + field_combo.tmr_enable.tmr_enable.next = next_c; + field_combo.tmr_enable.tmr_enable.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_enable.tmr_enable.value <= 1'h0; + end else begin + if(field_combo.tmr_enable.tmr_enable.load_next) begin + field_storage.tmr_enable.tmr_enable.value <= field_combo.tmr_enable.tmr_enable.next; + end + end + end + assign hwif_out.tmr_enable.tmr_enable.value = field_storage.tmr_enable.tmr_enable.value; + // Field: hmr_tmr.tmr_config.delay_resynch + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_config.delay_resynch.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_config.delay_resynch.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else if(hwif_in.tmr_config.delay_resynch.we) begin // HW Write - we + next_c = hwif_in.tmr_config.delay_resynch.next; + load_next_c = '1; + end + field_combo.tmr_config.delay_resynch.next = next_c; + field_combo.tmr_config.delay_resynch.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_config.delay_resynch.value <= 1'h0; + end else begin + if(field_combo.tmr_config.delay_resynch.load_next) begin + field_storage.tmr_config.delay_resynch.value <= field_combo.tmr_config.delay_resynch.next; + end + end + end + assign hwif_out.tmr_config.delay_resynch.value = field_storage.tmr_config.delay_resynch.value; + // Field: hmr_tmr.tmr_config.setback + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_config.setback.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_config.setback.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end else if(hwif_in.tmr_config.setback.we) begin // HW Write - we + next_c = hwif_in.tmr_config.setback.next; + load_next_c = '1; + end + field_combo.tmr_config.setback.next = next_c; + field_combo.tmr_config.setback.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_config.setback.value <= 1'h1; + end else begin + if(field_combo.tmr_config.setback.load_next) begin + field_storage.tmr_config.setback.value <= field_combo.tmr_config.setback.next; + end + end + end + assign hwif_out.tmr_config.setback.value = field_storage.tmr_config.setback.value; + // Field: hmr_tmr.tmr_config.reload_setback + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_config.reload_setback.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_config.reload_setback.value & ~decoded_wr_biten[2:2]) | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]); + load_next_c = '1; + end else if(hwif_in.tmr_config.reload_setback.we) begin // HW Write - we + next_c = hwif_in.tmr_config.reload_setback.next; + load_next_c = '1; + end + field_combo.tmr_config.reload_setback.next = next_c; + field_combo.tmr_config.reload_setback.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_config.reload_setback.value <= 1'h1; + end else begin + if(field_combo.tmr_config.reload_setback.load_next) begin + field_storage.tmr_config.reload_setback.value <= field_combo.tmr_config.reload_setback.next; + end + end + end + assign hwif_out.tmr_config.reload_setback.value = field_storage.tmr_config.reload_setback.value; + // Field: hmr_tmr.tmr_config.rapid_recovery + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_config.rapid_recovery.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_config.rapid_recovery.value & ~decoded_wr_biten[3:3]) | (decoded_wr_data[3:3] & decoded_wr_biten[3:3]); + load_next_c = '1; + end else if(hwif_in.tmr_config.rapid_recovery.we) begin // HW Write - we + next_c = hwif_in.tmr_config.rapid_recovery.next; + load_next_c = '1; + end + field_combo.tmr_config.rapid_recovery.next = next_c; + field_combo.tmr_config.rapid_recovery.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_config.rapid_recovery.value <= 1'h0; + end else begin + if(field_combo.tmr_config.rapid_recovery.load_next) begin + field_storage.tmr_config.rapid_recovery.value <= field_combo.tmr_config.rapid_recovery.next; + end + end + end + assign hwif_out.tmr_config.rapid_recovery.value = field_storage.tmr_config.rapid_recovery.value; + // Field: hmr_tmr.tmr_config.force_resynch + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.tmr_config.force_resynch.value; + load_next_c = '0; + if(decoded_reg_strb.tmr_config && decoded_req_is_wr) begin // SW write + next_c = (field_storage.tmr_config.force_resynch.value & ~decoded_wr_biten[4:4]) | (decoded_wr_data[4:4] & decoded_wr_biten[4:4]); + load_next_c = '1; + end else if(hwif_in.tmr_config.force_resynch.we) begin // HW Write - we + next_c = hwif_in.tmr_config.force_resynch.next; + load_next_c = '1; + end + field_combo.tmr_config.force_resynch.next = next_c; + field_combo.tmr_config.force_resynch.load_next = load_next_c; + end + always_ff @(posedge clk or negedge arst_n) begin + if(~arst_n) begin + field_storage.tmr_config.force_resynch.value <= 1'h0; + end else begin + if(field_combo.tmr_config.force_resynch.load_next) begin + field_storage.tmr_config.force_resynch.value <= field_combo.tmr_config.force_resynch.next; + end + end + end + assign hwif_out.tmr_config.force_resynch.value = field_storage.tmr_config.force_resynch.value; + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [31:0] readback_array[2]; + assign readback_array[0][0:0] = (decoded_reg_strb.tmr_enable && !decoded_req_is_wr) ? field_storage.tmr_enable.tmr_enable.value : '0; + assign readback_array[0][31:1] = '0; + assign readback_array[1][0:0] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.delay_resynch.value : '0; + assign readback_array[1][1:1] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.setback.value : '0; + assign readback_array[1][2:2] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.reload_setback.value : '0; + assign readback_array[1][3:3] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.rapid_recovery.value : '0; + assign readback_array[1][4:4] = (decoded_reg_strb.tmr_config && !decoded_req_is_wr) ? field_storage.tmr_config.force_resynch.value : '0; + assign readback_array[1][31:5] = '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<2; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign cpuif_rd_ack = readback_done; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; endmodule - - diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index bbabbce5..f1c56e31 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -38,9 +38,9 @@ module hmr_unit #( parameter type bus_outputs_t = logic, /// Default bus outputs when output ports are disabled (requires SeparateData) parameter bus_outputs_t DefaultBusOutputs = '{ default: '0 }, - /// Register bus types - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, + /// APB bus types for config registers + parameter type apb_req_t = logic, + parameter type apb_resp_t = logic, /// Enables rapid recovery feature parameter bit RapidRecovery = 1'b0, /// Address width of the core register file (in RISC-V it should be always 6) (requires RapidRecovery) @@ -72,8 +72,8 @@ module hmr_unit #( input logic rst_ni, /// Port to configuration unit - input reg_req_t reg_request_i , - output reg_rsp_t reg_response_o, + input apb_req_t apb_req_i , + output apb_resp_t apb_resp_o, /// TMR signals /// Indicates if the TMR group has multiple mismatches @@ -241,119 +241,156 @@ module hmr_unit #( '0; end - reg_req_t [3:0] top_register_reqs; - reg_rsp_t [3:0] top_register_resps; + apb_req_t [3:0] top_register_reqs; + apb_resp_t [3:0] top_register_resps; // 0x000-0x100 -> Top config // 0x100-0x200 -> Core configs // 0x200-0x300 -> DMR configs // 0x300-0x400 -> TMR configs - reg_demux #( - .NoPorts ( 4 ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) + apb_demux #( + .NoMstPorts ( 4 ), + .req_t ( apb_req_t ), + .resp_t ( apb_resp_t ) ) i_reg_demux ( - .clk_i, - .rst_ni, - .in_select_i( reg_request_i.addr[9:8] ), - .in_req_i ( reg_request_i ), - .in_rsp_o ( reg_response_o ), - .out_req_o ( top_register_reqs ), - .out_rsp_i ( top_register_resps ) + .select_i ( apb_req_i.paddr[9:8] ), + .slv_req_i ( apb_req_i ), + .slv_resp_o ( apb_resp_o ), + .mst_req_o ( top_register_reqs ), + .mst_resp_i ( top_register_resps ) ); // Global config registers - hmr_registers_reg_pkg::hmr_registers_hw2reg_t hmr_hw2reg; - hmr_registers_reg_pkg::hmr_registers_reg2hw_t hmr_reg2hw; - - hmr_registers_reg_top #( - .reg_req_t( reg_req_t ), - .reg_rsp_t( reg_rsp_t ) - ) i_hmr_registers ( - .clk_i, - .rst_ni, - .reg_req_i(top_register_reqs[0] ), - .reg_rsp_o(top_register_resps[0]), - .reg2hw (hmr_reg2hw), - .hw2reg (hmr_hw2reg), - .devmode_i('0) + hmr_registers_reg_pkg::hmr__in_t hmr_hw2reg; + hmr_registers_reg_pkg::hmr__out_t hmr_reg2hw; + + hmr_registers_reg_top i_hmr_registers ( + .clk (clk_i), + .arst_n (rst_ni), + .s_apb_psel (top_register_reqs[0].psel), + .s_apb_penable (top_register_reqs[0].penable), + .s_apb_pwrite (top_register_reqs[0].pwrite), + .s_apb_pprot (top_register_reqs[0].pprot), + .s_apb_paddr (top_register_reqs[0].paddr[4:0]), + .s_apb_pwdata (top_register_reqs[0].pwdata), + .s_apb_pstrb (top_register_reqs[0].pstrb), + .s_apb_pready (top_register_resps[0].pready), + .s_apb_prdata (top_register_resps[0].prdata), + .s_apb_pslverr (top_register_resps[0].pslverr), + .hwif_out (hmr_reg2hw), + .hwif_in (hmr_hw2reg) ); - assign hmr_hw2reg.avail_config.independent.d = ~(TMRFixed | DMRFixed); - assign hmr_hw2reg.avail_config.dual.d = DMRFixed | DMRSupported; - assign hmr_hw2reg.avail_config.triple.d = TMRFixed | TMRSupported; - assign hmr_hw2reg.avail_config.rapid_recovery.d = RapidRecovery; - always_comb begin : proc_reg_status - hmr_hw2reg.cores_en.d = '0; - hmr_hw2reg.cores_en.d = core_en_as_master; - - hmr_hw2reg.dmr_enable.d = '0; - hmr_hw2reg.dmr_enable.d[NumDMRGroups-1:0] = ~dmr_grp_in_independent; - hmr_hw2reg.tmr_enable.d = '0; - hmr_hw2reg.tmr_enable.d[NumTMRGroups-1:0] = ~tmr_grp_in_independent; + hmr_hw2reg.avail_config.rd_data = '{default: '0}; + hmr_hw2reg.avail_config.rd_data.independent = ~(TMRFixed | DMRFixed); + hmr_hw2reg.avail_config.rd_data.dual = DMRFixed | DMRSupported; + hmr_hw2reg.avail_config.rd_data.triple = TMRFixed | TMRSupported; + hmr_hw2reg.avail_config.rd_data.rapid_recovery = RapidRecovery; + + hmr_hw2reg.cores_en.rd_data = '{default: '0}; + hmr_hw2reg.cores_en.rd_data.cores_en = core_en_as_master; + + hmr_hw2reg.dmr_enable.rd_data = '{default: '0}; + hmr_hw2reg.dmr_enable.rd_data.dmr_enable[NumDMRGroups-1:0] = ~dmr_grp_in_independent; + + hmr_hw2reg.tmr_enable.rd_data = '{default: '0}; + hmr_hw2reg.tmr_enable.rd_data.tmr_enable[NumTMRGroups-1:0] = ~tmr_grp_in_independent; + + hmr_hw2reg.tmr_config.rd_data = '{default: '0}; + hmr_hw2reg.tmr_config.rd_data.delay_resynch = '0; + hmr_hw2reg.tmr_config.rd_data.setback = '0; + hmr_hw2reg.tmr_config.rd_data.reload_setback = '0; + hmr_hw2reg.tmr_config.rd_data.force_resynch = '0; + hmr_hw2reg.tmr_config.rd_data.rapid_recovery = '0; + + hmr_hw2reg.dmr_config.rd_data = '{default: '0}; + hmr_hw2reg.dmr_config.rd_data.rapid_recovery = '0; + hmr_hw2reg.dmr_config.rd_data.force_recovery = '0; end - - assign hmr_hw2reg.tmr_config.delay_resynch.d = '0; - assign hmr_hw2reg.tmr_config.setback.d = '0; - assign hmr_hw2reg.tmr_config.reload_setback.d = '0; - assign hmr_hw2reg.tmr_config.force_resynch.d = '0; - assign hmr_hw2reg.tmr_config.rapid_recovery.d = '0; - - assign hmr_hw2reg.dmr_config.rapid_recovery.d = '0; - assign hmr_hw2reg.dmr_config.force_recovery.d = '0; + assign hmr_hw2reg.avail_config.rd_ack = hmr_reg2hw.avail_config.req && + !hmr_reg2hw.avail_config.req_is_wr; + assign hmr_hw2reg.cores_en.rd_ack = hmr_reg2hw.cores_en.req && + !hmr_reg2hw.cores_en.req_is_wr; + assign hmr_hw2reg.dmr_enable.rd_ack = hmr_reg2hw.dmr_enable.req && + !hmr_reg2hw.dmr_enable.req_is_wr; + assign hmr_hw2reg.dmr_enable.wr_ack = hmr_reg2hw.dmr_enable.req && + hmr_reg2hw.dmr_enable.req_is_wr; + assign hmr_hw2reg.tmr_enable.rd_ack = hmr_reg2hw.tmr_enable.req && + !hmr_reg2hw.tmr_enable.req_is_wr; + assign hmr_hw2reg.tmr_enable.wr_ack = hmr_reg2hw.tmr_enable.req && + hmr_reg2hw.tmr_enable.req_is_wr; + + assign hmr_hw2reg.tmr_config.rd_ack = hmr_reg2hw.tmr_config.req && + !hmr_reg2hw.tmr_config.req_is_wr; + assign hmr_hw2reg.tmr_config.wr_ack = hmr_reg2hw.tmr_config.req && + hmr_reg2hw.tmr_config.req_is_wr; + + assign hmr_hw2reg.dmr_config.rd_ack = hmr_reg2hw.dmr_config.req && + !hmr_reg2hw.dmr_config.req_is_wr; + assign hmr_hw2reg.dmr_config.wr_ack = hmr_reg2hw.dmr_config.req && + hmr_reg2hw.dmr_config.req_is_wr; // Core Config Registers - reg_req_t [NumCores-1:0] core_register_reqs; - reg_rsp_t [NumCores-1:0] core_register_resps; + apb_req_t [NumCores-1:0] core_register_reqs; + apb_resp_t [NumCores-1:0] core_register_resps; // 4 words per core - reg_demux #( - .NoPorts ( NumCores ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) + apb_demux #( + .NoMstPorts ( NumCores ), + .req_t ( apb_req_t ), + .resp_t ( apb_resp_t ) ) i_core_reg_demux ( - .clk_i, - .rst_ni, - .in_select_i( top_register_reqs [1].addr[4+$clog2(NumCores)-1:4] ), - .in_req_i ( top_register_reqs [1] ), - .in_rsp_o ( top_register_resps[1] ), - .out_req_o ( core_register_reqs ), - .out_rsp_i ( core_register_resps ) + .select_i ( top_register_reqs [1].paddr[4+$clog2(NumCores)-1:4] ), + .slv_req_i ( top_register_reqs [1] ), + .slv_resp_o ( top_register_resps[1] ), + .mst_req_o ( core_register_reqs ), + .mst_resp_i ( core_register_resps ) ); - hmr_core_regs_reg_pkg::hmr_core_regs_reg2hw_t [NumCores-1:0] core_config_reg2hw; - hmr_core_regs_reg_pkg::hmr_core_regs_hw2reg_t [NumCores-1:0] core_config_hw2reg; + hmr_core_regs_reg_pkg::hmr_core__out_t core_config_reg2hw [NumCores]; + hmr_core_regs_reg_pkg::hmr_core__in_t core_config_hw2reg [NumCores]; logic [NumCores-1:0] tmr_incr_mismatches; logic [NumCores-1:0] dmr_incr_mismatches; for (genvar i = 0; i < NumCores; i++) begin : gen_core_registers - hmr_core_regs_reg_top #( - .reg_req_t(reg_req_t), - .reg_rsp_t(reg_rsp_t) - ) icore_registers ( - .clk_i, - .rst_ni, - .reg_req_i( core_register_reqs [i] ), - .reg_rsp_o( core_register_resps[i] ), - .reg2hw ( core_config_reg2hw [i] ), - .hw2reg ( core_config_hw2reg [i] ), - .devmode_i('0) + hmr_core_regs_reg_top i_core_registers ( + .clk (clk_i), + .arst_n (rst_ni), + .s_apb_psel ( core_register_reqs [i].psel ), + .s_apb_penable ( core_register_reqs [i].penable ), + .s_apb_pwrite ( core_register_reqs [i].pwrite ), + .s_apb_pprot ( core_register_reqs [i].pprot ), + .s_apb_paddr ( core_register_reqs [i].paddr[3:0] ), + .s_apb_pwdata ( core_register_reqs [i].pwdata ), + .s_apb_pstrb ( core_register_reqs [i].pstrb ), + .s_apb_pready ( core_register_resps[i].pready ), + .s_apb_prdata ( core_register_resps[i].prdata ), + .s_apb_pslverr ( core_register_resps[i].pslverr ), + .hwif_out ( core_config_reg2hw [i] ), + .hwif_in ( core_config_hw2reg [i] ) ); - assign core_config_hw2reg[i].mismatches.d = core_config_reg2hw[i].mismatches.q + 1; - assign core_config_hw2reg[i].mismatches.de = tmr_incr_mismatches[i] | dmr_incr_mismatches[i]; - assign core_config_hw2reg[i].current_mode.independent.d = core_in_independent[i]; - assign core_config_hw2reg[i].current_mode.dual.d = core_in_dmr[i]; - assign core_config_hw2reg[i].current_mode.triple.d = core_in_tmr[i]; - assign sp_store_is_zero[i] = core_config_reg2hw[i].sp_store.q == '0; - assign sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.qe && - core_register_reqs[i].wdata == '0; + assign core_config_hw2reg[i].mismatches.mismatches.next = + core_config_reg2hw[i].mismatches.mismatches.value + 1; + assign core_config_hw2reg[i].mismatches.mismatches.we = tmr_incr_mismatches[i] | + dmr_incr_mismatches[i]; + always_comb begin + core_config_hw2reg[i].current_mode.rd_data = '{default: '0}; + core_config_hw2reg[i].current_mode.rd_data.independent = core_in_independent[i]; + core_config_hw2reg[i].current_mode.rd_data.dual = core_in_dmr[i]; + core_config_hw2reg[i].current_mode.rd_data.triple = core_in_tmr[i]; + core_config_hw2reg[i].current_mode.rd_ack = core_config_reg2hw[i].current_mode.req && + !core_config_reg2hw[i].current_mode.req_is_wr; + end + assign sp_store_is_zero[i] = core_config_reg2hw[i].sp_store.sp_store.value == '0; + assign sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.sp_store.swmod && + core_register_reqs[i].pwdata == '0; end /********************************************************** @@ -363,8 +400,8 @@ module hmr_unit #( if (TMRSupported || TMRFixed) begin : gen_tmr_logic if (TMRFixed && NumCores % 3 != 0) $warning("Extra cores added not properly handled!"); - reg_req_t [NumTMRGroups-1:0] tmr_register_reqs; - reg_rsp_t [NumTMRGroups-1:0] tmr_register_resps; + apb_req_t [NumTMRGroups-1:0] tmr_register_reqs; + apb_resp_t [NumTMRGroups-1:0] tmr_register_resps; logic [NumTMRGroups-1:0] tmr_sw_resynch_req, tmr_sw_synch_req; localparam int unsigned TMRSelWidth = $clog2(NumTMRGroups); @@ -376,18 +413,16 @@ module hmr_unit #( assign tmr_register_reqs[0] = top_register_reqs[3]; assign top_register_resps[3] = tmr_register_resps[0]; end else begin : gen_multi_tmr_group_reg_connect - reg_demux #( - .NoPorts ( NumTMRGroups ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) + apb_demux #( + .NoMstPorts ( NumTMRGroups ), + .req_t ( apb_req_t ), + .resp_t ( apb_resp_t ) ) i_reg_demux ( - .clk_i, - .rst_ni, - .in_select_i( top_register_reqs[3].addr[4+$clog2(NumTMRGroups)-1:4] ), - .in_req_i ( top_register_reqs[3] ), - .in_rsp_o ( top_register_resps[3] ), - .out_req_o ( tmr_register_reqs ), - .out_rsp_i ( tmr_register_resps ) + .select_i ( top_register_reqs[3].paddr[4+$clog2(NumTMRGroups)-1:4] ), + .slv_req_i ( top_register_reqs[3] ), + .slv_resp_o ( top_register_resps[3] ), + .mst_req_o ( tmr_register_reqs ), + .mst_resp_i ( tmr_register_resps ) ); end @@ -400,8 +435,8 @@ module hmr_unit #( for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups hmr_tmr_ctrl #( - .reg_req_t ( reg_req_t ), - .reg_resp_t ( reg_rsp_t ), + .apb_req_t ( apb_req_t ), + .apb_resp_t ( apb_resp_t ), .TMRFixed ( TMRFixed ), .InterleaveGrps ( InterleaveGrps ), .DefaultInTMR ( 1'b0 ), @@ -410,21 +445,33 @@ module hmr_unit #( .clk_i, .rst_ni, - .reg_req_i ( tmr_register_reqs[i] ), - .reg_resp_o ( tmr_register_resps[i] ), - - .tmr_enable_q_i ( hmr_reg2hw.tmr_enable.q[i] ), - .tmr_enable_qe_i ( hmr_reg2hw.tmr_enable.qe ), - .delay_resynch_q_i ( hmr_reg2hw.tmr_config.delay_resynch.q ), - .delay_resynch_qe_i ( hmr_reg2hw.tmr_config.delay_resynch.qe ), - .setback_q_i ( hmr_reg2hw.tmr_config.setback.q ), - .setback_qe_i ( hmr_reg2hw.tmr_config.setback.qe ), - .reload_setback_q_i ( hmr_reg2hw.tmr_config.reload_setback.q ), - .reload_setback_qe_i ( hmr_reg2hw.tmr_config.reload_setback.qe ), - .rapid_recovery_q_i ( hmr_reg2hw.tmr_config.rapid_recovery.q ), - .rapid_recovery_qe_i ( hmr_reg2hw.tmr_config.rapid_recovery.qe ), - .force_resynch_q_i ( hmr_reg2hw.tmr_config.force_resynch.q ), - .force_resynch_qe_i ( hmr_reg2hw.tmr_config.force_resynch.qe ), + .apb_req_i ( tmr_register_reqs[i] ), + .apb_resp_o ( tmr_register_resps[i] ), + + .tmr_enable_q_i ( hmr_reg2hw.tmr_enable.wr_data.tmr_enable[i] ), + .tmr_enable_qe_i ( hmr_reg2hw.tmr_enable.req & + hmr_reg2hw.tmr_enable.req_is_wr & + hmr_reg2hw.tmr_enable.wr_data.tmr_enable[i] ), + .delay_resynch_q_i ( hmr_reg2hw.tmr_config.wr_data.delay_resynch ), + .delay_resynch_qe_i ( hmr_reg2hw.tmr_config.req & + hmr_reg2hw.tmr_config.req_is_wr & + hmr_reg2hw.tmr_config.wr_data.delay_resynch ), + .setback_q_i ( hmr_reg2hw.tmr_config.wr_data.setback ), + .setback_qe_i ( hmr_reg2hw.tmr_config.req & + hmr_reg2hw.tmr_config.req_is_wr & + hmr_reg2hw.tmr_config.wr_data.setback ), + .reload_setback_q_i ( hmr_reg2hw.tmr_config.wr_data.reload_setback ), + .reload_setback_qe_i ( hmr_reg2hw.tmr_config.req & + hmr_reg2hw.tmr_config.req_is_wr & + hmr_reg2hw.tmr_config.wr_data.reload_setback ), + .rapid_recovery_q_i ( hmr_reg2hw.tmr_config.wr_data.rapid_recovery ), + .rapid_recovery_qe_i ( hmr_reg2hw.tmr_config.req & + hmr_reg2hw.tmr_config.req_is_wr & + hmr_reg2hw.tmr_config.wr_data.rapid_recovery ), + .force_resynch_q_i ( hmr_reg2hw.tmr_config.wr_data.force_resynch ), + .force_resynch_qe_i ( hmr_reg2hw.tmr_config.req & + hmr_reg2hw.tmr_config.req_is_wr & + hmr_reg2hw.tmr_config.wr_data.force_resynch ), .setback_o ( tmr_setback_q[i] ), .sw_resynch_req_o ( tmr_sw_resynch_req[i] ), @@ -508,9 +555,13 @@ module hmr_unit #( assign tmr_failure = '0; assign tmr_nominal_outputs = DefaultNominalOutputs; assign tmr_bus_outputs = DefaultBusOutputs; - assign top_register_resps[3].rdata = '0; - assign top_register_resps[3].error = 1'b1; - assign top_register_resps[3].ready = 1'b1; + apb_err_slv #( + .req_t ( apb_req_t ), + .resp_t( apb_resp_t ) + ) i_apb_err_slv ( + .apb_req_i ( top_register_reqs[3] ), + .apb_resp_o ( top_register_resps[3] ) + ); assign tmr_incr_mismatches = '0; assign tmr_grp_in_independent = '1; assign tmr_setback_q = '0; @@ -524,11 +575,8 @@ module hmr_unit #( if (DMRSupported || DMRFixed) begin: gen_dmr_logic - hmr_dmr_regs_reg_pkg::hmr_dmr_regs_reg2hw_t [NumDMRGroups-1:0] dmr_reg2hw; - hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t [NumDMRGroups-1:0] dmr_hw2reg; - - reg_req_t [NumDMRGroups-1:0] dmr_register_reqs; - reg_rsp_t [NumDMRGroups-1:0] dmr_register_resps; + apb_req_t [NumDMRGroups-1:0] dmr_register_reqs; + apb_resp_t [NumDMRGroups-1:0] dmr_register_resps; logic [NumDMRGroups-1:0] dmr_sw_synch_req; logic [NumDMRGroups-1:0] dmr_sw_resynch_req; @@ -541,18 +589,16 @@ module hmr_unit #( assign dmr_register_reqs[0] = top_register_reqs[2]; assign top_register_resps[2] = dmr_register_resps[0]; end else begin : gen_multi_dmr_group_reg_connect - reg_demux #( - .NoPorts ( NumDMRGroups ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) + apb_demux #( + .NoMstPorts ( NumDMRGroups ), + .req_t ( apb_req_t ), + .resp_t ( apb_resp_t ) ) i_reg_demux ( - .clk_i, - .rst_ni, - .in_select_i( top_register_reqs[2].addr[4+$clog2(NumDMRGroups)-1:4] ), - .in_req_i ( top_register_reqs[2] ), - .in_rsp_o ( top_register_resps[2] ), - .out_req_o ( dmr_register_reqs ), - .out_rsp_i ( dmr_register_resps ) + .select_i ( top_register_reqs[2].paddr[4+$clog2(NumDMRGroups)-1:4] ), + .slv_req_i ( top_register_reqs[2] ), + .slv_resp_o ( top_register_resps[2] ), + .mst_req_o ( dmr_register_reqs ), + .mst_resp_i ( dmr_register_resps ) ); end @@ -565,8 +611,8 @@ module hmr_unit #( for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_dmr_groups hmr_dmr_ctrl #( - .reg_req_t ( reg_req_t ), - .reg_resp_t ( reg_rsp_t ), + .apb_req_t ( apb_req_t ), + .apb_resp_t ( apb_resp_t ), .DataWidth ( SysDataWidth ), .InterleaveGrps( InterleaveGrps ), .DMRFixed ( DMRFixed ), @@ -576,15 +622,21 @@ module hmr_unit #( .clk_i, .rst_ni, - .reg_req_i ( dmr_register_reqs [i] ), - .reg_resp_o ( dmr_register_resps[i] ), - - .dmr_enable_q_i ( hmr_reg2hw.dmr_enable.q[i] ), - .dmr_enable_qe_i ( hmr_reg2hw.dmr_enable.qe ), - .rapid_recovery_q_i ( hmr_reg2hw.dmr_config.rapid_recovery.q ), - .rapid_recovery_qe_i ( hmr_reg2hw.dmr_config.rapid_recovery.qe ), - .force_recovery_q_i ( hmr_reg2hw.dmr_config.force_recovery.q ), - .force_recovery_qe_i ( hmr_reg2hw.dmr_config.force_recovery.qe ), + .apb_req_i ( dmr_register_reqs [i] ), + .apb_resp_o ( dmr_register_resps[i] ), + + .dmr_enable_q_i ( hmr_reg2hw.dmr_enable.wr_data.dmr_enable[i] ), + .dmr_enable_qe_i ( hmr_reg2hw.dmr_enable.req & + hmr_reg2hw.dmr_enable.req_is_wr & + hmr_reg2hw.dmr_enable.wr_biten.dmr_enable[i] ), + .rapid_recovery_q_i ( hmr_reg2hw.dmr_config.wr_data.rapid_recovery ), + .rapid_recovery_qe_i ( hmr_reg2hw.dmr_config.req & + hmr_reg2hw.dmr_config.req_is_wr & + hmr_reg2hw.dmr_config.wr_biten.rapid_recovery ), + .force_recovery_q_i ( hmr_reg2hw.dmr_config.wr_data.force_recovery ), + .force_recovery_qe_i ( hmr_reg2hw.dmr_config.req & + hmr_reg2hw.dmr_config.req_is_wr & + hmr_reg2hw.dmr_config.wr_biten.force_recovery ), .setback_o ( dmr_setback_q [i] ), .sw_resynch_req_o ( dmr_sw_resynch_req [i] ), @@ -715,9 +767,13 @@ module hmr_unit #( assign dmr_incr_mismatches = '0; assign dmr_nominal_outputs = DefaultNominalOutputs; assign dmr_bus_outputs = DefaultBusOutputs; - assign top_register_resps[2].rdata = '0; - assign top_register_resps[2].error = 1'b1; - assign top_register_resps[2].ready = 1'b1; + apb_err_slv #( + .req_t ( apb_req_t ), + .resp_t( apb_resp_t ) + ) i_dmr_err_slv ( + .slv_req_i ( top_register_reqs[2] ), + .slv_resp_o( top_register_resps[2] ) + ); assign dmr_sw_synch_req_o = '0; assign dmr_resynch_req_o = '0; assign dmr_grp_in_independent = '1; diff --git a/rtl/HMR/hmr_v1.h b/rtl/HMR/hmr_v1.h deleted file mode 100644 index 7a4e0bfa..00000000 --- a/rtl/HMR/hmr_v1.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2023 ETH Zurich and University of Bologna - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ARCHI_HMR_HMR_V1_H__ -#define __ARCHI_HMR_HMR_V1_H__ - -#define HMR_IN_INTERLEAVED 1 - -#define HMR_TOP_OFFSET 0x000 -#define HMR_CORE_OFFSET 0x100 -#define HMR_DMR_OFFSET 0x200 -#define HMR_TMR_OFFSET 0x300 - -#define HMR_CORE_INCREMENT 0x010 -#define HMR_CORE_SLL 0x004 -#define HMR_DMR_INCREMENT 0x010 -#define HMR_DMR_SLL 0x004 -#define HMR_TMR_INCREMENT 0x010 -#define HMR_TMR_SLL 0x004 - -// Generated register defines for HMR_registers - -#ifndef _HMR_REGISTERS_REG_DEFS_ -#define _HMR_REGISTERS_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -#define HMR_REGISTERS_PARAM_NUM_CORES 12 - -#define HMR_REGISTERS_PARAM_NUM_D_M_R_GROUPS 6 - -#define HMR_REGISTERS_PARAM_NUM_T_M_R_GROUPS 4 - -// Register width -#define HMR_REGISTERS_PARAM_REG_WIDTH 32 - -// Available Configurations from implemented hardware. -#define HMR_REGISTERS_AVAIL_CONFIG_REG_OFFSET 0x0 -#define HMR_REGISTERS_AVAIL_CONFIG_INDEPENDENT_BIT 0 -#define HMR_REGISTERS_AVAIL_CONFIG_DUAL_BIT 1 -#define HMR_REGISTERS_AVAIL_CONFIG_TRIPLE_BIT 2 -#define HMR_REGISTERS_AVAIL_CONFIG_RAPID_RECOVERY_BIT 8 - -// Enabled cores, based on the configuration. Can be used for barriers. -#define HMR_REGISTERS_CORES_EN_REG_OFFSET 0x4 -#define HMR_REGISTERS_CORES_EN_CORES_EN_MASK 0xfff -#define HMR_REGISTERS_CORES_EN_CORES_EN_OFFSET 0 -#define HMR_REGISTERS_CORES_EN_CORES_EN_FIELD \ - ((bitfield_field32_t) { .mask = HMR_REGISTERS_CORES_EN_CORES_EN_MASK, .index = HMR_REGISTERS_CORES_EN_CORES_EN_OFFSET }) - -// DMR configuration enable, on bit per DMR group. -#define HMR_REGISTERS_DMR_ENABLE_REG_OFFSET 0x8 -#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_MASK 0x3f -#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_OFFSET 0 -#define HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_FIELD \ - ((bitfield_field32_t) { .mask = HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_MASK, .index = HMR_REGISTERS_DMR_ENABLE_DMR_ENABLE_OFFSET }) - -// TMR configuration enable, one bit per TMR group. -#define HMR_REGISTERS_TMR_ENABLE_REG_OFFSET 0xc -#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_MASK 0xf -#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_OFFSET 0 -#define HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_FIELD \ - ((bitfield_field32_t) { .mask = HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_MASK, .index = HMR_REGISTERS_TMR_ENABLE_TMR_ENABLE_OFFSET }) - -// DMR configuration bits. -#define HMR_REGISTERS_DMR_CONFIG_REG_OFFSET 0x10 -#define HMR_REGISTERS_DMR_CONFIG_RAPID_RECOVERY_BIT 0 -#define HMR_REGISTERS_DMR_CONFIG_FORCE_RECOVERY_BIT 1 - -// TMR configuration bits. -#define HMR_REGISTERS_TMR_CONFIG_REG_OFFSET 0x14 -#define HMR_REGISTERS_TMR_CONFIG_DELAY_RESYNCH_BIT 0 -#define HMR_REGISTERS_TMR_CONFIG_SETBACK_BIT 1 -#define HMR_REGISTERS_TMR_CONFIG_RELOAD_SETBACK_BIT 2 -#define HMR_REGISTERS_TMR_CONFIG_RAPID_RECOVERY_BIT 3 -#define HMR_REGISTERS_TMR_CONFIG_FORCE_RESYNCH_BIT 4 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_REGISTERS_REG_DEFS_ -// End generated register defines for HMR_registers - -// Generated register defines for HMR_core_regs - -#ifndef _HMR_CORE_REGS_REG_DEFS_ -#define _HMR_CORE_REGS_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -// Register width -#define HMR_CORE_REGS_PARAM_REG_WIDTH 32 - -// Value to determine wich redundancy mode the core with that ID is in. -#define HMR_CORE_REGS_CURRENT_MODE_REG_OFFSET 0x0 -#define HMR_CORE_REGS_CURRENT_MODE_INDEPENDENT_BIT 0 -#define HMR_CORE_REGS_CURRENT_MODE_DUAL_BIT 1 -#define HMR_CORE_REGS_CURRENT_MODE_TRIPLE_BIT 2 - -// Mismatches of the core -#define HMR_CORE_REGS_MISMATCHES_REG_OFFSET 0x4 - -// Stack Pointer storage register -#define HMR_CORE_REGS_SP_STORE_REG_OFFSET 0x8 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_CORE_REGS_REG_DEFS_ -// End generated register defines for HMR_core_regs - -// Generated register defines for HMR_dmr_regs - -#ifndef _HMR_DMR_REGS_REG_DEFS_ -#define _HMR_DMR_REGS_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -// Register width -#define HMR_DMR_REGS_PARAM_REG_WIDTH 32 - -// DMR configuration enable. -#define HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET 0x0 -#define HMR_DMR_REGS_DMR_ENABLE_DMR_ENABLE_BIT 0 - -// DMR configuration bits. -#define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4 -#define HMR_DMR_REGS_DMR_CONFIG_RAPID_RECOVERY_BIT 0 -#define HMR_DMR_REGS_DMR_CONFIG_FORCE_RECOVERY_BIT 1 - -// Address for the last checkpoint. -#define HMR_DMR_REGS_CHECKPOINT_ADDR_REG_OFFSET 0x8 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_DMR_REGS_REG_DEFS_ -// End generated register defines for HMR_dmr_regs - -// Generated register defines for HMR_tmr_regs - -#ifndef _HMR_TMR_REGS_REG_DEFS_ -#define _HMR_TMR_REGS_REG_DEFS_ - -#ifdef __cplusplus -extern "C" { -#endif -// Register width -#define HMR_TMR_REGS_PARAM_REG_WIDTH 32 - -// TMR configuration enable. -#define HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET 0x0 -#define HMR_TMR_REGS_TMR_ENABLE_TMR_ENABLE_BIT 0 - -// TMR configuration bits. -#define HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET 0x4 -#define HMR_TMR_REGS_TMR_CONFIG_DELAY_RESYNCH_BIT 0 -#define HMR_TMR_REGS_TMR_CONFIG_SETBACK_BIT 1 -#define HMR_TMR_REGS_TMR_CONFIG_RELOAD_SETBACK_BIT 2 -#define HMR_TMR_REGS_TMR_CONFIG_RAPID_RECOVERY_BIT 3 -#define HMR_TMR_REGS_TMR_CONFIG_FORCE_RESYNCH_BIT 4 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_TMR_REGS_REG_DEFS_ -// End generated register defines for HMR_tmr_regs - - -#endif // __ARCHI_HMR_HMR_V1_H__