From 1f3240c09447469494f7d7bc28f50668353733f2 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 22 Dec 2022 15:56:58 +0100 Subject: [PATCH 01/66] HMR: Add initial wrapper structure HMR: Add ODRG & TCLS support HMR: add initial configuration regfile HMR: additional registers Add files, initial fixes Add registers for tmr, modify and connect config Clarify core interleaving with functions, fixes Clean up Changed HMR interface's core grouping parameters to localparam as they depend on other parameters. Removed dependency from red_mode_q in generate statements. Indentation :art: Having couples of cores with the same inputs and generating the same outputs. Integrated DMR Core Checker. Use functions for DMR core selection Reposition TMR registers and FSM Externalize TMR control from HMR Add DMR configuration registers HMR: Add C include files Fix signal assignment in TMR mode --- Bender.yml | 13 + Makefile | 17 + rtl/DMR_checker.sv | 34 ++ rtl/HMR/HMR_core_regs.hjson | 48 ++ rtl/HMR/HMR_dmr_regs.hjson | 52 ++ rtl/HMR/HMR_regs.hjson | 123 ++++ rtl/HMR/HMR_tmr_regs.hjson | 68 +++ rtl/HMR/HMR_wrap.sv | 949 +++++++++++++++++++++++++++++++ rtl/HMR/doc.html | 80 +++ rtl/HMR/doc.md | 312 ++++++++++ rtl/HMR/hmr_core.h | 25 + rtl/HMR/hmr_core_regs_reg_pkg.sv | 71 +++ rtl/HMR/hmr_core_regs_reg_top.sv | 267 +++++++++ rtl/HMR/hmr_dmr.h | 27 + rtl/HMR/hmr_dmr_regs_reg_pkg.sv | 80 +++ rtl/HMR/hmr_dmr_regs_reg_top.sv | 278 +++++++++ rtl/HMR/hmr_global.h | 56 ++ rtl/HMR/hmr_registers_reg_pkg.sv | 144 +++++ rtl/HMR/hmr_registers_reg_top.sv | 417 ++++++++++++++ rtl/HMR/hmr_tmr.h | 30 + rtl/HMR/hmr_tmr_ctrl.sv | 179 ++++++ rtl/HMR/hmr_tmr_regs_reg_pkg.sv | 108 ++++ rtl/HMR/hmr_tmr_regs_reg_top.sv | 378 ++++++++++++ 23 files changed, 3756 insertions(+) create mode 100644 rtl/DMR_checker.sv create mode 100644 rtl/HMR/HMR_core_regs.hjson create mode 100644 rtl/HMR/HMR_dmr_regs.hjson create mode 100644 rtl/HMR/HMR_regs.hjson create mode 100644 rtl/HMR/HMR_tmr_regs.hjson create mode 100644 rtl/HMR/HMR_wrap.sv create mode 100644 rtl/HMR/doc.html create mode 100644 rtl/HMR/doc.md create mode 100644 rtl/HMR/hmr_core.h create mode 100644 rtl/HMR/hmr_core_regs_reg_pkg.sv create mode 100644 rtl/HMR/hmr_core_regs_reg_top.sv create mode 100644 rtl/HMR/hmr_dmr.h create mode 100644 rtl/HMR/hmr_dmr_regs_reg_pkg.sv create mode 100644 rtl/HMR/hmr_dmr_regs_reg_top.sv create mode 100644 rtl/HMR/hmr_global.h create mode 100644 rtl/HMR/hmr_registers_reg_pkg.sv create mode 100644 rtl/HMR/hmr_registers_reg_top.sv create mode 100644 rtl/HMR/hmr_tmr.h create mode 100644 rtl/HMR/hmr_tmr_ctrl.sv create mode 100644 rtl/HMR/hmr_tmr_regs_reg_pkg.sv create mode 100644 rtl/HMR/hmr_tmr_regs_reg_top.sv diff --git a/Bender.yml b/Bender.yml index 8ef80285..64ffede7 100644 --- a/Bender.yml +++ b/Bender.yml @@ -28,6 +28,7 @@ sources: - rtl/TMR_voter.sv - rtl/TMR_voter_fail.sv - rtl/TMR_word_voter.sv + - rtl/DMR_checker.sv # Level 1 - rtl/ODRG_unit/odrg_manager_reg_top.sv - rtl/ecc_wrap/ecc_manager_reg_top.sv @@ -103,6 +104,18 @@ sources: - test/tb_bitwise_tmr_voter_fail.sv - test/tb_voter_macros.sv + - files: + - rtl/HMR/hmr_registers_reg_pkg.sv + - rtl/HMR/hmr_core_regs_reg_pkg.sv + - rtl/HMR/hmr_dmr_regs_reg_pkg.sv + - rtl/HMR/hmr_tmr_regs_reg_pkg.sv + - rtl/HMR/hmr_registers_reg_top.sv + - rtl/HMR/hmr_core_regs_reg_top.sv + - rtl/HMR/hmr_dmr_regs_reg_top.sv + - rtl/HMR/hmr_tmr_regs_reg_top.sv + - rtl/HMR/hmr_tmr_ctrl.sv + - rtl/HMR/HMR_wrap.sv + vendor_package: - name: lowrisc_opentitan target_dir: "util/lowrisc_opentitan" diff --git a/Makefile b/Makefile index a68dda84..a9151e25 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,15 @@ REG_TOOL = $(REG_PATH)/vendor/lowrisc_opentitan/util/regtool.py 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 HJSON_ECC = rtl/ecc_wrap/ecc_sram_wrapper.hjson TARGET_DIR_ODRG = rtl/ODRG_unit TARGET_DIR_TCLS = rtl/pulpissimo_tcls +TARGET_DIR_HMR = rtl/HMR TARGET_DIR_ECC = rtl/ecc_wrap .PHONY: gen_ODRG gen_TCLS gen_ecc_registers gen_ECC @@ -39,6 +44,18 @@ 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) -D > $(TARGET_DIR_HMR)/hmr_global.h + 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_core) -D > $(TARGET_DIR_HMR)/hmr_core.h + python $(REG_TOOL) $(HJSON_HMR_dmr) -t $(TARGET_DIR_HMR) -r + python $(REG_TOOL) $(HJSON_HMR_dmr) -D > $(TARGET_DIR_HMR)/hmr_dmr.h + python $(REG_TOOL) $(HJSON_HMR_tmr) -t $(TARGET_DIR_HMR) -r + python $(REG_TOOL) $(HJSON_HMR_tmr) -D > $(TARGET_DIR_HMR)/hmr_tmr.h + gen_ecc_registers: python $(REG_TOOL) $(HJSON_ECC) -t $(TARGET_DIR_ECC) -r python $(REG_TOOL) $(HJSON_ECC) -d > $(TARGET_DIR_ECC)/doc.md diff --git a/rtl/DMR_checker.sv b/rtl/DMR_checker.sv new file mode 100644 index 00000000..21842bdb --- /dev/null +++ b/rtl/DMR_checker.sv @@ -0,0 +1,34 @@ +/* Copyright 2020 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. + * + * Dual Modular Redundancy Checker + * Compares the outputs generated by two IPs and returns error signals + * in case of mismatch + * + */ + +module DMR_checker #( + parameter int unsigned DataWidth = 41 +)( + input logic [DataWidth-1:0] inp_a_i, + input logic [DataWidth-1:0] inp_b_i, + output logic [DataWidth-1:0] check_o, + output logic error_o +); + +logic error; +logic [DataWidth-1:0] compare; + +assign compare = inp_a_i ^ inp_b_i; +assign error = |compare; +assign check_o = (!error) ? inp_a_i : '0; +assign error_o = error; + +endmodule : DMR_checker diff --git a/rtl/HMR/HMR_core_regs.hjson b/rtl/HMR/HMR_core_regs.hjson new file mode 100644 index 00000000..b37d5499 --- /dev/null +++ b/rtl/HMR/HMR_core_regs.hjson @@ -0,0 +1,48 @@ +{ 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" + } + ] + } + ] +} diff --git a/rtl/HMR/HMR_dmr_regs.hjson b/rtl/HMR/HMR_dmr_regs.hjson new file mode 100644 index 00000000..dcf54459 --- /dev/null +++ b/rtl/HMR/HMR_dmr_regs.hjson @@ -0,0 +1,52 @@ +{ + 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: "TMR_enable", + desc: "TMR configuration enable." + } + ] + }, + { name: "DMR_config", + desc: "DMR configuration bits." + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + fields: [ + { bits: "0", + name: "todo", + desc: "TODO" + } + ] + }, + { 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 new file mode 100644 index 00000000..30b98a8c --- /dev/null +++ b/rtl/HMR/HMR_regs.hjson @@ -0,0 +1,123 @@ +{ + 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 32 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." + } + ] + }, + { 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", + # fields: [] + # }, + { 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: "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 new file mode 100644 index 00000000..ec01dad2 --- /dev/null +++ b/rtl/HMR/HMR_tmr_regs.hjson @@ -0,0 +1,68 @@ +{ + 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: "force_resynch", + resval: "0", + desc: "Forces a resynchronization routine" + } + ] + }, + { name: "sp_store", + desc: "Stack Pointer storage register", + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + fields: [ + { bits: "31:0", + name: "SP", + desc: "Stack Pointer" + } + ] + } + ] +} diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv new file mode 100644 index 00000000..f6296558 --- /dev/null +++ b/rtl/HMR/HMR_wrap.sv @@ -0,0 +1,949 @@ +// Copyright 2022 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. +// +// Hybrid modular redundancy wrapping unit + +module HMR_wrap #( + // Wrapper parameters + parameter int unsigned NumCores = 0, + parameter bit DMRSupported = 1'b1, + parameter bit DMRFixed = 1'b0, + parameter bit TMRSupported = 1'b1, + parameter bit TMRFixed = 1'b0, + parameter bit SeparateData = 1'b1, + parameter bit BackupRegfile = 1'b0, + parameter bit InterleaveGrps = 1'b1, // alternative is sequential grouping + parameter int unsigned InstrDataWidth = 32, + parameter int unsigned DataWidth = 32, + parameter int unsigned BeWidth = 4, + parameter int unsigned UserWidth = 0, + parameter int unsigned NumExtPerf = 5, + parameter type reg_req_t = logic, + parameter type reg_resp_t = logic, + // Local parameters depending on the above ones + localparam int unsigned NumTMRGroups = NumCores/3, + localparam int unsigned NumTMRCores = NumTMRGroups * 3, + localparam int unsigned NumTMRLeftover = NumCores - NumTMRCores, + localparam int unsigned NumDMRGroups = NumCores/2, + localparam int unsigned NumDMRCores = NumDMRGroups * 2, + localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, + localparam int unsigned NumSysCores = DMRFixed ? NumDMRCores : TMRFixed ? NumTMRCores : NumCores +) ( + input logic clk_i , + input logic rst_ni, + + // Port to configuration unit + input reg_req_t reg_request_i , + output reg_resp_t reg_response_o, + + // TMR signals + output logic [NumTMRGroups-1:0] tmr_failure_o , + output logic [ NumSysCores-1:0] tmr_error_o , // Should this not be NumTMRCores? or NumCores? + output logic [NumTMRGroups-1:0] tmr_resynch_req_o, + input logic [NumTMRGroups-1:0] tmr_cores_synch_i, + + // DMR signals + output logic [NumDMRGroups-1:0] dmr_failure_o , + output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? + output logic [NumDMRGroups-1:0] dmr_resynch_req_o, + input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + + // TODO other required signals + + // Ports connecting to System + input logic [NumSysCores-1:0][ 3:0] sys_core_id_i , + input logic [NumSysCores-1:0][ 5:0] sys_cluster_id_i , + + input logic [NumSysCores-1:0] sys_clock_en_i , + input logic [NumSysCores-1:0] sys_fetch_en_i , + input logic [NumSysCores-1:0][ 31:0] sys_boot_addr_i , + output logic [NumSysCores-1:0] sys_core_busy_o , + + input logic [NumSysCores-1:0] sys_irq_req_i , + output logic [NumSysCores-1:0] sys_irq_ack_o , + input logic [NumSysCores-1:0][ 4:0] sys_irq_id_i , + output logic [NumSysCores-1:0][ 4:0] sys_irq_ack_id_o , + + output logic [NumSysCores-1:0] sys_instr_req_o , + input logic [NumSysCores-1:0] sys_instr_gnt_i , + output logic [NumSysCores-1:0][ 31:0] sys_instr_addr_o , + input logic [NumSysCores-1:0][InstrDataWidth-1:0] sys_instr_r_rdata_i, + input logic [NumSysCores-1:0] sys_instr_r_valid_i, + input logic [NumSysCores-1:0] sys_instr_err_i , + + input logic [NumSysCores-1:0] sys_debug_req_i , + + output logic [NumSysCores-1:0] sys_data_req_o , + output logic [NumSysCores-1:0][ 31:0] sys_data_add_o , + output logic [NumSysCores-1:0] sys_data_wen_o , + output logic [NumSysCores-1:0][ DataWidth-1:0] sys_data_wdata_o , + output logic [NumSysCores-1:0][ UserWidth-1:0] sys_data_user_o , + output logic [NumSysCores-1:0][ BeWidth-1:0] sys_data_be_o , + input logic [NumSysCores-1:0] sys_data_gnt_i , + input logic [NumSysCores-1:0] sys_data_r_opc_i , + input logic [NumSysCores-1:0][ DataWidth-1:0] sys_data_r_rdata_i , + input logic [NumSysCores-1:0][ UserWidth-1:0] sys_data_r_user_i , + input logic [NumSysCores-1:0] sys_data_r_valid_i , + input logic [NumSysCores-1:0] sys_data_err_i , + + input logic [NumSysCores-1:0][NumExtPerf-1:0] sys_perf_counters_i, + + // Ports connecting to the cores + output logic [ NumCores-1:0] core_setback_o , + + output logic [ NumCores-1:0][ 3:0] core_core_id_o , + output logic [ NumCores-1:0][ 5:0] core_cluster_id_o , + + output logic [ NumCores-1:0] core_clock_en_o , + output logic [ NumCores-1:0] core_fetch_en_o , + output logic [ NumCores-1:0][ 31:0] core_boot_addr_o , + input logic [ NumCores-1:0] core_core_busy_i , + + output logic [ NumCores-1:0] core_irq_req_o , + input logic [ NumCores-1:0] core_irq_ack_i , + output logic [ NumCores-1:0][ 4:0] core_irq_id_o , + input logic [ NumCores-1:0][ 4:0] core_irq_ack_id_i , + + input logic [ NumCores-1:0] core_instr_req_i , + output logic [ NumCores-1:0] core_instr_gnt_o , + input logic [ NumCores-1:0][ 31:0] core_instr_addr_i , + output logic [ NumCores-1:0][InstrDataWidth-1:0] core_instr_r_rdata_o, + output logic [ NumCores-1:0] core_instr_r_valid_o, + output logic [ NumCores-1:0] core_instr_err_o , + + output logic [ NumCores-1:0] core_debug_req_o , + + input logic [ NumCores-1:0] core_data_req_i , + input logic [ NumCores-1:0][ 31:0] core_data_add_i , + input logic [ NumCores-1:0] core_data_wen_i , + input logic [ NumCores-1:0][ DataWidth-1:0] core_data_wdata_i , + input logic [ NumCores-1:0][ UserWidth-1:0] core_data_user_i , + input logic [ NumCores-1:0][ BeWidth-1:0] core_data_be_i , + output logic [ NumCores-1:0] core_data_gnt_o , + output logic [ NumCores-1:0] core_data_r_opc_o , + output logic [ NumCores-1:0][ DataWidth-1:0] core_data_r_rdata_o , + output logic [ NumCores-1:0][ UserWidth-1:0] core_data_r_user_o , + output logic [ NumCores-1:0] core_data_r_valid_o , + output logic [ NumCores-1:0] core_data_err_o , + + output logic [ NumCores-1:0][NumExtPerf-1:0] core_perf_counters_o + + // APU/SHARED_FPU not implemented +); + + function int tmr_group_id (int core_id); + if (InterleaveGrps) return core_id % NumTMRGroups; + else return (core_id/3); + endfunction + + function int tmr_core_id (int group_id, int core_offset); + if (InterleaveGrps) return group_id + core_offset * NumTMRGroups; + else return (group_id * 3) + core_offset; + endfunction + + function int dmr_group_id (int core_id); + if (InterleaveGrps) return core_id % NumDMRGroups; + else return (core_id/2); + endfunction + + function int dmr_core_id (int group_id, int core_offset); + if (InterleaveGrps) return group_id + core_offset * NumDMRGroups; + else return (group_id * 2) + core_offset; + endfunction + + if (TMRFixed && DMRFixed) $fatal(1, "Cannot fix both TMR and DMR!"); + + localparam int unsigned CtrlConcatWidth = 1 + 1 + 5 + 1 + 32 + 1; + // busy irq_ack irq_ack_id i_req i_addr d_req + localparam int unsigned DataConcatWidth = 32 + 1 + DataWidth + BeWidth + UserWidth; + // data_add data_wen data_wdata data_be data_user + localparam int unsigned MainConcatWidth = SeparateData ? CtrlConcatWidth : + CtrlConcatWidth + DataConcatWidth; + + logic [ NumCores-1:0][MainConcatWidth-1:0] main_concat_in; + logic [NumTMRGroups-1:0][MainConcatWidth-1:0] main_tmr_out; + logic [NumDMRGroups-1:0][MainConcatWidth-1:0] main_dmr_out; + + logic [ NumCores-1:0][DataConcatWidth-1:0] data_concat_in; + logic [NumTMRGroups-1:0][DataConcatWidth-1:0] data_tmr_out; + logic [NumDMRGroups-1:0][DataConcatWidth-1:0] data_dmr_out; + + logic [NumTMRGroups-1:0] tmr_failure, tmr_failure_main, tmr_failure_data; + logic [NumTMRGroups-1:0][2:0] tmr_error, tmr_error_main, tmr_error_data; + logic [NumTMRGroups-1:0] tmr_single_mismatch; + + logic [NumTMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_data; + logic [NumTMRGroups-1:0][2:0] dmr_error, dmr_error_main, dmr_error_data; + logic [NumTMRGroups-1:0] dmr_single_mismatch; + + logic [NumTMRGroups-1:0] tmr_core_busy_out; + logic [NumTMRGroups-1:0] tmr_irq_ack_out; + logic [NumTMRGroups-1:0][ 4:0] tmr_irq_ack_id_out; + logic [NumTMRGroups-1:0] tmr_instr_req_out; + logic [NumTMRGroups-1:0][ 31:0] tmr_instr_addr_out; + logic [NumTMRGroups-1:0] tmr_data_req_out; + logic [NumTMRGroups-1:0][ 31:0] tmr_data_add_out; + logic [NumTMRGroups-1:0] tmr_data_wen_out; + logic [NumTMRGroups-1:0][ DataWidth-1:0] tmr_data_wdata_out; + logic [NumTMRGroups-1:0][ UserWidth-1:0] tmr_data_user_out; + logic [NumTMRGroups-1:0][ BeWidth-1:0] tmr_data_be_out; + + logic [NumDMRGroups-1:0] dmr_core_busy_out; + logic [NumDMRGroups-1:0] dmr_irq_ack_out; + logic [NumDMRGroups-1:0][ 4:0] dmr_irq_ack_id_out; + logic [NumDMRGroups-1:0] dmr_instr_req_out; + logic [NumDMRGroups-1:0][ 31:0] dmr_instr_addr_out; + logic [NumDMRGroups-1:0] dmr_data_req_out; + logic [NumDMRGroups-1:0][ 31:0] dmr_data_add_out; + logic [NumDMRGroups-1:0] dmr_data_wen_out; + logic [NumDMRGroups-1:0][ DataWidth-1:0] dmr_data_wdata_out; + logic [NumDMRGroups-1:0][ UserWidth-1:0] dmr_data_user_out; + logic [NumDMRGroups-1:0][ BeWidth-1:0] dmr_data_be_out; + + for (genvar i = 0; i < NumCores; i++) begin : gen_concat + if (SeparateData) begin + assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], + core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i]}; + assign data_concat_in[i] = {core_data_add_i[i], core_data_wen_i[i], core_data_wdata_i[i], + core_data_be_i[i], core_data_user_i[i]}; + end else begin + assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], + core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], core_data_add_i[i], + core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i]}; + assign data_concat_in = '0; + end + end + + /*************************** + * HMR Control Registers * + ***************************/ + + logic [NumSysCores-1:0] core_en_as_master; + logic [NumSysCores-1:0] core_in_independent; + logic [NumSysCores-1:0] core_in_dmr; + logic [NumSysCores-1:0] core_in_tmr; + + for (genvar i = 0; i < NumSysCores; i++) begin + assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; + assign core_in_dmr[i] = 1'b0; + assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & + ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); + end + + reg_req_t [3:0] top_register_reqs; + reg_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_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 ) + ); + + // 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_resp_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) + ); + + 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; + + always_comb begin + hmr_hw2reg.cores_en.d = '0; + hmr_hw2reg.cores_en.d = core_en_as_master; + end + + assign hmr_hw2reg.dmr_enable.d = '0; + assign hmr_hw2reg.tmr_enable.d = '0; + + 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; + + // Core Config Registers + + reg_req_t [NumCores-1:0] core_register_reqs; + reg_resp_t [NumCores-1:0] core_register_resps; + + // 2 words per core + + reg_demux #( + .NoPorts ( NumCores ), + .req_t ( reg_req_t ), + .rsp_t ( reg_resp_t ) + ) i_core_reg_demux ( + .clk_i, + .rst_ni, + .in_select_i( top_register_reqs [1].addr[3+$clog2(NumCores)-1:3] ), + .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 ) + ); + + 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; + + logic [NumCores-1:0] tmr_incr_mismatches; + logic [NumCores-1:0] dmr_incr_mismatches; + assign dmr_incr_mismatches = '0; + + for (genvar i = 0; i < NumCores; i++) begin + hmr_core_regs_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_resp_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) + ); + + 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]; + end + + logic [NumTMRGroups-1:0] tmr_setback_q; + logic [NumTMRGroups-1:0] tmr_grp_in_independent; + + + /********************************************************** + ******************** TMR Voters & Regs ******************* + **********************************************************/ + + if (TMRSupported || TMRFixed) begin : gen_tmr_logic + if (TMRFixed && NumCores % 3 != 0) $warning("Extra cores added not properly handled!"); + + hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t [NumTMRGroups-1:0] tmr_reg2hw; + hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t [NumTMRGroups-1:0] tmr_hw2reg; + + reg_req_t [NumTMRGroups-1:0] tmr_register_reqs; + reg_resp_t [NumTMRGroups-1:0] tmr_register_resps; + + localparam TMRSelWidth = $clog2(NumTMRGroups); + + /*************** + * Registers * + ***************/ + reg_demux #( + .NoPorts ( NumTMRGroups ), + .req_t ( reg_req_t ), + .rsp_t ( reg_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 ) + ); + + for (genvar i = 0; i < NumTMRCores; i++) begin : gen_core_in_tmr + assign core_in_tmr[i] = !tmr_grp_in_independent[tmr_group_id(i)]; + end + + for (genvar i = NumTMRCores; i < NumCores; i++) begin : gen_extra_core_assigns + assign tmr_incr_mismatches[i] = '0; + assign core_in_tmr[i] = '0; + end + + for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups + + hmr_tmr_ctrl #( + .reg_req_t (reg_req_t), + .reg_resp_t (reg_resp_t), + .TMRFixed (TMRFixed), + .InterleaveGrps(InterleaveGrps), + .DefaultInTMR (1'b0) + ) i_tmr_ctrl ( + .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 ), + .force_resynch_q_i ( hmr_reg2hw.tmr_config.force_resynch.q ), + .force_resynch_qe_i ( hmr_reg2hw.tmr_config.force_resynch.qe ), + + .setback_o ( tmr_setback_q[i] ), + .grp_in_independent_o ( tmr_grp_in_independent[i] ), + .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), + .tmr_single_mismatch_i( tmr_single_mismatch[i] ), + .tmr_error_i ( tmr_error[i] ), + .tmr_failure_i ( tmr_failure[i] ), + .fetch_en_i ( sys_fetch_en_i[tmr_core_id(i, 0)] ), + .cores_synch_i ( tmr_cores_synch_i[i] ) + ); + + assign tmr_failure[i] = tmr_data_req_out[i] ? + tmr_failure_main | tmr_failure_data : tmr_failure_main; + assign tmr_error[i] = tmr_data_req_out[i] ? + tmr_error_main[i] | tmr_error_data[i] : tmr_error_main[i]; + assign tmr_single_mismatch[i] = tmr_error[i] != 3'b000; + + bitwise_TMR_voter #( + .DataWidth( MainConcatWidth ), + .VoterType( 0 ) + ) i_main_voter ( + .a_i ( main_concat_in[tmr_core_id(i, 0)] ), + .b_i ( main_concat_in[tmr_core_id(i, 1)] ), + .c_i ( main_concat_in[tmr_core_id(i, 2)] ), + .majority_o ( main_tmr_out [i ] ), + .error_o ( tmr_failure_main[i] ), + .error_cba_o( tmr_error_main[i ] ) + ); + if (SeparateData) begin : gen_data_voter + bitwise_TMR_voter #( + .DataWidth( DataConcatWidth ), + .VoterType( 0 ) + ) i_main_voter ( + .a_i ( data_concat_in[tmr_core_id(i, 0)] ), + .b_i ( data_concat_in[tmr_core_id(i, 1)] ), + .c_i ( data_concat_in[tmr_core_id(i, 2)] ), + .majority_o ( data_tmr_out [i ] ), + .error_o ( tmr_failure_data[i] ), + .error_cba_o( tmr_error_data[i ] ) + ); + + assign {tmr_core_busy_out[i], tmr_irq_ack_out[i], tmr_irq_ack_id_out[i], + tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i]} = main_tmr_out[i]; + assign {tmr_data_add_out[i], tmr_data_wen_out[i], tmr_data_wdata_out[i], + tmr_data_be_out[i], tmr_data_user_out[i]} = data_tmr_out[i]; + end else begin : gen_data_in_main + assign tmr_failure_data[i] = 1'b0; + assign tmr_error_data[i] = 3'b000; + assign {tmr_core_busy_out[i], tmr_irq_ack_out[i], tmr_irq_ack_id_out[i], + tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i], + tmr_data_add_out[i], tmr_data_wen_out[i], tmr_data_wdata_out[i], + tmr_data_be_out[i], tmr_data_user_out[i]} = main_tmr_out[i]; + end + end + end else begin : gen_no_tmr_voted + assign tmr_error_main = '0; + assign tmr_error_data = '0; + assign tmr_error = '0; + assign tmr_failure_main = '0; + assign tmr_failure_data = '0; + assign tmr_failure = '0; + assign main_tmr_out = '0; + assign data_tmr_out = '0; + assign {tmr_core_busy_out, tmr_irq_ack_out, tmr_irq_ack_id_out, + tmr_instr_req_out, tmr_instr_addr_out, tmr_data_req_out, + tmr_data_add_out, tmr_data_wen_out, tmr_data_wdata_out, + tmr_data_be_out, tmr_data_user_out} = '0; + assign top_register_resps[3].rdata = '0; + assign top_register_resps[3].error = 1'b1; + assign top_register_resps[3].ready = 1'b1; + assign tmr_incr_mismatches = '0; + assign tmr_grp_in_independent = '0; + assign core_in_tmr = '0; + assign tmr_setback_q = '0; + end + + /************************************************************ + ******************** DMR Voters and Regs ******************* + ************************************************************/ + + if (DMRSupported || DMRFixed) begin: gen_dmr_checkers + for (genvar i = 0; i < NumDMRGroups; i++) begin + assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main | dmr_failure_data) + : dmr_failure_main; + assign dmr_error [i*2+:2] = dmr_data_req_out [i] ? (dmr_error_main [i*2+:2] | dmr_error_data [i*2+:2]) + : tmr_error_main [i*2+:2]; + assign dmr_single_mismatch [i] = dmr_error [i*2+:2] != 3'b000; + + DMR_checker #( + .DataWidth ( MainConcatWidth ) + ) dmr_core_checker_main ( + .inp_a_i ( main_concat_in [dmr_core_id(i, 0)]), + .inp_b_i ( main_concat_in [dmr_core_id(i, 1)]), + .check_o ( main_dmr_out [i] ), + .error_o ( dmr_failure_main [i]) + ); + if (SeparateData) begin : gen_data_checker + DMR_checker # ( + .DataWidth ( DataConcatWidth ) + ) dmr_core_checker_data ( + .inp_a_i ( data_concat_in [dmr_core_id(i, 0)]), + .inp_b_i ( data_concat_in [dmr_core_id(i, 1)]), + .check_o ( data_dmr_out [i] ), + .error_o ( dmr_failure_data [i]) + ); + assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], + dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] } + = main_dmr_out[i]; + assign {dmr_data_add_out[i], dmr_data_wen_out[i] , dmr_data_wdata_out[i], + dmr_data_be_out[i] , dmr_data_user_out[i] } + = data_dmr_out[i]; + end else begin : gen_data_in_main + assign dmr_failure_data[i] = 1'b0; + assign dmr_error_data[i] = 3'b000; + assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], + dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] , + dmr_data_add_out[i] , dmr_data_wen_out[i] , dmr_data_wdata_out[i], + dmr_data_be_out[i] , dmr_data_user_out[i]} + = main_dmr_out[i]; + end + end + if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error + assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; + assign dmr_error_data[NumCores-1-:NumDMRLeftover] = '0; + assign dmr_error [NumCores-1-:NumDMRLeftover] = '0; + end + end else begin: no_dmr_checkers // block: gen_dmr_checkers + assign dmr_error_main = '0; + assign dmr_error_data = '0; + assign dmr_error = '0; + assign dmr_failure_main = '0; + assign dmr_failure_data = '0; + assign dmr_failure = '0; + assign main_dmr_out = '0; + assign data_dmr_out = '0; + assign {dmr_core_busy_out, dmr_irq_ack_out , dmr_irq_ack_id_out, + dmr_instr_req_out, dmr_instr_addr_out, dmr_data_req_out , + dmr_data_add_out , dmr_data_wen_out , dmr_data_wdata_out, + dmr_data_be_out , dmr_data_user_out} + = '0; + assign top_register_resps[2].rdata = '0; + assign top_register_resps[2].error = 1'b1; + assign top_register_resps[2].ready = 1'b1; + end + + // Assign output signals + if (DMRSupported && TMRSupported) begin : gen_full_HMR + /***************** + *** TMR & DMR *** + *****************/ + if (TMRFixed || DMRFixed) $fatal(1, "Cannot support both TMR and DMR and fix one!"); + + // TODO + + end else if (TMRSupported || TMRFixed) begin : gen_TMR_only + /***************** + *** TMR only *** + *****************/ + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); + always_comb begin + if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + + // CTRL + core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; + core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; + + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; + core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; + + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; + core_perf_counters_o[i] = sys_perf_counters_i[SysCoreIndex]; + + // IRQ + core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; + core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; + + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[SysCoreIndex]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[SysCoreIndex]; + core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; + + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; + core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; + core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + + end else begin : independent_mode + core_setback_o [i] = '0; + + // CTRL + core_core_id_o [i] = sys_core_id_i [i]; + core_cluster_id_o [i] = sys_cluster_id_i [i]; + + core_clock_en_o [i] = sys_clock_en_i [i]; + core_fetch_en_o [i] = sys_fetch_en_i [i]; + core_boot_addr_o [i] = sys_boot_addr_i [i]; + + core_debug_req_o [i] = sys_debug_req_i [i]; + core_perf_counters_o[i] = sys_perf_counters_i[i]; + + // IRQ + core_irq_req_o [i] = sys_irq_req_i [i]; + core_irq_id_o [i] = sys_irq_id_i [i]; + + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_err_o [i] = sys_instr_err_i [i]; + + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_r_opc_o [i] = sys_data_r_opc_i [i]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; + core_data_r_user_o [i] = sys_data_r_user_i [i]; + core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_err_o [i] = sys_data_err_i [i]; + + end + end + end + + for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs + localparam CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); + if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr + // CTRL + assign sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; + + // IRQ + assign sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; + assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + + // INSTR + assign sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; + assign sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + + // DATA + assign sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; + assign sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; + assign sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; + assign sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; + assign sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; + assign sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + end else begin + if (i >= NumTMRCores) begin : independent_stragglers + // CTRL + assign sys_core_busy_o [i] = core_core_busy_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + + // IRQ + assign sys_irq_ack_o [i] = core_irq_ack_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + + // INSTR + assign sys_instr_req_o [i] = core_instr_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_instr_addr_o [i] = core_instr_addr_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + + // DATA + assign sys_data_req_o [i] = core_data_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_add_o [i] = core_data_add_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_wen_o [i] = core_data_wen_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_wdata_o [i] = core_data_wdata_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_user_o [i] = core_data_user_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_be_o [i] = core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + end else begin + always_comb begin + if (core_in_tmr[i]) begin : tmr_mode + if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core + + // CTRL + sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; + + // IRQ + sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; + sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + + // INSTR + sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; + sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + + // DATA + sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; + sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; + sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; + sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; + sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; + sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + + end else begin : disable_core // Assign disable + + // CTLR + sys_core_busy_o [i] = '0; + + // IRQ + sys_irq_ack_o [i] = '0; + sys_irq_ack_id_o [i] = '0; + + // INSTR + sys_instr_req_o [i] = '0; + sys_instr_addr_o [i] = '0; + + // DATA + sys_data_req_o [i] = '0; + sys_data_add_o [i] = '0; + sys_data_wen_o [i] = '0; + sys_data_wdata_o [i] = '0; + sys_data_user_o [i] = '0; + sys_data_be_o [i] = '0; + + end + end else begin : independent_mode + // CTRL + sys_core_busy_o [i] = core_core_busy_i [i]; + + // IRQ + sys_irq_ack_o [i] = core_irq_ack_i [i]; + sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; + + // INSTR + sys_instr_req_o [i] = core_instr_req_i [i]; + sys_instr_addr_o [i] = core_instr_addr_i[i]; + + // DATA + sys_data_req_o [i] = core_data_req_i [i]; + sys_data_add_o [i] = core_data_add_i [i]; + sys_data_wen_o [i] = core_data_wen_i [i]; + sys_data_wdata_o [i] = core_data_wdata_i[i]; + sys_data_user_o [i] = core_data_user_i [i]; + sys_data_be_o [i] = core_data_be_i [i]; + end + end + end + end + end + + end else if (DMRSupported || DMRFixed) begin : gen_DMR_only + /***************** + *** DMR only *** + *****************/ + if (DMRFixed && NumCores % 2 != 0) $warning("Extra cores added not properly handled! :)"); + // Binding DMR outputs to zero for now + assign dmr_failure_o = '0; + assign dmr_error_o = '0; + assign dmr_resynch_req_o = '0; + + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); + if (i < NumDMRCores && DMRFixed) begin : gen_dmr_mode + // CTRL + assign core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; + assign core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; + + assign core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + assign core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; + assign core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; + + assign core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; + assign core_perf_counters_o[i] = sys_perf_counters_i[SysCoreIndex]; + + // IRQ + assign core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; + assign core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; + + // INSTR + assign core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[SysCoreIndex]; + assign core_instr_r_valid_o[i] = sys_instr_r_valid_i[SysCoreIndex]; + assign core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; + + // DATA + assign core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + assign core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; + assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; + assign core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; + assign core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + assign core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + + end else begin : gen_independent_mode + + // CTRL + assign core_core_id_o [i] = sys_core_id_i [i]; + assign core_cluster_id_o [i] = sys_cluster_id_i [i]; + + assign core_clock_en_o [i] = sys_clock_en_i [i]; + assign core_fetch_en_o [i] = sys_fetch_en_i [i]; + assign core_boot_addr_o [i] = sys_boot_addr_i [i]; + + assign core_debug_req_o [i] = sys_debug_req_i [i]; + assign core_perf_counters_o[i] = sys_perf_counters_i[i]; + + // IRQ + assign core_irq_req_o [i] = sys_irq_req_i [i]; + assign core_irq_id_o [i] = sys_irq_id_i [i]; + + // INSTR + assign core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; + assign core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + assign core_instr_err_o [i] = sys_instr_err_i [i]; + + // DATA + assign core_data_gnt_o [i] = sys_data_gnt_i [i]; + assign core_data_r_opc_o [i] = sys_data_r_opc_i [i]; + assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; + assign core_data_r_user_o [i] = sys_data_r_user_i [i]; + assign core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + assign core_data_err_o [i] = sys_data_err_i [i]; + + end + end // gen_core_inputs + + for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs + localparam CoreCoreIndex = DMRFixed ? i : dmr_core_id(i, 0); + if ((DMRFixed && i < NumDMRGroups) || (i < NumDMRCores)) begin : gen_dmr_mode + if (DMRFixed || (InterleaveGrps && i < NumDMRGroups) || (!InterleaveGrps && i%2 == 0)) begin : gen_is_dmr + + // CTRL + assign sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; + + // IRQ + assign sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; + assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + + // INSTR + assign sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; + assign sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + + // DATA + assign sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; + assign sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; + assign sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; + assign sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; + assign sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; + assign sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + + end else begin : gen_disable_core // Assign disable + + // CTLR + assign sys_core_busy_o [i] = '0; + + // IRQ + assign sys_irq_ack_o [i] = '0; + assign sys_irq_ack_id_o [i] = '0; + + // INSTR + assign sys_instr_req_o [i] = '0; + assign sys_instr_addr_o [i] = '0; + + // DATA + assign sys_data_req_o [i] = '0; + assign sys_data_add_o [i] = '0; + assign sys_data_wen_o [i] = '0; + assign sys_data_wdata_o [i] = '0; + assign sys_data_user_o [i] = '0; + assign sys_data_be_o [i] = '0; + + end + end else begin : gen_independent_mode + // CTRL + assign sys_core_busy_o [i] = core_core_busy_i [i]; + + // IRQ + assign sys_irq_ack_o [i] = core_irq_ack_i [i]; + assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; + + // INSTR + assign sys_instr_req_o [i] = core_instr_req_i [i]; + assign sys_instr_addr_o [i] = core_instr_addr_i[i]; + + // DATA + assign sys_data_req_o [i] = core_data_req_i [i]; + assign sys_data_add_o [i] = core_data_add_i [i]; + assign sys_data_wen_o [i] = core_data_wen_i [i]; + assign sys_data_wdata_o [i] = core_data_wdata_i[i]; + assign sys_data_user_o [i] = core_data_user_i [i]; + assign sys_data_be_o [i] = core_data_be_i [i]; + end + end // gen_core_outputs + + end else begin : gen_no_redundancy + /***************** + *** none *** + *****************/ + // Direct assignment, disable all + assign core_setback_o = '0; + + // CTRL + assign core_core_id_o = sys_core_id_i; + assign core_cluster_id_o = sys_cluster_id_i; + + assign core_clock_en_o = sys_clock_en_i; + assign core_fetch_en_o = sys_fetch_en_i; + assign core_boot_addr_o = sys_boot_addr_i; + assign sys_core_busy_o = core_core_busy_i; + + assign core_debug_req_o = sys_debug_req_i; + assign core_perf_counters_o = sys_perf_counters_i; + + // IRQ + assign core_irq_req_o = sys_irq_req_i; + assign sys_irq_ack_o = core_irq_ack_i; + assign core_irq_id_o = sys_irq_id_i; + assign sys_irq_ack_id_o = core_irq_ack_id_i; + + // INSTR + assign sys_instr_req_o = core_instr_req_i; + assign core_instr_gnt_o = sys_instr_gnt_i; + assign sys_instr_addr_o = core_instr_addr_i; + assign core_instr_r_rdata_o = sys_instr_r_rdata_i; + assign core_instr_r_valid_o = sys_instr_r_valid_i; + assign core_instr_err_o = sys_instr_err_i; + + // DATA + assign sys_data_req_o = core_data_req_i; + assign sys_data_add_o = core_data_add_i; + assign sys_data_wen_o = core_data_wen_i; + assign sys_data_wdata_o = core_data_wdata_i; + assign sys_data_user_o = core_data_user_i; + assign sys_data_be_o = core_data_be_i; + assign core_data_gnt_o = sys_data_gnt_i; + assign core_data_r_opc_o = sys_data_r_opc_i; + assign core_data_r_rdata_o = sys_data_r_rdata_i; + assign core_data_r_user_o = sys_data_r_user_i; + assign core_data_r_valid_o = sys_data_r_valid_i; + assign core_data_err_o = sys_data_err_i; + end + +endmodule diff --git a/rtl/HMR/doc.html b/rtl/HMR/doc.html new file mode 100644 index 00000000..ee0cb44f --- /dev/null +++ b/rtl/HMR/doc.html @@ -0,0 +1,80 @@ + + + + + +
+
HMR_registers.avail_config @ 0x0
+

Available Configurations from implemented hardware.

+
Reset default = 0x0, mask 0x7
+
+ + + + + +
31302928272625242322212019181716
 
1514131211109876543210
 tripledualindependent
BitsTypeResetNameDescription
0roxindependent

Independent mode is available.

1roxdual

Dual Modular Redundancy (DMR) is available.

2roxtriple

Triple Modular Redundancy (TMR) 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.TMR_config @ 0x10
+

TMR configuration bits.

+
Reset default = 0x6, mask 0xf
+
+ + + + + + +
31302928272625242322212019181716
 
1514131211109876543210
 force_resynchreload_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)

3rw0x0force_resynch

Forces a resynchronization routine

+
diff --git a/rtl/HMR/doc.md b/rtl/HMR/doc.md new file mode 100644 index 00000000..892ab665 --- /dev/null +++ b/rtl/HMR/doc.md @@ -0,0 +1,312 @@ + + + + +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_core.h b/rtl/HMR/hmr_core.h new file mode 100644 index 00000000..58d7d0c5 --- /dev/null +++ b/rtl/HMR/hmr_core.h @@ -0,0 +1,25 @@ +// 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 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _HMR_CORE_REGS_REG_DEFS_ +// End generated register defines for HMR_core_regs \ No newline at end of file diff --git a/rtl/HMR/hmr_core_regs_reg_pkg.sv b/rtl/HMR/hmr_core_regs_reg_pkg.sv new file mode 100644 index 00000000..b594350c --- /dev/null +++ b/rtl/HMR/hmr_core_regs_reg_pkg.sv @@ -0,0 +1,71 @@ +// 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 + +package hmr_core_regs_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 3; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic [31:0] q; + } hmr_core_regs_reg2hw_mismatches_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; // [31: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 = 3'h 0; + parameter logic [BlockAw-1:0] HMR_CORE_REGS_MISMATCHES_OFFSET = 3'h 4; + + // 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_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] HMR_CORE_REGS_PERMIT [2] = '{ + 4'b 0001, // index[0] HMR_CORE_REGS_CURRENT_MODE + 4'b 1111 // index[1] HMR_CORE_REGS_MISMATCHES + }; + +endpackage + diff --git a/rtl/HMR/hmr_core_regs_reg_top.sv b/rtl/HMR/hmr_core_regs_reg_top.sv new file mode 100644 index 00000000..39e65762 --- /dev/null +++ b/rtl/HMR/hmr_core_regs_reg_top.sv @@ -0,0 +1,267 @@ +// 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 = 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_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; + + // 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) + ); + + + + + logic [1: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); + 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))))); + 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]; + + // 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 + + 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 = 3, + 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 + ); + +endmodule + + diff --git a/rtl/HMR/hmr_dmr.h b/rtl/HMR/hmr_dmr.h new file mode 100644 index 00000000..a97a51bc --- /dev/null +++ b/rtl/HMR/hmr_dmr.h @@ -0,0 +1,27 @@ +// 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_TMR_ENABLE_BIT 0 + +// DMR configuration bits. +#define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4 +#define HMR_DMR_REGS_DMR_CONFIG_TODO_BIT 0 + +// 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 \ No newline at end of file diff --git a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv new file mode 100644 index 00000000..b568f175 --- /dev/null +++ b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv @@ -0,0 +1,80 @@ +// 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 + +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 { + logic q; + logic qe; + } 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 { + logic d; + logic de; + } 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; // [36:35] + hmr_dmr_regs_reg2hw_dmr_config_reg_t dmr_config; // [34: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; // [36:35] + hmr_dmr_regs_hw2reg_dmr_config_reg_t dmr_config; // [34: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 + }; + +endpackage + diff --git a/rtl/HMR/hmr_dmr_regs_reg_top.sv b/rtl/HMR/hmr_dmr_regs_reg_top.sv new file mode 100644 index 00000000..80722d6b --- /dev/null +++ b/rtl/HMR/hmr_dmr_regs_reg_top.sv @@ -0,0 +1,278 @@ +// 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_qs; + logic dmr_config_wd; + logic dmr_config_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) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_dmr_config ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dmr_config_we), + .wd (dmr_config_wd), + + // from internal hardware + .de (hw2reg.dmr_config.de), + .d (hw2reg.dmr_config.d ), + + // to internal hardware + .qe (reg2hw.dmr_config.qe), + .q (reg2hw.dmr_config.q ), + + // to register interface (read) + .qs (dmr_config_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_we = addr_hit[1] & reg_we & !reg_error; + assign dmr_config_wd = reg_wdata[0]; + + 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_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)) + +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_global.h b/rtl/HMR/hmr_global.h new file mode 100644 index 00000000..6a687f15 --- /dev/null +++ b/rtl/HMR/hmr_global.h @@ -0,0 +1,56 @@ +// 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 + +// 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 }) + +// TMR configuration bits. +#define HMR_REGISTERS_TMR_CONFIG_REG_OFFSET 0x10 +#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_FORCE_RESYNCH_BIT 3 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _HMR_REGISTERS_REG_DEFS_ +// End generated register defines for HMR_registers \ No newline at end of file diff --git a/rtl/HMR/hmr_registers_reg_pkg.sv b/rtl/HMR/hmr_registers_reg_pkg.sv new file mode 100644 index 00000000..3858c81d --- /dev/null +++ b/rtl/HMR/hmr_registers_reg_pkg.sv @@ -0,0 +1,144 @@ +// 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 + +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; + } delay_resynch; + struct packed { + logic q; + logic qe; + } setback; + struct packed { + logic q; + logic qe; + } reload_setback; + 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; + } 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; + } delay_resynch; + struct packed { + logic d; + } setback; + struct packed { + logic d; + } reload_setback; + 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; // [19:13] + hmr_registers_reg2hw_tmr_enable_reg_t tmr_enable; // [12:8] + hmr_registers_reg2hw_tmr_config_reg_t tmr_config; // [7:0] + } hmr_registers_reg2hw_t; + + // HW -> register type + typedef struct packed { + hmr_registers_hw2reg_avail_config_reg_t avail_config; // [28:26] + hmr_registers_hw2reg_cores_en_reg_t cores_en; // [25:14] + hmr_registers_hw2reg_dmr_enable_reg_t dmr_enable; // [13:8] + hmr_registers_hw2reg_tmr_enable_reg_t tmr_enable; // [7:4] + hmr_registers_hw2reg_tmr_config_reg_t tmr_config; // [3: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_TMR_CONFIG_OFFSET = 5'h 10; + + // Reset values for hwext registers and their fields + parameter logic [2:0] HMR_REGISTERS_AVAIL_CONFIG_RESVAL = 3'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 [3:0] HMR_REGISTERS_TMR_CONFIG_RESVAL = 4'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_TMR_CONFIG + } hmr_registers_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] HMR_REGISTERS_PERMIT [5] = '{ + 4'b 0001, // 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_TMR_CONFIG + }; + +endpackage + diff --git a/rtl/HMR/hmr_registers_reg_top.sv b/rtl/HMR/hmr_registers_reg_top.sv new file mode 100644 index 00000000..e2649082 --- /dev/null +++ b/rtl/HMR/hmr_registers_reg_top.sv @@ -0,0 +1,417 @@ +// 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 [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 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_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) + ); + + + // 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[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[force_resynch]: 3:3 + 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 [4: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_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))))); + 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 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 tmr_config_delay_resynch_we = addr_hit[4] & reg_we & !reg_error; + assign tmr_config_delay_resynch_wd = reg_wdata[0]; + assign tmr_config_delay_resynch_re = addr_hit[4] & reg_re & !reg_error; + + assign tmr_config_setback_we = addr_hit[4] & reg_we & !reg_error; + assign tmr_config_setback_wd = reg_wdata[1]; + assign tmr_config_setback_re = addr_hit[4] & reg_re & !reg_error; + + assign tmr_config_reload_setback_we = addr_hit[4] & reg_we & !reg_error; + assign tmr_config_reload_setback_wd = reg_wdata[2]; + assign tmr_config_reload_setback_re = addr_hit[4] & reg_re & !reg_error; + + assign tmr_config_force_resynch_we = addr_hit[4] & reg_we & !reg_error; + assign tmr_config_force_resynch_wd = reg_wdata[3]; + assign tmr_config_force_resynch_re = addr_hit[4] & 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; + 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] = 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_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_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_tmr.h b/rtl/HMR/hmr_tmr.h new file mode 100644 index 00000000..9751e30d --- /dev/null +++ b/rtl/HMR/hmr_tmr.h @@ -0,0 +1,30 @@ +// 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_FORCE_RESYNCH_BIT 3 + +// Stack Pointer storage register +#define HMR_TMR_REGS_SP_STORE_REG_OFFSET 0x8 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _HMR_TMR_REGS_REG_DEFS_ +// End generated register defines for HMR_tmr_regs \ No newline at end of file diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv new file mode 100644 index 00000000..13055a3f --- /dev/null +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -0,0 +1,179 @@ +// Copyright 2022 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. +// +// Hybrid modular redundancy TMR control unit + +module hmr_tmr_ctrl #( + parameter bit InterleaveGrps = 1'b0, + parameter bit TMRFixed = 1'b0, + parameter bit DefaultInTMR = TMRFixed ? 1'b1 : 1'b0, + parameter type reg_req_t = logic, + parameter type reg_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, + + // CTRL from external (e.g. HMR ctr regs) + input logic tmr_enable_q_i, + input logic tmr_enable_qe_i, + input logic delay_resynch_q_i, + input logic delay_resynch_qe_i, + input logic setback_q_i, + input logic setback_qe_i, + input logic reload_setback_q_i, + input logic reload_setback_qe_i, + input logic force_resynch_q_i, + input logic force_resynch_qe_i, + + // TMR control signals + output logic setback_o, + output logic grp_in_independent_o, + output logic [2:0] tmr_incr_mismatches_o, + input logic tmr_single_mismatch_i, + input logic [2:0] tmr_error_i, + input logic tmr_failure_i, + input logic fetch_en_i, + input logic cores_synch_i +); + + typedef enum logic [1:0] {NON_TMR, TMR_RUN, TMR_UNLOAD, TMR_RELOAD} 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; + + tmr_mode_e tmr_red_mode_d, tmr_red_mode_q; + logic tmr_setback_d, tmr_setback_q; + + assign setback_o = tmr_setback_q; + assign grp_in_independent_o = tmr_red_mode_q == NON_TMR; + + 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) + ); + + // 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.force_resynch.d = force_resynch_qe_i ? force_resynch_q_i : 1'b0; + + /************************** + * FSM for TMR lockstep * + **************************/ + always_comb begin : proc_fsm + tmr_setback_d = 1'b0; + tmr_red_mode_d = tmr_red_mode_q; + tmr_incr_mismatches_o[0] = 1'b0; + tmr_incr_mismatches_o[1] = 1'b0; + tmr_incr_mismatches_o[2] = 1'b0; + + tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; + + // If forced execute resynchronization + if (tmr_red_mode_q == TMR_RUN && tmr_reg2hw.tmr_config.force_resynch.q) begin + tmr_hw2reg.tmr_config.force_resynch.de = 1'b1; + if (tmr_reg2hw.tmr_config.delay_resynch == 0) begin + tmr_red_mode_d = TMR_UNLOAD; + // TODO: buffer the restoration until delay_resynch is disabled + end + end + + // If error detected, do resynchronization + if (tmr_red_mode_q == TMR_RUN && tmr_single_mismatch_i) begin + $display("[ODRG] %t - mismatch detected", $realtime); + if (tmr_error_i[0]) tmr_incr_mismatches_o[0] = 1'b1; + 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.delay_resynch == 0) begin + tmr_red_mode_d = TMR_UNLOAD; + // TODO: buffer the restoration until delay_resynch is disabled + end + end + + // If unload complete, go to reload (and reset) + if (tmr_red_mode_q == TMR_UNLOAD) begin + if (tmr_reg2hw.sp_store.q != '0) begin + tmr_red_mode_d = TMR_RELOAD; + if (tmr_reg2hw.tmr_config.setback.q) begin + tmr_setback_d = 1'b1; + end + end + end + + // If reload complete, finish (or reset if error happens during reload) + if (tmr_red_mode_q == TMR_RELOAD) begin + if (tmr_reg2hw.sp_store.q == '0) begin + $display("[ODRG] %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 && + !(tmr_reg2hw.sp_store.qe && reg_req_i.wdata == '0)) begin + tmr_setback_d = 1'b1; + end + end + end + + // Before core startup: set TMR mode from reg2hw.mode.mode + if (!TMRFixed) begin + if (fetch_en_i == 0) begin + if (tmr_reg2hw.tmr_enable.q == 1'b0) begin + tmr_red_mode_d = NON_TMR; + end else begin + tmr_red_mode_d = TMR_RUN; + end + end + // split single-error 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 + tmr_red_mode_d = NON_TMR; + end + end + // Set TMR mode on external signal that cores are synchronized + if (tmr_red_mode_q == NON_TMR && cores_synch_i) begin + if (tmr_reg2hw.tmr_enable.q == 1'b1) begin + tmr_red_mode_d = TMR_RUN; + end + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode + if(!rst_ni) begin + tmr_red_mode_q <= DefaultTMRMode; + tmr_setback_q <= '0; + end else begin + tmr_red_mode_q <= tmr_red_mode_d; + tmr_setback_q <= tmr_setback_d; + end + end + +endmodule diff --git a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv new file mode 100644 index 00000000..0643b9c0 --- /dev/null +++ b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv @@ -0,0 +1,108 @@ +// 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 + +package hmr_tmr_regs_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 4; + + //////////////////////////// + // 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; + } force_resynch; + } hmr_tmr_regs_reg2hw_tmr_config_reg_t; + + typedef struct packed { + logic [31:0] q; + logic qe; + } hmr_tmr_regs_reg2hw_sp_store_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; + } force_resynch; + } hmr_tmr_regs_hw2reg_tmr_config_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } hmr_tmr_regs_hw2reg_sp_store_reg_t; + + // Register -> HW type + typedef struct packed { + hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [42:41] + hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [40:33] + hmr_tmr_regs_reg2hw_sp_store_reg_t sp_store; // [32:0] + } hmr_tmr_regs_reg2hw_t; + + // HW -> register type + typedef struct packed { + hmr_tmr_regs_hw2reg_tmr_enable_reg_t tmr_enable; // [42:41] + hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [40:33] + hmr_tmr_regs_hw2reg_sp_store_reg_t sp_store; // [32:0] + } hmr_tmr_regs_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_ENABLE_OFFSET = 4'h 0; + parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_CONFIG_OFFSET = 4'h 4; + parameter logic [BlockAw-1:0] HMR_TMR_REGS_SP_STORE_OFFSET = 4'h 8; + + // Register index + typedef enum int { + HMR_TMR_REGS_TMR_ENABLE, + HMR_TMR_REGS_TMR_CONFIG, + HMR_TMR_REGS_SP_STORE + } hmr_tmr_regs_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] HMR_TMR_REGS_PERMIT [3] = '{ + 4'b 0001, // index[0] HMR_TMR_REGS_TMR_ENABLE + 4'b 0001, // index[1] HMR_TMR_REGS_TMR_CONFIG + 4'b 1111 // index[2] HMR_TMR_REGS_SP_STORE + }; + +endpackage + diff --git a/rtl/HMR/hmr_tmr_regs_reg_top.sv b/rtl/HMR/hmr_tmr_regs_reg_top.sv new file mode 100644 index 00000000..25879e1c --- /dev/null +++ b/rtl/HMR/hmr_tmr_regs_reg_top.sv @@ -0,0 +1,378 @@ +// 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 = 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_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_force_resynch_qs; + logic tmr_config_force_resynch_wd; + logic tmr_config_force_resynch_we; + logic [31:0] sp_store_qs; + logic [31:0] sp_store_wd; + logic sp_store_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[force_resynch]: 3:3 + 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) + ); + + + // 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 (hw2reg.sp_store.de), + .d (hw2reg.sp_store.d ), + + // 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_TMR_REGS_TMR_ENABLE_OFFSET); + addr_hit[1] = (reg_addr == HMR_TMR_REGS_TMR_CONFIG_OFFSET); + addr_hit[2] = (reg_addr == HMR_TMR_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_TMR_REGS_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(HMR_TMR_REGS_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(HMR_TMR_REGS_PERMIT[2] & ~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_force_resynch_we = addr_hit[1] & reg_we & !reg_error; + assign tmr_config_force_resynch_wd = reg_wdata[3]; + + 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] = 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_force_resynch_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_tmr_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_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 + ); + +endmodule + + From 3fd6d902c2e6f3f9d821be393d5ca9060ca8afe6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 8 May 2023 11:33:17 +0200 Subject: [PATCH 02/66] Integrated ECC-protected Recovery RF. Making clear that the internal Floating-Point memory decoder is actually for Floating-Points. Added functions for DMR grouping. Reverted grouping functions to previous implementations Recovery Routine quite complete for RF refill. Successfully rewriting cores' RF from backup copy. Resuming cores from debug mode during recovery routine. Reverted phase of instruction lock signal. Reverted core reset into synchronous setback for clear. Recovering cores' Program Counter during the Recovery Routine. Move recovery and DMR files to HMR Change debug_rsp to debug_halted Bind branch address read from Recovery PC to assertion of internal branch detection. Fixed PC backup. Remove intruder lock Making DMR address generator start from 0. --- Bender.yml | 27 ++- rtl/HMR/DMR_address_generator.sv | 71 +++++++ rtl/{ => HMR}/DMR_checker.sv | 0 rtl/HMR/DMR_controller.sv | 341 +++++++++++++++++++++++++++++++ rtl/HMR/HMR_wrap.sv | 294 +++++++++++++++++++++++--- rtl/HMR/recovery_pc.sv | 190 +++++++++++++++++ rtl/HMR/recovery_pkg.sv | 53 +++++ rtl/HMR/recovery_rf.sv | 257 +++++++++++++++++++++++ 8 files changed, 1189 insertions(+), 44 deletions(-) create mode 100644 rtl/HMR/DMR_address_generator.sv rename rtl/{ => HMR}/DMR_checker.sv (100%) create mode 100644 rtl/HMR/DMR_controller.sv create mode 100644 rtl/HMR/recovery_pc.sv create mode 100644 rtl/HMR/recovery_pkg.sv create mode 100644 rtl/HMR/recovery_rf.sv diff --git a/Bender.yml b/Bender.yml index 64ffede7..f3889ee4 100644 --- a/Bender.yml +++ b/Bender.yml @@ -28,7 +28,6 @@ sources: - rtl/TMR_voter.sv - rtl/TMR_voter_fail.sv - rtl/TMR_word_voter.sv - - rtl/DMR_checker.sv # Level 1 - rtl/ODRG_unit/odrg_manager_reg_top.sv - rtl/ecc_wrap/ecc_manager_reg_top.sv @@ -105,16 +104,22 @@ sources: - test/tb_voter_macros.sv - files: - - rtl/HMR/hmr_registers_reg_pkg.sv - - rtl/HMR/hmr_core_regs_reg_pkg.sv - - rtl/HMR/hmr_dmr_regs_reg_pkg.sv - - rtl/HMR/hmr_tmr_regs_reg_pkg.sv - - rtl/HMR/hmr_registers_reg_top.sv - - rtl/HMR/hmr_core_regs_reg_top.sv - - rtl/HMR/hmr_dmr_regs_reg_top.sv - - rtl/HMR/hmr_tmr_regs_reg_top.sv - - rtl/HMR/hmr_tmr_ctrl.sv - - rtl/HMR/HMR_wrap.sv + - rtl/HMR/recovery_pkg.sv + - rtl/HMR/recovery_rf.sv + - rtl/HMR/recovery_pc.sv + - rtl/HMR/DMR_checker.sv + - rtl/HMR/DMR_address_generator.sv + - rtl/HMR/DMR_controller.sv + - rtl/HMR/hmr_registers_reg_pkg.sv + - rtl/HMR/hmr_core_regs_reg_pkg.sv + - rtl/HMR/hmr_dmr_regs_reg_pkg.sv + - rtl/HMR/hmr_tmr_regs_reg_pkg.sv + - rtl/HMR/hmr_registers_reg_top.sv + - rtl/HMR/hmr_core_regs_reg_top.sv + - rtl/HMR/hmr_dmr_regs_reg_top.sv + - rtl/HMR/hmr_tmr_regs_reg_top.sv + - rtl/HMR/hmr_tmr_ctrl.sv + - rtl/HMR/HMR_wrap.sv vendor_package: - name: lowrisc_opentitan diff --git a/rtl/HMR/DMR_address_generator.sv b/rtl/HMR/DMR_address_generator.sv new file mode 100644 index 00000000..12e4d41d --- /dev/null +++ b/rtl/HMR/DMR_address_generator.sv @@ -0,0 +1,71 @@ +/* Copyright 2020 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. + * + * Dual Modular Address Generator + * Generates addresses for RF refill + * + */ + +module DMR_address_generator #( + parameter AddrWidth = 5 +)( + input logic clk_i , + input logic rst_ni , + input logic clear_i , + input logic enable_i , + output logic done_o , + output logic fatal_o , + output logic [AddrWidth-1:0] address_o +); + +localparam int unsigned NumAddr = 2 ** (AddrWidth - 1); +localparam int unsigned NumVotingSignals = 3; +localparam int unsigned NumTMRResults = 1; +localparam int unsigned ArrayWidth = NumVotingSignals + NumTMRResults; + +logic addr_count_err; +logic [NumVotingSignals-1:0] addr_count_rst; +logic [ArrayWidth-1:0][AddrWidth-1:0] addr_count; + +generate + for (genvar i = 0; i < NumVotingSignals; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : address_generator_counter + if (~rst_ni) + addr_count [i] <= '0; + else begin + if (clear_i || addr_count_rst [i]) + addr_count [i] <= '0; + else if (enable_i) + addr_count [i] <= addr_count [i] + 1; + else + addr_count [i] <= addr_count [i]; + end + end + assign addr_count_rst [i] = ( addr_count [i] == NumAddr/2 ) ? 1'b1 : 1'b0; + end +endgenerate + +bitwise_TMR_voter #( + .DataWidth ( AddrWidth ), + .VoterType ( 0 ) +) address_counter_voter ( + .a_i ( addr_count [0] ), + .b_i ( addr_count [1] ), + .c_i ( addr_count [2] ), + .majority_o ( addr_count [3] ), + .error_o ( addr_count_err ), + .error_cba_o ( /* ... */ ) +); + +assign address_o = addr_count [3]; // Result of TMR address voter +assign fatal_o = addr_count_err; // Error from one of the two TMR voters +assign done_o = |addr_count_rst; + +endmodule : DMR_address_generator diff --git a/rtl/DMR_checker.sv b/rtl/HMR/DMR_checker.sv similarity index 100% rename from rtl/DMR_checker.sv rename to rtl/HMR/DMR_checker.sv diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv new file mode 100644 index 00000000..b0e1927c --- /dev/null +++ b/rtl/HMR/DMR_controller.sv @@ -0,0 +1,341 @@ +/* Copyright 2020 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. + * + * Dual Modular Redundancy Controller + * Handles the occurrence of errors and starts recovery routine + * + */ + +import recovery_pkg::*; + +module DMR_controller #( + parameter int unsigned NumCores = 0, + parameter bit DMRFixed = 1'b0, + parameter int unsigned RFAddrWidth = 6, + localparam int unsigned NumDMRGroups = NumCores/2, + localparam int unsigned NumDMRCores = NumDMRGroups * 2, + localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, + localparam int unsigned NumSysCores = DMRFixed ? NumDMRCores : NumCores +)( + input logic clk_i , + input logic rst_ni, + input logic [NumDMRGroups-1:0] dmr_rf_checker_error_port_a_i, + input logic [NumDMRGroups-1:0] dmr_rf_checker_error_port_b_i, + input logic [NumDMRGroups-1:0] dmr_core_checker_error_main_i, + input logic [NumDMRGroups-1:0] dmr_core_checker_error_data_i, + input regfile_write_t [NumDMRGroups-1:0] backup_regfile_write_i, + output regfile_write_t [NumDMRGroups-1:0] core_recovery_regfile_wport_o, + output logic [NumDMRGroups-1:0] regfile_readback_o, + output regfile_raddr_t [NumDMRGroups-1:0] regfile_raddr_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_pc_read_enable_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_pc_write_enable_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_debug_req_o, + input logic [NumDMRGroups-1:0] dmr_ctrl_core_debug_rsp_i, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_instr_lock_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_setback_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_recover_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_debug_resume_o, + output logic [NumDMRGroups-1:0] dmr_ctrl_core_clk_en_o +); + +/******************************************************** +******************** Recovery Routine ******************* +*********************************************************/ +/************************ + * Signals Declarations * + ************************/ +logic clear, + routine_start; +logic core_instr_lock_rst, + core_recover_rst, + pc_write_enable_rst; +logic addr_gen_start, + addr_gen_error, + addr_gen_done; + +logic restore_pc_cycles_d, + restore_pc_cycles_q, + restore_pc_cycles_rst; + +logic [RFAddrWidth-1:0] addr_gen_res; + +logic [NumDMRGroups-1:0] dmr_ctrl_core_setback_out , + dmr_ctrl_core_debug_rsp_in , + dmr_ctrl_core_clk_en_out, + dmr_ctrl_core_debug_req_out, + dmr_ctrl_pc_read_enable_out, + dmr_ctrl_pc_write_enable_d, + dmr_ctrl_pc_write_enable_q, + dmr_ctrl_core_recover_d, + dmr_ctrl_core_recover_q, + dmr_ctrl_core_instr_lock_d, + dmr_ctrl_core_instr_lock_q; + +recovery_routine_state_e current, next; +logic [$clog2(NumDMRGroups)-1:0] error_index_d, + error_index_q; +/****************** + * Output Assigns * + ******************/ +for (genvar i = 0; i < NumDMRGroups; i++) begin + assign dmr_ctrl_core_setback_o [i] = dmr_ctrl_core_setback_out [i]; + assign dmr_ctrl_core_clk_en_o [i] = dmr_ctrl_core_clk_en_out [i]; + assign dmr_ctrl_pc_read_enable_o [i] = dmr_ctrl_pc_read_enable_out [i]; + assign dmr_ctrl_pc_write_enable_o [i] = dmr_ctrl_pc_write_enable_q [i]; + assign dmr_ctrl_core_instr_lock_o [i] = dmr_ctrl_core_instr_lock_q [i]; + assign dmr_ctrl_core_debug_req_o [i] = dmr_ctrl_core_debug_req_out [i]; + assign dmr_ctrl_core_recover_o [i] = dmr_ctrl_core_recover_q [i]; + assign dmr_ctrl_core_debug_rsp_in [i] = dmr_ctrl_core_debug_rsp_i [i]; + assign regfile_readback_o [i] = '0; + assign regfile_raddr_o [i] = '0; +end + +/************** + * Comb logic * + **************/ + +/* + * Error index identifier. + * Identifies the index of the group that is faulty. + */ +always_comb begin + error_index_d = error_index_q; + for (int i = 0; i < NumDMRGroups; i++) begin + if (dmr_rf_checker_error_port_a_i [i] || + dmr_rf_checker_error_port_b_i [i] || + dmr_core_checker_error_main_i [i] || + dmr_core_checker_error_data_i [i] ) + error_index_d = i; + end +end + +/* + * Routine start signal. + * Checks if there are any errors from external checkers to start the FSM Recovery Routine. + */ +assign routine_start = (|dmr_rf_checker_error_port_a_i) | + (|dmr_rf_checker_error_port_a_i) | + (|dmr_core_checker_error_main_i) | + (|dmr_core_checker_error_data_i) ; +/************ +* Registers * +*************/ + +/* + * Error index register. + * If the controller receives an error from one of the input NumDMRGroups, + * this register saves the index of the faulty input group. + */ +always_ff @(posedge clk_i, negedge rst_ni) begin : error_index_register + if (~rst_ni) + error_index_q <= '0; + else begin + if (clear) + error_index_q <= '0; + else + error_index_q <= error_index_d; + end +end + +/* + * Instruction lock registers. + * These registers prevent PULP obi adapter to propagate + * inexistent instruction requests towards iCache while the cores are in debug mode (halted). + */ +generate + for (genvar i = 0; i < NumDMRGroups; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : instruction_lock_registers + if (~rst_ni) begin + dmr_ctrl_core_instr_lock_q [i] <= 1'b0; + end else begin + if (clear || core_instr_lock_rst) begin + dmr_ctrl_core_instr_lock_q [i] <= 1'b0; + end else + dmr_ctrl_core_instr_lock_q [i] <= dmr_ctrl_core_instr_lock_d [i]; + end + end + end +endgenerate + +/* + * Core Recover Registers. + * These registers raise the recover signal towards the cores to + * allow their register files to be reloaded with the RRF content. + */ +generate + for (genvar i = 0; i < NumDMRGroups; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : core_recover_registers + if (~rst_ni) begin + dmr_ctrl_core_recover_q [i] <= 1'b0; + end else begin + if (clear || core_recover_rst) begin + dmr_ctrl_core_recover_q [i] <= 1'b0; + end else + dmr_ctrl_core_recover_q [i] <= dmr_ctrl_core_recover_d [i]; + end + end + end +endgenerate + +/* + * Program Counter Write Enable Register. + * During a recovery routine, this register blocks the Recovery PC + * from sampling new values from the cores. + */ +generate + for (genvar i = 0; i < NumDMRGroups; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : program_counter_write_enable + if (~rst_ni) begin + dmr_ctrl_pc_write_enable_q [i] <= 1'b1; + end else begin + if (clear || pc_write_enable_rst) begin + dmr_ctrl_pc_write_enable_q [i] <= 1'b1; + end else + dmr_ctrl_pc_write_enable_q [i] <= dmr_ctrl_pc_write_enable_d [i]; + end + end + end +endgenerate + +/* + * Program Counter Restore Counter. + * Counter that keeps the Recovery Routine FSM in the RECOVERY_PC state + * for two cycles to make sure that the PC state is safely restored. + */ +always_ff @(posedge clk_i, negedge rst_ni) begin : pc_restore_counter + if (~rst_ni) + restore_pc_cycles_q <= '0; + else begin + if (clear || restore_pc_cycles_rst) + restore_pc_cycles_q <= '0; + else + restore_pc_cycles_q <= restore_pc_cycles_d; + end +end + +/*********************** +* RF Address Generator * +************************/ +DMR_address_generator #( + .AddrWidth ( RFAddrWidth ) +) RF_address_generator ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clear_i ( clear ), + .enable_i ( addr_gen_start ), + .done_o ( addr_gen_done ), + .fatal_o ( addr_gen_error ), + .address_o ( addr_gen_res ) +); + +/* Binding recovery signals towards RRF and cores */ +always_comb begin : RF_ports_binding + core_recovery_regfile_wport_o = '0; + for (int i = 0; i < NumDMRGroups; i++) begin + if (i == error_index_q) begin + core_recovery_regfile_wport_o[i].we_a = (addr_gen_start) ? 1'b1 : 1'b0; + core_recovery_regfile_wport_o[i].waddr_a = addr_gen_res; + core_recovery_regfile_wport_o[i].we_b = (addr_gen_start) ? 1'b1 : 1'b0; + core_recovery_regfile_wport_o[i].waddr_b = 5'd16 + addr_gen_res; + end else + core_recovery_regfile_wport_o = '0; + end +end + +/******************************** +* Recovery Routine State Update * +*********************************/ +always_ff @(posedge clk_i, negedge rst_ni) begin : recovery_routine_register + if (~rst_ni) + current <= IDLE; + else begin + current <= next; + end +end + +/*********************** +* Recovery Routine FSM * +************************/ +always_comb begin : recovery_routine_fsm + next = current; + clear = 1'b0; + addr_gen_start = 1'b0; + core_recover_rst = '0; + pc_write_enable_rst = 1'b0; + core_instr_lock_rst = 1'b0; + restore_pc_cycles_rst = 1'b0; + dmr_ctrl_core_setback_out = '0; + dmr_ctrl_core_clk_en_out = '1; + dmr_ctrl_core_recover_d = dmr_ctrl_core_recover_q; + dmr_ctrl_core_instr_lock_d = dmr_ctrl_core_instr_lock_q; + dmr_ctrl_core_debug_req_out = '0; + dmr_ctrl_core_debug_resume_o = '0; + dmr_ctrl_pc_read_enable_out = '0; + dmr_ctrl_pc_write_enable_d = dmr_ctrl_pc_write_enable_q; + restore_pc_cycles_d = restore_pc_cycles_q; + case (current) + IDLE: begin + if (routine_start) begin + next = RESET; + end else + next = current; + end + + RESET: begin + dmr_ctrl_core_setback_out [error_index_q] = 1'b1; + dmr_ctrl_core_instr_lock_d [error_index_q] = 1'b1; + dmr_ctrl_pc_write_enable_d [error_index_q] = 1'b0; + next = HALT_REQ; + end + + HALT_REQ: begin + dmr_ctrl_core_debug_req_out [error_index_q] = 1'b1; + next = HALT_WAIT; + end + + HALT_WAIT: begin + if (dmr_ctrl_core_debug_rsp_in [error_index_q]) begin + next = RESTORE_PC; + end else + next = current; + end + + RESTORE_PC: begin + dmr_ctrl_pc_read_enable_out [error_index_q] = 1'b1; + restore_pc_cycles_d = restore_pc_cycles_q + 1'd1; + if (restore_pc_cycles_q == 1'd1) begin + restore_pc_cycles_d = 1'd0; + next = RESTORE_RF; + end else + next = current; + end + + RESTORE_RF: begin + dmr_ctrl_core_recover_d [error_index_q] = 1'b1; + addr_gen_start = 1'b1; + if (addr_gen_done) begin + dmr_ctrl_core_instr_lock_d [error_index_q] = 1'b0; + dmr_ctrl_core_debug_resume_o [error_index_q] = 1'b1; + next = EXIT; + end else + next = current; + end + + RESTORE_CSR: begin + end + + EXIT: begin + clear = 1'b1; + next = IDLE; + end + endcase +end : recovery_routine_fsm + +endmodule : DMR_controller diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index f6296558..eea74848 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -10,7 +10,7 @@ // // Hybrid modular redundancy wrapping unit -module HMR_wrap #( +module HMR_wrap import recovery_pkg::*; #( // Wrapper parameters parameter int unsigned NumCores = 0, parameter bit DMRSupported = 1'b1, @@ -53,8 +53,21 @@ module HMR_wrap #( output logic [NumDMRGroups-1:0] dmr_failure_o , output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? output logic [NumDMRGroups-1:0] dmr_resynch_req_o, + output logic [ NumCores-1:0] dmr_rf_readback_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + // Backup Port from Cores'Program Counter + input logic [ NumCores-1:0][DataWidth-1:0] backup_program_counter_i, + output logic [ NumCores-1:0] pc_recover_o, + output logic [ NumCores-1:0][DataWidth-1:0] recovery_program_counter_o, + input logic [ NumCores-1:0] backup_branch_i, + input logic [ NumCores-1:0][DataWidth-1:0] backup_branch_addr_i, + output logic [ NumCores-1:0] recovery_branch_o, + output logic [ NumCores-1:0][DataWidth-1:0] recovery_branch_addr_o, + // Backup ports from Cores' RFs + input regfile_write_t [ NumCores-1:0] backup_regfile_wport_i, + output regfile_raddr_t [ NumSysCores-1:0] core_regfile_raddr_o, + output regfile_write_t [ NumSysCores-1:0] core_recovery_regfile_wport_o, // TODO other required signals // Ports connecting to System @@ -97,6 +110,7 @@ module HMR_wrap #( // Ports connecting to the cores output logic [ NumCores-1:0] core_setback_o , + output logic [ NumCores-1:0] core_recover_o , output logic [ NumCores-1:0][ 3:0] core_core_id_o , output logic [ NumCores-1:0][ 5:0] core_cluster_id_o , @@ -116,9 +130,12 @@ module HMR_wrap #( input logic [ NumCores-1:0][ 31:0] core_instr_addr_i , output logic [ NumCores-1:0][InstrDataWidth-1:0] core_instr_r_rdata_o, output logic [ NumCores-1:0] core_instr_r_valid_o, + output logic [ NumCores-1:0] core_instr_lock_o , output logic [ NumCores-1:0] core_instr_err_o , output logic [ NumCores-1:0] core_debug_req_o , + output logic [ NumCores-1:0] core_debug_resume_o , + input logic [ NumCores-1:0] core_debug_halted_i , input logic [ NumCores-1:0] core_data_req_i , input logic [ NumCores-1:0][ 31:0] core_data_add_i , @@ -167,6 +184,8 @@ module HMR_wrap #( localparam int unsigned MainConcatWidth = SeparateData ? CtrlConcatWidth : CtrlConcatWidth + DataConcatWidth; + localparam int unsigned RFAddrWidth = 6; + logic [ NumCores-1:0][MainConcatWidth-1:0] main_concat_in; logic [NumTMRGroups-1:0][MainConcatWidth-1:0] main_tmr_out; logic [NumDMRGroups-1:0][MainConcatWidth-1:0] main_dmr_out; @@ -179,9 +198,9 @@ module HMR_wrap #( logic [NumTMRGroups-1:0][2:0] tmr_error, tmr_error_main, tmr_error_data; logic [NumTMRGroups-1:0] tmr_single_mismatch; - logic [NumTMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_data; - logic [NumTMRGroups-1:0][2:0] dmr_error, dmr_error_main, dmr_error_data; - logic [NumTMRGroups-1:0] dmr_single_mismatch; + logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_data; + logic [NumDMRGroups-1:0][2:0] dmr_error, dmr_error_main, dmr_error_data; + logic [NumDMRGroups-1:0] dmr_single_mismatch; logic [NumTMRGroups-1:0] tmr_core_busy_out; logic [NumTMRGroups-1:0] tmr_irq_ack_out; @@ -207,6 +226,38 @@ module HMR_wrap #( logic [NumDMRGroups-1:0][ UserWidth-1:0] dmr_data_user_out; logic [NumDMRGroups-1:0][ BeWidth-1:0] dmr_data_be_out; + logic [NumDMRGroups-1:0][ DataWidth-1:0] backup_branch_addr_int, + recovery_branch_addr_out, + backup_program_counter_int, + recovery_program_counter_out, + backup_regfile_wdata_a, + backup_regfile_wdata_b; + logic [NumDMRGroups-1:0] backup_branch_int, + recovery_branch_out, + backup_program_counter_error, + dmr_ctrl_pc_read_enable_out, + dmr_ctrl_pc_write_enable_out, + backup_regfile_we_a, + backup_regfile_we_b, + backup_regfile_error_a, + backup_regfile_error_b, + backup_branch_error, + backup_branch_addr_error, + regfile_readback_out, + dmr_ctrl_core_rstn_out, + dmr_ctrl_core_debug_req_out, + dmr_ctrl_core_debug_halted_in, + dmr_ctrl_core_instr_lock_out, + dmr_ctrl_core_setback_out, + dmr_ctrl_core_recover_out, + dmr_ctrl_debug_resume_out; + logic intruder_lock; + + regfile_raddr_t [NumDMRGroups-1:0] core_regfile_raddr_out; + regfile_rdata_t [NumDMRGroups-1:0] core_recovery_regfile_rdata_out; + regfile_write_t [NumDMRGroups-1:0] backup_regfile_wport_in, + core_recovery_regfile_wport_out; + for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], @@ -492,8 +543,45 @@ module HMR_wrap #( /************************************************************ ******************** DMR Voters and Regs ******************* ************************************************************/ + for (genvar i = 0; i < NumCores; i++) begin + assign backup_regfile_wport_in [i] = backup_regfile_wport_i [dmr_core_id(dmr_group_id(i), 0)]; + end + + for (genvar i = 0; i < NumDMRGroups; i++) begin + assign dmr_ctrl_core_debug_halted_in [i] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] + & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; + end + + /****************** + * DMR Controller * + ******************/ + DMR_controller #( + .NumCores ( NumCores ), + .DMRFixed ( DMRFixed ), + .RFAddrWidth ( RFAddrWidth ) + ) dmr_controller ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .dmr_rf_checker_error_port_a_i ( backup_regfile_error_a ), + .dmr_rf_checker_error_port_b_i ( backup_regfile_error_b ), + .dmr_core_checker_error_main_i ( dmr_failure_main ), + .dmr_core_checker_error_data_i ( dmr_failure_data ), + .backup_regfile_write_i ( backup_regfile_wport_in ), + .core_recovery_regfile_wport_o ( core_recovery_regfile_wport_out ), + .regfile_readback_o ( regfile_readback_out ), + .regfile_raddr_o ( core_regfile_raddr_out ), + .dmr_ctrl_core_debug_req_o ( dmr_ctrl_core_debug_req_out ), + .dmr_ctrl_core_debug_rsp_i ( dmr_ctrl_core_debug_halted_in ), + .dmr_ctrl_core_instr_lock_o ( dmr_ctrl_core_instr_lock_out ), + .dmr_ctrl_core_setback_o ( dmr_ctrl_core_setback_out ), + .dmr_ctrl_core_recover_o ( dmr_ctrl_core_recover_out ), + .dmr_ctrl_core_debug_resume_o ( dmr_ctrl_debug_resume_out ), + .dmr_ctrl_pc_read_enable_o ( dmr_ctrl_pc_read_enable_out ), + .dmr_ctrl_pc_write_enable_o ( dmr_ctrl_pc_write_enable_out ), + .dmr_ctrl_core_clk_en_o ( ) + ); - if (DMRSupported || DMRFixed) begin: gen_dmr_checkers + if (DMRSupported || DMRFixed) begin: gen_dmr_recovery_region for (genvar i = 0; i < NumDMRGroups; i++) begin assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main | dmr_failure_data) : dmr_failure_main; @@ -501,22 +589,25 @@ module HMR_wrap #( : tmr_error_main [i*2+:2]; assign dmr_single_mismatch [i] = dmr_error [i*2+:2] != 3'b000; + /********************* + * DMR Core Checkers * + *********************/ DMR_checker #( .DataWidth ( MainConcatWidth ) ) dmr_core_checker_main ( - .inp_a_i ( main_concat_in [dmr_core_id(i, 0)]), - .inp_b_i ( main_concat_in [dmr_core_id(i, 1)]), - .check_o ( main_dmr_out [i] ), - .error_o ( dmr_failure_main [i]) + .inp_a_i ( main_concat_in [dmr_core_id(i, 0)] ), + .inp_b_i ( main_concat_in [dmr_core_id(i, 1)] ), + .check_o ( main_dmr_out [i] ), + .error_o ( dmr_failure_main [i] ) ); if (SeparateData) begin : gen_data_checker DMR_checker # ( .DataWidth ( DataConcatWidth ) ) dmr_core_checker_data ( - .inp_a_i ( data_concat_in [dmr_core_id(i, 0)]), - .inp_b_i ( data_concat_in [dmr_core_id(i, 1)]), - .check_o ( data_dmr_out [i] ), - .error_o ( dmr_failure_data [i]) + .inp_a_i ( data_concat_in [dmr_core_id(i, 0)] ), + .inp_b_i ( data_concat_in [dmr_core_id(i, 1)] ), + .check_o ( data_dmr_out [i] ), + .error_o ( dmr_failure_data [i] ) ); assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] } @@ -533,13 +624,128 @@ module HMR_wrap #( dmr_data_be_out[i] , dmr_data_user_out[i]} = main_dmr_out[i]; end + + /****************** + * DMR PC Checker * + ******************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_pc_checker ( + .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), + .check_o ( backup_program_counter_int [i] ), + .error_o ( backup_program_counter_error [i] ) + ); + + /********************* + * DMR Branch Checker * + **********************/ + DMR_checker # ( + .DataWidth ( 1 ) + ) dmr_branch_checker ( + .inp_a_i ( backup_branch_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_branch_i[dmr_core_id(i, 1)] ), + .check_o ( backup_branch_int [i] ), + .error_o ( backup_branch_error [i] ) + ); + + /***************************** + * DMR Branch Address Checker * + ******************************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_branch_addr_checker ( + .inp_a_i ( backup_branch_addr_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_branch_addr_i[dmr_core_id(i, 1)] ), + .check_o ( backup_branch_addr_int [i] ), + .error_o ( backup_branch_addr_error [i] ) + ); + + /******************* + * DMR RF Checkers * + *******************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_rf_checker_port_a ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_a ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_a ), + .check_o ( backup_regfile_wdata_a[i] ), + .error_o ( backup_regfile_error_a[i] ) + ); + + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_rf_checker_port_b ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_b ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_b ), + .check_o ( backup_regfile_wdata_b [i] ), + .error_o ( backup_regfile_error_b [i] ) + ); + + assign backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a + & ~backup_regfile_error_a [i] + & ~dmr_ctrl_core_recover_out [i]; + assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b + & ~backup_regfile_error_b [i] + & ~dmr_ctrl_core_recover_out [i]; + /**************************** + * Recovery Program Counter * + ****************************/ + recovery_pc #( + .ECCEnabled ( 1 ) + ) RPC ( + // Control Ports + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clear_i ( '0 ), + .read_enable_i ( dmr_ctrl_pc_read_enable_out [i] ), + .write_enable_i ( ~backup_program_counter_error [i] + & dmr_ctrl_pc_write_enable_out [i] ), + // Backup Ports + .backup_program_counter_i ( backup_program_counter_int [i] ), + .backup_branch_i ( backup_branch_int [i] ), + .backup_branch_addr_i ( backup_branch_addr_i [i] ), + // Recovery Pors + .recovery_program_counter_o ( recovery_program_counter_out [i] ), + .recovery_branch_o ( recovery_branch_out [i] ), + .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) + ); + + /*************************** + * Recovery Register Files * + ***************************/ + recovery_rf #( + .ECCEnabled ( 1 ), + .ADDR_WIDTH ( RFAddrWidth ) + ) RRF ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( '0 ), + //Read port A + .raddr_a_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_a ), + .rdata_a_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_a ), + //Read port B + .raddr_b_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_b ), + .rdata_b_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_b ), + //Read port C + .raddr_c_i ( '0 ), + .rdata_c_o ( ), + // Write Port A + .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), + .wdata_a_i ( backup_regfile_wdata_a [i] ), + .we_a_i ( backup_regfile_we_a [i] ), + // Write Port B + .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), + .wdata_b_i ( backup_regfile_wdata_b [i] ), + .we_b_i ( backup_regfile_we_b [i] ) + ); end if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; assign dmr_error_data[NumCores-1-:NumDMRLeftover] = '0; assign dmr_error [NumCores-1-:NumDMRLeftover] = '0; end - end else begin: no_dmr_checkers // block: gen_dmr_checkers + end else begin: no_dmr_checkers assign dmr_error_main = '0; assign dmr_error_data = '0; assign dmr_error = '0; @@ -768,33 +974,52 @@ module HMR_wrap #( localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); if (i < NumDMRCores && DMRFixed) begin : gen_dmr_mode // CTRL - assign core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; - assign core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; + assign core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; + assign core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - assign core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; - assign core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; - assign core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; + assign core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + assign core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; + assign core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; - assign core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; - assign core_perf_counters_o[i] = sys_perf_counters_i[SysCoreIndex]; + assign core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + | dmr_ctrl_core_debug_req_out [SysCoreIndex]; + assign core_debug_resume_o [i] = dmr_ctrl_debug_resume_out [SysCoreIndex]; + assign core_perf_counters_o[i] = sys_perf_counters_i [SysCoreIndex]; // IRQ - assign core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; - assign core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; + assign core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; + assign core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; // INSTR - assign core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; - assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[SysCoreIndex]; - assign core_instr_r_valid_o[i] = sys_instr_r_valid_i[SysCoreIndex]; - assign core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; + assign core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; + assign core_instr_r_valid_o[i] = sys_instr_r_valid_i [SysCoreIndex]; + assign core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; + assign core_instr_lock_o [i] = dmr_ctrl_core_instr_lock_out [SysCoreIndex]; // DATA - assign core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; - assign core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; - assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; - assign core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; - assign core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; - assign core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + assign core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + assign core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; + assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; + assign core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; + assign core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + assign core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + + // PC + assign pc_recover_o [i] = dmr_ctrl_pc_read_enable_out [SysCoreIndex]; + assign recovery_program_counter_o [i] = recovery_program_counter_out [SysCoreIndex]; + assign recovery_branch_o [i] = recovery_branch_out [SysCoreIndex]; + assign recovery_branch_addr_o [i] = recovery_branch_addr_out [SysCoreIndex]; + + // RF + assign dmr_rf_readback_o [i] = regfile_readback_out [SysCoreIndex]; + assign core_regfile_raddr_o [i] = core_regfile_raddr_out [SysCoreIndex]; + assign core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[SysCoreIndex].we_a; + assign core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[SysCoreIndex].waddr_a; + assign core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_a; + assign core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[SysCoreIndex].we_b; + assign core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[SysCoreIndex].waddr_b; + assign core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_b; end else begin : gen_independent_mode @@ -854,6 +1079,9 @@ module HMR_wrap #( assign sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; assign sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + assign core_setback_o [i] = dmr_ctrl_core_setback_out [CoreCoreIndex]; + assign core_recover_o [i] = dmr_ctrl_core_recover_out [CoreCoreIndex]; + end else begin : gen_disable_core // Assign disable // CTLR diff --git a/rtl/HMR/recovery_pc.sv b/rtl/HMR/recovery_pc.sv new file mode 100644 index 00000000..8b5fdf53 --- /dev/null +++ b/rtl/HMR/recovery_pc.sv @@ -0,0 +1,190 @@ +/* Copyright 2020 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. + * + * Recovery Program Counter + * ECC-protected register that stores the Program Counter value from the cores + * + */ + +module recovery_pc #( + parameter ECCEnabled = 0, + parameter NonProtectedWidth = 32, + parameter ProtectedWidth = 39, + localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth +) ( + // Control Ports + input logic clk_i, + input logic rst_ni, + input logic clear_i, + input logic read_enable_i, + input logic write_enable_i, + // Backup Ports + input logic [NonProtectedWidth-1:0] backup_program_counter_i, + input logic backup_branch_i, + input logic [NonProtectedWidth-1:0] backup_branch_addr_i, + // Recovery Pors + output logic [NonProtectedWidth-1:0] recovery_program_counter_o, + output logic recovery_branch_o, + output logic [NonProtectedWidth-1:0] recovery_branch_addr_o +); + +logic branch_q; + +logic [DataWidth-1:0] pc_d, + pc_q, + branch_addr_d, + branch_addr_q; +logic [NonProtectedWidth-1:0] pc_out, + branch_addr_out; + +generate + if (ECCEnabled) begin : gen_ecc_region + /************************** + * Program Counter Backup * + **************************/ + prim_secded_39_32_enc pc_ecc_encoder ( + .in ( backup_program_counter_i ), + .out ( pc_d ) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin : pc_value_sampler + if (~rst_ni) + pc_q <= '0; + else begin + if (clear_i) + pc_q <= '0; + else if (write_enable_i && pc_d != '0) + pc_q <= pc_d; + else + pc_q <= pc_q; + end + end + + prim_secded_39_32_dec pc_ecc_decoder ( + .in ( pc_q ), + .d_o ( pc_out ), + .syndrome_o ( ), + .err_o ( ) + ); + + /********************** + * Branch Addr Backup * + **********************/ + prim_secded_39_32_enc branch_addr_ecc_encoder ( + .in ( backup_branch_addr_i ), + .out ( branch_addr_d ) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin : branch_addr_sampler + if (~rst_ni) + branch_addr_q <= '0; + else begin + if (clear_i) + branch_addr_q <= '0; + else if (backup_branch_i && write_enable_i) + branch_addr_q <= branch_addr_d; + else + branch_addr_q <= branch_addr_q; + end + end + + prim_secded_39_32_dec branch_addr_ecc_decoder ( + .in ( branch_addr_q ), + .d_o ( branch_addr_out ), + .syndrome_o ( ), + .err_o ( ) + ); + + /************************ + * Branch Signal Backup * + ************************/ + always_ff @(posedge clk_i, negedge rst_ni) begin : branch_sampler + if (~rst_ni) + branch_q <= '0; + else begin + if (clear_i) + branch_q <= '0; + else if (write_enable_i) + branch_q <= backup_branch_i; + else + branch_q <= branch_q; + end + end + + /***************** + * Output Assign * + *****************/ + assign recovery_program_counter_o = (read_enable_i) ? pc_out : '0; + assign recovery_branch_addr_o = (read_enable_i && branch_q) ? branch_addr_out : '0; + assign recovery_branch_o = (read_enable_i) ? branch_q : '0; + end else begin : gen_no_ecc_region + /************************** + * Program Counter Backup * + **************************/ + assign pc_d = backup_program_counter_i; + always_ff @(posedge clk_i, negedge rst_ni) begin : pc_value_sampler + if (~rst_ni) + pc_q <= '0; + else begin + if (clear_i) + pc_q <= '0; + else if (write_enable_i) + pc_q <= pc_d; + else + pc_q <= pc_d; + end + end + assign pc_out = pc_q; + + /********************** + * Branch Addr Backup * + **********************/ + assign branch_addr_d = backup_branch_addr_i; + always_ff @(posedge clk_i, negedge rst_ni) begin : branch_addr_sampler + if (~rst_ni) + branch_addr_q <= '0; + else begin + if (clear_i) + branch_addr_q <= '0; + else if (backup_branch_i && write_enable_i) + branch_addr_q <= branch_addr_d; + else + branch_addr_q <= branch_addr_q; + end + end + assign branch_addr_out = branch_addr_q; + + /************************ + * Branch Signal Backup * + ************************/ + always_ff @(posedge clk_i, negedge rst_ni) begin : branch_sampler + if (~rst_ni) + branch_q <= '0; + else begin + if (clear_i) + branch_q <= '0; + else if (write_enable_i) + branch_q <= backup_branch_i; + else + branch_q <= branch_q; + end + end + + /***************** + * Output Assign * + *****************/ + assign recovery_program_counter_o = (read_enable_i) ? pc_out : '0; + assign recovery_branch_addr_o = (read_enable_i) ? branch_addr_out : '0; + assign recovery_branch_o = (read_enable_i) ? branch_q : '0; + end +endgenerate + +endmodule : recovery_pc diff --git a/rtl/HMR/recovery_pkg.sv b/rtl/HMR/recovery_pkg.sv new file mode 100644 index 00000000..f3ec4ac5 --- /dev/null +++ b/rtl/HMR/recovery_pkg.sv @@ -0,0 +1,53 @@ +/* Copyright 2020 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. + * + * Recovery Region Package + * + */ + +package recovery_pkg; + +localparam int unsigned DataWidth = 32; +localparam int unsigned RegfileAddr = 6; +localparam int unsigned RecoveryStateBits = 3; + +typedef struct packed { + // Write Port A + logic we_a; + logic [RegfileAddr-1:0] waddr_a; + logic [ DataWidth-1:0] wdata_a; + // Write Port B + logic we_b; + logic [RegfileAddr-1:0] waddr_b; + logic [ DataWidth-1:0] wdata_b; +} regfile_write_t; + +typedef struct packed { + logic [RegfileAddr-1:0] raddr_a; + logic [RegfileAddr-1:0] raddr_b; +} regfile_raddr_t; + +typedef struct packed { + logic [DataWidth-1:0] rdata_a; + logic [DataWidth-1:0] rdata_b; +} regfile_rdata_t; + +typedef enum logic [RecoveryStateBits-1:0]{ + IDLE , + RESET , + HALT_REQ , + HALT_WAIT , + RESTORE_PC , + RESTORE_RF , + RESTORE_CSR, + EXIT +} recovery_routine_state_e; + +endpackage diff --git a/rtl/HMR/recovery_rf.sv b/rtl/HMR/recovery_rf.sv new file mode 100644 index 00000000..9572d26d --- /dev/null +++ b/rtl/HMR/recovery_rf.sv @@ -0,0 +1,257 @@ +// Copyright 2018 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Antonio Pullini - pullinia@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Sven Stucki - svstucki@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: RISC-V register file // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Register file with 31x 32 bit wide registers. Register 0 // +// is fixed to 0. This register file is based on latches and // +// is thus smaller than the flip-flop based register file. // +// Also supports the fp-register file now if FPU=1 // +// If PULP_ZFINX is 1, floating point operations take values // +// from the X register file // +// // +//////////////////////////////////////////////////////////////////////////////// + +module recovery_rf #( + parameter ECCEnabled = 0, + parameter ADDR_WIDTH = 5, + parameter NonProtectedWidth = 32, + parameter ProtectedWidth = 39, + parameter FPU = 0, + parameter PULP_ZFINX = 0, + localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, + + //Read port R1 + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [NonProtectedWidth-1:0] rdata_a_o, + + //Read port R2 + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [NonProtectedWidth-1:0] rdata_b_o, + + //Read port R3 + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [NonProtectedWidth-1:0] rdata_c_o, + + // Write port W1 + input logic [ADDR_WIDTH-1:0] waddr_a_i, + input logic [NonProtectedWidth-1:0] wdata_a_i, + input logic we_a_i, + + // Write port W2 + input logic [ADDR_WIDTH-1:0] waddr_b_i, + input logic [NonProtectedWidth-1:0] wdata_b_i, + input logic we_b_i +); + + // number of integer registers + localparam NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + // number of floating point registers + localparam NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + + // integer register file + logic [NonProtectedWidth-1:0] mem [NUM_WORDS]; + logic [ DataWidth-1:0] ecc_mem [NUM_WORDS]; + logic [NUM_TOT_WORDS-1:1] waddr_onehot_a; + logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , + waddr_onehot_b_q; + logic [NUM_TOT_WORDS-1:1] mem_clocks; + logic [DataWidth-1:0] wdata_a , + wdata_a_q , + wdata_a_ecc; + logic [DataWidth-1:0] wdata_b , + wdata_b_q , + wdata_b_ecc; + + // masked write addresses + logic [ADDR_WIDTH-1:0] waddr_a; + logic [ADDR_WIDTH-1:0] waddr_b; + + logic clk_int; + + // fp register file + logic [NonProtectedWidth-1:0] mem_fp [NUM_FP_WORDS]; + logic [ DataWidth-1:0] ecc_mem_fp [NUM_FP_WORDS]; + + int unsigned i; + int unsigned j; + int unsigned k; + int unsigned l; + + genvar x; + genvar y; + + generate + if (ECCEnabled) begin : gen_ecc_region + + prim_secded_39_32_enc a_port_ecc_encoder ( + .in ( wdata_a_i ), + .out ( wdata_a_ecc) + ); + assign wdata_a = wdata_a_ecc; + + prim_secded_39_32_enc b_port_ecc_encoder ( + .in ( wdata_b_i ), + .out ( wdata_b_ecc) + ); + assign wdata_b = wdata_b_ecc; + + for (genvar index = 0; index < NUM_WORDS; index++) begin + prim_secded_39_32_dec internal_memory_decoder ( + .in ( ecc_mem [index] ), + .d_o ( mem [index] ), + .syndrome_o ( ), + .err_o ( ) + ); + end + + if (FPU == 1 && PULP_ZFINX == 0) begin + for (genvar index = 0; index < NUM_FP_WORDS; index++) begin + prim_secded_39_32_dec internal_fp_memory_decoder ( + .in ( ecc_mem_fp [index] ), + .d_o ( mem_fp [index] ), + .syndrome_o ( ), + .err_o ( ) + ); + end + end + end else begin : no_ecc_region + assign wdata_a = wdata_a_i; + assign wdata_a_ecc = '0; + assign wdata_b = wdata_b_i; + assign wdata_b_ecc = '0; + + for (genvar index = 0; index < NUM_WORDS; index++) + assign mem [index] = ecc_mem [index]; + + for (genvar index = 0; index < NUM_FP_WORDS; index++) + assign mem_fp [index] = ecc_mem_fp [index]; + end + endgenerate + + //----------------------------------------------------------------------------- + //-- READ : Read address decoder RAD + //----------------------------------------------------------------------------- + if (FPU == 1 && PULP_ZFINX == 0) begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end else begin + assign rdata_a_o = mem[raddr_a_i[4:0]]; + assign rdata_b_o = mem[raddr_b_i[4:0]]; + assign rdata_c_o = mem[raddr_c_i[4:0]]; + end + + //----------------------------------------------------------------------------- + // WRITE : SAMPLE INPUT DATA + //--------------------------------------------------------------------------- + + tc_clk_gating CG_WE_GLOBAL ( + .clk_i ( clk_i ), + .en_i ( we_a_i | we_b_i ), + .test_en_i ( test_en_i ), + .clk_o ( clk_int ) + ); + + // use clk_int here, since otherwise we don't want to write anything anyway + always_ff @(posedge clk_int, negedge rst_ni) begin : sample_waddr + if (~rst_ni) begin + wdata_a_q <= '0; + wdata_b_q <= '0; + waddr_onehot_b_q <= '0; + end else begin + if (we_a_i) wdata_a_q <= wdata_a; + + if (we_b_i) wdata_b_q <= wdata_b; + + waddr_onehot_b_q <= waddr_onehot_b; + end + end + + //----------------------------------------------------------------------------- + //-- WRITE : Write Address Decoder (WAD), combinatorial process + //----------------------------------------------------------------------------- + + assign waddr_a = waddr_a_i; + assign waddr_b = waddr_b_i; + + genvar gidx; + generate + for (gidx = 1; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder + assign waddr_onehot_a[gidx] = (we_a_i == 1'b1) && (waddr_a == gidx); + assign waddr_onehot_b[gidx] = (we_b_i == 1'b1) && (waddr_b == gidx); + end + endgenerate + + //----------------------------------------------------------------------------- + //-- WRITE : Clock gating (if integrated clock-gating cells are available) + //----------------------------------------------------------------------------- + generate + for (x = 1; x < NUM_TOT_WORDS; x++) begin : gen_clock_gate + tc_clk_gating clock_gate_i ( + .clk_i ( clk_int ), + .en_i ( waddr_onehot_a[x] | waddr_onehot_b[x] ), + .test_en_i ( test_en_i ), + .clk_o ( mem_clocks[x] ) + ); + end + endgenerate + + //----------------------------------------------------------------------------- + //-- WRITE : Write operation + //----------------------------------------------------------------------------- + //-- Generate M = WORDS sequential processes, each of which describes one + //-- word of the memory. The processes are synchronized with the clocks + //-- ClocksxC(i), i = 0, 1, ..., M-1 + //-- Use active low, i.e. transparent on low latches as storage elements + //-- Data is sampled on rising clock edge + + // Integer registers + always_latch begin : latch_wdata + // Note: The assignment has to be done inside this process or Modelsim complains about it + ecc_mem[0] = '0; + + for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter + if (~rst_ni) ecc_mem[k] = '0; + else if (mem_clocks[k] == 1'b1) ecc_mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + end + end + + if (FPU == 1 && PULP_ZFINX == 0) begin + // Floating point registers + always_latch begin : latch_wdata_fp + if (FPU == 1) begin + for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter + if (~rst_ni) ecc_mem_fp[l] = '0; + else if (mem_clocks[l+NUM_WORDS] == 1'b1) + ecc_mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + end + end + end + end +endmodule From dd734c0b7ca15ee86f4e9d167002a448f1bf7203 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 27 Jan 2023 16:50:32 +0100 Subject: [PATCH 03/66] Fix TMR and DMR assignments Add TMR-DMR support in assignments --- rtl/HMR/HMR_wrap.sv | 584 +++++++++++++++++++++++++++++++++----------- 1 file changed, 444 insertions(+), 140 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index eea74848..858aaff6 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -771,13 +771,249 @@ module HMR_wrap import recovery_pkg::*; #( *****************/ if (TMRFixed || DMRFixed) $fatal(1, "Cannot support both TMR and DMR and fix one!"); - // TODO + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); + localparam DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); + + always_comb begin + if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + + // CTRL + core_core_id_o [i] = sys_core_id_i [TMRCoreIndex]; + core_cluster_id_o [i] = sys_cluster_id_i [TMRCoreIndex]; + + core_clock_en_o [i] = sys_clock_en_i [TMRCoreIndex]; + core_fetch_en_o [i] = sys_fetch_en_i [TMRCoreIndex]; + core_boot_addr_o [i] = sys_boot_addr_i [TMRCoreIndex]; + + core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex]; + core_perf_counters_o[i] = sys_perf_counters_i[TMRCoreIndex]; + + // IRQ + core_irq_req_o [i] = sys_irq_req_i [TMRCoreIndex]; + core_irq_id_o [i] = sys_irq_id_i [TMRCoreIndex]; + + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [TMRCoreIndex]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[TMRCoreIndex]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[TMRCoreIndex]; + core_instr_err_o [i] = sys_instr_err_i [TMRCoreIndex]; + + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [TMRCoreIndex]; + core_data_r_opc_o [i] = sys_data_r_opc_i [TMRCoreIndex]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [TMRCoreIndex]; + core_data_r_user_o [i] = sys_data_r_user_i [TMRCoreIndex]; + core_data_r_valid_o [i] = sys_data_r_valid_i [TMRCoreIndex]; + core_data_err_o [i] = sys_data_err_i [TMRCoreIndex]; + end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode + core_setback_o [i] = '0; + + // CTRL + core_core_id_o [i] = sys_core_id_i [DMRCoreIndex]; + core_cluster_id_o [i] = sys_cluster_id_i [DMRCoreIndex]; + + core_clock_en_o [i] = sys_clock_en_i [DMRCoreIndex]; + core_fetch_en_o [i] = sys_fetch_en_i [DMRCoreIndex]; + core_boot_addr_o [i] = sys_boot_addr_i [DMRCoreIndex]; + + core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex]; + core_perf_counters_o[i] = sys_perf_counters_i[DMRCoreIndex]; + + // IRQ + core_irq_req_o [i] = sys_irq_req_i [DMRCoreIndex]; + core_irq_id_o [i] = sys_irq_id_i [DMRCoreIndex]; + + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [DMRCoreIndex]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[DMRCoreIndex]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[DMRCoreIndex]; + core_instr_err_o [i] = sys_instr_err_i [DMRCoreIndex]; + + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [DMRCoreIndex]; + core_data_r_opc_o [i] = sys_data_r_opc_i [DMRCoreIndex]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [DMRCoreIndex]; + core_data_r_user_o [i] = sys_data_r_user_i [DMRCoreIndex]; + core_data_r_valid_o [i] = sys_data_r_valid_i [DMRCoreIndex]; + core_data_err_o [i] = sys_data_err_i [DMRCoreIndex]; + end else begin : independent_mode + core_setback_o [i] = '0; + + // CTRL + core_core_id_o [i] = sys_core_id_i [i]; + core_cluster_id_o [i] = sys_cluster_id_i [i]; + + core_clock_en_o [i] = sys_clock_en_i [i]; + core_fetch_en_o [i] = sys_fetch_en_i [i]; + core_boot_addr_o [i] = sys_boot_addr_i [i]; + + core_debug_req_o [i] = sys_debug_req_i [i]; + core_perf_counters_o[i] = sys_perf_counters_i[i]; + + // IRQ + core_irq_req_o [i] = sys_irq_req_i [i]; + core_irq_id_o [i] = sys_irq_id_i [i]; + + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_err_o [i] = sys_instr_err_i [i]; + + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_r_opc_o [i] = sys_data_r_opc_i [i]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; + core_data_r_user_o [i] = sys_data_r_user_i [i]; + core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_err_o [i] = sys_data_err_i [i]; + end + end + end + + for (genvar i = 0; i < NumSysCores/*==NumCores*/; i++) begin : gen_core_outputs + localparam TMRCoreIndex = tmr_group_id(i); + localparam DMRCoreIndex = dmr_group_id(i); + always_comb begin + if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode + if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core + // CTRL + sys_core_busy_o [i] = tmr_core_busy_out [TMRCoreIndex]; + + // IRQ + sys_irq_ack_o [i] = tmr_irq_ack_out [TMRCoreIndex]; + sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[TMRCoreIndex]; + + // INSTR + sys_instr_req_o [i] = tmr_instr_req_out [TMRCoreIndex]; + sys_instr_addr_o [i] = tmr_instr_addr_out[TMRCoreIndex]; + + // DATA + sys_data_req_o [i] = tmr_data_req_out [TMRCoreIndex]; + sys_data_add_o [i] = tmr_data_add_out [TMRCoreIndex]; + sys_data_wen_o [i] = tmr_data_wen_out [TMRCoreIndex]; + sys_data_wdata_o [i] = tmr_data_wdata_out[TMRCoreIndex]; + sys_data_user_o [i] = tmr_data_user_out [TMRCoreIndex]; + sys_data_be_o [i] = tmr_data_be_out [TMRCoreIndex]; + + end else begin : disable_core // Assign disable + + // CTLR + sys_core_busy_o [i] = '0; + + // IRQ + sys_irq_ack_o [i] = '0; + sys_irq_ack_id_o [i] = '0; + + // INSTR + sys_instr_req_o [i] = '0; + sys_instr_addr_o [i] = '0; + + // DATA + sys_data_req_o [i] = '0; + sys_data_add_o [i] = '0; + sys_data_wen_o [i] = '0; + sys_data_wdata_o [i] = '0; + sys_data_user_o [i] = '0; + sys_data_be_o [i] = '0; + + end + end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode + if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core + // CTRL + sys_core_busy_o [i] = dmr_core_busy_out [DMRCoreIndex]; + + // IRQ + sys_irq_ack_o [i] = dmr_irq_ack_out [DMRCoreIndex]; + sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[DMRCoreIndex]; + + // INSTR + sys_instr_req_o [i] = dmr_instr_req_out [DMRCoreIndex]; + sys_instr_addr_o [i] = dmr_instr_addr_out[DMRCoreIndex]; + + // DATA + sys_data_req_o [i] = dmr_data_req_out [DMRCoreIndex]; + sys_data_add_o [i] = dmr_data_add_out [DMRCoreIndex]; + sys_data_wen_o [i] = dmr_data_wen_out [DMRCoreIndex]; + sys_data_wdata_o [i] = dmr_data_wdata_out[DMRCoreIndex]; + sys_data_user_o [i] = dmr_data_user_out [DMRCoreIndex]; + sys_data_be_o [i] = dmr_data_be_out [DMRCoreIndex]; + + end else begin : disable_core // Assign disable + + // CTLR + sys_core_busy_o [i] = '0; + + // IRQ + sys_irq_ack_o [i] = '0; + sys_irq_ack_id_o [i] = '0; + + // INSTR + sys_instr_req_o [i] = '0; + sys_instr_addr_o [i] = '0; + + // DATA + sys_data_req_o [i] = '0; + sys_data_add_o [i] = '0; + sys_data_wen_o [i] = '0; + sys_data_wdata_o [i] = '0; + sys_data_user_o [i] = '0; + sys_data_be_o [i] = '0; + + end + end else begin : independent_mode + // CTRL + sys_core_busy_o [i] = core_core_busy_i [i]; + + // IRQ + sys_irq_ack_o [i] = core_irq_ack_i [i]; + sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; + + // INSTR + sys_instr_req_o [i] = core_instr_req_i [i]; + sys_instr_addr_o [i] = core_instr_addr_i[i]; + + // DATA + sys_data_req_o [i] = core_data_req_i [i]; + sys_data_add_o [i] = core_data_add_i [i]; + sys_data_wen_o [i] = core_data_wen_i [i]; + sys_data_wdata_o [i] = core_data_wdata_i[i]; + sys_data_user_o [i] = core_data_user_i [i]; + sys_data_be_o [i] = core_data_be_i [i]; + end + end + end end else if (TMRSupported || TMRFixed) begin : gen_TMR_only /***************** *** TMR only *** *****************/ for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + // Temporary disable of RapidRecovery + assign core_debug_resume_o [i] = '0; + + // Setback + assign core_recover_o [i] = '0; + assign core_instr_lock_o [i] = '0; + + // PC + assign pc_recover_o [i] = '0; + assign recovery_program_counter_o [i] = '0; + assign recovery_branch_o [i] = '0; + assign recovery_branch_addr_o [i] = '0; + + // RF + assign dmr_rf_readback_o [i] = '0; + assign core_regfile_raddr_o [i] = '0; + assign core_recovery_regfile_wport_o[i].we_a = '0; + assign core_recovery_regfile_wport_o[i].waddr_a = '0; + assign core_recovery_regfile_wport_o[i].wdata_a = '0; + assign core_recovery_regfile_wport_o[i].we_b = '0; + assign core_recovery_regfile_wport_o[i].waddr_b = '0; + assign core_recovery_regfile_wport_o[i].wdata_b = '0; + localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode @@ -855,20 +1091,20 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; // IRQ - assign sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; - assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + assign sys_irq_ack_o [i] = tmr_irq_ack_out [CoreCoreIndex]; + assign sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - assign sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; - assign sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + assign sys_instr_req_o [i] = tmr_instr_req_out [CoreCoreIndex]; + assign sys_instr_addr_o [i] = tmr_instr_addr_out[CoreCoreIndex]; // DATA - assign sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; - assign sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; - assign sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; - assign sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; - assign sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; - assign sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + assign sys_data_req_o [i] = tmr_data_req_out [CoreCoreIndex]; + assign sys_data_add_o [i] = tmr_data_add_out [CoreCoreIndex]; + assign sys_data_wen_o [i] = tmr_data_wen_out [CoreCoreIndex]; + assign sys_data_wdata_o [i] = tmr_data_wdata_out[CoreCoreIndex]; + assign sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; + assign sys_data_be_o [i] = tmr_data_be_out [CoreCoreIndex]; end else begin if (i >= NumTMRCores) begin : independent_stragglers // CTRL @@ -898,20 +1134,20 @@ module HMR_wrap import recovery_pkg::*; #( sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; // IRQ - sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; - sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + sys_irq_ack_o [i] = tmr_irq_ack_out [CoreCoreIndex]; + sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; - sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + sys_instr_req_o [i] = tmr_instr_req_out [CoreCoreIndex]; + sys_instr_addr_o [i] = tmr_instr_addr_out[CoreCoreIndex]; // DATA - sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; - sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; - sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; - sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; - sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; - sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + sys_data_req_o [i] = tmr_data_req_out [CoreCoreIndex]; + sys_data_add_o [i] = tmr_data_add_out [CoreCoreIndex]; + sys_data_wen_o [i] = tmr_data_wen_out [CoreCoreIndex]; + sys_data_wdata_o [i] = tmr_data_wdata_out[CoreCoreIndex]; + sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; + sys_data_be_o [i] = tmr_data_be_out [CoreCoreIndex]; end else begin : disable_core // Assign disable @@ -972,159 +1208,227 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); - if (i < NumDMRCores && DMRFixed) begin : gen_dmr_mode - // CTRL - assign core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; - assign core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; + localparam SysGroupId = DMRFixed ? i/2 : dmr_group_id(i); + always_comb begin + if (i < NumDMRCores && (DMRFixed || core_in_dmr[i])) begin : dmr_mode + // CTRL + core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; + core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - assign core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; - assign core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; - assign core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; + core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; - assign core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] - | dmr_ctrl_core_debug_req_out [SysCoreIndex]; - assign core_debug_resume_o [i] = dmr_ctrl_debug_resume_out [SysCoreIndex]; - assign core_perf_counters_o[i] = sys_perf_counters_i [SysCoreIndex]; + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + | dmr_ctrl_core_debug_req_out [SysGroupId]; + core_debug_resume_o [i] = dmr_ctrl_debug_resume_out [SysGroupId]; + core_perf_counters_o[i] = sys_perf_counters_i [SysCoreIndex]; - // IRQ - assign core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; - assign core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; + // Setback + core_setback_o [i] = dmr_ctrl_core_setback_out [SysGroupId]; + core_recover_o [i] = dmr_ctrl_core_recover_out [SysGroupId]; - // INSTR - assign core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; - assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; - assign core_instr_r_valid_o[i] = sys_instr_r_valid_i [SysCoreIndex]; - assign core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; - assign core_instr_lock_o [i] = dmr_ctrl_core_instr_lock_out [SysCoreIndex]; + // IRQ + core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; + core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; - // DATA - assign core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; - assign core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; - assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; - assign core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; - assign core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; - assign core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; - - // PC - assign pc_recover_o [i] = dmr_ctrl_pc_read_enable_out [SysCoreIndex]; - assign recovery_program_counter_o [i] = recovery_program_counter_out [SysCoreIndex]; - assign recovery_branch_o [i] = recovery_branch_out [SysCoreIndex]; - assign recovery_branch_addr_o [i] = recovery_branch_addr_out [SysCoreIndex]; - - // RF - assign dmr_rf_readback_o [i] = regfile_readback_out [SysCoreIndex]; - assign core_regfile_raddr_o [i] = core_regfile_raddr_out [SysCoreIndex]; - assign core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[SysCoreIndex].we_a; - assign core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[SysCoreIndex].waddr_a; - assign core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_a; - assign core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[SysCoreIndex].we_b; - assign core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[SysCoreIndex].waddr_b; - assign core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_b; - - end else begin : gen_independent_mode + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i [SysCoreIndex]; + core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; + core_instr_lock_o [i] = dmr_ctrl_core_instr_lock_out [SysGroupId]; - // CTRL - assign core_core_id_o [i] = sys_core_id_i [i]; - assign core_cluster_id_o [i] = sys_cluster_id_i [i]; + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; + core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; + core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + + // PC + pc_recover_o [i] = dmr_ctrl_pc_read_enable_out [SysCoreIndex]; + recovery_program_counter_o [i] = recovery_program_counter_out [SysCoreIndex]; + recovery_branch_o [i] = recovery_branch_out [SysCoreIndex]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [SysCoreIndex]; + + // RF + dmr_rf_readback_o [i] = regfile_readback_out [SysCoreIndex]; + core_regfile_raddr_o [i] = core_regfile_raddr_out [SysCoreIndex]; + core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[SysCoreIndex].we_a; + core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[SysCoreIndex].waddr_a; + core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_a; + core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[SysCoreIndex].we_b; + core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[SysCoreIndex].waddr_b; + core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_b; + + end else begin : gen_independent_mode + // CTRL + core_core_id_o [i] = sys_core_id_i [i]; + core_cluster_id_o [i] = sys_cluster_id_i [i]; - assign core_clock_en_o [i] = sys_clock_en_i [i]; - assign core_fetch_en_o [i] = sys_fetch_en_i [i]; - assign core_boot_addr_o [i] = sys_boot_addr_i [i]; + core_clock_en_o [i] = sys_clock_en_i [i]; + core_fetch_en_o [i] = sys_fetch_en_i [i]; + core_boot_addr_o [i] = sys_boot_addr_i [i]; - assign core_debug_req_o [i] = sys_debug_req_i [i]; - assign core_perf_counters_o[i] = sys_perf_counters_i[i]; + core_debug_req_o [i] = sys_debug_req_i [i]; + core_debug_resume_o [i] = '0; + core_perf_counters_o[i] = sys_perf_counters_i[i]; - // IRQ - assign core_irq_req_o [i] = sys_irq_req_i [i]; - assign core_irq_id_o [i] = sys_irq_id_i [i]; + // Setback + core_setback_o [i] = '0; + core_recover_o [i] = '0; - // INSTR - assign core_instr_gnt_o [i] = sys_instr_gnt_i [i]; - assign core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; - assign core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; - assign core_instr_err_o [i] = sys_instr_err_i [i]; + // IRQ + core_irq_req_o [i] = sys_irq_req_i [i]; + core_irq_id_o [i] = sys_irq_id_i [i]; - // DATA - assign core_data_gnt_o [i] = sys_data_gnt_i [i]; - assign core_data_r_opc_o [i] = sys_data_r_opc_i [i]; - assign core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; - assign core_data_r_user_o [i] = sys_data_r_user_i [i]; - assign core_data_r_valid_o [i] = sys_data_r_valid_i [i]; - assign core_data_err_o [i] = sys_data_err_i [i]; + // INSTR + core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; + core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_err_o [i] = sys_instr_err_i [i]; + core_instr_lock_o [i] = '0; + // DATA + core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_r_opc_o [i] = sys_data_r_opc_i [i]; + core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; + core_data_r_user_o [i] = sys_data_r_user_i [i]; + core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_err_o [i] = sys_data_err_i [i]; + + // PC + pc_recover_o [i] = '0; + recovery_program_counter_o [i] = '0; + recovery_branch_o [i] = '0; + recovery_branch_addr_o [i] = '0; + + // RF + dmr_rf_readback_o [i] = '0; + core_regfile_raddr_o [i] = '0; + core_recovery_regfile_wport_o[i].we_a = '0; + core_recovery_regfile_wport_o[i].waddr_a = '0; + core_recovery_regfile_wport_o[i].wdata_a = '0; + core_recovery_regfile_wport_o[i].we_b = '0; + core_recovery_regfile_wport_o[i].waddr_b = '0; + core_recovery_regfile_wport_o[i].wdata_b = '0; + end end end // gen_core_inputs for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs - localparam CoreCoreIndex = DMRFixed ? i : dmr_core_id(i, 0); - if ((DMRFixed && i < NumDMRGroups) || (i < NumDMRCores)) begin : gen_dmr_mode - if (DMRFixed || (InterleaveGrps && i < NumDMRGroups) || (!InterleaveGrps && i%2 == 0)) begin : gen_is_dmr - + localparam CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); + if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr + // CTRL + assign sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; + + // IRQ + assign sys_irq_ack_o [i] = dmr_irq_ack_out [CoreCoreIndex]; + assign sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[CoreCoreIndex]; + + // INSTR + assign sys_instr_req_o [i] = dmr_instr_req_out [CoreCoreIndex]; + assign sys_instr_addr_o [i] = dmr_instr_addr_out[CoreCoreIndex]; + + // DATA + assign sys_data_req_o [i] = dmr_data_req_out [CoreCoreIndex]; + assign sys_data_add_o [i] = dmr_data_add_out [CoreCoreIndex]; + assign sys_data_wen_o [i] = dmr_data_wen_out [CoreCoreIndex]; + assign sys_data_wdata_o [i] = dmr_data_wdata_out[CoreCoreIndex]; + assign sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; + assign sys_data_be_o [i] = dmr_data_be_out [CoreCoreIndex]; + end else begin + if (i >= NumDMRCores) begin : independent_stragglers // CTRL - assign sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; + assign sys_core_busy_o [i] = dmr_core_busy_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // IRQ - assign sys_irq_ack_o [i] = core_irq_ack_i [CoreCoreIndex]; - assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[CoreCoreIndex]; + assign sys_irq_ack_o [i] = dmr_irq_ack_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // INSTR - assign sys_instr_req_o [i] = core_instr_req_i [CoreCoreIndex]; - assign sys_instr_addr_o [i] = core_instr_addr_i[CoreCoreIndex]; + assign sys_instr_req_o [i] = dmr_instr_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_instr_addr_o [i] = dmr_instr_addr_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // DATA - assign sys_data_req_o [i] = core_data_req_i [CoreCoreIndex]; - assign sys_data_add_o [i] = core_data_add_i [CoreCoreIndex]; - assign sys_data_wen_o [i] = core_data_wen_i [CoreCoreIndex]; - assign sys_data_wdata_o [i] = core_data_wdata_i[CoreCoreIndex]; - assign sys_data_user_o [i] = core_data_user_i [CoreCoreIndex]; - assign sys_data_be_o [i] = core_data_be_i [CoreCoreIndex]; + assign sys_data_req_o [i] = dmr_data_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_add_o [i] = dmr_data_add_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_wen_o [i] = dmr_data_wen_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_wdata_o [i] = dmr_data_wdata_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_user_o [i] = dmr_data_user_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_be_o [i] = dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + end else begin + always_comb begin + if (core_in_dmr[i]) begin : dmr_mode + if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core + + // CTRL + sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; - assign core_setback_o [i] = dmr_ctrl_core_setback_out [CoreCoreIndex]; - assign core_recover_o [i] = dmr_ctrl_core_recover_out [CoreCoreIndex]; + // IRQ + sys_irq_ack_o [i] = dmr_irq_ack_out [CoreCoreIndex]; + sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[CoreCoreIndex]; - end else begin : gen_disable_core // Assign disable + // INSTR + sys_instr_req_o [i] = dmr_instr_req_out [CoreCoreIndex]; + sys_instr_addr_o [i] = dmr_instr_addr_out[CoreCoreIndex]; - // CTLR - assign sys_core_busy_o [i] = '0; + // DATA + sys_data_req_o [i] = dmr_data_req_out [CoreCoreIndex]; + sys_data_add_o [i] = dmr_data_add_out [CoreCoreIndex]; + sys_data_wen_o [i] = dmr_data_wen_out [CoreCoreIndex]; + sys_data_wdata_o [i] = dmr_data_wdata_out[CoreCoreIndex]; + sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; + sys_data_be_o [i] = dmr_data_be_out [CoreCoreIndex]; - // IRQ - assign sys_irq_ack_o [i] = '0; - assign sys_irq_ack_id_o [i] = '0; + end else begin : disable_core // Assign disable - // INSTR - assign sys_instr_req_o [i] = '0; - assign sys_instr_addr_o [i] = '0; + // CTLR + sys_core_busy_o [i] = '0; - // DATA - assign sys_data_req_o [i] = '0; - assign sys_data_add_o [i] = '0; - assign sys_data_wen_o [i] = '0; - assign sys_data_wdata_o [i] = '0; - assign sys_data_user_o [i] = '0; - assign sys_data_be_o [i] = '0; + // IRQ + sys_irq_ack_o [i] = '0; + sys_irq_ack_id_o [i] = '0; - end - end else begin : gen_independent_mode - // CTRL - assign sys_core_busy_o [i] = core_core_busy_i [i]; + // INSTR + sys_instr_req_o [i] = '0; + sys_instr_addr_o [i] = '0; - // IRQ - assign sys_irq_ack_o [i] = core_irq_ack_i [i]; - assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; + // DATA + sys_data_req_o [i] = '0; + sys_data_add_o [i] = '0; + sys_data_wen_o [i] = '0; + sys_data_wdata_o [i] = '0; + sys_data_user_o [i] = '0; + sys_data_be_o [i] = '0; - // INSTR - assign sys_instr_req_o [i] = core_instr_req_i [i]; - assign sys_instr_addr_o [i] = core_instr_addr_i[i]; + end + end else begin : independent_mode + // CTRL + sys_core_busy_o [i] = core_core_busy_i [i]; - // DATA - assign sys_data_req_o [i] = core_data_req_i [i]; - assign sys_data_add_o [i] = core_data_add_i [i]; - assign sys_data_wen_o [i] = core_data_wen_i [i]; - assign sys_data_wdata_o [i] = core_data_wdata_i[i]; - assign sys_data_user_o [i] = core_data_user_i [i]; - assign sys_data_be_o [i] = core_data_be_i [i]; + // IRQ + sys_irq_ack_o [i] = core_irq_ack_i [i]; + sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; + + // INSTR + sys_instr_req_o [i] = core_instr_req_i [i]; + sys_instr_addr_o [i] = core_instr_addr_i[i]; + + // DATA + sys_data_req_o [i] = core_data_req_i [i]; + sys_data_add_o [i] = core_data_add_i [i]; + sys_data_wen_o [i] = core_data_wen_i [i]; + sys_data_wdata_o [i] = core_data_wdata_i[i]; + sys_data_user_o [i] = core_data_user_i [i]; + sys_data_be_o [i] = core_data_be_i [i]; + end + end + end end - end // gen_core_outputs + end end else begin : gen_no_redundancy /***************** From e1cbb4bad49f80704d93ffb7435924239e059d2c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 27 Jan 2023 16:52:12 +0100 Subject: [PATCH 04/66] Add RapidRecovery parameter to en-/disable backup RF --- rtl/HMR/DMR_controller.sv | 1 + rtl/HMR/HMR_wrap.sv | 234 +++++++++++++++++++------------------- 2 files changed, 121 insertions(+), 114 deletions(-) diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index b0e1927c..1d8fd3f3 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -18,6 +18,7 @@ import recovery_pkg::*; module DMR_controller #( parameter int unsigned NumCores = 0, parameter bit DMRFixed = 1'b0, + parameter bit RapidRecovery = 1'b0, parameter int unsigned RFAddrWidth = 6, localparam int unsigned NumDMRGroups = NumCores/2, localparam int unsigned NumDMRCores = NumDMRGroups * 2, diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 858aaff6..e01b2f09 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -17,8 +17,8 @@ module HMR_wrap import recovery_pkg::*; #( parameter bit DMRFixed = 1'b0, parameter bit TMRSupported = 1'b1, parameter bit TMRFixed = 1'b0, + parameter bit RapidRecovery = 1'b0, // Backup Regfile parameter bit SeparateData = 1'b1, - parameter bit BackupRegfile = 1'b0, parameter bit InterleaveGrps = 1'b1, // alternative is sequential grouping parameter int unsigned InstrDataWidth = 32, parameter int unsigned DataWidth = 32, @@ -556,9 +556,10 @@ module HMR_wrap import recovery_pkg::*; #( * DMR Controller * ******************/ DMR_controller #( - .NumCores ( NumCores ), - .DMRFixed ( DMRFixed ), - .RFAddrWidth ( RFAddrWidth ) + .NumCores ( NumCores ), + .DMRFixed ( DMRFixed ), + .RapidRecovery ( RapidRecovery ), + .RFAddrWidth ( RFAddrWidth ) ) dmr_controller ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -625,120 +626,125 @@ module HMR_wrap import recovery_pkg::*; #( = main_dmr_out[i]; end - /****************** - * DMR PC Checker * - ******************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_pc_checker ( - .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), - .check_o ( backup_program_counter_int [i] ), - .error_o ( backup_program_counter_error [i] ) - ); - - /********************* - * DMR Branch Checker * - **********************/ - DMR_checker # ( - .DataWidth ( 1 ) - ) dmr_branch_checker ( - .inp_a_i ( backup_branch_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_branch_i[dmr_core_id(i, 1)] ), - .check_o ( backup_branch_int [i] ), - .error_o ( backup_branch_error [i] ) - ); - - /***************************** - * DMR Branch Address Checker * - ******************************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_branch_addr_checker ( - .inp_a_i ( backup_branch_addr_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_branch_addr_i[dmr_core_id(i, 1)] ), - .check_o ( backup_branch_addr_int [i] ), - .error_o ( backup_branch_addr_error [i] ) - ); - - /******************* - * DMR RF Checkers * - *******************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_rf_checker_port_a ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_a ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_a ), - .check_o ( backup_regfile_wdata_a[i] ), - .error_o ( backup_regfile_error_a[i] ) - ); + if (RapidRecovery) begin - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_rf_checker_port_b ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_b ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_b ), - .check_o ( backup_regfile_wdata_b [i] ), - .error_o ( backup_regfile_error_b [i] ) - ); + /****************** + * DMR PC Checker * + ******************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_pc_checker ( + .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), + .check_o ( backup_program_counter_int [i] ), + .error_o ( backup_program_counter_error [i] ) + ); + + /********************** + * DMR Branch Checker * + **********************/ + DMR_checker # ( + .DataWidth ( 1 ) + ) dmr_branch_checker ( + .inp_a_i ( backup_branch_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_branch_i[dmr_core_id(i, 1)] ), + .check_o ( backup_branch_int [i] ), + .error_o ( backup_branch_error [i] ) + ); + + /***************************** + * DMR Branch Address Checker * + ******************************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_branch_addr_checker ( + .inp_a_i ( backup_branch_addr_i[dmr_core_id(i, 0)] ), + .inp_b_i ( backup_branch_addr_i[dmr_core_id(i, 1)] ), + .check_o ( backup_branch_addr_int [i] ), + .error_o ( backup_branch_addr_error [i] ) + ); - assign backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a - & ~backup_regfile_error_a [i] - & ~dmr_ctrl_core_recover_out [i]; - assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b - & ~backup_regfile_error_b [i] - & ~dmr_ctrl_core_recover_out [i]; - /**************************** - * Recovery Program Counter * - ****************************/ - recovery_pc #( - .ECCEnabled ( 1 ) - ) RPC ( - // Control Ports - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clear_i ( '0 ), - .read_enable_i ( dmr_ctrl_pc_read_enable_out [i] ), - .write_enable_i ( ~backup_program_counter_error [i] - & dmr_ctrl_pc_write_enable_out [i] ), - // Backup Ports - .backup_program_counter_i ( backup_program_counter_int [i] ), - .backup_branch_i ( backup_branch_int [i] ), - .backup_branch_addr_i ( backup_branch_addr_i [i] ), - // Recovery Pors - .recovery_program_counter_o ( recovery_program_counter_out [i] ), - .recovery_branch_o ( recovery_branch_out [i] ), - .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) - ); - - /*************************** - * Recovery Register Files * - ***************************/ - recovery_rf #( + /******************* + * DMR RF Checkers * + *******************/ + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_rf_checker_port_a ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_a ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_a ), + .check_o ( backup_regfile_wdata_a[i] ), + .error_o ( backup_regfile_error_a[i] ) + ); + + DMR_checker # ( + .DataWidth ( DataWidth ) + ) dmr_rf_checker_port_b ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_b ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_b ), + .check_o ( backup_regfile_wdata_b [i] ), + .error_o ( backup_regfile_error_b [i] ) + ); + + assign backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a + & ~backup_regfile_error_a [i] + & ~dmr_ctrl_core_recover_out [i]; + assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b + & ~backup_regfile_error_b [i] + & ~dmr_ctrl_core_recover_out [i]; + /**************************** + * Recovery Program Counter * + ****************************/ + recovery_pc #( + .ECCEnabled ( 1 ) + ) RPC ( + // Control Ports + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clear_i ( '0 ), + .read_enable_i ( dmr_ctrl_pc_read_enable_out [i] ), + .write_enable_i ( ~backup_program_counter_error [i] + & dmr_ctrl_pc_write_enable_out [i] ), + // Backup Ports + .backup_program_counter_i ( backup_program_counter_int [i] ), + .backup_branch_i ( backup_branch_int [i] ), + .backup_branch_addr_i ( backup_branch_addr_i [i] ), + // Recovery Pors + .recovery_program_counter_o ( recovery_program_counter_out [i] ), + .recovery_branch_o ( recovery_branch_out [i] ), + .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) + ); + + /*************************** + * Recovery Register Files * + ***************************/ + recovery_rf #( .ECCEnabled ( 1 ), .ADDR_WIDTH ( RFAddrWidth ) - ) RRF ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .test_en_i ( '0 ), - //Read port A - .raddr_a_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_a ), - .rdata_a_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_a ), - //Read port B - .raddr_b_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_b ), - .rdata_b_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_b ), - //Read port C - .raddr_c_i ( '0 ), - .rdata_c_o ( ), - // Write Port A - .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), - .wdata_a_i ( backup_regfile_wdata_a [i] ), - .we_a_i ( backup_regfile_we_a [i] ), - // Write Port B - .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), - .wdata_b_i ( backup_regfile_wdata_b [i] ), - .we_b_i ( backup_regfile_we_b [i] ) - ); + ) RRF ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .test_en_i ( '0 ), + //Read port A + .raddr_a_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_a ), + .rdata_a_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_a ), + //Read port B + .raddr_b_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_b ), + .rdata_b_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_b ), + //Read port C + .raddr_c_i ( '0 ), + .rdata_c_o ( ), + // Write Port A + .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), + .wdata_a_i ( backup_regfile_wdata_a [i] ), + .we_a_i ( backup_regfile_we_a [i] ), + // Write Port B + .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), + .wdata_b_i ( backup_regfile_wdata_b [i] ), + .we_b_i ( backup_regfile_we_b [i] ) + ); + end else begin + + end end if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; From c577999092b35e4c14dc245f4d24c886b307a6ad Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Fri, 27 Jan 2023 10:49:36 +0100 Subject: [PATCH 05/66] Added clock gating to lock unfaulty cores during recovery routine. --- rtl/HMR/DMR_controller.sv | 28 +++++++++++++++++++++++++++- rtl/HMR/HMR_wrap.sv | 6 ++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index 1d8fd3f3..3fb9bd17 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -77,7 +77,9 @@ logic [NumDMRGroups-1:0] dmr_ctrl_core_setback_out , dmr_ctrl_core_recover_d, dmr_ctrl_core_recover_q, dmr_ctrl_core_instr_lock_d, - dmr_ctrl_core_instr_lock_q; + dmr_ctrl_core_instr_lock_q, + dmr_ctrl_core_clk_en_d, + dmr_ctrl_core_clk_en_q; recovery_routine_state_e current, next; logic [$clog2(NumDMRGroups)-1:0] error_index_d, @@ -165,6 +167,25 @@ generate end endgenerate +/* + * Core clock enable. + * Clock gate the cores that do not need to recover during the recovery routine. + */ +generate + for (genvar i = 0; i < NumDMRGroups; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : core_clock_enable + if (~rst_ni) begin + dmr_ctrl_core_clk_en_q [i] <= 1'b1; + end else begin + if (clear) begin + dmr_ctrl_core_clk_en_q [i] <= 1'b1; + end else + dmr_ctrl_core_clk_en_q [i] <= dmr_ctrl_core_clk_en_d [i]; + end + end + end +endgenerate + /* * Core Recover Registers. * These registers raise the recover signal towards the cores to @@ -276,6 +297,7 @@ always_comb begin : recovery_routine_fsm dmr_ctrl_core_clk_en_out = '1; dmr_ctrl_core_recover_d = dmr_ctrl_core_recover_q; dmr_ctrl_core_instr_lock_d = dmr_ctrl_core_instr_lock_q; + dmr_ctrl_core_clk_en_d = dmr_ctrl_core_clk_en_q; dmr_ctrl_core_debug_req_out = '0; dmr_ctrl_core_debug_resume_o = '0; dmr_ctrl_pc_read_enable_out = '0; @@ -293,6 +315,10 @@ always_comb begin : recovery_routine_fsm dmr_ctrl_core_setback_out [error_index_q] = 1'b1; dmr_ctrl_core_instr_lock_d [error_index_q] = 1'b1; dmr_ctrl_pc_write_enable_d [error_index_q] = 1'b0; + for (int i = 0; i < NumDMRGroups; i++) begin + if (i != error_index_q) + dmr_ctrl_core_clk_en_d [i] = 1'b0; + end next = HALT_REQ; end diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index e01b2f09..727bcf33 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -237,6 +237,7 @@ module HMR_wrap import recovery_pkg::*; #( backup_program_counter_error, dmr_ctrl_pc_read_enable_out, dmr_ctrl_pc_write_enable_out, + dmr_ctrl_core_clk_en_out, backup_regfile_we_a, backup_regfile_we_b, backup_regfile_error_a, @@ -579,7 +580,7 @@ module HMR_wrap import recovery_pkg::*; #( .dmr_ctrl_core_debug_resume_o ( dmr_ctrl_debug_resume_out ), .dmr_ctrl_pc_read_enable_o ( dmr_ctrl_pc_read_enable_out ), .dmr_ctrl_pc_write_enable_o ( dmr_ctrl_pc_write_enable_out ), - .dmr_ctrl_core_clk_en_o ( ) + .dmr_ctrl_core_clk_en_o ( dmr_ctrl_core_clk_en_out ) ); if (DMRSupported || DMRFixed) begin: gen_dmr_recovery_region @@ -1221,7 +1222,8 @@ module HMR_wrap import recovery_pkg::*; #( core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] + & dmr_ctrl_core_clk_en_out[SysGroupId]; core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; From 256a2cb90e92abd127110eba4e4b6adf9ad79bd2 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 27 Jan 2023 17:28:55 +0100 Subject: [PATCH 06/66] Add parameter documentation --- rtl/HMR/DMR_controller.sv | 4 +--- rtl/HMR/HMR_wrap.sv | 48 +++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index 3fb9bd17..f6c83fd3 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -13,9 +13,7 @@ * */ -import recovery_pkg::*; - -module DMR_controller #( +module DMR_controller import recovery_pkg::*; #( parameter int unsigned NumCores = 0, parameter bit DMRFixed = 1'b0, parameter bit RapidRecovery = 1'b0, diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 727bcf33..02337d5e 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -12,14 +12,22 @@ module HMR_wrap import recovery_pkg::*; #( // Wrapper parameters + /// Number of physical cores parameter int unsigned NumCores = 0, + /// Enables support for Dual Modular Redundancy parameter bit DMRSupported = 1'b1, + /// Locks HMR into permanent DMR mode parameter bit DMRFixed = 1'b0, + /// Enables support for Triple Modular Redundancy parameter bit TMRSupported = 1'b1, + /// Locks HMR into permanent TMR mode parameter bit TMRFixed = 1'b0, - parameter bit RapidRecovery = 1'b0, // Backup Regfile + /// Enables rapid recovery with a backup register file, PC, ... + parameter bit RapidRecovery = 1'b0, + /// Separates voters and checkers for data, which are then only checked if data request is valid parameter bit SeparateData = 1'b1, - parameter bit InterleaveGrps = 1'b1, // alternative is sequential grouping + /// Interleave DMR/TMR cores, alternatively with sequential grouping + parameter bit InterleaveGrps = 1'b1, parameter int unsigned InstrDataWidth = 32, parameter int unsigned DataWidth = 32, parameter int unsigned BeWidth = 4, @@ -28,12 +36,19 @@ module HMR_wrap import recovery_pkg::*; #( parameter type reg_req_t = logic, parameter type reg_resp_t = logic, // Local parameters depending on the above ones + /// Number of TMR groups (virtual TMR cores) localparam int unsigned NumTMRGroups = NumCores/3, + /// Number of physical cores used for TMR localparam int unsigned NumTMRCores = NumTMRGroups * 3, + /// Number of physical cores NOT used for TMR localparam int unsigned NumTMRLeftover = NumCores - NumTMRCores, + /// Number of DMR groups (virtual DMR cores) localparam int unsigned NumDMRGroups = NumCores/2, + /// Nubmer of physical cores used for DMR localparam int unsigned NumDMRCores = NumDMRGroups * 2, + /// Number of physical cores NOT used for DMR localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, + /// Number of cores visible to the system (Fixed mode removes unneeded system ports) localparam int unsigned NumSysCores = DMRFixed ? NumDMRCores : TMRFixed ? NumTMRCores : NumCores ) ( input logic clk_i , @@ -199,8 +214,8 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumTMRGroups-1:0] tmr_single_mismatch; logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_data; - logic [NumDMRGroups-1:0][2:0] dmr_error, dmr_error_main, dmr_error_data; - logic [NumDMRGroups-1:0] dmr_single_mismatch; + // logic [NumDMRGroups-1:0][2:0] dmr_error, dmr_error_main, dmr_error_data; + // logic [NumDMRGroups-1:0] dmr_single_mismatch; logic [NumTMRGroups-1:0] tmr_core_busy_out; logic [NumTMRGroups-1:0] tmr_irq_ack_out; @@ -587,9 +602,9 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumDMRGroups; i++) begin assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main | dmr_failure_data) : dmr_failure_main; - assign dmr_error [i*2+:2] = dmr_data_req_out [i] ? (dmr_error_main [i*2+:2] | dmr_error_data [i*2+:2]) - : tmr_error_main [i*2+:2]; - assign dmr_single_mismatch [i] = dmr_error [i*2+:2] != 3'b000; + // assign dmr_error [i*2+:2] = dmr_data_req_out [i] ? (dmr_error_main [i*2+:2] | dmr_error_data [i*2+:2]) + // : dmr_error_main [i*2+:2]; + // assign dmr_single_mismatch [i] = dmr_error [i*2+:2] != 3'b000; /********************* * DMR Core Checkers * @@ -619,7 +634,7 @@ module HMR_wrap import recovery_pkg::*; #( = data_dmr_out[i]; end else begin : gen_data_in_main assign dmr_failure_data[i] = 1'b0; - assign dmr_error_data[i] = 3'b000; + // assign dmr_error_data[i] = 3'b000; assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] , dmr_data_add_out[i] , dmr_data_wen_out[i] , dmr_data_wdata_out[i], @@ -747,15 +762,15 @@ module HMR_wrap import recovery_pkg::*; #( end end - if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error - assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; - assign dmr_error_data[NumCores-1-:NumDMRLeftover] = '0; - assign dmr_error [NumCores-1-:NumDMRLeftover] = '0; - end + // if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error + // assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; + // assign dmr_error_data[NumCores-1-:NumDMRLeftover] = '0; + // assign dmr_error [NumCores-1-:NumDMRLeftover] = '0; + // end end else begin: no_dmr_checkers - assign dmr_error_main = '0; - assign dmr_error_data = '0; - assign dmr_error = '0; + // assign dmr_error_main = '0; + // assign dmr_error_data = '0; + // assign dmr_error = '0; assign dmr_failure_main = '0; assign dmr_failure_data = '0; assign dmr_failure = '0; @@ -1086,7 +1101,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; - end end end From 28eb908312919cd067f0680f2dfa639d1c7a8348 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 30 Jan 2023 19:42:29 +0100 Subject: [PATCH 07/66] Update TMR signalling --- rtl/HMR/HMR_wrap.sv | 49 +++++++++++------------- rtl/HMR/hmr_tmr_ctrl.sv | 85 +++++++++++++++++++++++------------------ 2 files changed, 69 insertions(+), 65 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 02337d5e..9008e4c6 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -88,26 +88,26 @@ module HMR_wrap import recovery_pkg::*; #( // Ports connecting to System input logic [NumSysCores-1:0][ 3:0] sys_core_id_i , input logic [NumSysCores-1:0][ 5:0] sys_cluster_id_i , - + input logic [NumSysCores-1:0] sys_clock_en_i , input logic [NumSysCores-1:0] sys_fetch_en_i , input logic [NumSysCores-1:0][ 31:0] sys_boot_addr_i , output logic [NumSysCores-1:0] sys_core_busy_o , - + input logic [NumSysCores-1:0] sys_irq_req_i , output logic [NumSysCores-1:0] sys_irq_ack_o , input logic [NumSysCores-1:0][ 4:0] sys_irq_id_i , output logic [NumSysCores-1:0][ 4:0] sys_irq_ack_id_o , - + output logic [NumSysCores-1:0] sys_instr_req_o , input logic [NumSysCores-1:0] sys_instr_gnt_i , output logic [NumSysCores-1:0][ 31:0] sys_instr_addr_o , input logic [NumSysCores-1:0][InstrDataWidth-1:0] sys_instr_r_rdata_i, input logic [NumSysCores-1:0] sys_instr_r_valid_i, input logic [NumSysCores-1:0] sys_instr_err_i , - + input logic [NumSysCores-1:0] sys_debug_req_i , - + output logic [NumSysCores-1:0] sys_data_req_o , output logic [NumSysCores-1:0][ 31:0] sys_data_add_o , output logic [NumSysCores-1:0] sys_data_wen_o , @@ -129,17 +129,17 @@ module HMR_wrap import recovery_pkg::*; #( output logic [ NumCores-1:0][ 3:0] core_core_id_o , output logic [ NumCores-1:0][ 5:0] core_cluster_id_o , - + output logic [ NumCores-1:0] core_clock_en_o , output logic [ NumCores-1:0] core_fetch_en_o , output logic [ NumCores-1:0][ 31:0] core_boot_addr_o , input logic [ NumCores-1:0] core_core_busy_i , - + output logic [ NumCores-1:0] core_irq_req_o , input logic [ NumCores-1:0] core_irq_ack_i , output logic [ NumCores-1:0][ 4:0] core_irq_id_o , input logic [ NumCores-1:0][ 4:0] core_irq_ack_id_i , - + input logic [ NumCores-1:0] core_instr_req_i , output logic [ NumCores-1:0] core_instr_gnt_o , input logic [ NumCores-1:0][ 31:0] core_instr_addr_i , @@ -147,11 +147,11 @@ module HMR_wrap import recovery_pkg::*; #( output logic [ NumCores-1:0] core_instr_r_valid_o, output logic [ NumCores-1:0] core_instr_lock_o , output logic [ NumCores-1:0] core_instr_err_o , - + output logic [ NumCores-1:0] core_debug_req_o , output logic [ NumCores-1:0] core_debug_resume_o , input logic [ NumCores-1:0] core_debug_halted_i , - + input logic [ NumCores-1:0] core_data_req_i , input logic [ NumCores-1:0][ 31:0] core_data_add_i , input logic [ NumCores-1:0] core_data_wen_i , @@ -164,7 +164,7 @@ module HMR_wrap import recovery_pkg::*; #( output logic [ NumCores-1:0][ UserWidth-1:0] core_data_r_user_o , output logic [ NumCores-1:0] core_data_r_valid_o , output logic [ NumCores-1:0] core_data_err_o , - + output logic [ NumCores-1:0][NumExtPerf-1:0] core_perf_counters_o // APU/SHARED_FPU not implemented @@ -292,14 +292,18 @@ module HMR_wrap import recovery_pkg::*; #( * HMR Control Registers * ***************************/ - logic [NumSysCores-1:0] core_en_as_master; - logic [NumSysCores-1:0] core_in_independent; - logic [NumSysCores-1:0] core_in_dmr; - logic [NumSysCores-1:0] core_in_tmr; + logic [NumCores-1:0] core_en_as_master; + logic [NumCores-1:0] core_in_independent; + logic [NumCores-1:0] core_in_dmr; + logic [NumCores-1:0] core_in_tmr; + + logic [NumTMRGroups-1:0] tmr_setback_q; + logic [NumTMRGroups-1:0] tmr_grp_in_independent; - for (genvar i = 0; i < NumSysCores; i++) begin + for (genvar i = 0; i < NumCores; i++) begin assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; assign core_in_dmr[i] = 1'b0; + assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? !tmr_grp_in_independent[tmr_group_id(i)] : '0; assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); end @@ -410,9 +414,6 @@ module HMR_wrap import recovery_pkg::*; #( assign core_config_hw2reg[i].current_mode.triple.d = core_in_tmr[i]; end - logic [NumTMRGroups-1:0] tmr_setback_q; - logic [NumTMRGroups-1:0] tmr_grp_in_independent; - /********************************************************** ******************** TMR Voters & Regs ******************* @@ -421,9 +422,6 @@ module HMR_wrap import recovery_pkg::*; #( if (TMRSupported || TMRFixed) begin : gen_tmr_logic if (TMRFixed && NumCores % 3 != 0) $warning("Extra cores added not properly handled!"); - hmr_tmr_regs_reg_pkg::hmr_tmr_regs_reg2hw_t [NumTMRGroups-1:0] tmr_reg2hw; - hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t [NumTMRGroups-1:0] tmr_hw2reg; - reg_req_t [NumTMRGroups-1:0] tmr_register_reqs; reg_resp_t [NumTMRGroups-1:0] tmr_register_resps; @@ -445,14 +443,9 @@ module HMR_wrap import recovery_pkg::*; #( .out_req_o ( tmr_register_reqs ), .out_rsp_i ( tmr_register_resps ) ); - - for (genvar i = 0; i < NumTMRCores; i++) begin : gen_core_in_tmr - assign core_in_tmr[i] = !tmr_grp_in_independent[tmr_group_id(i)]; - end for (genvar i = NumTMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign tmr_incr_mismatches[i] = '0; - assign core_in_tmr[i] = '0; end for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups @@ -482,6 +475,7 @@ module HMR_wrap import recovery_pkg::*; #( .force_resynch_qe_i ( hmr_reg2hw.tmr_config.force_resynch.qe ), .setback_o ( tmr_setback_q[i] ), + .sw_resynch_req_o ( tmr_resynch_req_o[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), .tmr_single_mismatch_i( tmr_single_mismatch[i] ), @@ -554,6 +548,7 @@ module HMR_wrap import recovery_pkg::*; #( assign tmr_grp_in_independent = '0; assign core_in_tmr = '0; assign tmr_setback_q = '0; + assign tmr_resynch_req_o = '0; end /************************************************************ diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 13055a3f..9bf2df4d 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -25,7 +25,7 @@ module hmr_tmr_ctrl #( input reg_req_t reg_req_i, output reg_resp_t reg_resp_o, - // CTRL from external (e.g. HMR ctr regs) + // CTRL from external (e.g. HMR ctrl regs) input logic tmr_enable_q_i, input logic tmr_enable_qe_i, input logic delay_resynch_q_i, @@ -39,6 +39,7 @@ module hmr_tmr_ctrl #( // TMR control signals output logic setback_o, + output logic sw_resynch_req_o, output logic grp_in_independent_o, output logic [2:0] tmr_incr_mismatches_o, input logic tmr_single_mismatch_i, @@ -59,6 +60,7 @@ module hmr_tmr_ctrl #( assign setback_o = tmr_setback_q; assign grp_in_independent_o = tmr_red_mode_q == NON_TMR; + assign tmr_resynch_req_o = tmr_red_mode_q == TMR_UNLOAD; hmr_tmr_regs_reg_top #( .reg_req_t(reg_req_t), @@ -96,51 +98,58 @@ module hmr_tmr_ctrl #( tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; - // If forced execute resynchronization - if (tmr_red_mode_q == TMR_RUN && tmr_reg2hw.tmr_config.force_resynch.q) begin - tmr_hw2reg.tmr_config.force_resynch.de = 1'b1; - if (tmr_reg2hw.tmr_config.delay_resynch == 0) begin - tmr_red_mode_d = TMR_UNLOAD; - // TODO: buffer the restoration until delay_resynch is disabled - end - end - - // If error detected, do resynchronization - if (tmr_red_mode_q == TMR_RUN && tmr_single_mismatch_i) begin - $display("[ODRG] %t - mismatch detected", $realtime); - if (tmr_error_i[0]) tmr_incr_mismatches_o[0] = 1'b1; - if (tmr_error_i[1]) tmr_incr_mismatches_o[1] = 1'b1; - if (tmr_error_i[2]) tmr_incr_mismatches_o[2] = 1'b1; + 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.delay_resynch == 0) begin + tmr_red_mode_d = TMR_UNLOAD; + // TODO: buffer the restoration until delay_resynch is disabled + end + end - if (tmr_reg2hw.tmr_config.delay_resynch == 0) begin - tmr_red_mode_d = TMR_UNLOAD; - // TODO: buffer the restoration until delay_resynch is disabled + // If error detected, do resynchronization + if (tmr_single_mismatch_i) begin + $display("[ODRG] %t - mismatch detected", $realtime); + if (tmr_error_i[0]) tmr_incr_mismatches_o[0] = 1'b1; + 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.delay_resynch == 0) begin + tmr_red_mode_d = TMR_UNLOAD; + // TODO: buffer the restoration until delay_resynch is disabled + end + end end - end - // If unload complete, go to reload (and reset) - if (tmr_red_mode_q == TMR_UNLOAD) begin - if (tmr_reg2hw.sp_store.q != '0) begin - tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q) begin - tmr_setback_d = 1'b1; + TMR_UNLOAD: begin + // If unload complete, go to reload (and reset) + if (tmr_reg2hw.sp_store.q != '0) begin + tmr_red_mode_d = TMR_RELOAD; + if (tmr_reg2hw.tmr_config.setback.q) begin + tmr_setback_d = 1'b1; + end end end - end - // If reload complete, finish (or reset if error happens during reload) - if (tmr_red_mode_q == TMR_RELOAD) begin - if (tmr_reg2hw.sp_store.q == '0) begin - $display("[ODRG] %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 && - !(tmr_reg2hw.sp_store.qe && reg_req_i.wdata == '0)) begin - tmr_setback_d = 1'b1; + TMR_RELOAD: begin + // If reload complete, finish (or reset if error happens during reload) + if (tmr_reg2hw.sp_store.q == '0) begin + $display("[ODRG] %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 && + !(tmr_reg2hw.sp_store.qe && reg_req_i.wdata == '0)) begin + tmr_setback_d = 1'b1; + end end end - end + + // Default: do nothing + + endcase // Before core startup: set TMR mode from reg2hw.mode.mode if (!TMRFixed) begin From c8eada6bc14f23c015cfaa0d8973dafb0bfb05d0 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 31 Jan 2023 16:01:03 +0100 Subject: [PATCH 08/66] Update signal alignments --- rtl/HMR/HMR_wrap.sv | 42 ++++++++++++++++------------------------- rtl/HMR/hmr_tmr_ctrl.sv | 9 ++++----- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 9008e4c6..8c8e7b47 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -794,8 +794,6 @@ module HMR_wrap import recovery_pkg::*; #( always_comb begin if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; - // CTRL core_core_id_o [i] = sys_core_id_i [TMRCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [TMRCoreIndex]; @@ -824,9 +822,10 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [TMRCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [TMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [TMRCoreIndex]; - end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode - core_setback_o [i] = '0; + // Special signals + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [DMRCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [DMRCoreIndex]; @@ -855,9 +854,10 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [DMRCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [DMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [DMRCoreIndex]; - end else begin : independent_mode + + // Special signals core_setback_o [i] = '0; - + end else begin : independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; core_cluster_id_o [i] = sys_cluster_id_i [i]; @@ -886,6 +886,9 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; + + // Special signals + core_setback_o [i] = '0; end end end @@ -914,9 +917,7 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = tmr_data_wdata_out[TMRCoreIndex]; sys_data_user_o [i] = tmr_data_user_out [TMRCoreIndex]; sys_data_be_o [i] = tmr_data_be_out [TMRCoreIndex]; - end else begin : disable_core // Assign disable - // CTLR sys_core_busy_o [i] = '0; @@ -935,7 +936,6 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = '0; sys_data_user_o [i] = '0; sys_data_be_o [i] = '0; - end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core @@ -957,9 +957,7 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = dmr_data_wdata_out[DMRCoreIndex]; sys_data_user_o [i] = dmr_data_user_out [DMRCoreIndex]; sys_data_be_o [i] = dmr_data_be_out [DMRCoreIndex]; - end else begin : disable_core // Assign disable - // CTLR sys_core_busy_o [i] = '0; @@ -978,7 +976,6 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = '0; sys_data_user_o [i] = '0; sys_data_be_o [i] = '0; - end end else begin : independent_mode // CTRL @@ -1034,8 +1031,6 @@ module HMR_wrap import recovery_pkg::*; #( localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; - // CTRL core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; @@ -1065,9 +1060,9 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + // Special signals + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; end else begin : independent_mode - core_setback_o [i] = '0; - // CTRL core_core_id_o [i] = sys_core_id_i [i]; core_cluster_id_o [i] = sys_cluster_id_i [i]; @@ -1096,6 +1091,9 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; + + // Special signals + core_setback_o [i] = '0; end end end @@ -1145,7 +1143,6 @@ module HMR_wrap import recovery_pkg::*; #( always_comb begin if (core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core - // CTRL sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; @@ -1164,9 +1161,7 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = tmr_data_wdata_out[CoreCoreIndex]; sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; sys_data_be_o [i] = tmr_data_be_out [CoreCoreIndex]; - end else begin : disable_core // Assign disable - // CTLR sys_core_busy_o [i] = '0; @@ -1185,7 +1180,6 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = '0; sys_data_user_o [i] = '0; sys_data_be_o [i] = '0; - end end else begin : independent_mode // CTRL @@ -1380,7 +1374,6 @@ module HMR_wrap import recovery_pkg::*; #( always_comb begin if (core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core - // CTRL sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; @@ -1399,9 +1392,7 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = dmr_data_wdata_out[CoreCoreIndex]; sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; sys_data_be_o [i] = dmr_data_be_out [CoreCoreIndex]; - end else begin : disable_core // Assign disable - // CTLR sys_core_busy_o [i] = '0; @@ -1420,7 +1411,6 @@ module HMR_wrap import recovery_pkg::*; #( sys_data_wdata_o [i] = '0; sys_data_user_o [i] = '0; sys_data_be_o [i] = '0; - end end else begin : independent_mode // CTRL @@ -1453,7 +1443,7 @@ module HMR_wrap import recovery_pkg::*; #( *****************/ // Direct assignment, disable all assign core_setback_o = '0; - + // CTRL assign core_core_id_o = sys_core_id_i; assign core_cluster_id_o = sys_cluster_id_i; @@ -1462,7 +1452,7 @@ module HMR_wrap import recovery_pkg::*; #( assign core_fetch_en_o = sys_fetch_en_i; assign core_boot_addr_o = sys_boot_addr_i; assign sys_core_busy_o = core_core_busy_i; - + assign core_debug_req_o = sys_debug_req_i; assign core_perf_counters_o = sys_perf_counters_i; diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 9bf2df4d..0244fb2f 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -92,9 +92,7 @@ module hmr_tmr_ctrl #( always_comb begin : proc_fsm tmr_setback_d = 1'b0; tmr_red_mode_d = tmr_red_mode_q; - tmr_incr_mismatches_o[0] = 1'b0; - tmr_incr_mismatches_o[1] = 1'b0; - tmr_incr_mismatches_o[2] = 1'b0; + tmr_incr_mismatches_o = '0; tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; @@ -151,8 +149,9 @@ module hmr_tmr_ctrl #( endcase - // Before core startup: set TMR mode from reg2hw.mode.mode + // Logic to switch in and out of TMR if (!TMRFixed) begin + // 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 tmr_red_mode_d = NON_TMR; @@ -160,7 +159,7 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = TMR_RUN; end end - // split single-error tolerant mode to performance mode anytime (but require correct core state) + // 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 tmr_red_mode_d = NON_TMR; From ee3ede58b25c3902949de0c14a949152d816c66a Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 31 Jan 2023 17:53:30 +0100 Subject: [PATCH 09/66] Add individual dmr controller (separated rapid-recovery) --- Bender.yml | 3 +- rtl/HMR/HMR_wrap.sv | 294 +++++++++++++++++----------------------- rtl/HMR/hmr_dmr_ctrl.sv | 137 +++++++++++++++++++ 3 files changed, 262 insertions(+), 172 deletions(-) create mode 100644 rtl/HMR/hmr_dmr_ctrl.sv diff --git a/Bender.yml b/Bender.yml index f3889ee4..10e0009f 100644 --- a/Bender.yml +++ b/Bender.yml @@ -109,7 +109,7 @@ sources: - rtl/HMR/recovery_pc.sv - rtl/HMR/DMR_checker.sv - rtl/HMR/DMR_address_generator.sv - - rtl/HMR/DMR_controller.sv + # - rtl/HMR/DMR_controller.sv - rtl/HMR/hmr_registers_reg_pkg.sv - rtl/HMR/hmr_core_regs_reg_pkg.sv - rtl/HMR/hmr_dmr_regs_reg_pkg.sv @@ -117,6 +117,7 @@ sources: - rtl/HMR/hmr_registers_reg_top.sv - rtl/HMR/hmr_core_regs_reg_top.sv - rtl/HMR/hmr_dmr_regs_reg_top.sv + - 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 diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 8c8e7b47..b2f57935 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -297,12 +297,15 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumCores-1:0] core_in_dmr; logic [NumCores-1:0] core_in_tmr; + logic [NumDMRGroups-1:0] dmr_setback_q; + logic [NumDMRGroups-1:0] dmr_grp_in_independent; + logic [NumTMRGroups-1:0] tmr_setback_q; logic [NumTMRGroups-1:0] tmr_grp_in_independent; for (genvar i = 0; i < NumCores; i++) begin assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; - assign core_in_dmr[i] = 1'b0; + assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? !dmr_grp_in_independent[dmr_group_id(i)] : '0; assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? !tmr_grp_in_independent[tmr_group_id(i)] : '0; assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); @@ -391,7 +394,6 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumCores-1:0] tmr_incr_mismatches; logic [NumCores-1:0] dmr_incr_mismatches; - assign dmr_incr_mismatches = '0; for (genvar i = 0; i < NumCores; i++) begin hmr_core_regs_reg_top #( @@ -451,17 +453,17 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups hmr_tmr_ctrl #( - .reg_req_t (reg_req_t), - .reg_resp_t (reg_resp_t), - .TMRFixed (TMRFixed), - .InterleaveGrps(InterleaveGrps), - .DefaultInTMR (1'b0) + .reg_req_t ( reg_req_t ), + .reg_resp_t ( reg_resp_t ), + .TMRFixed ( TMRFixed ), + .InterleaveGrps ( InterleaveGrps ), + .DefaultInTMR ( 1'b0 ) ) i_tmr_ctrl ( .clk_i, .rst_ni, - .reg_req_i ( tmr_register_reqs[i]), - .reg_resp_o ( tmr_register_resps[i]), + .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 ), @@ -486,7 +488,7 @@ module HMR_wrap import recovery_pkg::*; #( ); assign tmr_failure[i] = tmr_data_req_out[i] ? - tmr_failure_main | tmr_failure_data : tmr_failure_main; + tmr_failure_main[i] | tmr_failure_data[i] : tmr_failure_main[i]; assign tmr_error[i] = tmr_data_req_out[i] ? tmr_error_main[i] | tmr_error_data[i] : tmr_error_main[i]; assign tmr_single_mismatch[i] = tmr_error[i] != 3'b000; @@ -546,7 +548,6 @@ module HMR_wrap import recovery_pkg::*; #( assign top_register_resps[3].ready = 1'b1; assign tmr_incr_mismatches = '0; assign tmr_grp_in_independent = '0; - assign core_in_tmr = '0; assign tmr_setback_q = '0; assign tmr_resynch_req_o = '0; end @@ -563,43 +564,68 @@ module HMR_wrap import recovery_pkg::*; #( & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; end - /****************** - * DMR Controller * - ******************/ - DMR_controller #( - .NumCores ( NumCores ), - .DMRFixed ( DMRFixed ), - .RapidRecovery ( RapidRecovery ), - .RFAddrWidth ( RFAddrWidth ) - ) dmr_controller ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .dmr_rf_checker_error_port_a_i ( backup_regfile_error_a ), - .dmr_rf_checker_error_port_b_i ( backup_regfile_error_b ), - .dmr_core_checker_error_main_i ( dmr_failure_main ), - .dmr_core_checker_error_data_i ( dmr_failure_data ), - .backup_regfile_write_i ( backup_regfile_wport_in ), - .core_recovery_regfile_wport_o ( core_recovery_regfile_wport_out ), - .regfile_readback_o ( regfile_readback_out ), - .regfile_raddr_o ( core_regfile_raddr_out ), - .dmr_ctrl_core_debug_req_o ( dmr_ctrl_core_debug_req_out ), - .dmr_ctrl_core_debug_rsp_i ( dmr_ctrl_core_debug_halted_in ), - .dmr_ctrl_core_instr_lock_o ( dmr_ctrl_core_instr_lock_out ), - .dmr_ctrl_core_setback_o ( dmr_ctrl_core_setback_out ), - .dmr_ctrl_core_recover_o ( dmr_ctrl_core_recover_out ), - .dmr_ctrl_core_debug_resume_o ( dmr_ctrl_debug_resume_out ), - .dmr_ctrl_pc_read_enable_o ( dmr_ctrl_pc_read_enable_out ), - .dmr_ctrl_pc_write_enable_o ( dmr_ctrl_pc_write_enable_out ), - .dmr_ctrl_core_clk_en_o ( dmr_ctrl_core_clk_en_out ) - ); - if (DMRSupported || DMRFixed) begin: gen_dmr_recovery_region + + 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_resp_t [NumDMRGroups-1:0] dmr_register_resps; + + localparam DMRSelWidth = $clog2(NumDMRGroups); + + /*************** + * Registers * + ***************/ + reg_demux #( + .NoPorts ( NumDMRGroups ), + .req_t ( reg_req_t ), + .rsp_t ( reg_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 ) + ); + + for (genvar i = NumDMRCores; i < NumCores; i++) begin : gen_extra_core_assigns + assign dmr_incr_mismatches[i] = '0; + end + for (genvar i = 0; i < NumDMRGroups; i++) begin - assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main | dmr_failure_data) - : dmr_failure_main; - // assign dmr_error [i*2+:2] = dmr_data_req_out [i] ? (dmr_error_main [i*2+:2] | dmr_error_data [i*2+:2]) - // : dmr_error_main [i*2+:2]; - // assign dmr_single_mismatch [i] = dmr_error [i*2+:2] != 3'b000; + + hmr_dmr_ctrl #( + .reg_req_t ( reg_req_t ), + .reg_resp_t ( reg_resp_t ), + .InterleaveGrps( InterleaveGrps ), + .DMRFixed ( DMRFixed ), + .RapidRecovery ( RapidRecovery ), + .DefaultInDMR ( 1'b0 ) + ) i_dmr_ctrl ( + .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 ), + + .setback_o ( dmr_setback_q[i] ), + .sw_resynch_req_o ( dmr_resynch_req_o[i] ), + .grp_in_independent_o ( dmr_grp_in_independent[i] ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), + .dmr_error_i ( dmr_failure[i] ), + + .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), + .cores_synch_i ( dmr_cores_synch_i[i] ), + + .recovery_request_o (), + .recovery_finished_i () + ); /********************* * DMR Core Checkers * @@ -702,73 +728,17 @@ module HMR_wrap import recovery_pkg::*; #( assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b & ~backup_regfile_error_b [i] & ~dmr_ctrl_core_recover_out [i]; - /**************************** - * Recovery Program Counter * - ****************************/ - recovery_pc #( - .ECCEnabled ( 1 ) - ) RPC ( - // Control Ports - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clear_i ( '0 ), - .read_enable_i ( dmr_ctrl_pc_read_enable_out [i] ), - .write_enable_i ( ~backup_program_counter_error [i] - & dmr_ctrl_pc_write_enable_out [i] ), - // Backup Ports - .backup_program_counter_i ( backup_program_counter_int [i] ), - .backup_branch_i ( backup_branch_int [i] ), - .backup_branch_addr_i ( backup_branch_addr_i [i] ), - // Recovery Pors - .recovery_program_counter_o ( recovery_program_counter_out [i] ), - .recovery_branch_o ( recovery_branch_out [i] ), - .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) - ); - - /*************************** - * Recovery Register Files * - ***************************/ - recovery_rf #( - .ECCEnabled ( 1 ), - .ADDR_WIDTH ( RFAddrWidth ) - ) RRF ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .test_en_i ( '0 ), - //Read port A - .raddr_a_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_a ), - .rdata_a_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_a ), - //Read port B - .raddr_b_i ( core_recovery_regfile_wport_out[dmr_core_id(i, 0)].waddr_b ), - .rdata_b_o ( core_recovery_regfile_rdata_out[dmr_core_id(i, 0)].rdata_b ), - //Read port C - .raddr_c_i ( '0 ), - .rdata_c_o ( ), - // Write Port A - .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), - .wdata_a_i ( backup_regfile_wdata_a [i] ), - .we_a_i ( backup_regfile_we_a [i] ), - // Write Port B - .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), - .wdata_b_i ( backup_regfile_wdata_b [i] ), - .we_b_i ( backup_regfile_we_b [i] ) - ); + end else begin - + assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) + : dmr_failure_main[i]; end end - // if (NumDMRLeftover > 0) begin : gen_dmr_leftover_error - // assign dmr_error_main[NumCores-1-:NumDMRLeftover] = '0; - // assign dmr_error_data[NumCores-1-:NumDMRLeftover] = '0; - // assign dmr_error [NumCores-1-:NumDMRLeftover] = '0; - // end end else begin: no_dmr_checkers - // assign dmr_error_main = '0; - // assign dmr_error_data = '0; - // assign dmr_error = '0; assign dmr_failure_main = '0; assign dmr_failure_data = '0; assign dmr_failure = '0; + assign dmr_incr_mismatches = '0; assign main_dmr_out = '0; assign data_dmr_out = '0; assign {dmr_core_busy_out, dmr_irq_ack_out , dmr_irq_ack_id_out, @@ -781,6 +751,36 @@ module HMR_wrap import recovery_pkg::*; #( assign top_register_resps[2].ready = 1'b1; end + // RapidRecovery output signals + if (RapidRecovery) begin : gen_rapid_recovery + // TODO: + end else begin : gen_sw_recovery + for (genvar i = 0; i < NumCores; i++) begin : gen_cores + // Temporary disable of RapidRecovery + assign core_debug_resume_o [i] = '0; + + // Setback + assign core_recover_o [i] = '0; + assign core_instr_lock_o [i] = '0; + + // PC + assign pc_recover_o [i] = '0; + assign recovery_program_counter_o [i] = '0; + assign recovery_branch_o [i] = '0; + assign recovery_branch_addr_o [i] = '0; + + // RF + assign dmr_rf_readback_o [i] = '0; + assign core_regfile_raddr_o [i] = '0; + assign core_recovery_regfile_wport_o[i].we_a = '0; + assign core_recovery_regfile_wport_o[i].waddr_a = '0; + assign core_recovery_regfile_wport_o[i].wdata_a = '0; + assign core_recovery_regfile_wport_o[i].we_b = '0; + assign core_recovery_regfile_wport_o[i].waddr_b = '0; + assign core_recovery_regfile_wport_o[i].wdata_b = '0; + end + end + // Assign output signals if (DMRSupported && TMRSupported) begin : gen_full_HMR /***************** @@ -1005,29 +1005,6 @@ module HMR_wrap import recovery_pkg::*; #( *** TMR only *** *****************/ for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - // Temporary disable of RapidRecovery - assign core_debug_resume_o [i] = '0; - - // Setback - assign core_recover_o [i] = '0; - assign core_instr_lock_o [i] = '0; - - // PC - assign pc_recover_o [i] = '0; - assign recovery_program_counter_o [i] = '0; - assign recovery_branch_o [i] = '0; - assign recovery_branch_addr_o [i] = '0; - - // RF - assign dmr_rf_readback_o [i] = '0; - assign core_regfile_raddr_o [i] = '0; - assign core_recovery_regfile_wport_o[i].we_a = '0; - assign core_recovery_regfile_wport_o[i].waddr_a = '0; - assign core_recovery_regfile_wport_o[i].wdata_a = '0; - assign core_recovery_regfile_wport_o[i].we_b = '0; - assign core_recovery_regfile_wport_o[i].waddr_b = '0; - assign core_recovery_regfile_wport_o[i].wdata_b = '0; - localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode @@ -1214,7 +1191,7 @@ module HMR_wrap import recovery_pkg::*; #( // Binding DMR outputs to zero for now assign dmr_failure_o = '0; assign dmr_error_o = '0; - assign dmr_resynch_req_o = '0; + // assign dmr_resynch_req_o = '0; for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); @@ -1225,19 +1202,30 @@ module HMR_wrap import recovery_pkg::*; #( core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] + if (RapidRecovery) begin + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] & dmr_ctrl_core_clk_en_out[SysGroupId]; + end else begin + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; + end core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; - core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + + if (RapidRecovery) begin + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] | dmr_ctrl_core_debug_req_out [SysGroupId]; - core_debug_resume_o [i] = dmr_ctrl_debug_resume_out [SysGroupId]; + end else begin + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; + end core_perf_counters_o[i] = sys_perf_counters_i [SysCoreIndex]; // Setback - core_setback_o [i] = dmr_ctrl_core_setback_out [SysGroupId]; - core_recover_o [i] = dmr_ctrl_core_recover_out [SysGroupId]; + if (RapidRecovery) begin + core_setback_o [i] = dmr_ctrl_core_setback_out [SysGroupId]; + end else begin + core_setback_o [i] = '0; + end // IRQ core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; @@ -1248,7 +1236,6 @@ module HMR_wrap import recovery_pkg::*; #( core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; core_instr_r_valid_o[i] = sys_instr_r_valid_i [SysCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; - core_instr_lock_o [i] = dmr_ctrl_core_instr_lock_out [SysGroupId]; // DATA core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; @@ -1258,22 +1245,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; - // PC - pc_recover_o [i] = dmr_ctrl_pc_read_enable_out [SysCoreIndex]; - recovery_program_counter_o [i] = recovery_program_counter_out [SysCoreIndex]; - recovery_branch_o [i] = recovery_branch_out [SysCoreIndex]; - recovery_branch_addr_o [i] = recovery_branch_addr_out [SysCoreIndex]; - - // RF - dmr_rf_readback_o [i] = regfile_readback_out [SysCoreIndex]; - core_regfile_raddr_o [i] = core_regfile_raddr_out [SysCoreIndex]; - core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[SysCoreIndex].we_a; - core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[SysCoreIndex].waddr_a; - core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_a; - core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[SysCoreIndex].we_b; - core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[SysCoreIndex].waddr_b; - core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[SysCoreIndex].rdata_b; - end else begin : gen_independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1284,12 +1255,10 @@ module HMR_wrap import recovery_pkg::*; #( core_boot_addr_o [i] = sys_boot_addr_i [i]; core_debug_req_o [i] = sys_debug_req_i [i]; - core_debug_resume_o [i] = '0; core_perf_counters_o[i] = sys_perf_counters_i[i]; // Setback core_setback_o [i] = '0; - core_recover_o [i] = '0; // IRQ core_irq_req_o [i] = sys_irq_req_i [i]; @@ -1300,7 +1269,6 @@ module HMR_wrap import recovery_pkg::*; #( core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; core_instr_err_o [i] = sys_instr_err_i [i]; - core_instr_lock_o [i] = '0; // DATA core_data_gnt_o [i] = sys_data_gnt_i [i]; @@ -1309,22 +1277,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; - - // PC - pc_recover_o [i] = '0; - recovery_program_counter_o [i] = '0; - recovery_branch_o [i] = '0; - recovery_branch_addr_o [i] = '0; - - // RF - dmr_rf_readback_o [i] = '0; - core_regfile_raddr_o [i] = '0; - core_recovery_regfile_wport_o[i].we_a = '0; - core_recovery_regfile_wport_o[i].waddr_a = '0; - core_recovery_regfile_wport_o[i].wdata_a = '0; - core_recovery_regfile_wport_o[i].we_b = '0; - core_recovery_regfile_wport_o[i].waddr_b = '0; - core_recovery_regfile_wport_o[i].wdata_b = '0; end end end // gen_core_inputs diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv new file mode 100644 index 00000000..1ed809d0 --- /dev/null +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -0,0 +1,137 @@ +// Copyright 2023 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. +// +// Hybrid modular redundancy DMR control unit + +module hmr_dmr_ctrl import recovery_pkg::*; #( + parameter bit InterleaveGrps = 1'b0, + 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 +) ( + 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, + + // CTRL from external (e.g. HMR ctrl regs) + input logic dmr_enable_q_i, + input logic dmr_enable_qe_i, + + // DMR control signals + output logic setback_o, + output logic sw_resynch_req_o, + output logic grp_in_independent_o, + output logic [1:0] dmr_incr_mismatches_o, + input logic dmr_error_i, + output logic recovery_request_o, + input logic recovery_finished_i, + + input logic fetch_en_i, + input logic cores_synch_i +); + + 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; + + dmr_mode_e dmr_red_mode_d, dmr_red_mode_q; + logic dmr_setback_d, dmr_setback_q; + + assign setback_o = dmr_setback_q; + assign grp_in_independent_o = dmr_red_mode_q == NON_DMR; + + hmr_dmr_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 (dmr_reg2hw), + .hw2reg (dmr_hw2reg), + .devmode_i('0) + ); + + // Global config update + assign dmr_hw2reg.dmr_enable.de = dmr_enable_qe_i; + assign dmr_hw2reg.dmr_enable.d = dmr_enable_q_i; + + /************************** + * FSM for DMR lockstep * + **************************/ + + always_comb begin : proc_fsm + dmr_setback_d = 1'b0; + dmr_red_mode_d = dmr_red_mode_q; + dmr_incr_mismatches_o = '0; + + case (dmr_red_mode_q) + DMR_RUN: begin + // If error detected, restore + if (dmr_error_i && RapidRecovery) begin + dmr_red_mode_d = DMR_RESTORE; + recovery_request_o = 1'b1; + end + end + + DMR_RESTORE: begin + if (recovery_finished_i) begin + dmr_red_mode_d = DMR_RUN; + end + end + + // Default: do nothing + endcase + + // Logic to switch in and out of DMR + if (!DMRFixed) begin + // 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 + dmr_red_mode_d = NON_DMR; + end else begin + dmr_red_mode_d = DMR_RUN; + end + 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 + dmr_red_mode_d = NON_DMR; + end + end + // Set DMR mode on external signal that cores are synchronized + if (dmr_red_mode_q == NON_DMR && cores_synch_i) begin + if (dmr_reg2hw.dmr_enable.q == 1'b1) begin + dmr_red_mode_d = DMR_RUN; + end + end + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode + if(!rst_ni) begin + dmr_red_mode_q <= DefaultDMRMode; + dmr_setback_q <= '0; + end else begin + dmr_red_mode_q <= dmr_red_mode_d; + dmr_setback_q <= dmr_setback_d; + end + end + +endmodule From 5fe050ea5a0af2e1dd0788b895f493677e7009b0 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 31 Jan 2023 18:38:30 +0100 Subject: [PATCH 10/66] Add dmr and rapid-recovery configuration registers Start adding rapid_recovery --- Bender.yml | 1 + rtl/HMR/HMR_dmr_regs.hjson | 8 +- rtl/HMR/HMR_regs.hjson | 32 ++- rtl/HMR/HMR_tmr_regs.hjson | 4 + rtl/HMR/HMR_wrap.sv | 372 ++++++++++++++++++++++------- rtl/HMR/doc.html | 33 ++- rtl/HMR/hmr_dmr.h | 3 +- rtl/HMR/hmr_dmr_ctrl.sv | 18 ++ rtl/HMR/hmr_dmr_regs_reg_pkg.sv | 28 ++- rtl/HMR/hmr_dmr_regs_reg_top.sv | 62 +++-- rtl/HMR/hmr_global.h | 11 +- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 140 +++++++++++ rtl/HMR/hmr_registers_reg_pkg.sv | 64 +++-- rtl/HMR/hmr_registers_reg_top.sv | 127 ++++++++-- rtl/HMR/hmr_tmr.h | 3 +- rtl/HMR/hmr_tmr_ctrl.sv | 9 +- rtl/HMR/hmr_tmr_regs_reg_pkg.sv | 16 +- rtl/HMR/hmr_tmr_regs_reg_top.sv | 39 ++- 18 files changed, 809 insertions(+), 161 deletions(-) create mode 100644 rtl/HMR/hmr_rapid_recovery_ctrl.sv diff --git a/Bender.yml b/Bender.yml index 10e0009f..bc388634 100644 --- a/Bender.yml +++ b/Bender.yml @@ -110,6 +110,7 @@ sources: - rtl/HMR/DMR_checker.sv - rtl/HMR/DMR_address_generator.sv # - rtl/HMR/DMR_controller.sv + - rtl/HMR/hmr_rapid_recovery_ctrl.sv - rtl/HMR/hmr_registers_reg_pkg.sv - rtl/HMR/hmr_core_regs_reg_pkg.sv - rtl/HMR/hmr_dmr_regs_reg_pkg.sv diff --git a/rtl/HMR/HMR_dmr_regs.hjson b/rtl/HMR/HMR_dmr_regs.hjson index dcf54459..682c4b5b 100644 --- a/rtl/HMR/HMR_dmr_regs.hjson +++ b/rtl/HMR/HMR_dmr_regs.hjson @@ -31,8 +31,12 @@ hwqe: "true", fields: [ { bits: "0", - name: "todo", - desc: "TODO" + 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)." } ] }, diff --git a/rtl/HMR/HMR_regs.hjson b/rtl/HMR/HMR_regs.hjson index 30b98a8c..fb02cebc 100644 --- a/rtl/HMR/HMR_regs.hjson +++ b/rtl/HMR/HMR_regs.hjson @@ -40,6 +40,10 @@ { bits: "2", name: "triple", desc: "Triple Modular Redundancy (TMR) is available." + }, + { bits: "8", + name: "rapid_recovery", + desc: "Rapid Recovery is available." } ] }, @@ -83,13 +87,23 @@ } ] }, - # { name: "DMR_config", - # desc: "DMR configuration bits." - # swaccess: "rw", - # hwaccess: "hrw", - # hwqe: "true", - # fields: [] - # }, + { 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", @@ -113,6 +127,10 @@ 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 index ec01dad2..e01825b9 100644 --- a/rtl/HMR/HMR_tmr_regs.hjson +++ b/rtl/HMR/HMR_tmr_regs.hjson @@ -46,6 +46,10 @@ 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_wrap.sv b/rtl/HMR/HMR_wrap.sv index b2f57935..81ac22cf 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -68,22 +68,25 @@ module HMR_wrap import recovery_pkg::*; #( output logic [NumDMRGroups-1:0] dmr_failure_o , output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? output logic [NumDMRGroups-1:0] dmr_resynch_req_o, - output logic [ NumCores-1:0] dmr_rf_readback_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, // Backup Port from Cores'Program Counter - input logic [ NumCores-1:0][DataWidth-1:0] backup_program_counter_i, - output logic [ NumCores-1:0] pc_recover_o, - output logic [ NumCores-1:0][DataWidth-1:0] recovery_program_counter_o, - input logic [ NumCores-1:0] backup_branch_i, - input logic [ NumCores-1:0][DataWidth-1:0] backup_branch_addr_i, - output logic [ NumCores-1:0] recovery_branch_o, - output logic [ NumCores-1:0][DataWidth-1:0] recovery_branch_addr_o, + input logic [ NumCores-1:0][DataWidth-1:0] backup_program_counter_i, + output logic [ NumCores-1:0] pc_recover_o, + output logic [ NumCores-1:0][DataWidth-1:0] recovery_program_counter_o, + input logic [ NumCores-1:0] backup_branch_i, + input logic [ NumCores-1:0][DataWidth-1:0] backup_branch_addr_i, + output logic [ NumCores-1:0] recovery_branch_o, + output logic [ NumCores-1:0][DataWidth-1:0] recovery_branch_addr_o, // Backup ports from Cores' RFs - input regfile_write_t [ NumCores-1:0] backup_regfile_wport_i, - output regfile_raddr_t [ NumSysCores-1:0] core_regfile_raddr_o, - output regfile_write_t [ NumSysCores-1:0] core_recovery_regfile_wport_o, - // TODO other required signals + input regfile_write_t [NumCores-1:0] backup_regfile_wport_i, + output regfile_raddr_t [NumCores-1:0] core_regfile_raddr_o, + output regfile_write_t [NumCores-1:0] core_recovery_regfile_wport_o, + // Nonstandard core control signals + output logic [ NumCores-1:0] core_setback_o , + output logic [ NumCores-1:0] core_instr_lock_o , + output logic [ NumCores-1:0] core_recover_o , + output logic [ NumCores-1:0] core_debug_resume_o , // Ports connecting to System input logic [NumSysCores-1:0][ 3:0] sys_core_id_i , @@ -124,9 +127,6 @@ module HMR_wrap import recovery_pkg::*; #( input logic [NumSysCores-1:0][NumExtPerf-1:0] sys_perf_counters_i, // Ports connecting to the cores - output logic [ NumCores-1:0] core_setback_o , - output logic [ NumCores-1:0] core_recover_o , - output logic [ NumCores-1:0][ 3:0] core_core_id_o , output logic [ NumCores-1:0][ 5:0] core_cluster_id_o , @@ -145,11 +145,9 @@ module HMR_wrap import recovery_pkg::*; #( input logic [ NumCores-1:0][ 31:0] core_instr_addr_i , output logic [ NumCores-1:0][InstrDataWidth-1:0] core_instr_r_rdata_o, output logic [ NumCores-1:0] core_instr_r_valid_o, - output logic [ NumCores-1:0] core_instr_lock_o , output logic [ NumCores-1:0] core_instr_err_o , output logic [ NumCores-1:0] core_debug_req_o , - output logic [ NumCores-1:0] core_debug_resume_o , input logic [ NumCores-1:0] core_debug_halted_i , input logic [ NumCores-1:0] core_data_req_i , @@ -180,6 +178,11 @@ module HMR_wrap import recovery_pkg::*; #( else return (group_id * 3) + core_offset; endfunction + function int tmr_shared_id (int group_id); + if (InterleaveGrps) return group_id; + else return group_id + group_id/2; + endfunction + function int dmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumDMRGroups; else return (core_id/2); @@ -190,6 +193,10 @@ module HMR_wrap import recovery_pkg::*; #( else return (group_id * 2) + core_offset; endfunction + function int dmr_shared_id(int group_id); + return group_id; + endfunction + if (TMRFixed && DMRFixed) $fatal(1, "Cannot fix both TMR and DMR!"); localparam int unsigned CtrlConcatWidth = 1 + 1 + 5 + 1 + 32 + 1; @@ -199,6 +206,8 @@ module HMR_wrap import recovery_pkg::*; #( localparam int unsigned MainConcatWidth = SeparateData ? CtrlConcatWidth : CtrlConcatWidth + DataConcatWidth; + let max(a,b) = (a > b) ? a : b; + localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); localparam int unsigned RFAddrWidth = 6; logic [ NumCores-1:0][MainConcatWidth-1:0] main_concat_in; @@ -241,37 +250,39 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumDMRGroups-1:0][ UserWidth-1:0] dmr_data_user_out; logic [NumDMRGroups-1:0][ BeWidth-1:0] dmr_data_be_out; - logic [NumDMRGroups-1:0][ DataWidth-1:0] backup_branch_addr_int, - recovery_branch_addr_out, - backup_program_counter_int, - recovery_program_counter_out, - backup_regfile_wdata_a, - backup_regfile_wdata_b; - logic [NumDMRGroups-1:0] backup_branch_int, - recovery_branch_out, - backup_program_counter_error, - dmr_ctrl_pc_read_enable_out, - dmr_ctrl_pc_write_enable_out, - dmr_ctrl_core_clk_en_out, - backup_regfile_we_a, - backup_regfile_we_b, - backup_regfile_error_a, - backup_regfile_error_b, - backup_branch_error, - backup_branch_addr_error, - regfile_readback_out, - dmr_ctrl_core_rstn_out, - dmr_ctrl_core_debug_req_out, - dmr_ctrl_core_debug_halted_in, - dmr_ctrl_core_instr_lock_out, - dmr_ctrl_core_setback_out, - dmr_ctrl_core_recover_out, - dmr_ctrl_debug_resume_out; - logic intruder_lock; - - regfile_raddr_t [NumDMRGroups-1:0] core_regfile_raddr_out; - regfile_rdata_t [NumDMRGroups-1:0] core_recovery_regfile_rdata_out; - regfile_write_t [NumDMRGroups-1:0] backup_regfile_wport_in, + + logic [ NumDMRGroups-1:0][ DataWidth-1:0] dmr_backup_program_counter; + logic [ NumTMRGroups-1:0][ DataWidth-1:0] tmr_backup_program_counter; + logic [NumBackupRegfiles-1:0][ DataWidth-1:0] backup_branch_addr_int, + recovery_branch_addr_out, + backup_program_counter_int, + recovery_program_counter_out, + backup_regfile_wdata_a, + backup_regfile_wdata_b; + logic [NumBackupRegfiles-1:0] backup_branch_int, + recovery_branch_out, + backup_program_counter_error, + backup_pc_enable_out, // dmr_ctrl_pc_read_enable_out, + recovery_pc_enable_out, // dmr_ctrl_pc_write_enable_out, + // dmr_ctrl_core_clk_en_out, + backup_regfile_we_a, + backup_regfile_we_b, + backup_regfile_error_a, + backup_regfile_error_b, + backup_branch_error, + backup_branch_addr_error, + // regfile_readback_out, + // dmr_ctrl_core_rstn_out, + recovery_debug_req_out, // dmr_ctrl_core_debug_req_out, + recovery_debug_halted_in, // dmr_ctrl_core_debug_halted_in, + recovery_instr_lock_out, // dmr_ctrl_core_instr_lock_out, + recovery_setback_out, // dmr_ctrl_core_setback_out, + recovery_trigger_out, // dmr_ctrl_core_recover_out, // TODO: for regfile only?!? + recovery_debug_resume_out; // dmr_ctrl_debug_resume_out; + + regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; + regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; + regfile_write_t [NumBackupRegfiles-1:0] backup_regfile_wport_in, core_recovery_regfile_wport_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat @@ -296,19 +307,25 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumCores-1:0] core_in_independent; logic [NumCores-1:0] core_in_dmr; logic [NumCores-1:0] core_in_tmr; + logic [NumCores-1:0] dmr_core_rapid_recovery_en; + logic [NumCores-1:0] tmr_core_rapid_recovery_en; logic [NumDMRGroups-1:0] dmr_setback_q; logic [NumDMRGroups-1:0] dmr_grp_in_independent; + logic [NumDMRGroups-1:0] dmr_rapid_recovery_en; logic [NumTMRGroups-1:0] tmr_setback_q; logic [NumTMRGroups-1:0] tmr_grp_in_independent; + logic [NumTMRGroups-1:0] tmr_rapid_recovery_en; for (genvar i = 0; i < NumCores; i++) begin assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; - assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? !dmr_grp_in_independent[dmr_group_id(i)] : '0; - assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? !tmr_grp_in_independent[tmr_group_id(i)] : '0; + assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; + assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? ~tmr_grp_in_independent[tmr_group_id(i)] : '0; assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); + assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && i < NumDMRCores && RapidRecovery ? dmr_rapid_recovery_en[dmr_group_id(i)] : '0; + assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && i < NumTMRCores && RapidRecovery ? tmr_rapid_recovery_en[tmr_group_id(i)] : '0; end reg_req_t [3:0] top_register_reqs; @@ -354,19 +371,26 @@ module HMR_wrap import recovery_pkg::*; #( 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 hmr_hw2reg.cores_en.d = '0; hmr_hw2reg.cores_en.d = core_en_as_master; - end - assign hmr_hw2reg.dmr_enable.d = '0; - assign hmr_hw2reg.tmr_enable.d = '0; + 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; + 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; // Core Config Registers @@ -473,12 +497,15 @@ module HMR_wrap import recovery_pkg::*; #( .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 ), .setback_o ( tmr_setback_q[i] ), .sw_resynch_req_o ( tmr_resynch_req_o[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), + .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), .tmr_single_mismatch_i( tmr_single_mismatch[i] ), .tmr_error_i ( tmr_error[i] ), @@ -488,9 +515,11 @@ module HMR_wrap import recovery_pkg::*; #( ); assign tmr_failure[i] = tmr_data_req_out[i] ? - tmr_failure_main[i] | tmr_failure_data[i] : tmr_failure_main[i]; - assign tmr_error[i] = tmr_data_req_out[i] ? - tmr_error_main[i] | tmr_error_data[i] : tmr_error_main[i]; + tmr_failure_main[i] | tmr_failure_data[i] : + tmr_failure_main[i]; + assign tmr_error[i] = tmr_data_req_out[i] ? + tmr_error_main[i] | tmr_error_data[i] : + tmr_error_main[i]; assign tmr_single_mismatch[i] = tmr_error[i] != 3'b000; bitwise_TMR_voter #( @@ -555,12 +584,14 @@ module HMR_wrap import recovery_pkg::*; #( /************************************************************ ******************** DMR Voters and Regs ******************* ************************************************************/ - for (genvar i = 0; i < NumCores; i++) begin + for (genvar i = 0; i < NumBackupRegfiles; i++) begin + // TODO fix assignment assign backup_regfile_wport_in [i] = backup_regfile_wport_i [dmr_core_id(dmr_group_id(i), 0)]; end for (genvar i = 0; i < NumDMRGroups; i++) begin - assign dmr_ctrl_core_debug_halted_in [i] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] + // TODO fix assignment + assign recovery_debug_halted_in [i] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; end @@ -608,23 +639,28 @@ module HMR_wrap import recovery_pkg::*; #( .clk_i, .rst_ni, - .reg_req_i ( dmr_register_reqs[i] ), - .reg_resp_o ( dmr_register_resps[i] ), + .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 ), + .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 ), - .setback_o ( dmr_setback_q[i] ), - .sw_resynch_req_o ( dmr_resynch_req_o[i] ), - .grp_in_independent_o ( dmr_grp_in_independent[i] ), - .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), - .dmr_error_i ( dmr_failure[i] ), + .setback_o ( dmr_setback_q[i] ), + .sw_resynch_req_o ( dmr_resynch_req_o[i] ), + .grp_in_independent_o ( dmr_grp_in_independent[i] ), + .rapid_recovery_en_o ( dmr_rapid_recovery_en[i] ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), + .dmr_error_i ( dmr_failure[i] ), - .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), - .cores_synch_i ( dmr_cores_synch_i[i] ), + .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), + .cores_synch_i ( dmr_cores_synch_i[i] ), - .recovery_request_o (), - .recovery_finished_i () + .recovery_request_o (), + .recovery_finished_i () ); /********************* @@ -665,6 +701,14 @@ module HMR_wrap import recovery_pkg::*; #( if (RapidRecovery) begin + assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) + : dmr_failure_main[i]) | + backup_program_counter_error[i] | + backup_branch_error [i] | + backup_branch_addr_error [i] | + backup_regfile_error_a [i] | + backup_regfile_error_b [i]; + /****************** * DMR PC Checker * ******************/ @@ -673,7 +717,7 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_pc_checker ( .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), - .check_o ( backup_program_counter_int [i] ), + .check_o ( dmr_backup_program_counter[i] ), .error_o ( backup_program_counter_error [i] ) ); @@ -724,10 +768,10 @@ module HMR_wrap import recovery_pkg::*; #( assign backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a & ~backup_regfile_error_a [i] - & ~dmr_ctrl_core_recover_out [i]; + & ~recovery_trigger_out [i]; assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b & ~backup_regfile_error_b [i] - & ~dmr_ctrl_core_recover_out [i]; + & ~recovery_trigger_out [i]; end else begin assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) @@ -753,10 +797,173 @@ module HMR_wrap import recovery_pkg::*; #( // RapidRecovery output signals if (RapidRecovery) begin : gen_rapid_recovery + for (genvar i = 0; i < NumBackupRegfiles; i++) begin + hmr_rapid_recovery_ctrl #( + .RFAddrWidth( RFAddrWidth ) + ) i_rapid_recovery_ctrl ( + .clk_i, + .rst_ni, + .start_recovery_i (), + .recovery_finished_o (), + .setback_o ( recovery_setback_out [i] ), + .instr_lock_o ( recovery_instr_lock_out [i] ), + .debug_req_o ( recovery_debug_req_out [i] ), + .debug_halt_i ( recovery_debug_halted_in [i] ), + .debug_resume_o ( recovery_debug_resume_out [i] ), + .recovery_regfile_waddr_o ( core_recovery_regfile_wport_out[i] ), + .backup_pc_enable_o ( backup_pc_enable_out [i] ), + .recover_pc_enable_o ( recovery_pc_enable_out [i] ), + .recover_rf_enable_o ( recovery_trigger_out [i] ) + ); + + /**************************** + * Recovery Program Counter * + ****************************/ + recovery_pc #( + .ECCEnabled ( 1 ) + ) RPC ( + // Control Ports + .clk_i, + .rst_ni, + .clear_i ( '0 ), + .read_enable_i ( backup_pc_enable_out [i] ), + .write_enable_i ( ~backup_program_counter_error [i] + & recovery_pc_enable_out [i] ), + // Backup Ports + .backup_program_counter_i ( backup_program_counter_int [i] ), + .backup_branch_i ( backup_branch_int [i] ), + .backup_branch_addr_i ( backup_branch_addr_i [i] ), + // Recovery Pors + .recovery_program_counter_o ( recovery_program_counter_out [i] ), + .recovery_branch_o ( recovery_branch_out [i] ), + .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) + ); + + /*************************** + * Recovery Register Files * + ***************************/ + recovery_rf #( + .ECCEnabled ( 1 ), + .ADDR_WIDTH ( RFAddrWidth ) + ) RRF ( + .clk_i, + .rst_ni, + .test_en_i ( '0 ), + //Read port A + .raddr_a_i ( core_recovery_regfile_wport_out[i].waddr_a ), + .rdata_a_o ( core_recovery_regfile_rdata_out[i].rdata_a ), + //Read port B + .raddr_b_i ( core_recovery_regfile_wport_out[i].waddr_b ), + .rdata_b_o ( core_recovery_regfile_rdata_out[i].rdata_b ), + //Read port C + .raddr_c_i ( '0 ), + .rdata_c_o ( ), + // Write Port A + .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), + .wdata_a_i ( backup_regfile_wdata_a [i] ), + .we_a_i ( backup_regfile_we_a [i] ), + // Write Port B + .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), + .wdata_b_i ( backup_regfile_wdata_b [i] ), + .we_b_i ( backup_regfile_we_b [i] ) + ); + + end + + + always_comb begin + backup_program_counter_int = '0; + + for (int i = 0; i < NumDMRGroups; i++) begin + if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin + backup_program_counter_int[dmr_shared_id(i)] = dmr_backup_program_counter[i]; + end + end + + for (int i = 0; i < NumTMRGroups; i++) begin + if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin + backup_program_counter_int[tmr_shared_id(i)] = tmr_backup_program_counter[i]; + end + end + end + + for (genvar i = 0; i < NumCores; i++) begin : gen_cores + always_comb begin + if ((DMRFixed || (DMRSupported && core_in_dmr[i])) && dmr_core_rapid_recovery_en[i]) begin + + core_debug_resume_o [i] = recovery_debug_resume_out [dmr_shared_id(dmr_group_id(i))]; + + // Setback + core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; + + // PC + pc_recover_o [i] = backup_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; + recovery_program_counter_o [i] = recovery_program_counter_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [dmr_shared_id(dmr_group_id(i))]; + + // RF + core_regfile_raddr_o [i] = core_regfile_raddr_out [dmr_shared_id(dmr_group_id(i))]; + core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_a; + core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_a; + core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_a; + core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_b; + core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_b; + core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_b; + + end else if ((TMRFixed || (TMRSupported && core_in_tmr[i])) && tmr_core_rapid_recovery_en[i]) begin + core_debug_resume_o [i] = recovery_debug_resume_out [tmr_shared_id(tmr_group_id(i))]; + + // Setback + core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; + + // PC + pc_recover_o [i] = backup_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; + recovery_program_counter_o [i] = recovery_program_counter_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [tmr_shared_id(tmr_group_id(i))]; + + // RF + core_regfile_raddr_o [i] = core_regfile_raddr_out [tmr_shared_id(tmr_group_id(i))]; + core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_a; + core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_a; + core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_a; + core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_b; + core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_b; + core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_b; + + end else begin + // Disable RapidRecovery + core_debug_resume_o [i] = '0; + + // Setback + core_recover_o [i] = '0; + core_instr_lock_o [i] = '0; + + // PC + pc_recover_o [i] = '0; + recovery_program_counter_o [i] = '0; + recovery_branch_o [i] = '0; + recovery_branch_addr_o [i] = '0; + + // RF + core_regfile_raddr_o [i] = '0; + core_recovery_regfile_wport_o[i].we_a = '0; + core_recovery_regfile_wport_o[i].waddr_a = '0; + core_recovery_regfile_wport_o[i].wdata_a = '0; + core_recovery_regfile_wport_o[i].we_b = '0; + core_recovery_regfile_wport_o[i].waddr_b = '0; + core_recovery_regfile_wport_o[i].wdata_b = '0; + end + end + end + // TODO: end else begin : gen_sw_recovery for (genvar i = 0; i < NumCores; i++) begin : gen_cores - // Temporary disable of RapidRecovery + // Disable RapidRecovery assign core_debug_resume_o [i] = '0; // Setback @@ -770,7 +977,6 @@ module HMR_wrap import recovery_pkg::*; #( assign recovery_branch_addr_o [i] = '0; // RF - assign dmr_rf_readback_o [i] = '0; assign core_regfile_raddr_o [i] = '0; assign core_recovery_regfile_wport_o[i].we_a = '0; assign core_recovery_regfile_wport_o[i].waddr_a = '0; @@ -1202,19 +1408,19 @@ module HMR_wrap import recovery_pkg::*; #( core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - if (RapidRecovery) begin - core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] - & dmr_ctrl_core_clk_en_out[SysGroupId]; - end else begin + // if (RapidRecovery) begin + // core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] + // & dmr_ctrl_core_clk_en_out[SysGroupId]; + // end else begin core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; - end + // end core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; if (RapidRecovery) begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] - | dmr_ctrl_core_debug_req_out [SysGroupId]; + | recovery_debug_req_out [SysGroupId]; end else begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; end @@ -1222,7 +1428,7 @@ module HMR_wrap import recovery_pkg::*; #( // Setback if (RapidRecovery) begin - core_setback_o [i] = dmr_ctrl_core_setback_out [SysGroupId]; + core_setback_o [i] = recovery_setback_out [SysGroupId]; end else begin core_setback_o [i] = '0; end diff --git a/rtl/HMR/doc.html b/rtl/HMR/doc.html index ee0cb44f..ab3898ef 100644 --- a/rtl/HMR/doc.html +++ b/rtl/HMR/doc.html @@ -3,17 +3,19 @@
HMR_registers.avail_config @ 0x0

Available Configurations from implemented hardware.

-
Reset default = 0x0, mask 0x7
+
Reset default = 0x0, mask 0x107
- + + +
31302928272625242322212019181716
 
1514131211109876543210
 
1514131211109876543210
 rapid_recovery  triple dual independent
-BitsTypeResetNameDescription0roxindependent

Independent mode is available.

1roxdual

Dual Modular Redundancy (DMR) is available.

2roxtriple

Triple Modular Redundancy (TMR) is available.

+BitsTypeResetNameDescription0roxindependent

Independent mode is available.

1roxdual

Dual Modular Redundancy (DMR) is available.

2roxtriple

Triple Modular Redundancy (TMR) is available.

7:3Reserved8roxrapid_recovery

Rapid Recovery is available.


@@ -60,21 +62,38 @@
BitsTypeResetNameDescription3: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 @ 0x10
+
HMR_registers.TMR_config @ 0x14

TMR configuration bits.

-
Reset default = 0x6, mask 0xf
+
Reset default = 0x6, mask 0x1f
- + +
31302928272625242322212019181716
 
1514131211109876543210
 
1514131211109876543210
  force_resynchrapid_recovery reload_setback setback delay_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)

3rw0x0force_resynch

Forces a resynchronization routine

+BitsTypeResetNameDescription0rw0x0delay_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/hmr_dmr.h b/rtl/HMR/hmr_dmr.h index a97a51bc..d197bcb3 100644 --- a/rtl/HMR/hmr_dmr.h +++ b/rtl/HMR/hmr_dmr.h @@ -15,7 +15,8 @@ extern "C" { // DMR configuration bits. #define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4 -#define HMR_DMR_REGS_DMR_CONFIG_TODO_BIT 0 +#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 diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 1ed809d0..85ec8771 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -29,11 +29,16 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // CTRL from external (e.g. HMR ctrl regs) input logic dmr_enable_q_i, input logic dmr_enable_qe_i, + input logic rapid_recovery_q_i, + input logic rapid_recovery_qe_i, + input logic force_recovery_q_i, + input logic force_recovery_qe_i, // DMR control signals output logic setback_o, output logic sw_resynch_req_o, output logic grp_in_independent_o, + output logic rapid_recovery_en_o, output logic [1:0] dmr_incr_mismatches_o, input logic dmr_error_i, output logic recovery_request_o, @@ -54,6 +59,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( assign setback_o = dmr_setback_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; hmr_dmr_regs_reg_top #( .reg_req_t(reg_req_t), @@ -71,6 +77,9 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // 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; + assign dmr_hw2reg.dmr_config.rapid_recovery.d = rapid_recovery_q_i; + assign dmr_hw2reg.dmr_config.force_recovery.d = force_recovery_qe_i ? force_recovery_q_i : 1'b0; /************************** * FSM for DMR lockstep * @@ -80,9 +89,18 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( dmr_setback_d = 1'b0; dmr_red_mode_d = dmr_red_mode_q; dmr_incr_mismatches_o = '0; + recovery_request_o = 1'b0; + + dmr_hw2reg.dmr_config.force_recovery.de = 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) begin + dmr_hw2reg.dmr_config.force_recovery.de = 1'b1; + dmr_red_mode_d = DMR_RESTORE; + end + // If error detected, restore if (dmr_error_i && RapidRecovery) begin dmr_red_mode_d = DMR_RESTORE; diff --git a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv index b568f175..95199d4c 100644 --- a/rtl/HMR/hmr_dmr_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_dmr_regs_reg_pkg.sv @@ -19,8 +19,14 @@ package hmr_dmr_regs_reg_pkg; } hmr_dmr_regs_reg2hw_dmr_enable_reg_t; typedef struct packed { - logic q; - logic qe; + 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 { @@ -34,8 +40,14 @@ package hmr_dmr_regs_reg_pkg; } hmr_dmr_regs_hw2reg_dmr_enable_reg_t; typedef struct packed { - logic d; - logic de; + 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 { @@ -45,15 +57,15 @@ package hmr_dmr_regs_reg_pkg; // Register -> HW type typedef struct packed { - hmr_dmr_regs_reg2hw_dmr_enable_reg_t dmr_enable; // [36:35] - hmr_dmr_regs_reg2hw_dmr_config_reg_t dmr_config; // [34:33] + 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; // [36:35] - hmr_dmr_regs_hw2reg_dmr_config_reg_t dmr_config; // [34:33] + 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; diff --git a/rtl/HMR/hmr_dmr_regs_reg_top.sv b/rtl/HMR/hmr_dmr_regs_reg_top.sv index 80722d6b..209d9348 100644 --- a/rtl/HMR/hmr_dmr_regs_reg_top.sv +++ b/rtl/HMR/hmr_dmr_regs_reg_top.sv @@ -71,9 +71,12 @@ module hmr_dmr_regs_reg_top #( logic dmr_enable_qs; logic dmr_enable_wd; logic dmr_enable_we; - logic dmr_config_qs; - logic dmr_config_wd; - logic dmr_config_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; @@ -108,28 +111,55 @@ module hmr_dmr_regs_reg_top #( // R[dmr_config]: V(False) + // F[rapid_recovery]: 0:0 prim_subreg #( .DW (1), .SWACCESS("RW"), .RESVAL (1'h0) - ) u_dmr_config ( + ) u_dmr_config_rapid_recovery ( .clk_i (clk_i ), .rst_ni (rst_ni ), // from register interface - .we (dmr_config_we), - .wd (dmr_config_wd), + .we (dmr_config_rapid_recovery_we), + .wd (dmr_config_rapid_recovery_wd), // from internal hardware - .de (hw2reg.dmr_config.de), - .d (hw2reg.dmr_config.d ), + .de (hw2reg.dmr_config.rapid_recovery.de), + .d (hw2reg.dmr_config.rapid_recovery.d ), // to internal hardware - .qe (reg2hw.dmr_config.qe), - .q (reg2hw.dmr_config.q ), + .qe (reg2hw.dmr_config.rapid_recovery.qe), + .q (reg2hw.dmr_config.rapid_recovery.q ), // to register interface (read) - .qs (dmr_config_qs) + .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) ); @@ -183,8 +213,11 @@ module hmr_dmr_regs_reg_top #( assign dmr_enable_we = addr_hit[0] & reg_we & !reg_error; assign dmr_enable_wd = reg_wdata[0]; - assign dmr_config_we = addr_hit[1] & reg_we & !reg_error; - assign dmr_config_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]; @@ -198,7 +231,8 @@ module hmr_dmr_regs_reg_top #( end addr_hit[1]: begin - reg_rdata_next[0] = dmr_config_qs; + reg_rdata_next[0] = dmr_config_rapid_recovery_qs; + reg_rdata_next[1] = dmr_config_force_recovery_qs; end addr_hit[2]: begin diff --git a/rtl/HMR/hmr_global.h b/rtl/HMR/hmr_global.h index 6a687f15..ef710129 100644 --- a/rtl/HMR/hmr_global.h +++ b/rtl/HMR/hmr_global.h @@ -20,6 +20,7 @@ extern "C" { #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 @@ -42,12 +43,18 @@ extern "C" { #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 0x10 +#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_FORCE_RESYNCH_BIT 3 +#define HMR_REGISTERS_TMR_CONFIG_RAPID_RECOVERY_BIT 3 +#define HMR_REGISTERS_TMR_CONFIG_FORCE_RESYNCH_BIT 4 #ifdef __cplusplus } // extern "C" diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv new file mode 100644 index 00000000..5f409733 --- /dev/null +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -0,0 +1,140 @@ +// Copyright 2023 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. +// +// Hybrid modular redundancy Rapid Recovery control unit + +module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( + parameter int unsigned RFAddrWidth = 6 +) ( + input logic clk_i, + input logic rst_ni, + // input logic test_en_i, + + input logic start_recovery_i, + output logic recovery_finished_o, + + // Signals to core + output logic setback_o, + output logic instr_lock_o, + output logic debug_req_o, + input logic debug_halt_i, + output logic debug_resume_o, + output regfile_write_t recovery_regfile_waddr_o, + + // Signals to backup state + output logic backup_pc_enable_o, + output logic recover_pc_enable_o, + output logic recover_rf_enable_o +); + + typedef enum logic [1:0] {IDLE, RESET, HALT, RESTORE} recovery_mode_e; + recovery_mode_e rec_mode_d, rec_mode_q; + + logic instr_lock_d, instr_lock_q; + logic backup_pc_enable_d, backup_pc_enable_q; + logic setback_d, setback_q; + logic addr_gen_done; + logic [RFAddrWidth-1:0] addr_gen_result; + + DMR_address_generator #( + .AddrWidth ( RFAddrWidth ) + ) i_rf_address_generator ( + .clk_i, + .rst_ni, + .clear_i ('0), + .enable_i ( recover_rf_enable_o ), + .done_o ( addr_gen_done ), + .fatal_o (), + .address_o (addr_gen_result) + ); + + assign recovery_regfile_waddr_o.we_a = recover_rf_enable_o; + assign recovery_regfile_waddr_o.waddr_a = addr_gen_result; + assign recovery_regfile_waddr_o.wdata_a = '0; + assign recovery_regfile_waddr_o.we_b = recover_rf_enable_o; + assign recovery_regfile_waddr_o.waddr_b = 16 + addr_gen_result; + assign recovery_regfile_waddr_o.wdata_b = '0; + + + assign instr_lock_o = instr_lock_q; + assign backup_pc_enable_o = backup_pc_enable_q; + assign setback_o = setback_q; + + always_comb begin + rec_mode_d = rec_mode_q; + instr_lock_d = instr_lock_q; + backup_pc_enable_d = backup_pc_enable_q; + setback_d = 1'b0; + debug_req_o = 1'b0; + recover_pc_enable_o = 1'b0; + recover_rf_enable_o = 1'b0; + debug_resume_o = 1'b0; + recovery_finished_o = 1'b0; + + case (rec_mode_q) + IDLE: begin + // If requested start the routine in the reset state + if (start_recovery_i) begin + rec_mode_d = RESET; + end + end + + RESET: begin + // Clear the core state + setback_d = 1'b1; + // Lock the instruction requests + instr_lock_d = 1'b1; + // Disable reading for the backup PC + backup_pc_enable_d = 1'b0; + // Go to request halt of the core + rec_mode_d = HALT; + end + + HALT: begin + // Requesst a debug halt + debug_req_o = 1'b1; + // Wait until the core has halted + if (debug_halt_i) begin + rec_mode_d = RESTORE; + end + end + + RESTORE: begin + // Enable the PC recovery routine + recover_pc_enable_o = 1'b1; + // Enable the RF recovery routine + recover_rf_enable_o = 1'b1; + // If recovery routine complete, continue + if (addr_gen_done) begin + instr_lock_d = 1'b0; + backup_pc_enable_d = 1'b1; + rec_mode_d = IDLE; + debug_resume_o = 1'b1; + recovery_finished_o = 1'b1; + end + end + endcase + end + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + instr_lock_q <= 1'b0; + rec_mode_q <= IDLE; + backup_pc_enable_q <= 1'b1; + setback_q <= 1'b0; + end else begin + instr_lock_q <= instr_lock_d; + rec_mode_q <= rec_mode_d; + backup_pc_enable_q <= backup_pc_enable_d; + setback_q <= setback_d; + end + end + +endmodule diff --git a/rtl/HMR/hmr_registers_reg_pkg.sv b/rtl/HMR/hmr_registers_reg_pkg.sv index 3858c81d..1c590cce 100644 --- a/rtl/HMR/hmr_registers_reg_pkg.sv +++ b/rtl/HMR/hmr_registers_reg_pkg.sv @@ -28,6 +28,17 @@ package hmr_registers_reg_pkg; 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; @@ -41,6 +52,10 @@ package hmr_registers_reg_pkg; logic q; logic qe; } reload_setback; + struct packed { + logic q; + logic qe; + } rapid_recovery; struct packed { logic q; logic qe; @@ -57,6 +72,9 @@ package hmr_registers_reg_pkg; struct packed { logic d; } triple; + struct packed { + logic d; + } rapid_recovery; } hmr_registers_hw2reg_avail_config_reg_t; typedef struct packed { @@ -71,6 +89,15 @@ package hmr_registers_reg_pkg; 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; @@ -81,6 +108,9 @@ package hmr_registers_reg_pkg; struct packed { logic d; } reload_setback; + struct packed { + logic d; + } rapid_recovery; struct packed { logic d; } force_resynch; @@ -88,18 +118,20 @@ package hmr_registers_reg_pkg; // Register -> HW type typedef struct packed { - hmr_registers_reg2hw_dmr_enable_reg_t dmr_enable; // [19:13] - hmr_registers_reg2hw_tmr_enable_reg_t tmr_enable; // [12:8] - hmr_registers_reg2hw_tmr_config_reg_t tmr_config; // [7:0] + 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; // [28:26] - hmr_registers_hw2reg_cores_en_reg_t cores_en; // [25:14] - hmr_registers_hw2reg_dmr_enable_reg_t dmr_enable; // [13:8] - hmr_registers_hw2reg_tmr_enable_reg_t tmr_enable; // [7:4] - hmr_registers_hw2reg_tmr_config_reg_t tmr_config; // [3:0] + 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 @@ -107,16 +139,18 @@ package hmr_registers_reg_pkg; 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_TMR_CONFIG_OFFSET = 5'h 10; + 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 [2:0] HMR_REGISTERS_AVAIL_CONFIG_RESVAL = 3'h 0; + 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 [3:0] HMR_REGISTERS_TMR_CONFIG_RESVAL = 4'h 6; + 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; @@ -128,16 +162,18 @@ package hmr_registers_reg_pkg; 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 [5] = '{ - 4'b 0001, // index[0] HMR_REGISTERS_AVAIL_CONFIG + 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_TMR_CONFIG + 4'b 0001, // index[4] HMR_REGISTERS_DMR_CONFIG + 4'b 0001 // index[5] HMR_REGISTERS_TMR_CONFIG }; endpackage diff --git a/rtl/HMR/hmr_registers_reg_top.sv b/rtl/HMR/hmr_registers_reg_top.sv index e2649082..9769fed7 100644 --- a/rtl/HMR/hmr_registers_reg_top.sv +++ b/rtl/HMR/hmr_registers_reg_top.sv @@ -74,6 +74,8 @@ module hmr_registers_reg_top #( 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; @@ -84,6 +86,14 @@ module hmr_registers_reg_top #( 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; @@ -96,6 +106,10 @@ module hmr_registers_reg_top #( 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; @@ -149,6 +163,21 @@ module hmr_registers_reg_top #( ); + // 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 #( @@ -197,6 +226,38 @@ module hmr_registers_reg_top #( ); + // 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 @@ -244,7 +305,22 @@ module hmr_registers_reg_top #( ); - // F[force_resynch]: 3:3 + // 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 ( @@ -261,14 +337,15 @@ module hmr_registers_reg_top #( - logic [4:0] addr_hit; + 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_TMR_CONFIG_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 ; @@ -280,7 +357,8 @@ module hmr_registers_reg_top #( (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[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; @@ -289,6 +367,8 @@ module hmr_registers_reg_top #( 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; @@ -299,21 +379,33 @@ module hmr_registers_reg_top #( assign tmr_enable_wd = reg_wdata[3:0]; assign tmr_enable_re = addr_hit[3] & reg_re & !reg_error; - assign tmr_config_delay_resynch_we = addr_hit[4] & reg_we & !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[4] & reg_re & !reg_error; + assign tmr_config_delay_resynch_re = addr_hit[5] & reg_re & !reg_error; - assign tmr_config_setback_we = addr_hit[4] & reg_we & !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[4] & reg_re & !reg_error; + assign tmr_config_setback_re = addr_hit[5] & reg_re & !reg_error; - assign tmr_config_reload_setback_we = addr_hit[4] & reg_we & !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[4] & reg_re & !reg_error; + 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[4] & reg_we & !reg_error; - assign tmr_config_force_resynch_wd = reg_wdata[3]; - assign tmr_config_force_resynch_re = addr_hit[4] & 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 @@ -323,6 +415,7 @@ module hmr_registers_reg_top #( 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 @@ -338,10 +431,16 @@ module hmr_registers_reg_top #( 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_force_resynch_qs; + reg_rdata_next[3] = tmr_config_rapid_recovery_qs; + reg_rdata_next[4] = tmr_config_force_resynch_qs; end default: begin diff --git a/rtl/HMR/hmr_tmr.h b/rtl/HMR/hmr_tmr.h index 9751e30d..2058c9e6 100644 --- a/rtl/HMR/hmr_tmr.h +++ b/rtl/HMR/hmr_tmr.h @@ -18,7 +18,8 @@ extern "C" { #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_FORCE_RESYNCH_BIT 3 +#define HMR_TMR_REGS_TMR_CONFIG_RAPID_RECOVERY_BIT 3 +#define HMR_TMR_REGS_TMR_CONFIG_FORCE_RESYNCH_BIT 4 // Stack Pointer storage register #define HMR_TMR_REGS_SP_STORE_REG_OFFSET 0x8 diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 0244fb2f..11e0b27d 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -14,6 +14,7 @@ module hmr_tmr_ctrl #( parameter bit InterleaveGrps = 1'b0, 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 ) ( @@ -34,6 +35,8 @@ module hmr_tmr_ctrl #( input logic setback_qe_i, input logic reload_setback_q_i, input logic reload_setback_qe_i, + input logic rapid_recovery_q_i, + input logic rapid_recovery_qe_i, input logic force_resynch_q_i, input logic force_resynch_qe_i, @@ -41,6 +44,7 @@ module hmr_tmr_ctrl #( output logic setback_o, output logic sw_resynch_req_o, output logic grp_in_independent_o, + output logic rapid_recovery_en_o, output logic [2:0] tmr_incr_mismatches_o, input logic tmr_single_mismatch_i, input logic [2:0] tmr_error_i, @@ -61,6 +65,7 @@ module hmr_tmr_ctrl #( assign setback_o = tmr_setback_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; hmr_tmr_regs_reg_top #( .reg_req_t(reg_req_t), @@ -84,6 +89,8 @@ module hmr_tmr_ctrl #( 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; /************************** @@ -94,7 +101,7 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; - tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; + tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; case (tmr_red_mode_q) TMR_RUN: begin diff --git a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv index 0643b9c0..148055e7 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv @@ -31,6 +31,10 @@ package hmr_tmr_regs_reg_pkg; logic q; logic qe; } reload_setback; + struct packed { + logic q; + logic qe; + } rapid_recovery; struct packed { logic q; logic qe; @@ -60,6 +64,10 @@ package hmr_tmr_regs_reg_pkg; logic d; logic de; } reload_setback; + struct packed { + logic d; + logic de; + } rapid_recovery; struct packed { logic d; logic de; @@ -73,15 +81,15 @@ package hmr_tmr_regs_reg_pkg; // Register -> HW type typedef struct packed { - hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [42:41] - hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [40:33] + hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [44:43] + hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [42:33] hmr_tmr_regs_reg2hw_sp_store_reg_t sp_store; // [32:0] } hmr_tmr_regs_reg2hw_t; // HW -> register type typedef struct packed { - hmr_tmr_regs_hw2reg_tmr_enable_reg_t tmr_enable; // [42:41] - hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [40:33] + hmr_tmr_regs_hw2reg_tmr_enable_reg_t tmr_enable; // [44:43] + hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [42:33] hmr_tmr_regs_hw2reg_sp_store_reg_t sp_store; // [32:0] } hmr_tmr_regs_hw2reg_t; diff --git a/rtl/HMR/hmr_tmr_regs_reg_top.sv b/rtl/HMR/hmr_tmr_regs_reg_top.sv index 25879e1c..666d010a 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_top.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_top.sv @@ -80,6 +80,9 @@ module hmr_tmr_regs_reg_top #( 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; @@ -195,7 +198,33 @@ module hmr_tmr_regs_reg_top #( ); - // F[force_resynch]: 3:3 + // 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"), @@ -280,8 +309,11 @@ module hmr_tmr_regs_reg_top #( 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[3]; + assign tmr_config_force_resynch_wd = reg_wdata[4]; assign sp_store_we = addr_hit[2] & reg_we & !reg_error; assign sp_store_wd = reg_wdata[31:0]; @@ -298,7 +330,8 @@ module hmr_tmr_regs_reg_top #( 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_force_resynch_qs; + reg_rdata_next[3] = tmr_config_rapid_recovery_qs; + reg_rdata_next[4] = tmr_config_force_resynch_qs; end addr_hit[2]: begin From 47240d90e73f14bb57e4b1dddff00cf7a0abed30 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 1 Feb 2023 08:43:17 +0100 Subject: [PATCH 11/66] Update header file generation --- Makefile | 54 ++++++++++++- rtl/HMR/hmr_core.h | 25 ------ rtl/HMR/hmr_dmr.h | 28 ------- rtl/HMR/hmr_global.h | 63 --------------- rtl/HMR/hmr_tmr.h | 31 -------- rtl/HMR/hmr_v1.h | 183 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 233 insertions(+), 151 deletions(-) delete mode 100644 rtl/HMR/hmr_core.h delete mode 100644 rtl/HMR/hmr_dmr.h delete mode 100644 rtl/HMR/hmr_global.h delete mode 100644 rtl/HMR/hmr_tmr.h create mode 100644 rtl/HMR/hmr_v1.h diff --git a/Makefile b/Makefile index a9151e25..812c5f33 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,46 @@ 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 0x008 +#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 @@ -47,14 +87,20 @@ gen_TCLS: 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) -D > $(TARGET_DIR_HMR)/hmr_global.h 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_core) -D > $(TARGET_DIR_HMR)/hmr_core.h python $(REG_TOOL) $(HJSON_HMR_dmr) -t $(TARGET_DIR_HMR) -r - python $(REG_TOOL) $(HJSON_HMR_dmr) -D > $(TARGET_DIR_HMR)/hmr_dmr.h python $(REG_TOOL) $(HJSON_HMR_tmr) -t $(TARGET_DIR_HMR) -r - python $(REG_TOOL) $(HJSON_HMR_tmr) -D > $(TARGET_DIR_HMR)/hmr_tmr.h + + @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_ecc_registers: python $(REG_TOOL) $(HJSON_ECC) -t $(TARGET_DIR_ECC) -r diff --git a/rtl/HMR/hmr_core.h b/rtl/HMR/hmr_core.h deleted file mode 100644 index 58d7d0c5..00000000 --- a/rtl/HMR/hmr_core.h +++ /dev/null @@ -1,25 +0,0 @@ -// 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 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_CORE_REGS_REG_DEFS_ -// End generated register defines for HMR_core_regs \ No newline at end of file diff --git a/rtl/HMR/hmr_dmr.h b/rtl/HMR/hmr_dmr.h deleted file mode 100644 index d197bcb3..00000000 --- a/rtl/HMR/hmr_dmr.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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_TMR_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 \ No newline at end of file diff --git a/rtl/HMR/hmr_global.h b/rtl/HMR/hmr_global.h deleted file mode 100644 index ef710129..00000000 --- a/rtl/HMR/hmr_global.h +++ /dev/null @@ -1,63 +0,0 @@ -// 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 \ No newline at end of file diff --git a/rtl/HMR/hmr_tmr.h b/rtl/HMR/hmr_tmr.h deleted file mode 100644 index 2058c9e6..00000000 --- a/rtl/HMR/hmr_tmr.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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 - -// Stack Pointer storage register -#define HMR_TMR_REGS_SP_STORE_REG_OFFSET 0x8 - -#ifdef __cplusplus -} // extern "C" -#endif -#endif // _HMR_TMR_REGS_REG_DEFS_ -// End generated register defines for HMR_tmr_regs \ No newline at end of file diff --git a/rtl/HMR/hmr_v1.h b/rtl/HMR/hmr_v1.h new file mode 100644 index 00000000..92ed91bb --- /dev/null +++ b/rtl/HMR/hmr_v1.h @@ -0,0 +1,183 @@ +/* + * 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 0x008 +#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 + +#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_TMR_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 + +// Stack Pointer storage register +#define HMR_TMR_REGS_SP_STORE_REG_OFFSET 0x8 + +#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__ From 97dfe421781fc6611aaa1e0188690d26a8258b4e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 1 Feb 2023 11:32:22 +0100 Subject: [PATCH 12/66] Fix configurable rapid-recovery assignments --- Makefile | 2 + rtl/HMR/HMR_wrap.sv | 285 ++++++++++++++++++++++++++------------------ 2 files changed, 174 insertions(+), 113 deletions(-) diff --git a/Makefile b/Makefile index 812c5f33..9910dd8d 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,8 @@ define HMR_H_HEADER_STRING #define HMR_TMR_OFFSET 0x300 #define HMR_CORE_INCREMENT 0x008 +#define HMR_DMR_INCREMENT 0x010 +#define HMR_DMR_SLL 0x004 #define HMR_TMR_INCREMENT 0x010 #define HMR_TMR_SLL 0x004 \n diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 81ac22cf..f331ee17 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -80,7 +80,6 @@ module HMR_wrap import recovery_pkg::*; #( output logic [ NumCores-1:0][DataWidth-1:0] recovery_branch_addr_o, // Backup ports from Cores' RFs input regfile_write_t [NumCores-1:0] backup_regfile_wport_i, - output regfile_raddr_t [NumCores-1:0] core_regfile_raddr_o, output regfile_write_t [NumCores-1:0] core_recovery_regfile_wport_o, // Nonstandard core control signals output logic [ NumCores-1:0] core_setback_o , @@ -251,8 +250,27 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumDMRGroups-1:0][ BeWidth-1:0] dmr_data_be_out; - logic [ NumDMRGroups-1:0][ DataWidth-1:0] dmr_backup_program_counter; + logic [ NumDMRGroups-1:0][RFAddrWidth-1:0] dmr_backup_regfile_waddr_a, + dmr_backup_regfile_waddr_b; + logic [ NumDMRGroups-1:0][ DataWidth-1:0] dmr_backup_program_counter, + dmr_backup_regfile_wdata_a, + dmr_backup_regfile_wdata_b, + dmr_backup_branch_addr_int; + logic [ NumDMRGroups-1:0] dmr_backup_program_counter_error, + dmr_backup_branch_error, + dmr_backup_branch_addr_error, + dmr_backup_regfile_error_a, + dmr_backup_regfile_error_b, + dmr_backup_regfile_addr_error_a, + dmr_backup_regfile_addr_error_b, + dmr_backup_branch_int, + dmr_start_recovery, + dmr_backup_regfile_we_a, + dmr_backup_regfile_we_b, + dmr_recovery_finished; logic [ NumTMRGroups-1:0][ DataWidth-1:0] tmr_backup_program_counter; + logic [NumBackupRegfiles-1:0][RFAddrWidth-1:0] backup_regfile_waddr_a, + backup_regfile_waddr_b; logic [NumBackupRegfiles-1:0][ DataWidth-1:0] backup_branch_addr_int, recovery_branch_addr_out, backup_program_counter_int, @@ -260,30 +278,24 @@ module HMR_wrap import recovery_pkg::*; #( backup_regfile_wdata_a, backup_regfile_wdata_b; logic [NumBackupRegfiles-1:0] backup_branch_int, - recovery_branch_out, - backup_program_counter_error, - backup_pc_enable_out, // dmr_ctrl_pc_read_enable_out, - recovery_pc_enable_out, // dmr_ctrl_pc_write_enable_out, - // dmr_ctrl_core_clk_en_out, backup_regfile_we_a, backup_regfile_we_b, - backup_regfile_error_a, - backup_regfile_error_b, - backup_branch_error, - backup_branch_addr_error, - // regfile_readback_out, - // dmr_ctrl_core_rstn_out, - recovery_debug_req_out, // dmr_ctrl_core_debug_req_out, - recovery_debug_halted_in, // dmr_ctrl_core_debug_halted_in, - recovery_instr_lock_out, // dmr_ctrl_core_instr_lock_out, - recovery_setback_out, // dmr_ctrl_core_setback_out, - recovery_trigger_out, // dmr_ctrl_core_recover_out, // TODO: for regfile only?!? - recovery_debug_resume_out; // dmr_ctrl_debug_resume_out; + backup_program_counter_error, + recovery_branch_out, + backup_pc_enable_out, + recovery_pc_enable_out, + recovery_debug_req_out, + recovery_debug_halted_in, + recovery_instr_lock_out, + recovery_setback_out, + recovery_trigger_out, // TODO: for regfile only?!? + recovery_debug_resume_out, + start_recovery, + recovery_finished; regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; - regfile_write_t [NumBackupRegfiles-1:0] backup_regfile_wport_in, - core_recovery_regfile_wport_out; + regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin @@ -584,16 +596,6 @@ module HMR_wrap import recovery_pkg::*; #( /************************************************************ ******************** DMR Voters and Regs ******************* ************************************************************/ - for (genvar i = 0; i < NumBackupRegfiles; i++) begin - // TODO fix assignment - assign backup_regfile_wport_in [i] = backup_regfile_wport_i [dmr_core_id(dmr_group_id(i), 0)]; - end - - for (genvar i = 0; i < NumDMRGroups; i++) begin - // TODO fix assignment - assign recovery_debug_halted_in [i] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] - & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; - end if (DMRSupported || DMRFixed) begin: gen_dmr_recovery_region @@ -639,7 +641,7 @@ module HMR_wrap import recovery_pkg::*; #( .clk_i, .rst_ni, - .reg_req_i ( dmr_register_reqs[i] ), + .reg_req_i ( dmr_register_reqs [i] ), .reg_resp_o ( dmr_register_resps[i] ), .dmr_enable_q_i ( hmr_reg2hw.dmr_enable.q[i] ), @@ -649,18 +651,18 @@ module HMR_wrap import recovery_pkg::*; #( .force_recovery_q_i ( hmr_reg2hw.dmr_config.force_recovery.q ), .force_recovery_qe_i ( hmr_reg2hw.dmr_config.force_recovery.qe ), - .setback_o ( dmr_setback_q[i] ), - .sw_resynch_req_o ( dmr_resynch_req_o[i] ), + .setback_o ( dmr_setback_q [i] ), + .sw_resynch_req_o ( dmr_resynch_req_o [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), - .rapid_recovery_en_o ( dmr_rapid_recovery_en[i] ), + .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), - .dmr_error_i ( dmr_failure[i] ), + .dmr_error_i ( dmr_failure [i] ), .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), .cores_synch_i ( dmr_cores_synch_i[i] ), - .recovery_request_o (), - .recovery_finished_i () + .recovery_request_o ( dmr_start_recovery [i] ), + .recovery_finished_i ( dmr_recovery_finished[i] ) ); /********************* @@ -671,8 +673,8 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_core_checker_main ( .inp_a_i ( main_concat_in [dmr_core_id(i, 0)] ), .inp_b_i ( main_concat_in [dmr_core_id(i, 1)] ), - .check_o ( main_dmr_out [i] ), - .error_o ( dmr_failure_main [i] ) + .check_o ( main_dmr_out [i] ), + .error_o ( dmr_failure_main [i] ) ); if (SeparateData) begin : gen_data_checker DMR_checker # ( @@ -680,8 +682,8 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_core_checker_data ( .inp_a_i ( data_concat_in [dmr_core_id(i, 0)] ), .inp_b_i ( data_concat_in [dmr_core_id(i, 1)] ), - .check_o ( data_dmr_out [i] ), - .error_o ( dmr_failure_data [i] ) + .check_o ( data_dmr_out [i] ), + .error_o ( dmr_failure_data [i] ) ); assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] } @@ -703,11 +705,13 @@ module HMR_wrap import recovery_pkg::*; #( assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]) | - backup_program_counter_error[i] | - backup_branch_error [i] | - backup_branch_addr_error [i] | - backup_regfile_error_a [i] | - backup_regfile_error_b [i]; + dmr_backup_program_counter_error[i] | + dmr_backup_branch_error [i] | + dmr_backup_branch_addr_error [i] | + dmr_backup_regfile_error_a [i] | + dmr_backup_regfile_error_b [i] | + dmr_backup_regfile_addr_error_a [i] | + dmr_backup_regfile_addr_error_b [i]; /****************** * DMR PC Checker * @@ -717,8 +721,8 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_pc_checker ( .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_backup_program_counter[i] ), - .error_o ( backup_program_counter_error [i] ) + .check_o ( dmr_backup_program_counter [i] ), + .error_o ( dmr_backup_program_counter_error [i] ) ); /********************** @@ -729,8 +733,8 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_branch_checker ( .inp_a_i ( backup_branch_i[dmr_core_id(i, 0)] ), .inp_b_i ( backup_branch_i[dmr_core_id(i, 1)] ), - .check_o ( backup_branch_int [i] ), - .error_o ( backup_branch_error [i] ) + .check_o ( dmr_backup_branch_int [i] ), + .error_o ( dmr_backup_branch_error [i] ) ); /***************************** @@ -741,8 +745,8 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_branch_addr_checker ( .inp_a_i ( backup_branch_addr_i[dmr_core_id(i, 0)] ), .inp_b_i ( backup_branch_addr_i[dmr_core_id(i, 1)] ), - .check_o ( backup_branch_addr_int [i] ), - .error_o ( backup_branch_addr_error [i] ) + .check_o ( dmr_backup_branch_addr_int [i] ), + .error_o ( dmr_backup_branch_addr_error [i] ) ); /******************* @@ -753,8 +757,17 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_rf_checker_port_a ( .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_a ), .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_a ), - .check_o ( backup_regfile_wdata_a[i] ), - .error_o ( backup_regfile_error_a[i] ) + .check_o ( dmr_backup_regfile_wdata_a [i] ), + .error_o ( dmr_backup_regfile_error_a [i] ) + ); + + DMR_checker # ( + .DataWidth ( RFAddrWidth ) + ) dmr_rf_checker_addr_port_a ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].waddr_a ), + .check_o ( dmr_backup_regfile_waddr_a [i] ), + .error_o ( dmr_backup_regfile_addr_error_a [i] ) ); DMR_checker # ( @@ -762,17 +775,29 @@ module HMR_wrap import recovery_pkg::*; #( ) dmr_rf_checker_port_b ( .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_b ), .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_b ), - .check_o ( backup_regfile_wdata_b [i] ), - .error_o ( backup_regfile_error_b [i] ) + .check_o ( dmr_backup_regfile_wdata_b [i] ), + .error_o ( dmr_backup_regfile_error_b [i] ) ); - assign backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a - & ~backup_regfile_error_a [i] - & ~recovery_trigger_out [i]; - assign backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b - & ~backup_regfile_error_b [i] - & ~recovery_trigger_out [i]; - + DMR_checker # ( + .DataWidth ( RFAddrWidth ) + ) dmr_rf_checker_addr_port_b ( + .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), + .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].waddr_b ), + .check_o ( dmr_backup_regfile_waddr_b [i] ), + .error_o ( dmr_backup_regfile_addr_error_b [i] ) + ); + + assign dmr_backup_regfile_we_a [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_a + & backup_regfile_wport_i[dmr_core_id(i, 1)].we_a + & ~dmr_backup_regfile_error_a [i] + & ~dmr_backup_regfile_addr_error_a [i]; + + assign dmr_backup_regfile_we_b [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_b + & backup_regfile_wport_i[dmr_core_id(i, 1)].we_b + & ~dmr_backup_regfile_error_b [i] + & ~dmr_backup_regfile_addr_error_b [i]; + end else begin assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]; @@ -803,17 +828,17 @@ module HMR_wrap import recovery_pkg::*; #( ) i_rapid_recovery_ctrl ( .clk_i, .rst_ni, - .start_recovery_i (), - .recovery_finished_o (), - .setback_o ( recovery_setback_out [i] ), - .instr_lock_o ( recovery_instr_lock_out [i] ), - .debug_req_o ( recovery_debug_req_out [i] ), - .debug_halt_i ( recovery_debug_halted_in [i] ), + .start_recovery_i ( start_recovery [i] ), + .recovery_finished_o ( recovery_finished [i] ), + .setback_o ( recovery_setback_out [i] ), + .instr_lock_o ( recovery_instr_lock_out [i] ), + .debug_req_o ( recovery_debug_req_out [i] ), + .debug_halt_i ( recovery_debug_halted_in [i] ), .debug_resume_o ( recovery_debug_resume_out [i] ), .recovery_regfile_waddr_o ( core_recovery_regfile_wport_out[i] ), - .backup_pc_enable_o ( backup_pc_enable_out [i] ), - .recover_pc_enable_o ( recovery_pc_enable_out [i] ), - .recover_rf_enable_o ( recovery_trigger_out [i] ) + .backup_pc_enable_o ( backup_pc_enable_out [i] ), + .recover_pc_enable_o ( recovery_pc_enable_out [i] ), + .recover_rf_enable_o ( recovery_trigger_out [i] ) ); /**************************** @@ -825,18 +850,18 @@ module HMR_wrap import recovery_pkg::*; #( // Control Ports .clk_i, .rst_ni, - .clear_i ( '0 ), - .read_enable_i ( backup_pc_enable_out [i] ), + .clear_i ( '0 ), + .read_enable_i ( backup_pc_enable_out [i] ), .write_enable_i ( ~backup_program_counter_error [i] - & recovery_pc_enable_out [i] ), + & recovery_pc_enable_out [i] ), // Backup Ports - .backup_program_counter_i ( backup_program_counter_int [i] ), - .backup_branch_i ( backup_branch_int [i] ), - .backup_branch_addr_i ( backup_branch_addr_i [i] ), + .backup_program_counter_i ( backup_program_counter_int [i] ), + .backup_branch_i ( backup_branch_int [i] ), + .backup_branch_addr_i ( backup_branch_addr_int [i] ), // Recovery Pors - .recovery_program_counter_o ( recovery_program_counter_out [i] ), - .recovery_branch_o ( recovery_branch_out [i] ), - .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) + .recovery_program_counter_o ( recovery_program_counter_out [i] ), + .recovery_branch_o ( recovery_branch_out [i] ), + .recovery_branch_addr_o ( recovery_branch_addr_out [i] ) ); /*************************** @@ -859,30 +884,68 @@ module HMR_wrap import recovery_pkg::*; #( .raddr_c_i ( '0 ), .rdata_c_o ( ), // Write Port A - .waddr_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), + .waddr_a_i ( backup_regfile_waddr_a [i] ), .wdata_a_i ( backup_regfile_wdata_a [i] ), - .we_a_i ( backup_regfile_we_a [i] ), + .we_a_i ( backup_regfile_we_a[i] & ~recovery_trigger_out[i] ), // Write Port B - .waddr_b_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), + .waddr_b_i ( backup_regfile_waddr_b [i] ), .wdata_b_i ( backup_regfile_wdata_b [i] ), - .we_b_i ( backup_regfile_we_b [i] ) + .we_b_i ( backup_regfile_we_b[i] & ~recovery_trigger_out[i] ) ); end - always_comb begin - backup_program_counter_int = '0; + backup_program_counter_int = '0; + backup_program_counter_error = '0; + backup_branch_int = '0; + backup_branch_addr_int = '0; + backup_regfile_wdata_a = '0; + backup_regfile_wdata_b = '0; + backup_regfile_we_a = '0; + backup_regfile_we_b = '0; + backup_regfile_waddr_a = '0; + backup_regfile_waddr_b = '0; + start_recovery = '0; + dmr_recovery_finished = '0; + recovery_debug_halted_in = '0; for (int i = 0; i < NumDMRGroups; i++) begin if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin - backup_program_counter_int[dmr_shared_id(i)] = dmr_backup_program_counter[i]; + backup_program_counter_int [dmr_shared_id(i)] = dmr_backup_program_counter [i]; + backup_program_counter_error[dmr_shared_id(i)] = dmr_backup_program_counter_error[i]; + backup_branch_int [dmr_shared_id(i)] = dmr_backup_branch_int [i]; + backup_branch_addr_int [dmr_shared_id(i)] = dmr_backup_branch_addr_int [i]; + backup_regfile_wdata_a [dmr_shared_id(i)] = dmr_backup_regfile_wdata_a [i]; + backup_regfile_wdata_b [dmr_shared_id(i)] = dmr_backup_regfile_wdata_b [i]; + backup_regfile_we_a [dmr_shared_id(i)] = dmr_backup_regfile_we_a [i]; + backup_regfile_we_b [dmr_shared_id(i)] = dmr_backup_regfile_we_b [i]; + backup_regfile_waddr_a [dmr_shared_id(i)] = dmr_backup_regfile_waddr_a [i]; + backup_regfile_waddr_b [dmr_shared_id(i)] = dmr_backup_regfile_waddr_b [i]; + start_recovery [dmr_shared_id(i)] = dmr_start_recovery [i]; + dmr_recovery_finished[i] = recovery_finished[dmr_shared_id(i)]; + recovery_debug_halted_in [dmr_shared_id(i)] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] + & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; end end for (int i = 0; i < NumTMRGroups; i++) begin if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin - backup_program_counter_int[tmr_shared_id(i)] = tmr_backup_program_counter[i]; + backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; + // backup_program_counter_error[tmr_shared_id(i)] = tmr_backup_program_counter_error[i]; + // backup_branch_int [tmr_shared_id(i)] = tmr_backup_branch_int [i]; + // backup_branch_addr_int [tmr_shared_id(i)] = tmr_backup_branch_addr_int [i]; + // backup_regfile_wdata_a [tmr_shared_id(i)] = tmr_backup_regfile_wdata_a [i]; + // backup_regfile_wdata_b [tmr_shared_id(i)] = tmr_backup_regfile_wdata_b [i]; + // backup_regfile_we_a [tmr_shared_id(i)] = tmr_backup_regfile_we_a [i]; + // backup_regfile_we_b [tmr_shared_id(i)] = tmr_backup_regfile_we_b [i]; + // backup_regfile_waddr_a [tmr_shared_id(i)] = tmr_backup_regfile_waddr_a [i]; + // backup_regfile_waddr_b [tmr_shared_id(i)] = tmr_backup_regfile_waddr_b [i]; + // start_recovery [tmr_shared_id(i)] = tmr_start_recovery [i]; + // tmr_recovery_finished[i] = recovery_finished[tmr_shared_id(i)]; + // recovery_debug_halted_in [tmr_shared_id(i)] = core_debug_halted_i [tmr_core_id(tmr_group_id(i), 0)] + // & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 1)]; + // & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 2)]; end end end @@ -891,20 +954,19 @@ module HMR_wrap import recovery_pkg::*; #( always_comb begin if ((DMRFixed || (DMRSupported && core_in_dmr[i])) && dmr_core_rapid_recovery_en[i]) begin - core_debug_resume_o [i] = recovery_debug_resume_out [dmr_shared_id(dmr_group_id(i))]; + core_debug_resume_o [i] = recovery_debug_resume_out [dmr_shared_id(dmr_group_id(i))]; // Setback - core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; - core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; + core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; // PC - pc_recover_o [i] = backup_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; + pc_recover_o [i] = recovery_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; recovery_program_counter_o [i] = recovery_program_counter_out [dmr_shared_id(dmr_group_id(i))]; - recovery_branch_o [i] = recovery_branch_out [dmr_shared_id(dmr_group_id(i))]; - recovery_branch_addr_o [i] = recovery_branch_addr_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [dmr_shared_id(dmr_group_id(i))]; // RF - core_regfile_raddr_o [i] = core_regfile_raddr_out [dmr_shared_id(dmr_group_id(i))]; core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_a; core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_a; core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_a; @@ -913,20 +975,20 @@ module HMR_wrap import recovery_pkg::*; #( core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_b; end else if ((TMRFixed || (TMRSupported && core_in_tmr[i])) && tmr_core_rapid_recovery_en[i]) begin - core_debug_resume_o [i] = recovery_debug_resume_out [tmr_shared_id(tmr_group_id(i))]; + core_debug_resume_o [i] = recovery_debug_resume_out [tmr_shared_id(tmr_group_id(i))]; // Setback - core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; - core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; + core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; // PC - pc_recover_o [i] = backup_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; + pc_recover_o [i] = recovery_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; recovery_program_counter_o [i] = recovery_program_counter_out [tmr_shared_id(tmr_group_id(i))]; - recovery_branch_o [i] = recovery_branch_out [tmr_shared_id(tmr_group_id(i))]; - recovery_branch_addr_o [i] = recovery_branch_addr_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [tmr_shared_id(tmr_group_id(i))]; // RF - core_regfile_raddr_o [i] = core_regfile_raddr_out [tmr_shared_id(tmr_group_id(i))]; + // core_regfile_raddr_o [i] = core_regfile_raddr_out [tmr_shared_id(tmr_group_id(i))]; core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_a; core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_a; core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_a; @@ -936,11 +998,11 @@ module HMR_wrap import recovery_pkg::*; #( end else begin // Disable RapidRecovery - core_debug_resume_o [i] = '0; + core_debug_resume_o [i] = '0; // Setback - core_recover_o [i] = '0; - core_instr_lock_o [i] = '0; + core_recover_o [i] = '0; + core_instr_lock_o [i] = '0; // PC pc_recover_o [i] = '0; @@ -949,7 +1011,6 @@ module HMR_wrap import recovery_pkg::*; #( recovery_branch_addr_o [i] = '0; // RF - core_regfile_raddr_o [i] = '0; core_recovery_regfile_wport_o[i].we_a = '0; core_recovery_regfile_wport_o[i].waddr_a = '0; core_recovery_regfile_wport_o[i].wdata_a = '0; @@ -960,15 +1021,14 @@ module HMR_wrap import recovery_pkg::*; #( end end - // TODO: end else begin : gen_sw_recovery for (genvar i = 0; i < NumCores; i++) begin : gen_cores // Disable RapidRecovery - assign core_debug_resume_o [i] = '0; + assign core_debug_resume_o [i] = '0; // Setback - assign core_recover_o [i] = '0; - assign core_instr_lock_o [i] = '0; + assign core_recover_o [i] = '0; + assign core_instr_lock_o [i] = '0; // PC assign pc_recover_o [i] = '0; @@ -977,7 +1037,6 @@ module HMR_wrap import recovery_pkg::*; #( assign recovery_branch_addr_o [i] = '0; // RF - assign core_regfile_raddr_o [i] = '0; assign core_recovery_regfile_wport_o[i].we_a = '0; assign core_recovery_regfile_wport_o[i].waddr_a = '0; assign core_recovery_regfile_wport_o[i].wdata_a = '0; From 1ec034feda473f132846434784ed00a1d3b43fe6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 1 Feb 2023 14:53:43 +0100 Subject: [PATCH 13/66] Fix connections for rapid-recovery --- rtl/HMR/HMR_wrap.sv | 88 +++++++++++++++++++++++++---------------- rtl/HMR/hmr_dmr_ctrl.sv | 18 ++++++--- rtl/HMR/hmr_tmr_ctrl.sv | 6 ++- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index f331ee17..5fcb53fc 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -298,12 +298,12 @@ module HMR_wrap import recovery_pkg::*; #( regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat - if (SeparateData) begin + if (SeparateData) begin : gen_separate_data assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i]}; assign data_concat_in[i] = {core_data_add_i[i], core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i]}; - end else begin + end else begin : gen_single_group assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], core_data_add_i[i], core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i]}; @@ -330,7 +330,7 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumTMRGroups-1:0] tmr_grp_in_independent; logic [NumTMRGroups-1:0] tmr_rapid_recovery_en; - for (genvar i = 0; i < NumCores; i++) begin + for (genvar i = 0; i < NumCores; i++) begin : gen_global_status assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? ~tmr_grp_in_independent[tmr_group_id(i)] : '0; @@ -385,7 +385,7 @@ module HMR_wrap import recovery_pkg::*; #( assign hmr_hw2reg.avail_config.triple.d = TMRFixed | TMRSupported; assign hmr_hw2reg.avail_config.rapid_recovery.d = RapidRecovery; - always_comb begin + always_comb begin : proc_reg_status hmr_hw2reg.cores_en.d = '0; hmr_hw2reg.cores_en.d = core_en_as_master; @@ -431,7 +431,7 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumCores-1:0] tmr_incr_mismatches; logic [NumCores-1:0] dmr_incr_mismatches; - for (genvar i = 0; i < NumCores; i++) begin + 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_resp_t) @@ -597,7 +597,7 @@ module HMR_wrap import recovery_pkg::*; #( ******************** DMR Voters and Regs ******************* ************************************************************/ - if (DMRSupported || DMRFixed) begin: gen_dmr_recovery_region + 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; @@ -628,7 +628,7 @@ module HMR_wrap import recovery_pkg::*; #( assign dmr_incr_mismatches[i] = '0; end - for (genvar i = 0; i < NumDMRGroups; i++) begin + for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_dmr_groups hmr_dmr_ctrl #( .reg_req_t ( reg_req_t ), @@ -701,7 +701,7 @@ module HMR_wrap import recovery_pkg::*; #( = main_dmr_out[i]; end - if (RapidRecovery) begin + if (RapidRecovery) begin : gen_rapid_recovery_connection assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]) | @@ -798,7 +798,7 @@ module HMR_wrap import recovery_pkg::*; #( & ~dmr_backup_regfile_error_b [i] & ~dmr_backup_regfile_addr_error_b [i]; - end else begin + end else begin : gen_standard_failure assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]; end @@ -822,7 +822,7 @@ module HMR_wrap import recovery_pkg::*; #( // RapidRecovery output signals if (RapidRecovery) begin : gen_rapid_recovery - for (genvar i = 0; i < NumBackupRegfiles; i++) begin + for (genvar i = 0; i < NumBackupRegfiles; i++) begin : gen_groups hmr_rapid_recovery_ctrl #( .RFAddrWidth( RFAddrWidth ) ) i_rapid_recovery_ctrl ( @@ -895,7 +895,7 @@ module HMR_wrap import recovery_pkg::*; #( end - always_comb begin + always_comb begin : proc_dmr_tmr_assignments backup_program_counter_int = '0; backup_program_counter_error = '0; backup_branch_int = '0; @@ -1067,7 +1067,12 @@ module HMR_wrap import recovery_pkg::*; #( core_fetch_en_o [i] = sys_fetch_en_i [TMRCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [TMRCoreIndex]; - core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex]; + if (RapidRecovery) begin + core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex] + | recovery_debug_req_out [tmr_shared_id(tmr_group_id(i))]; + end else begin + core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex]; + end core_perf_counters_o[i] = sys_perf_counters_i[TMRCoreIndex]; // IRQ @@ -1089,7 +1094,12 @@ module HMR_wrap import recovery_pkg::*; #( core_data_err_o [i] = sys_data_err_i [TMRCoreIndex]; // Special signals - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + if (RapidRecovery) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [DMRCoreIndex]; @@ -1099,7 +1109,12 @@ module HMR_wrap import recovery_pkg::*; #( core_fetch_en_o [i] = sys_fetch_en_i [DMRCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [DMRCoreIndex]; - core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex]; + if (RapidRecovery) begin + core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex] + | recovery_debug_req_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex]; + end core_perf_counters_o[i] = sys_perf_counters_i[DMRCoreIndex]; // IRQ @@ -1121,7 +1136,11 @@ module HMR_wrap import recovery_pkg::*; #( core_data_err_o [i] = sys_data_err_i [DMRCoreIndex]; // Special signals - core_setback_o [i] = '0; + if (RapidRecovery) begin + core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = '0; + end end else begin : independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1281,7 +1300,12 @@ module HMR_wrap import recovery_pkg::*; #( core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; - core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; + if (RapidRecovery) begin + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + | recovery_debug_req_out [tmr_shared_id(tmr_group_id(i))]; + end else begin + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; + end core_perf_counters_o[i] = sys_perf_counters_i[SysCoreIndex]; // IRQ @@ -1303,7 +1327,13 @@ module HMR_wrap import recovery_pkg::*; #( core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; // Special signals - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + // Setback + if (RapidRecovery) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + end end else begin : independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1460,38 +1490,24 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); - localparam SysGroupId = DMRFixed ? i/2 : dmr_group_id(i); always_comb begin if (i < NumDMRCores && (DMRFixed || core_in_dmr[i])) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; core_cluster_id_o [i] = sys_cluster_id_i [SysCoreIndex]; - // if (RapidRecovery) begin - // core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex] - // & dmr_ctrl_core_clk_en_out[SysGroupId]; - // end else begin - core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; - // end + core_clock_en_o [i] = sys_clock_en_i [SysCoreIndex]; core_fetch_en_o [i] = sys_fetch_en_i [SysCoreIndex]; core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; - if (RapidRecovery) begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] - | recovery_debug_req_out [SysGroupId]; + | recovery_debug_req_out [dmr_shared_id(dmr_group_id(i))]; end else begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; end core_perf_counters_o[i] = sys_perf_counters_i [SysCoreIndex]; - // Setback - if (RapidRecovery) begin - core_setback_o [i] = recovery_setback_out [SysGroupId]; - end else begin - core_setback_o [i] = '0; - end - // IRQ core_irq_req_o [i] = sys_irq_req_i [SysCoreIndex]; core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; @@ -1510,6 +1526,12 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; + // Setback + if (RapidRecovery) begin + core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = '0; + end end else begin : gen_independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 85ec8771..5df0e9e0 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -77,8 +77,8 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // 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; - assign dmr_hw2reg.dmr_config.rapid_recovery.d = rapid_recovery_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; /************************** @@ -90,26 +90,34 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( dmr_red_mode_d = dmr_red_mode_q; dmr_incr_mismatches_o = '0; recovery_request_o = 1'b0; + sw_resynch_req_o = 1'b0; dmr_hw2reg.dmr_config.force_recovery.de = 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) begin + 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; dmr_red_mode_d = DMR_RESTORE; end // If error detected, restore - if (dmr_error_i && RapidRecovery) begin + if (dmr_error_i && RapidRecovery && dmr_reg2hw.dmr_config.rapid_recovery.q) begin + $display("[HMR-dual] %t - mismatch detected, rapid recovery starting", $realtime); dmr_red_mode_d = DMR_RESTORE; - recovery_request_o = 1'b1; + end + + if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.q)) begin + $display("[HMR-dual] %t - mismatch detected, SW trigger", $realtime); + sw_resynch_req_o = 1'b1; end end DMR_RESTORE: begin + recovery_request_o = 1'b1; if (recovery_finished_i) begin + $display("[HMR-dual] %t - mismatch restored", $realtime); dmr_red_mode_d = DMR_RUN; end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 11e0b27d..6359ec8c 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -100,6 +100,7 @@ module hmr_tmr_ctrl #( tmr_setback_d = 1'b0; tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; + sw_resynch_req_o = 1'b0; tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; @@ -116,7 +117,7 @@ module hmr_tmr_ctrl #( // If error detected, do resynchronization if (tmr_single_mismatch_i) begin - $display("[ODRG] %t - mismatch detected", $realtime); + $display("[HMR-triple] %t - mismatch detected", $realtime); if (tmr_error_i[0]) tmr_incr_mismatches_o[0] = 1'b1; if (tmr_error_i[1]) tmr_incr_mismatches_o[1] = 1'b1; if (tmr_error_i[2]) tmr_incr_mismatches_o[2] = 1'b1; @@ -129,6 +130,7 @@ module hmr_tmr_ctrl #( end TMR_UNLOAD: begin + sw_resynch_req_o = 1'b1; // If unload complete, go to reload (and reset) if (tmr_reg2hw.sp_store.q != '0) begin tmr_red_mode_d = TMR_RELOAD; @@ -141,7 +143,7 @@ module hmr_tmr_ctrl #( TMR_RELOAD: begin // If reload complete, finish (or reset if error happens during reload) if (tmr_reg2hw.sp_store.q == '0) begin - $display("[ODRG] %t - mismatch restored", $realtime); + $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 && From eefb04a81069812605036903f739a343246b081e Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 1 Feb 2023 16:19:47 +0100 Subject: [PATCH 14/66] Generating correct offsets in RF address generator. --- rtl/HMR/DMR_address_generator.sv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/DMR_address_generator.sv b/rtl/HMR/DMR_address_generator.sv index 12e4d41d..e832de28 100644 --- a/rtl/HMR/DMR_address_generator.sv +++ b/rtl/HMR/DMR_address_generator.sv @@ -38,17 +38,17 @@ generate for (genvar i = 0; i < NumVotingSignals; i++) begin always_ff @(posedge clk_i, negedge rst_ni) begin : address_generator_counter if (~rst_ni) - addr_count [i] <= '0; + addr_count [i] <= '1; else begin if (clear_i || addr_count_rst [i]) - addr_count [i] <= '0; + addr_count [i] <= '1; else if (enable_i) addr_count [i] <= addr_count [i] + 1; else addr_count [i] <= addr_count [i]; end end - assign addr_count_rst [i] = ( addr_count [i] == NumAddr/2 ) ? 1'b1 : 1'b0; + assign addr_count_rst [i] = ( addr_count [i] == NumAddr/2 - 1) ? 1'b1 : 1'b0; end endgenerate From a13cb88b29c40cc6c24a93bde3bde76f9e0289fb Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Thu, 2 Feb 2023 18:39:30 +0100 Subject: [PATCH 15/66] Properly connecting rapid recovery controller signals to recovery PC. --- rtl/HMR/HMR_wrap.sv | 4 ++-- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 5fcb53fc..432ee0e1 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -851,9 +851,9 @@ module HMR_wrap import recovery_pkg::*; #( .clk_i, .rst_ni, .clear_i ( '0 ), - .read_enable_i ( backup_pc_enable_out [i] ), + .read_enable_i ( recovery_pc_enable_out [i] ), .write_enable_i ( ~backup_program_counter_error [i] - & recovery_pc_enable_out [i] ), + & backup_pc_enable_out [i] ), // Backup Ports .backup_program_counter_i ( backup_program_counter_int [i] ), .backup_branch_i ( backup_branch_int [i] ), diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv index 5f409733..97a094e7 100644 --- a/rtl/HMR/hmr_rapid_recovery_ctrl.sv +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -82,6 +82,8 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( IDLE: begin // If requested start the routine in the reset state if (start_recovery_i) begin + // Disable reading for the backup PC + backup_pc_enable_d = 1'b0; rec_mode_d = RESET; end end @@ -91,8 +93,6 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( setback_d = 1'b1; // Lock the instruction requests instr_lock_d = 1'b1; - // Disable reading for the backup PC - backup_pc_enable_d = 1'b0; // Go to request halt of the core rec_mode_d = HALT; end From 25ae5027e857d3dd0d8bd38cb6048c51712a96bc Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 2 Feb 2023 17:03:18 +0100 Subject: [PATCH 16/66] Update shared_id selection for only TMR support Turneded max into function because Synopsys does not synthesize it. --- rtl/HMR/HMR_wrap.sv | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 432ee0e1..d3e08b9a 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -166,6 +166,11 @@ module HMR_wrap import recovery_pkg::*; #( // APU/SHARED_FPU not implemented ); + function int max(int a, int b); + return (a > b) ? a : b; + endfunction + + localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); function int tmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumTMRGroups; @@ -178,7 +183,7 @@ module HMR_wrap import recovery_pkg::*; #( endfunction function int tmr_shared_id (int group_id); - if (InterleaveGrps) return group_id; + if (InterleaveGrps || !(DMRSupported || DMRFixed)) return group_id; else return group_id + group_id/2; endfunction @@ -205,8 +210,6 @@ module HMR_wrap import recovery_pkg::*; #( localparam int unsigned MainConcatWidth = SeparateData ? CtrlConcatWidth : CtrlConcatWidth + DataConcatWidth; - let max(a,b) = (a > b) ? a : b; - localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); localparam int unsigned RFAddrWidth = 6; logic [ NumCores-1:0][MainConcatWidth-1:0] main_concat_in; From 460a50d1940e43d1b7ff37fbd3a8afffcb70f319 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 3 Feb 2023 12:02:41 +0100 Subject: [PATCH 17/66] Add synch request signals Fix TMR synch request --- rtl/HMR/HMR_wrap.sv | 17 +++++++++++++++++ rtl/HMR/hmr_dmr_ctrl.sv | 2 ++ rtl/HMR/hmr_tmr_ctrl.sv | 16 +++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index d3e08b9a..b2ec1c5d 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -62,12 +62,14 @@ module HMR_wrap import recovery_pkg::*; #( output logic [NumTMRGroups-1:0] tmr_failure_o , output logic [ NumSysCores-1:0] tmr_error_o , // Should this not be NumTMRCores? or NumCores? output logic [NumTMRGroups-1:0] tmr_resynch_req_o, + output logic [ NumCores-1:0] tmr_sw_synch_req_o, input logic [NumTMRGroups-1:0] tmr_cores_synch_i, // DMR signals output logic [NumDMRGroups-1:0] dmr_failure_o , output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? output logic [NumDMRGroups-1:0] dmr_resynch_req_o, + output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, // Backup Port from Cores'Program Counter @@ -465,6 +467,7 @@ module HMR_wrap import recovery_pkg::*; #( reg_req_t [NumTMRGroups-1:0] tmr_register_reqs; reg_resp_t [NumTMRGroups-1:0] tmr_register_resps; + logic [NumTMRGroups-1:0] tmr_sw_synch_req; localparam TMRSelWidth = $clog2(NumTMRGroups); @@ -487,6 +490,7 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = NumTMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign tmr_incr_mismatches[i] = '0; + assign tmr_sw_synch_req_o[i] = '0; end for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups @@ -519,6 +523,7 @@ module HMR_wrap import recovery_pkg::*; #( .setback_o ( tmr_setback_q[i] ), .sw_resynch_req_o ( tmr_resynch_req_o[i] ), + .sw_synch_req_o ( tmr_sw_synch_req[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), @@ -529,6 +534,10 @@ module HMR_wrap import recovery_pkg::*; #( .cores_synch_i ( tmr_cores_synch_i[i] ) ); + assign tmr_sw_synch_req_o[tmr_core_id(i, 0)] = tmr_sw_synch_req[i]; + assign tmr_sw_synch_req_o[tmr_core_id(i, 1)] = tmr_sw_synch_req[i]; + assign tmr_sw_synch_req_o[tmr_core_id(i, 2)] = tmr_sw_synch_req[i]; + assign tmr_failure[i] = tmr_data_req_out[i] ? tmr_failure_main[i] | tmr_failure_data[i] : tmr_failure_main[i]; @@ -594,6 +603,7 @@ module HMR_wrap import recovery_pkg::*; #( assign tmr_grp_in_independent = '0; assign tmr_setback_q = '0; assign tmr_resynch_req_o = '0; + assign tmr_sw_synch_req_o = '0; end /************************************************************ @@ -607,6 +617,7 @@ module HMR_wrap import recovery_pkg::*; #( reg_req_t [NumDMRGroups-1:0] dmr_register_reqs; reg_resp_t [NumDMRGroups-1:0] dmr_register_resps; + logic [NumDMRGroups-1:0] dmr_sw_synch_req; localparam DMRSelWidth = $clog2(NumDMRGroups); @@ -629,6 +640,7 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = NumDMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign dmr_incr_mismatches[i] = '0; + assign dmr_sw_synch_req_o[i] = '0; end for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_dmr_groups @@ -656,6 +668,7 @@ module HMR_wrap import recovery_pkg::*; #( .setback_o ( dmr_setback_q [i] ), .sw_resynch_req_o ( dmr_resynch_req_o [i] ), + .sw_synch_req_o ( dmr_sw_synch_req [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), @@ -668,6 +681,9 @@ module HMR_wrap import recovery_pkg::*; #( .recovery_finished_i ( dmr_recovery_finished[i] ) ); + assign dmr_sw_synch_req_o[dmr_core_id(i, 0)] = dmr_sw_synch_req[i]; + assign dmr_sw_synch_req_o[dmr_core_id(i, 1)] = dmr_sw_synch_req[i]; + /********************* * DMR Core Checkers * *********************/ @@ -821,6 +837,7 @@ module HMR_wrap import recovery_pkg::*; #( assign top_register_resps[2].rdata = '0; assign top_register_resps[2].error = 1'b1; assign top_register_resps[2].ready = 1'b1; + assign dmr_sw_synch_req_o = '0; end // RapidRecovery output signals diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 5df0e9e0..e7ffed29 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -37,6 +37,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // DMR control signals output logic setback_o, output logic sw_resynch_req_o, + output logic sw_synch_req_o, output logic grp_in_independent_o, output logic rapid_recovery_en_o, output logic [1:0] dmr_incr_mismatches_o, @@ -60,6 +61,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( assign setback_o = dmr_setback_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 sw_synch_req_o = dmr_reg2hw.dmr_enable.q & dmr_red_mode_q == NON_DMR; hmr_dmr_regs_reg_top #( .reg_req_t(reg_req_t), diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 6359ec8c..78ac5b90 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -43,6 +43,7 @@ module hmr_tmr_ctrl #( // TMR control signals output logic setback_o, output logic sw_resynch_req_o, + output logic sw_synch_req_o, output logic grp_in_independent_o, output logic rapid_recovery_en_o, output logic [2:0] tmr_incr_mismatches_o, @@ -65,7 +66,7 @@ module hmr_tmr_ctrl #( assign setback_o = tmr_setback_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.q & RapidRecovery; hmr_tmr_regs_reg_top #( .reg_req_t(reg_req_t), @@ -101,6 +102,7 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; sw_resynch_req_o = 1'b0; + sw_synch_req_o = 1'b0; tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; @@ -109,7 +111,7 @@ module hmr_tmr_ctrl #( // 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.delay_resynch == 0) begin + if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin tmr_red_mode_d = TMR_UNLOAD; // TODO: buffer the restoration until delay_resynch is disabled end @@ -175,9 +177,13 @@ module hmr_tmr_ctrl #( end end // Set TMR mode on external signal that cores are synchronized - if (tmr_red_mode_q == NON_TMR && cores_synch_i) begin - if (tmr_reg2hw.tmr_enable.q == 1'b1) begin - tmr_red_mode_d = TMR_RUN; + if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.q == 1'b1) begin + sw_synch_req_o = 1'b1; + if (cores_synch_i) begin + tmr_red_mode_d = TMR_RELOAD; + if (tmr_reg2hw.tmr_config.setback.q) begin + tmr_setback_d = 1'b1; + end end end end From aca5789724266d983e56729aef166481469c8f93 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 3 Feb 2023 13:52:38 +0100 Subject: [PATCH 18/66] Move SP store reg from tmr to core registers --- Makefile | 3 +- rtl/HMR/HMR_core_regs.hjson | 12 ++++++++ rtl/HMR/HMR_regs.hjson | 2 +- rtl/HMR/HMR_tmr_regs.hjson | 12 -------- rtl/HMR/HMR_wrap.sv | 11 ++++++-- rtl/HMR/hmr_core_regs_reg_pkg.sv | 23 +++++++++++----- rtl/HMR/hmr_core_regs_reg_top.sv | 47 +++++++++++++++++++++++++++++--- rtl/HMR/hmr_tmr_ctrl.sv | 8 ++++-- rtl/HMR/hmr_tmr_regs_reg_pkg.sv | 35 +++++++----------------- rtl/HMR/hmr_tmr_regs_reg_top.sv | 47 +++----------------------------- rtl/HMR/hmr_v1.h | 11 +++++--- 11 files changed, 109 insertions(+), 102 deletions(-) diff --git a/Makefile b/Makefile index 9910dd8d..153a1446 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,8 @@ define HMR_H_HEADER_STRING #define HMR_DMR_OFFSET 0x200 #define HMR_TMR_OFFSET 0x300 -#define HMR_CORE_INCREMENT 0x008 +#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 diff --git a/rtl/HMR/HMR_core_regs.hjson b/rtl/HMR/HMR_core_regs.hjson index b37d5499..c55f5ede 100644 --- a/rtl/HMR/HMR_core_regs.hjson +++ b/rtl/HMR/HMR_core_regs.hjson @@ -43,6 +43,18 @@ 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_regs.hjson b/rtl/HMR/HMR_regs.hjson index fb02cebc..c6a10cbc 100644 --- a/rtl/HMR/HMR_regs.hjson +++ b/rtl/HMR/HMR_regs.hjson @@ -12,7 +12,7 @@ param_list: [ { name: "NumCores", - default: "12" # Supports up to 32 cores + default: "12" # Supports up to 16 cores }, { name: "NumDMRGroups", default: "6" diff --git a/rtl/HMR/HMR_tmr_regs.hjson b/rtl/HMR/HMR_tmr_regs.hjson index e01825b9..8d6dab90 100644 --- a/rtl/HMR/HMR_tmr_regs.hjson +++ b/rtl/HMR/HMR_tmr_regs.hjson @@ -55,18 +55,6 @@ desc: "Forces a resynchronization routine" } ] - }, - { name: "sp_store", - desc: "Stack Pointer storage register", - swaccess: "rw", - hwaccess: "hrw", - hwqe: "true", - fields: [ - { bits: "31:0", - name: "SP", - desc: "Stack Pointer" - } - ] } ] } diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index b2ec1c5d..51f78e70 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -335,6 +335,9 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumTMRGroups-1:0] tmr_grp_in_independent; logic [NumTMRGroups-1:0] tmr_rapid_recovery_en; + logic [NumCores-1:0] sp_store_is_zero; + logic [NumCores-1:0] sp_store_will_be_zero; + for (genvar i = 0; i < NumCores; i++) begin : gen_global_status assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; @@ -414,7 +417,7 @@ module HMR_wrap import recovery_pkg::*; #( reg_req_t [NumCores-1:0] core_register_reqs; reg_resp_t [NumCores-1:0] core_register_resps; - // 2 words per core + // 4 words per core reg_demux #( .NoPorts ( NumCores ), @@ -423,7 +426,7 @@ module HMR_wrap import recovery_pkg::*; #( ) i_core_reg_demux ( .clk_i, .rst_ni, - .in_select_i( top_register_reqs [1].addr[3+$clog2(NumCores)-1:3] ), + .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 ), @@ -455,6 +458,8 @@ module HMR_wrap import recovery_pkg::*; #( 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; end @@ -530,6 +535,8 @@ module HMR_wrap import recovery_pkg::*; #( .tmr_single_mismatch_i( tmr_single_mismatch[i] ), .tmr_error_i ( tmr_error[i] ), .tmr_failure_i ( tmr_failure[i] ), + .sp_store_is_zero ( sp_store_is_zero[tmr_core_id(i, 0)] ), + .sp_store_will_be_zero( sp_store_will_be_zero[tmr_core_id(i, 0)] ), .fetch_en_i ( sys_fetch_en_i[tmr_core_id(i, 0)] ), .cores_synch_i ( tmr_cores_synch_i[i] ) ); diff --git a/rtl/HMR/hmr_core_regs_reg_pkg.sv b/rtl/HMR/hmr_core_regs_reg_pkg.sv index b594350c..602bd91a 100644 --- a/rtl/HMR/hmr_core_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_core_regs_reg_pkg.sv @@ -7,7 +7,7 @@ package hmr_core_regs_reg_pkg; // Address widths within the block - parameter int BlockAw = 3; + parameter int BlockAw = 4; //////////////////////////// // Typedefs for registers // @@ -17,6 +17,11 @@ package hmr_core_regs_reg_pkg; 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; @@ -36,7 +41,8 @@ package hmr_core_regs_reg_pkg; // Register -> HW type typedef struct packed { - hmr_core_regs_reg2hw_mismatches_reg_t mismatches; // [31:0] + 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 @@ -46,8 +52,9 @@ package hmr_core_regs_reg_pkg; } hmr_core_regs_hw2reg_t; // Register offsets - parameter logic [BlockAw-1:0] HMR_CORE_REGS_CURRENT_MODE_OFFSET = 3'h 0; - parameter logic [BlockAw-1:0] HMR_CORE_REGS_MISMATCHES_OFFSET = 3'h 4; + 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; @@ -58,13 +65,15 @@ package hmr_core_regs_reg_pkg; // Register index typedef enum int { HMR_CORE_REGS_CURRENT_MODE, - HMR_CORE_REGS_MISMATCHES + 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 [2] = '{ + 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[1] HMR_CORE_REGS_MISMATCHES + 4'b 1111 // index[2] HMR_CORE_REGS_SP_STORE }; endpackage diff --git a/rtl/HMR/hmr_core_regs_reg_top.sv b/rtl/HMR/hmr_core_regs_reg_top.sv index 39e65762..d9cf8ceb 100644 --- a/rtl/HMR/hmr_core_regs_reg_top.sv +++ b/rtl/HMR/hmr_core_regs_reg_top.sv @@ -10,7 +10,7 @@ module hmr_core_regs_reg_top #( parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, - parameter int AW = 3 + parameter int AW = 4 ) ( input logic clk_i, input logic rst_ni, @@ -77,6 +77,9 @@ module hmr_core_regs_reg_top #( 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) @@ -153,13 +156,41 @@ module hmr_core_regs_reg_top #( ); + // 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 [1:0] addr_hit; + + + 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 ; @@ -168,7 +199,8 @@ module hmr_core_regs_reg_top #( 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[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; @@ -180,6 +212,9 @@ module hmr_core_regs_reg_top #( 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; @@ -194,6 +229,10 @@ module hmr_core_regs_reg_top #( 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 @@ -216,7 +255,7 @@ endmodule module hmr_core_regs_reg_top_intf #( - parameter int AW = 3, + parameter int AW = 4, localparam int DW = 32 ) ( input logic clk_i, diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 78ac5b90..12f78194 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -50,6 +50,8 @@ module hmr_tmr_ctrl #( input logic tmr_single_mismatch_i, input logic [2:0] tmr_error_i, input logic tmr_failure_i, + input logic sp_store_is_zero, + input logic sp_store_will_be_zero, input logic fetch_en_i, input logic cores_synch_i ); @@ -134,7 +136,7 @@ module hmr_tmr_ctrl #( TMR_UNLOAD: begin sw_resynch_req_o = 1'b1; // If unload complete, go to reload (and reset) - if (tmr_reg2hw.sp_store.q != '0) begin + if (!sp_store_is_zero) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q) begin tmr_setback_d = 1'b1; @@ -144,13 +146,13 @@ module hmr_tmr_ctrl #( TMR_RELOAD: begin // If reload complete, finish (or reset if error happens during reload) - if (tmr_reg2hw.sp_store.q == '0) begin + if (sp_store_is_zero) begin $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 && - !(tmr_reg2hw.sp_store.qe && reg_req_i.wdata == '0)) begin + !sp_store_will_be_zero) begin tmr_setback_d = 1'b1; end end diff --git a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv index 148055e7..89eeca99 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_pkg.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_pkg.sv @@ -7,7 +7,7 @@ package hmr_tmr_regs_reg_pkg; // Address widths within the block - parameter int BlockAw = 4; + parameter int BlockAw = 3; //////////////////////////// // Typedefs for registers // @@ -41,11 +41,6 @@ package hmr_tmr_regs_reg_pkg; } force_resynch; } hmr_tmr_regs_reg2hw_tmr_config_reg_t; - typedef struct packed { - logic [31:0] q; - logic qe; - } hmr_tmr_regs_reg2hw_sp_store_reg_t; - typedef struct packed { logic d; logic de; @@ -74,42 +69,32 @@ package hmr_tmr_regs_reg_pkg; } force_resynch; } hmr_tmr_regs_hw2reg_tmr_config_reg_t; - typedef struct packed { - logic [31:0] d; - logic de; - } hmr_tmr_regs_hw2reg_sp_store_reg_t; - // Register -> HW type typedef struct packed { - hmr_tmr_regs_reg2hw_tmr_enable_reg_t tmr_enable; // [44:43] - hmr_tmr_regs_reg2hw_tmr_config_reg_t tmr_config; // [42:33] - hmr_tmr_regs_reg2hw_sp_store_reg_t sp_store; // [32:0] + 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; // [44:43] - hmr_tmr_regs_hw2reg_tmr_config_reg_t tmr_config; // [42:33] - hmr_tmr_regs_hw2reg_sp_store_reg_t sp_store; // [32:0] + 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 = 4'h 0; - parameter logic [BlockAw-1:0] HMR_TMR_REGS_TMR_CONFIG_OFFSET = 4'h 4; - parameter logic [BlockAw-1:0] HMR_TMR_REGS_SP_STORE_OFFSET = 4'h 8; + 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_SP_STORE + 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 [3] = '{ + 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 - 4'b 1111 // index[2] HMR_TMR_REGS_SP_STORE + 4'b 0001 // index[1] HMR_TMR_REGS_TMR_CONFIG }; endpackage diff --git a/rtl/HMR/hmr_tmr_regs_reg_top.sv b/rtl/HMR/hmr_tmr_regs_reg_top.sv index 666d010a..1249580e 100644 --- a/rtl/HMR/hmr_tmr_regs_reg_top.sv +++ b/rtl/HMR/hmr_tmr_regs_reg_top.sv @@ -10,7 +10,7 @@ module hmr_tmr_regs_reg_top #( parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, - parameter int AW = 4 + parameter int AW = 3 ) ( input logic clk_i, input logic rst_ni, @@ -86,9 +86,6 @@ module hmr_tmr_regs_reg_top #( logic tmr_config_force_resynch_qs; logic tmr_config_force_resynch_wd; logic tmr_config_force_resynch_we; - logic [31:0] sp_store_qs; - logic [31:0] sp_store_wd; - logic sp_store_we; // Register instances // R[tmr_enable]: V(False) @@ -250,41 +247,13 @@ module hmr_tmr_regs_reg_top #( ); - // 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 (hw2reg.sp_store.de), - .d (hw2reg.sp_store.d ), - - // 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; + 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); - addr_hit[2] = (reg_addr == HMR_TMR_REGS_SP_STORE_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -293,8 +262,7 @@ module hmr_tmr_regs_reg_top #( 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))) | - (addr_hit[2] & (|(HMR_TMR_REGS_PERMIT[2] & ~reg_be))))); + (addr_hit[1] & (|(HMR_TMR_REGS_PERMIT[1] & ~reg_be))))); end assign tmr_enable_we = addr_hit[0] & reg_we & !reg_error; @@ -315,9 +283,6 @@ module hmr_tmr_regs_reg_top #( assign tmr_config_force_resynch_we = addr_hit[1] & reg_we & !reg_error; assign tmr_config_force_resynch_wd = reg_wdata[4]; - 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; @@ -334,10 +299,6 @@ module hmr_tmr_regs_reg_top #( reg_rdata_next[4] = tmr_config_force_resynch_qs; end - addr_hit[2]: begin - reg_rdata_next[31:0] = sp_store_qs; - end - default: begin reg_rdata_next = '1; end @@ -360,7 +321,7 @@ endmodule module hmr_tmr_regs_reg_top_intf #( - parameter int AW = 4, + parameter int AW = 3, localparam int DW = 32 ) ( input logic clk_i, diff --git a/rtl/HMR/hmr_v1.h b/rtl/HMR/hmr_v1.h index 92ed91bb..ec4f2d7e 100644 --- a/rtl/HMR/hmr_v1.h +++ b/rtl/HMR/hmr_v1.h @@ -24,7 +24,10 @@ #define HMR_DMR_OFFSET 0x200 #define HMR_TMR_OFFSET 0x300 -#define HMR_CORE_INCREMENT 0x008 +#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 @@ -112,6 +115,9 @@ extern "C" { // 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 @@ -170,9 +176,6 @@ extern "C" { #define HMR_TMR_REGS_TMR_CONFIG_RAPID_RECOVERY_BIT 3 #define HMR_TMR_REGS_TMR_CONFIG_FORCE_RESYNCH_BIT 4 -// Stack Pointer storage register -#define HMR_TMR_REGS_SP_STORE_REG_OFFSET 0x8 - #ifdef __cplusplus } // extern "C" #endif From 452ecdf824071a89feef4b041f67a368fac1acfa Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 8 May 2023 11:41:26 +0200 Subject: [PATCH 19/66] Merged CSRs backup and recovery. --- Bender.yml | 4 +- rtl/HMR/DMR_CSR_checker.sv | 51 ++++++++++ rtl/HMR/HMR_wrap.sv | 50 +++++++++- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 13 +++ rtl/HMR/recovery_csr.sv | 151 +++++++++++++++++++++++++++++ rtl/HMR/recovery_pkg.sv | 34 +++++-- 6 files changed, 291 insertions(+), 12 deletions(-) create mode 100644 rtl/HMR/DMR_CSR_checker.sv create mode 100644 rtl/HMR/recovery_csr.sv diff --git a/Bender.yml b/Bender.yml index bc388634..bac0b426 100644 --- a/Bender.yml +++ b/Bender.yml @@ -105,9 +105,11 @@ sources: - files: - rtl/HMR/recovery_pkg.sv - - rtl/HMR/recovery_rf.sv + - rtl/HMR/recovery_csr.sv - rtl/HMR/recovery_pc.sv + - rtl/HMR/recovery_rf.sv - rtl/HMR/DMR_checker.sv + - rtl/HMR/DMR_CSR_checker.sv - rtl/HMR/DMR_address_generator.sv # - rtl/HMR/DMR_controller.sv - rtl/HMR/hmr_rapid_recovery_ctrl.sv diff --git a/rtl/HMR/DMR_CSR_checker.sv b/rtl/HMR/DMR_CSR_checker.sv new file mode 100644 index 00000000..0bcd067f --- /dev/null +++ b/rtl/HMR/DMR_CSR_checker.sv @@ -0,0 +1,51 @@ +/* Copyright 2020 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. + * + * CS Registers Checker + * + */ + +import recovery_pkg::*; + +module DMR_CSR_checker ( + input csrs_intf_t csr_a_i, + input csrs_intf_t csr_b_i, + output csrs_intf_t check_o, + output logic error_o +); + +logic compare_mstatus; +logic compare_mie; +logic compare_mtvec; +logic compare_mscratch; +logic compare_mip; +logic compare_mepc; +logic compare_mcause; +logic error; + +assign compare_mstatus = |(csr_a_i.csr_mstatus ^ csr_b_i.csr_mstatus); +assign compare_mie = |(csr_a_i.csr_mie ^ csr_b_i.csr_mie); +assign compare_mtvec = |(csr_a_i.csr_mtvec ^ csr_b_i.csr_mtvec); +assign compare_mscratch = |(csr_a_i.csr_mscratch ^ csr_b_i.csr_mscratch); +assign compare_mip = |(csr_a_i.csr_mip ^ csr_b_i.csr_mip); +assign compare_mepc = |(csr_a_i.csr_mepc ^ csr_b_i.csr_mepc); +assign compare_mcause = |(csr_a_i.csr_mcause ^ csr_b_i.csr_mcause); + +assign error = compare_mstatus | + compare_mie | + compare_mtvec | + compare_mscratch | + compare_mip | + compare_mepc | + compare_mcause; +assign check_o = (error) ? csr_a_i : '0; +assign error_o = error; + +endmodule : DMR_CSR_checker diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 51f78e70..5bedda40 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -72,6 +72,10 @@ module HMR_wrap import recovery_pkg::*; #( output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + // Backup Port from Cores' CSRs + input csrs_intf_t [NumCores-1:0] backup_csr_i, + // Recovery Port to Cores' CSRs + output csrs_intf_t [NumCores-1:0] recovery_csr_o, // Backup Port from Cores'Program Counter input logic [ NumCores-1:0][DataWidth-1:0] backup_program_counter_i, output logic [ NumCores-1:0] pc_recover_o, @@ -261,7 +265,8 @@ module HMR_wrap import recovery_pkg::*; #( dmr_backup_regfile_wdata_a, dmr_backup_regfile_wdata_b, dmr_backup_branch_addr_int; - logic [ NumDMRGroups-1:0] dmr_backup_program_counter_error, + logic [ NumDMRGroups-1:0] dmr_backup_csr_error, + dmr_backup_program_counter_error, dmr_backup_branch_error, dmr_backup_branch_addr_error, dmr_backup_regfile_error_a, @@ -287,7 +292,9 @@ module HMR_wrap import recovery_pkg::*; #( backup_regfile_we_b, backup_program_counter_error, recovery_branch_out, + backup_csr_enable_out, backup_pc_enable_out, + recovery_csr_enable_out, recovery_pc_enable_out, recovery_debug_req_out, recovery_debug_halted_in, @@ -301,6 +308,7 @@ module HMR_wrap import recovery_pkg::*; #( regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; + csrs_intf_t [NumBackupRegfiles-1:0] dmr_backup_csr, recovery_csr_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin : gen_separate_data @@ -731,6 +739,7 @@ module HMR_wrap import recovery_pkg::*; #( assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]) | + dmr_backup_csr_error [i] | dmr_backup_program_counter_error[i] | dmr_backup_branch_error [i] | dmr_backup_branch_addr_error [i] | @@ -739,6 +748,16 @@ module HMR_wrap import recovery_pkg::*; #( dmr_backup_regfile_addr_error_a [i] | dmr_backup_regfile_addr_error_b [i]; + /******************** + * DMR CSRs Checker * + ********************/ + DMR_CSR_checker dmr_csr_checker ( + .csr_a_i ( backup_csr_i[dmr_core_id(i, 0)] ), + .csr_b_i ( backup_csr_i[dmr_core_id(i, 1)] ), + .check_o ( dmr_backup_csr [i] ), + .error_o ( dmr_backup_csr_error [i] ) + ); + /****************** * DMR PC Checker * ******************/ @@ -863,11 +882,28 @@ module HMR_wrap import recovery_pkg::*; #( .debug_halt_i ( recovery_debug_halted_in [i] ), .debug_resume_o ( recovery_debug_resume_out [i] ), .recovery_regfile_waddr_o ( core_recovery_regfile_wport_out[i] ), + .backup_csr_enable_o ( backup_csr_enable_out [i] ), .backup_pc_enable_o ( backup_pc_enable_out [i] ), + .recover_csr_enable_o ( recovery_csr_enable_out [i] ), .recover_pc_enable_o ( recovery_pc_enable_out [i] ), .recover_rf_enable_o ( recovery_trigger_out [i] ) ); + /************************* + * Recovery CS Registers * + *************************/ + recovery_csr #( + .ECCEnabled ( 1 ) + ) RCSR ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .read_enable_i ( recovery_csr_enable_out [i] ), + .write_enable_i ( ~dmr_backup_csr_error [i] + & backup_csr_enable_out [i] ), + .backup_csr_i ( dmr_backup_csr [i] ), + .recovery_csr_o ( recovery_csr_out [i] ) + ); + /**************************** * Recovery Program Counter * ****************************/ @@ -987,6 +1023,9 @@ module HMR_wrap import recovery_pkg::*; #( core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; + // CSRs + recovery_csr_o [i] = recovery_csr_out [dmr_shared_id(dmr_group_id(i))]; + // PC pc_recover_o [i] = recovery_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; recovery_program_counter_o [i] = recovery_program_counter_out [dmr_shared_id(dmr_group_id(i))]; @@ -1008,6 +1047,9 @@ module HMR_wrap import recovery_pkg::*; #( core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; + // CSRs + recovery_csr_o [i] = recovery_csr_out [tmr_shared_id(tmr_group_id(i))]; + // PC pc_recover_o [i] = recovery_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; recovery_program_counter_o [i] = recovery_program_counter_out [tmr_shared_id(tmr_group_id(i))]; @@ -1031,6 +1073,9 @@ module HMR_wrap import recovery_pkg::*; #( core_recover_o [i] = '0; core_instr_lock_o [i] = '0; + // CSRs + recovery_csr_o [i] = '0; + // PC pc_recover_o [i] = '0; recovery_program_counter_o [i] = '0; @@ -1057,6 +1102,9 @@ module HMR_wrap import recovery_pkg::*; #( assign core_recover_o [i] = '0; assign core_instr_lock_o [i] = '0; + // CSRs + assign recovery_csr_o [i] = '0; + // PC assign pc_recover_o [i] = '0; assign recovery_program_counter_o [i] = '0; diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv index 97a094e7..3315e271 100644 --- a/rtl/HMR/hmr_rapid_recovery_ctrl.sv +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -29,7 +29,9 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( output regfile_write_t recovery_regfile_waddr_o, // Signals to backup state + output logic backup_csr_enable_o, output logic backup_pc_enable_o, + output logic recover_csr_enable_o, output logic recover_pc_enable_o, output logic recover_rf_enable_o ); @@ -38,6 +40,7 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( recovery_mode_e rec_mode_d, rec_mode_q; logic instr_lock_d, instr_lock_q; + logic backup_csr_enable_d, backup_csr_enable_q; logic backup_pc_enable_d, backup_pc_enable_q; logic setback_d, setback_q; logic addr_gen_done; @@ -64,15 +67,18 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( assign instr_lock_o = instr_lock_q; + assign backup_csr_enable_o = backup_csr_enable_q; assign backup_pc_enable_o = backup_pc_enable_q; assign setback_o = setback_q; always_comb begin rec_mode_d = rec_mode_q; instr_lock_d = instr_lock_q; + backup_csr_enable_d = backup_csr_enable_q; backup_pc_enable_d = backup_pc_enable_q; setback_d = 1'b0; debug_req_o = 1'b0; + recover_csr_enable_o = 1'b0; recover_pc_enable_o = 1'b0; recover_rf_enable_o = 1'b0; debug_resume_o = 1'b0; @@ -82,6 +88,8 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( IDLE: begin // If requested start the routine in the reset state if (start_recovery_i) begin + // Disable reading for the backup CSR + backup_csr_enable_d = 1'b0; // Disable reading for the backup PC backup_pc_enable_d = 1'b0; rec_mode_d = RESET; @@ -107,6 +115,8 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( end RESTORE: begin + // Enable CSR recovery routine + recover_csr_enable_o = 1'b1; // Enable the PC recovery routine recover_pc_enable_o = 1'b1; // Enable the RF recovery routine @@ -114,6 +124,7 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( // If recovery routine complete, continue if (addr_gen_done) begin instr_lock_d = 1'b0; + backup_csr_enable_d = 1'b1; backup_pc_enable_d = 1'b1; rec_mode_d = IDLE; debug_resume_o = 1'b1; @@ -127,11 +138,13 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( if (!rst_ni) begin instr_lock_q <= 1'b0; rec_mode_q <= IDLE; + backup_csr_enable_q <= 1'b1; backup_pc_enable_q <= 1'b1; setback_q <= 1'b0; end else begin instr_lock_q <= instr_lock_d; rec_mode_q <= rec_mode_d; + backup_csr_enable_q <= backup_csr_enable_d; backup_pc_enable_q <= backup_pc_enable_d; setback_q <= setback_d; end diff --git a/rtl/HMR/recovery_csr.sv b/rtl/HMR/recovery_csr.sv new file mode 100644 index 00000000..8ef95555 --- /dev/null +++ b/rtl/HMR/recovery_csr.sv @@ -0,0 +1,151 @@ +/* Copyright 2020 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. + * + * Recovery Control Status Registers + * ECC-protected register that stores the CSRs values from the cores + * + */ + +import recovery_pkg::*; + +module recovery_csr #( + parameter ECCEnabled = 0, + parameter NonProtectedWidth = 32, + parameter ProtectedWidth = 39, + localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth +) ( +input logic clk_i , +input logic rst_ni, +input logic read_enable_i, +input logic write_enable_i, +input csrs_intf_t backup_csr_i, +output csrs_intf_t recovery_csr_o +); + +csrs_intf_t csr_inp, + csr_out; + +logic [31:0] csr_dec_mstatus, + csr_dec_mie, + csr_dec_mtvec, + csr_dec_mscratch, + csr_dec_mip, + csr_dec_mepc, + csr_dec_mcause; + +assign csr_inp = backup_csr_i; +assign recovery_csr_o = (read_enable_i) ? csr_out : '0; + +if (ECCEnabled) begin : gen_ecc_csrs + + ecc_csrs_intf_t csr_d, csr_q; + + prim_secded_39_32_enc csr_mstatus_ecc_encoder ( + .in ( {25'd0,csr_inp.csr_mstatus} ), // mtvec is a 7-bit value + .out ( csr_d.csr_mstatus ) + ); + prim_secded_39_32_enc csr_mie_ecc_encoder ( + .in ( csr_inp.csr_mie ), + .out ( csr_d.csr_mie ) + ); + prim_secded_39_32_enc csr_mtvec_ecc_encoder ( + .in ( {8'd0, csr_inp.csr_mtvec} ), // mtvec is a 24-bit value + .out ( csr_d.csr_mtvec ) + ); + prim_secded_39_32_enc csr_mscratch_ecc_encoder ( + .in ( csr_inp.csr_mscratch ), + .out ( csr_d.csr_mscratch ) + ); + prim_secded_39_32_enc csr_mip_ecc_encoder ( + .in ( csr_inp.csr_mip ), + .out ( csr_d.csr_mip ) + ); + prim_secded_39_32_enc csr_mepc_ecc_encoder ( + .in ( csr_inp.csr_mepc), + .out ( csr_d.csr_mepc ) + ); + prim_secded_39_32_enc csr_mcause_ecc_encoder ( + .in ( {26'd0, csr_inp.csr_mcause} ), // mcause is a 6-bit value + .out ( csr_d.csr_mcause ) + ); + + always_ff @(posedge clk_i, negedge rst_ni) begin : ecc_csr_backup + if (~rst_ni) + csr_q <= '0; + else if (write_enable_i) + csr_q <= csr_d; + end + + prim_secded_39_32_dec csr_mstatus_ecc_decoder ( + .in ( csr_q.csr_mstatus ), + .d_o ( csr_dec_mstatus ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mie_ecc_decoder ( + .in ( csr_q.csr_mie ), + .d_o ( csr_dec_mie ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mtvec_ecc_decoder ( + .in ( csr_q.csr_mtvec ), + .d_o ( csr_dec_mtvec ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mscratch_ecc_decoder ( + .in ( csr_q.csr_mscratch ), + .d_o ( csr_dec_mscratch ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mip_ecc_decoder ( + .in ( csr_q.csr_mip ), + .d_o ( csr_dec_mip ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mepc_ecc_decoder ( + .in ( csr_q.csr_mepc ), + .d_o ( csr_dec_mepc ), + .syndrome_o ( ), + .err_o ( ) + ); + prim_secded_39_32_dec csr_mcause_ecc_decoder ( + .in ( csr_q.csr_mcause ), + .d_o ( csr_dec_mcause ), + .syndrome_o ( ), + .err_o ( ) + ); + assign csr_out.csr_mstatus = csr_dec_mstatus[6:0]; + assign csr_out.csr_mie = csr_dec_mie; + assign csr_out.csr_mtvec = csr_dec_mtvec[23:0]; + assign csr_out.csr_mscratch = csr_dec_mscratch; + assign csr_out.csr_mip = csr_dec_mip; + assign csr_out.csr_mepc = csr_dec_mepc; + assign csr_out.csr_mcause = csr_dec_mcause[5:0]; +end else begin : gen_no_ecc_csrs + csrs_intf_t csr_d, csr_q; + + assign csr_d = csr_inp; + + always_ff @(posedge clk_i, negedge rst_ni) begin : csr_backup + if (~rst_ni) + csr_q <= '0; + else if (write_enable_i) + csr_q <= csr_d; + end + assign csr_out = csr_q; + +end + +endmodule : recovery_csr diff --git a/rtl/HMR/recovery_pkg.sv b/rtl/HMR/recovery_pkg.sv index f3ec4ac5..68dfc77a 100644 --- a/rtl/HMR/recovery_pkg.sv +++ b/rtl/HMR/recovery_pkg.sv @@ -15,8 +15,13 @@ package recovery_pkg; localparam int unsigned DataWidth = 32; +localparam int unsigned ProtectedWidth = 39; localparam int unsigned RegfileAddr = 6; localparam int unsigned RecoveryStateBits = 3; +/* CSRs */ +localparam int unsigned MstatusWidth = 7; +localparam int unsigned MtvecWidth = 24; +localparam int unsigned McauseWidth = 6; typedef struct packed { // Write Port A @@ -39,15 +44,24 @@ typedef struct packed { logic [DataWidth-1:0] rdata_b; } regfile_rdata_t; -typedef enum logic [RecoveryStateBits-1:0]{ - IDLE , - RESET , - HALT_REQ , - HALT_WAIT , - RESTORE_PC , - RESTORE_RF , - RESTORE_CSR, - EXIT -} recovery_routine_state_e; +typedef struct packed { + logic [MstatusWidth-1:0] csr_mstatus; + logic [ DataWidth-1:0] csr_mie; + logic [ MtvecWidth-1:0] csr_mtvec; + logic [ DataWidth-1:0] csr_mscratch; + logic [ DataWidth-1:0] csr_mip; + logic [ DataWidth-1:0] csr_mepc; + logic [ McauseWidth-1:0] csr_mcause; +} csrs_intf_t; + +typedef struct packed { + logic [ProtectedWidth-1:0] csr_mstatus; + logic [ProtectedWidth-1:0] csr_mie; + logic [ProtectedWidth-1:0] csr_mtvec; + logic [ProtectedWidth-1:0] csr_mscratch; + logic [ProtectedWidth-1:0] csr_mip; + logic [ProtectedWidth-1:0] csr_mepc; + logic [ProtectedWidth-1:0] csr_mcause; +} ecc_csrs_intf_t; endpackage From dbe9aa559cd71b57af16d89f4b6724796f6b0dd6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 6 Feb 2023 14:15:31 +0100 Subject: [PATCH 20/66] Add multibit setback, enable ungroup setback --- rtl/HMR/HMR_wrap.sv | 20 +++++++++++++++----- rtl/HMR/hmr_dmr_ctrl.sv | 15 +++++++++------ rtl/HMR/hmr_tmr_ctrl.sv | 19 +++++++++++-------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 5bedda40..6ea3f327 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -193,6 +193,11 @@ module HMR_wrap import recovery_pkg::*; #( else return group_id + group_id/2; endfunction + function int tmr_offset_id (int core_id); + if (InterleaveGrps) return core_id / NumTMRGroups; + else return core_id % 3; + endfunction + function int dmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumDMRGroups; else return (core_id/2); @@ -203,10 +208,15 @@ module HMR_wrap import recovery_pkg::*; #( else return (group_id * 2) + core_offset; endfunction - function int dmr_shared_id(int group_id); + function int dmr_shared_id (int group_id); return group_id; endfunction + function int dmr_offset_id (int core_id); + if (InterleaveGrps) return core_id / NumTMRGroups; + else return core_id % 2; + endfunction + if (TMRFixed && DMRFixed) $fatal(1, "Cannot fix both TMR and DMR!"); localparam int unsigned CtrlConcatWidth = 1 + 1 + 5 + 1 + 32 + 1; @@ -335,11 +345,11 @@ module HMR_wrap import recovery_pkg::*; #( logic [NumCores-1:0] dmr_core_rapid_recovery_en; logic [NumCores-1:0] tmr_core_rapid_recovery_en; - logic [NumDMRGroups-1:0] dmr_setback_q; + logic [NumDMRGroups-1:0][1:0] dmr_setback_q; logic [NumDMRGroups-1:0] dmr_grp_in_independent; logic [NumDMRGroups-1:0] dmr_rapid_recovery_en; - logic [NumTMRGroups-1:0] tmr_setback_q; + logic [NumTMRGroups-1:0][2:0] tmr_setback_q; logic [NumTMRGroups-1:0] tmr_grp_in_independent; logic [NumTMRGroups-1:0] tmr_rapid_recovery_en; @@ -1170,10 +1180,10 @@ module HMR_wrap import recovery_pkg::*; #( // Special signals if (RapidRecovery) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; end else begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode // CTRL diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index e7ffed29..101d7daf 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -35,7 +35,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( input logic force_recovery_qe_i, // DMR control signals - output logic setback_o, + output logic [1:0] setback_o, output logic sw_resynch_req_o, output logic sw_synch_req_o, output logic grp_in_independent_o, @@ -56,12 +56,11 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t dmr_hw2reg; dmr_mode_e dmr_red_mode_d, dmr_red_mode_q; - logic dmr_setback_d, dmr_setback_q; + logic [1:0] dmr_setback_d, dmr_setback_q; assign setback_o = dmr_setback_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 sw_synch_req_o = dmr_reg2hw.dmr_enable.q & dmr_red_mode_q == NON_DMR; hmr_dmr_regs_reg_top #( .reg_req_t(reg_req_t), @@ -88,11 +87,12 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( **************************/ always_comb begin : proc_fsm - dmr_setback_d = 1'b0; + dmr_setback_d = 2'b00; dmr_red_mode_d = dmr_red_mode_q; dmr_incr_mismatches_o = '0; recovery_request_o = 1'b0; sw_resynch_req_o = 1'b0; + sw_synch_req_o = 1'b0; dmr_hw2reg.dmr_config.force_recovery.de = force_recovery_qe_i; @@ -141,12 +141,15 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( if (dmr_red_mode_q == DMR_RUN) begin if (dmr_reg2hw.dmr_enable.q == 1'b0) begin dmr_red_mode_d = NON_DMR; + dmr_setback_d = 2'b10; end end // Set DMR mode on external signal that cores are synchronized - if (dmr_red_mode_q == NON_DMR && cores_synch_i) begin - if (dmr_reg2hw.dmr_enable.q == 1'b1) begin + if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.q == 1'b1) begin + sw_synch_req_o = 1'b1; + if (cores_synch_i == 1'b1) begin dmr_red_mode_d = DMR_RUN; + dmr_setback_d = 2'b11; end end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 12f78194..3aa64a66 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -41,7 +41,7 @@ module hmr_tmr_ctrl #( input logic force_resynch_qe_i, // TMR control signals - output logic setback_o, + output logic [2:0] setback_o, output logic sw_resynch_req_o, output logic sw_synch_req_o, output logic grp_in_independent_o, @@ -63,7 +63,7 @@ module hmr_tmr_ctrl #( hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t tmr_hw2reg; tmr_mode_e tmr_red_mode_d, tmr_red_mode_q; - logic tmr_setback_d, tmr_setback_q; + logic [2:0] tmr_setback_d, tmr_setback_q; assign setback_o = tmr_setback_q; assign grp_in_independent_o = tmr_red_mode_q == NON_TMR; @@ -100,7 +100,7 @@ module hmr_tmr_ctrl #( * FSM for TMR lockstep * **************************/ always_comb begin : proc_fsm - tmr_setback_d = 1'b0; + tmr_setback_d = 3'b000; tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; sw_resynch_req_o = 1'b0; @@ -139,7 +139,7 @@ module hmr_tmr_ctrl #( if (!sp_store_is_zero) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q) begin - tmr_setback_d = 1'b1; + tmr_setback_d = 3'b111; end end end @@ -153,7 +153,7 @@ module hmr_tmr_ctrl #( if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.q && tmr_reg2hw.tmr_config.reload_setback.q && !sp_store_will_be_zero) begin - tmr_setback_d = 1'b1; + tmr_setback_d = 3'b111; end end end @@ -175,16 +175,19 @@ module hmr_tmr_ctrl #( // 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 + tmr_setback_d = 3'b110; + end tmr_red_mode_d = NON_TMR; end end // 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 sw_synch_req_o = 1'b1; - if (cores_synch_i) begin + if (cores_synch_i == 1'b1) begin tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q) begin - tmr_setback_d = 1'b1; + if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin + tmr_setback_d = 3'b111; end end end From 4094c7eaa4aae4ab8cd6acbc5f4df01ca47b2d3e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 6 Feb 2023 19:04:14 +0100 Subject: [PATCH 21/66] Continually back up cores in interleaved mode --- rtl/HMR/HMR_wrap.sv | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 6ea3f327..8825180f 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -769,7 +769,7 @@ module HMR_wrap import recovery_pkg::*; #( ); /****************** - * DMR PC Checker * + * Recovery Checker * ******************/ DMR_checker # ( .DataWidth ( DataWidth ) @@ -983,6 +983,21 @@ module HMR_wrap import recovery_pkg::*; #( dmr_recovery_finished = '0; recovery_debug_halted_in = '0; + // Continually backup master cores in interleaved mode for fast entry + if (InterleaveGrps) begin + for (int i = 0; i < NumBackupRegfiles; i++) begin + backup_program_counter_int [i] = backup_program_counter_i [i]; + backup_branch_int [i] = backup_branch_i [i]; + backup_branch_addr_int [i] = backup_branch_addr_i [i]; + backup_regfile_wdata_a [i] = backup_regfile_wport_i[i].wdata_a; + backup_regfile_wdata_b [i] = backup_regfile_wport_i[i].wdata_b; + backup_regfile_we_a [i] = backup_regfile_wport_i[i].we_a; + backup_regfile_we_b [i] = backup_regfile_wport_i[i].we_b; + backup_regfile_waddr_a [i] = backup_regfile_wport_i[i].waddr_a; + backup_regfile_waddr_b [i] = backup_regfile_wport_i[i].waddr_b; + end + end + for (int i = 0; i < NumDMRGroups; i++) begin if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin backup_program_counter_int [dmr_shared_id(i)] = dmr_backup_program_counter [i]; From 48cd23b9acd34e9ee6f7b435ded16ac8c6820a5f Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 6 Feb 2023 19:05:08 +0100 Subject: [PATCH 22/66] Fix setback signals for proper ungrouping Squashing all DMR checkers into only one. Small cleanup. --- rtl/HMR/HMR_wrap.sv | 322 ++++++++++++----------------- rtl/HMR/hmr_dmr_ctrl.sv | 10 +- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 23 +-- rtl/HMR/hmr_tmr_ctrl.sv | 14 +- 4 files changed, 146 insertions(+), 223 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 8825180f..7d397534 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -221,10 +221,13 @@ module HMR_wrap import recovery_pkg::*; #( localparam int unsigned CtrlConcatWidth = 1 + 1 + 5 + 1 + 32 + 1; // busy irq_ack irq_ack_id i_req i_addr d_req + localparam int unsigned RapidRecoveryConcatWidth = RapidRecovery ? 165 + 65 + 76 : 0; + // csr pc rf localparam int unsigned DataConcatWidth = 32 + 1 + DataWidth + BeWidth + UserWidth; // data_add data_wen data_wdata data_be data_user - localparam int unsigned MainConcatWidth = SeparateData ? CtrlConcatWidth : - CtrlConcatWidth + DataConcatWidth; + localparam int unsigned MainConcatWidth = RapidRecoveryConcatWidth + + (SeparateData ? CtrlConcatWidth + : CtrlConcatWidth + DataConcatWidth); localparam int unsigned RFAddrWidth = 6; @@ -270,24 +273,16 @@ module HMR_wrap import recovery_pkg::*; #( logic [ NumDMRGroups-1:0][RFAddrWidth-1:0] dmr_backup_regfile_waddr_a, - dmr_backup_regfile_waddr_b; - logic [ NumDMRGroups-1:0][ DataWidth-1:0] dmr_backup_program_counter, - dmr_backup_regfile_wdata_a, - dmr_backup_regfile_wdata_b, - dmr_backup_branch_addr_int; - logic [ NumDMRGroups-1:0] dmr_backup_csr_error, - dmr_backup_program_counter_error, - dmr_backup_branch_error, - dmr_backup_branch_addr_error, - dmr_backup_regfile_error_a, - dmr_backup_regfile_error_b, - dmr_backup_regfile_addr_error_a, - dmr_backup_regfile_addr_error_b, - dmr_backup_branch_int, - dmr_start_recovery, - dmr_backup_regfile_we_a, - dmr_backup_regfile_we_b, - dmr_recovery_finished; + dmr_backup_regfile_waddr_b; + logic [ NumDMRGroups-1:0][ DataWidth-1:0] dmr_backup_program_counter, + dmr_backup_regfile_wdata_a, + dmr_backup_regfile_wdata_b, + dmr_backup_branch_addr_int; + logic [ NumDMRGroups-1:0] dmr_backup_branch_int, + dmr_start_recovery, + dmr_backup_regfile_we_a, + dmr_backup_regfile_we_b, + dmr_recovery_finished; logic [ NumTMRGroups-1:0][ DataWidth-1:0] tmr_backup_program_counter; logic [NumBackupRegfiles-1:0][RFAddrWidth-1:0] backup_regfile_waddr_a, backup_regfile_waddr_b; @@ -302,34 +297,66 @@ module HMR_wrap import recovery_pkg::*; #( backup_regfile_we_b, backup_program_counter_error, recovery_branch_out, - backup_csr_enable_out, - backup_pc_enable_out, + backup_enable, recovery_csr_enable_out, recovery_pc_enable_out, recovery_debug_req_out, recovery_debug_halted_in, recovery_instr_lock_out, recovery_setback_out, - recovery_trigger_out, // TODO: for regfile only?!? + recovery_trigger_out, recovery_debug_resume_out, start_recovery, recovery_finished; + logic [NumBackupRegfiles-1:0] rapid_recovery_backup_enable; regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; - csrs_intf_t [NumBackupRegfiles-1:0] dmr_backup_csr, recovery_csr_out; + csrs_intf_t [NumBackupRegfiles-1:0] backup_csr_int, dmr_backup_csr, recovery_csr_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin : gen_separate_data assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], - core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i]}; + core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], + // CSRs signals + backup_csr_i[i].csr_mstatus , // 7-bits + backup_csr_i[i].csr_mie , // 32-bits + backup_csr_i[i].csr_mtvec , // 24-bits + backup_csr_i[i].csr_mscratch, // 32-bits + backup_csr_i[i].csr_mip , // 32-bits + backup_csr_i[i].csr_mepc , // 32-bits + backup_csr_i[i].csr_mcause , // 6-bits + // PC signals + backup_program_counter_i[i], // 32-bits + backup_branch_i[i], backup_branch_addr_i[i], // 1-bits + 32-bits + // RF signals + backup_regfile_wport_i[i].wdata_a, // 32-bits + backup_regfile_wport_i[i].waddr_a, // 6-bits + backup_regfile_wport_i[i].wdata_b, // 32-bits + backup_regfile_wport_i[i].waddr_b};// 6-bits assign data_concat_in[i] = {core_data_add_i[i], core_data_wen_i[i], core_data_wdata_i[i], - core_data_be_i[i], core_data_user_i[i]}; + core_data_be_i[i], core_data_user_i[i]}; end else begin : gen_single_group assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], - core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], core_data_add_i[i], - core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i]}; + core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], core_data_add_i[i], + core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i], + // CSRs signals + backup_csr_i[i].csr_mstatus , // 7-bits + backup_csr_i[i].csr_mie , // 32-bits + backup_csr_i[i].csr_mtvec , // 24-bits + backup_csr_i[i].csr_mscratch, // 32-bits + backup_csr_i[i].csr_mip , // 32-bits + backup_csr_i[i].csr_mepc , // 32-bits + backup_csr_i[i].csr_mcause , // 6-bits + // PC signals + backup_program_counter_i[i], // 32-bits + backup_branch_i[i], backup_branch_addr_i[i], // 1-bits + 32-bits + // RF signals + backup_regfile_wport_i[i].wdata_a, // 32-bits + backup_regfile_wport_i[i].waddr_a, // 6-bits + backup_regfile_wport_i[i].wdata_b, // 32-bits + backup_regfile_wport_i[i].waddr_b};// 6-bits assign data_concat_in = '0; end end @@ -731,127 +758,53 @@ module HMR_wrap import recovery_pkg::*; #( ); assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] } - = main_dmr_out[i]; + = main_dmr_out[i][MainConcatWidth-1:MainConcatWidth-CtrlConcatWidth]; assign {dmr_data_add_out[i], dmr_data_wen_out[i] , dmr_data_wdata_out[i], dmr_data_be_out[i] , dmr_data_user_out[i] } = data_dmr_out[i]; end else begin : gen_data_in_main assign dmr_failure_data[i] = 1'b0; - // assign dmr_error_data[i] = 3'b000; assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] , dmr_data_add_out[i] , dmr_data_wen_out[i] , dmr_data_wdata_out[i], dmr_data_be_out[i] , dmr_data_user_out[i]} - = main_dmr_out[i]; + = main_dmr_out[i][MainConcatWidth-1:MainConcatWidth-(CtrlConcatWidth+DataConcatWidth)]; end if (RapidRecovery) begin : gen_rapid_recovery_connection assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) - : dmr_failure_main[i]) | - dmr_backup_csr_error [i] | - dmr_backup_program_counter_error[i] | - dmr_backup_branch_error [i] | - dmr_backup_branch_addr_error [i] | - dmr_backup_regfile_error_a [i] | - dmr_backup_regfile_error_b [i] | - dmr_backup_regfile_addr_error_a [i] | - dmr_backup_regfile_addr_error_b [i]; - - /******************** - * DMR CSRs Checker * - ********************/ - DMR_CSR_checker dmr_csr_checker ( - .csr_a_i ( backup_csr_i[dmr_core_id(i, 0)] ), - .csr_b_i ( backup_csr_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_backup_csr [i] ), - .error_o ( dmr_backup_csr_error [i] ) - ); - - /****************** - * Recovery Checker * - ******************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_pc_checker ( - .inp_a_i ( backup_program_counter_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_program_counter_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_backup_program_counter [i] ), - .error_o ( dmr_backup_program_counter_error [i] ) - ); - - /********************** - * DMR Branch Checker * - **********************/ - DMR_checker # ( - .DataWidth ( 1 ) - ) dmr_branch_checker ( - .inp_a_i ( backup_branch_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_branch_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_backup_branch_int [i] ), - .error_o ( dmr_backup_branch_error [i] ) - ); - - /***************************** - * DMR Branch Address Checker * - ******************************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_branch_addr_checker ( - .inp_a_i ( backup_branch_addr_i[dmr_core_id(i, 0)] ), - .inp_b_i ( backup_branch_addr_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_backup_branch_addr_int [i] ), - .error_o ( dmr_backup_branch_addr_error [i] ) - ); - - /******************* - * DMR RF Checkers * - *******************/ - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_rf_checker_port_a ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_a ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_a ), - .check_o ( dmr_backup_regfile_wdata_a [i] ), - .error_o ( dmr_backup_regfile_error_a [i] ) - ); - - DMR_checker # ( - .DataWidth ( RFAddrWidth ) - ) dmr_rf_checker_addr_port_a ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_a ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].waddr_a ), - .check_o ( dmr_backup_regfile_waddr_a [i] ), - .error_o ( dmr_backup_regfile_addr_error_a [i] ) - ); - - DMR_checker # ( - .DataWidth ( DataWidth ) - ) dmr_rf_checker_port_b ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].wdata_b ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].wdata_b ), - .check_o ( dmr_backup_regfile_wdata_b [i] ), - .error_o ( dmr_backup_regfile_error_b [i] ) - ); - - DMR_checker # ( - .DataWidth ( RFAddrWidth ) - ) dmr_rf_checker_addr_port_b ( - .inp_a_i ( backup_regfile_wport_i[dmr_core_id(i, 0)].waddr_b ), - .inp_b_i ( backup_regfile_wport_i[dmr_core_id(i, 1)].waddr_b ), - .check_o ( dmr_backup_regfile_waddr_b [i] ), - .error_o ( dmr_backup_regfile_addr_error_b [i] ) - ); + : dmr_failure_main[i]) ; + // Write Enable signal for backup registers + assign rapid_recovery_backup_enable[i] = tmr_core_rapid_recovery_en[i] ? backup_enable[i] // TMR mode + : dmr_core_rapid_recovery_en[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent mode + // Building checked singals back from DMR checker + // CSRs + assign dmr_backup_csr[i].csr_mstatus = main_dmr_out[i][305:299]; + assign dmr_backup_csr[i].csr_mie = main_dmr_out[i][298:267]; + assign dmr_backup_csr[i].csr_mtvec = main_dmr_out[i][266:243]; + assign dmr_backup_csr[i].csr_mscratch = main_dmr_out[i][242:211]; + assign dmr_backup_csr[i].csr_mip = main_dmr_out[i][210:179]; + assign dmr_backup_csr[i].csr_mepc = main_dmr_out[i][178:147]; + assign dmr_backup_csr[i].csr_mcause = main_dmr_out[i][146:141]; + // PC + assign dmr_backup_program_counter[i] = main_dmr_out[i][140:109]; + assign dmr_backup_branch_int [i] = main_dmr_out[i][ 108]; + assign dmr_backup_branch_addr_int[i] = main_dmr_out[i][107: 76]; + // RF + assign dmr_backup_regfile_wdata_a[i] = main_dmr_out[i][75:44]; + assign dmr_backup_regfile_waddr_a[i] = main_dmr_out[i][43:38]; + assign dmr_backup_regfile_wdata_b[i] = main_dmr_out[i][37:6]; + assign dmr_backup_regfile_waddr_b[i] = main_dmr_out[i][5:0]; assign dmr_backup_regfile_we_a [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_a & backup_regfile_wport_i[dmr_core_id(i, 1)].we_a - & ~dmr_backup_regfile_error_a [i] - & ~dmr_backup_regfile_addr_error_a [i]; + & ~dmr_failure [i]; assign dmr_backup_regfile_we_b [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_b & backup_regfile_wport_i[dmr_core_id(i, 1)].we_b - & ~dmr_backup_regfile_error_b [i] - & ~dmr_backup_regfile_addr_error_b [i]; + & ~dmr_failure [i]; end else begin : gen_standard_failure assign dmr_failure [i] = dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) @@ -892,8 +845,7 @@ module HMR_wrap import recovery_pkg::*; #( .debug_halt_i ( recovery_debug_halted_in [i] ), .debug_resume_o ( recovery_debug_resume_out [i] ), .recovery_regfile_waddr_o ( core_recovery_regfile_wport_out[i] ), - .backup_csr_enable_o ( backup_csr_enable_out [i] ), - .backup_pc_enable_o ( backup_pc_enable_out [i] ), + .backup_enable_o ( backup_enable [i] ), .recover_csr_enable_o ( recovery_csr_enable_out [i] ), .recover_pc_enable_o ( recovery_pc_enable_out [i] ), .recover_rf_enable_o ( recovery_trigger_out [i] ) @@ -905,13 +857,12 @@ module HMR_wrap import recovery_pkg::*; #( recovery_csr #( .ECCEnabled ( 1 ) ) RCSR ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .read_enable_i ( recovery_csr_enable_out [i] ), - .write_enable_i ( ~dmr_backup_csr_error [i] - & backup_csr_enable_out [i] ), - .backup_csr_i ( dmr_backup_csr [i] ), - .recovery_csr_o ( recovery_csr_out [i] ) + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .read_enable_i ( recovery_csr_enable_out [i] ), + .write_enable_i ( rapid_recovery_backup_enable [i] ), + .backup_csr_i ( backup_csr_int [i] ), + .recovery_csr_o ( recovery_csr_out [i] ) ); /**************************** @@ -924,9 +875,8 @@ module HMR_wrap import recovery_pkg::*; #( .clk_i, .rst_ni, .clear_i ( '0 ), - .read_enable_i ( recovery_pc_enable_out [i] ), - .write_enable_i ( ~backup_program_counter_error [i] - & backup_pc_enable_out [i] ), + .read_enable_i ( recovery_pc_enable_out [i] ), + .write_enable_i ( rapid_recovery_backup_enable [i] ), // Backup Ports .backup_program_counter_i ( backup_program_counter_int [i] ), .backup_branch_i ( backup_branch_int [i] ), @@ -957,18 +907,21 @@ module HMR_wrap import recovery_pkg::*; #( .raddr_c_i ( '0 ), .rdata_c_o ( ), // Write Port A - .waddr_a_i ( backup_regfile_waddr_a [i] ), - .wdata_a_i ( backup_regfile_wdata_a [i] ), - .we_a_i ( backup_regfile_we_a[i] & ~recovery_trigger_out[i] ), + .waddr_a_i ( backup_regfile_waddr_a [i] ), + .wdata_a_i ( backup_regfile_wdata_a [i] ), + .we_a_i ( backup_regfile_we_a[i] & + rapid_recovery_backup_enable [i] ), // Write Port B - .waddr_b_i ( backup_regfile_waddr_b [i] ), - .wdata_b_i ( backup_regfile_wdata_b [i] ), - .we_b_i ( backup_regfile_we_b[i] & ~recovery_trigger_out[i] ) + .waddr_b_i ( backup_regfile_waddr_b [i] ), + .wdata_b_i ( backup_regfile_wdata_b [i] ), + .we_b_i ( backup_regfile_we_b[i] & + rapid_recovery_backup_enable [i] ) ); end always_comb begin : proc_dmr_tmr_assignments + backup_csr_int = '0; backup_program_counter_int = '0; backup_program_counter_error = '0; backup_branch_int = '0; @@ -1000,8 +953,9 @@ module HMR_wrap import recovery_pkg::*; #( for (int i = 0; i < NumDMRGroups; i++) begin if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin + backup_csr_int [dmr_shared_id(i)] = dmr_backup_csr [i]; backup_program_counter_int [dmr_shared_id(i)] = dmr_backup_program_counter [i]; - backup_program_counter_error[dmr_shared_id(i)] = dmr_backup_program_counter_error[i]; + // backup_program_counter_error[dmr_shared_id(i)] = dmr_backup_program_counter_error[i]; backup_branch_int [dmr_shared_id(i)] = dmr_backup_branch_int [i]; backup_branch_addr_int [dmr_shared_id(i)] = dmr_backup_branch_addr_int [i]; backup_regfile_wdata_a [dmr_shared_id(i)] = dmr_backup_regfile_wdata_a [i]; @@ -1019,7 +973,8 @@ module HMR_wrap import recovery_pkg::*; #( for (int i = 0; i < NumTMRGroups; i++) begin if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin - backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; + // backup_csr_int [tmr_shared_id(i)] = tmr_backup_csr [i]; + // backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; // backup_program_counter_error[tmr_shared_id(i)] = tmr_backup_program_counter_error[i]; // backup_branch_int [tmr_shared_id(i)] = tmr_backup_branch_int [i]; // backup_branch_addr_int [tmr_shared_id(i)] = tmr_backup_branch_addr_int [i]; @@ -1158,6 +1113,18 @@ module HMR_wrap import recovery_pkg::*; #( localparam DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); always_comb begin + // Special signals + if (RapidRecovery) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; + end + if (i >= NumTMRCores && RapidRecovery) begin + core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else if (i >= NumTMRCores) begin + core_setback_o [i] = '0; + end if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [TMRCoreIndex]; @@ -1192,14 +1159,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [TMRCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [TMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [TMRCoreIndex]; - - // Special signals - if (RapidRecovery) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; - end else begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; - end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [DMRCoreIndex]; @@ -1234,13 +1193,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [DMRCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [DMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [DMRCoreIndex]; - - // Special signals - if (RapidRecovery) begin - core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; - end else begin - core_setback_o [i] = '0; - end end else begin : independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1270,9 +1222,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; - - // Special signals - core_setback_o [i] = '0; end end end @@ -1391,6 +1340,17 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin + // Special signals + // Setback + if (RapidRecovery) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + end + if (i >= NumTMRCores) begin + core_setback_o [i] = '0; + end if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; @@ -1425,15 +1385,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; - - // Special signals - // Setback - if (RapidRecovery) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] - | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; - end else begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; - end end else begin : independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1463,9 +1414,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [i]; core_data_r_valid_o [i] = sys_data_r_valid_i [i]; core_data_err_o [i] = sys_data_err_i [i]; - - // Special signals - core_setback_o [i] = '0; end end end @@ -1591,6 +1539,12 @@ module HMR_wrap import recovery_pkg::*; #( for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); always_comb begin + // Setback + if (RapidRecovery) begin + core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = '0; + end if (i < NumDMRCores && (DMRFixed || core_in_dmr[i])) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; @@ -1625,13 +1579,6 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; - - // Setback - if (RapidRecovery) begin - core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; - end else begin - core_setback_o [i] = '0; - end end else begin : gen_independent_mode // CTRL core_core_id_o [i] = sys_core_id_i [i]; @@ -1644,9 +1591,6 @@ module HMR_wrap import recovery_pkg::*; #( core_debug_req_o [i] = sys_debug_req_i [i]; core_perf_counters_o[i] = sys_perf_counters_i[i]; - // Setback - core_setback_o [i] = '0; - // IRQ core_irq_req_o [i] = sys_irq_req_i [i]; core_irq_id_o [i] = sys_irq_id_i [i]; diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 101d7daf..79388963 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -56,9 +56,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( hmr_dmr_regs_reg_pkg::hmr_dmr_regs_hw2reg_t dmr_hw2reg; dmr_mode_e dmr_red_mode_d, dmr_red_mode_q; - logic [1:0] dmr_setback_d, dmr_setback_q; - assign setback_o = dmr_setback_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; @@ -87,7 +85,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( **************************/ always_comb begin : proc_fsm - dmr_setback_d = 2'b00; + setback_o = 2'b00; dmr_red_mode_d = dmr_red_mode_q; dmr_incr_mismatches_o = '0; recovery_request_o = 1'b0; @@ -141,7 +139,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( if (dmr_red_mode_q == DMR_RUN) begin if (dmr_reg2hw.dmr_enable.q == 1'b0) begin dmr_red_mode_d = NON_DMR; - dmr_setback_d = 2'b10; + setback_o = 2'b10; end end // Set DMR mode on external signal that cores are synchronized @@ -149,7 +147,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( sw_synch_req_o = 1'b1; if (cores_synch_i == 1'b1) begin dmr_red_mode_d = DMR_RUN; - dmr_setback_d = 2'b11; + setback_o = 2'b11; end end end @@ -158,10 +156,8 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode if(!rst_ni) begin dmr_red_mode_q <= DefaultDMRMode; - dmr_setback_q <= '0; end else begin dmr_red_mode_q <= dmr_red_mode_d; - dmr_setback_q <= dmr_setback_d; end end diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv index 3315e271..e1205ea6 100644 --- a/rtl/HMR/hmr_rapid_recovery_ctrl.sv +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -29,8 +29,7 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( output regfile_write_t recovery_regfile_waddr_o, // Signals to backup state - output logic backup_csr_enable_o, - output logic backup_pc_enable_o, + output logic backup_enable_o, output logic recover_csr_enable_o, output logic recover_pc_enable_o, output logic recover_rf_enable_o @@ -40,8 +39,6 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( recovery_mode_e rec_mode_d, rec_mode_q; logic instr_lock_d, instr_lock_q; - logic backup_csr_enable_d, backup_csr_enable_q; - logic backup_pc_enable_d, backup_pc_enable_q; logic setback_d, setback_q; logic addr_gen_done; logic [RFAddrWidth-1:0] addr_gen_result; @@ -67,15 +64,12 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( assign instr_lock_o = instr_lock_q; - assign backup_csr_enable_o = backup_csr_enable_q; - assign backup_pc_enable_o = backup_pc_enable_q; assign setback_o = setback_q; always_comb begin rec_mode_d = rec_mode_q; instr_lock_d = instr_lock_q; - backup_csr_enable_d = backup_csr_enable_q; - backup_pc_enable_d = backup_pc_enable_q; + backup_enable_o = 1'b0; setback_d = 1'b0; debug_req_o = 1'b0; recover_csr_enable_o = 1'b0; @@ -86,12 +80,11 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( case (rec_mode_q) IDLE: begin + backup_enable_o = 1'b1; // If requested start the routine in the reset state if (start_recovery_i) begin - // Disable reading for the backup CSR - backup_csr_enable_d = 1'b0; - // Disable reading for the backup PC - backup_pc_enable_d = 1'b0; + // Disable all backups + backup_enable_o = 1'b0; rec_mode_d = RESET; end end @@ -124,8 +117,6 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( // If recovery routine complete, continue if (addr_gen_done) begin instr_lock_d = 1'b0; - backup_csr_enable_d = 1'b1; - backup_pc_enable_d = 1'b1; rec_mode_d = IDLE; debug_resume_o = 1'b1; recovery_finished_o = 1'b1; @@ -138,14 +129,10 @@ module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( if (!rst_ni) begin instr_lock_q <= 1'b0; rec_mode_q <= IDLE; - backup_csr_enable_q <= 1'b1; - backup_pc_enable_q <= 1'b1; setback_q <= 1'b0; end else begin instr_lock_q <= instr_lock_d; rec_mode_q <= rec_mode_d; - backup_csr_enable_q <= backup_csr_enable_d; - backup_pc_enable_q <= backup_pc_enable_d; setback_q <= setback_d; end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 3aa64a66..8ac9eaaa 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -63,9 +63,7 @@ module hmr_tmr_ctrl #( hmr_tmr_regs_reg_pkg::hmr_tmr_regs_hw2reg_t tmr_hw2reg; tmr_mode_e tmr_red_mode_d, tmr_red_mode_q; - logic [2:0] tmr_setback_d, tmr_setback_q; - assign setback_o = tmr_setback_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; @@ -100,7 +98,7 @@ module hmr_tmr_ctrl #( * FSM for TMR lockstep * **************************/ always_comb begin : proc_fsm - tmr_setback_d = 3'b000; + setback_o = 3'b000; tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; sw_resynch_req_o = 1'b0; @@ -139,7 +137,7 @@ module hmr_tmr_ctrl #( if (!sp_store_is_zero) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q) begin - tmr_setback_d = 3'b111; + setback_o = 3'b111; end end end @@ -153,7 +151,7 @@ module hmr_tmr_ctrl #( if ((tmr_single_mismatch_i || tmr_failure_i) && tmr_reg2hw.tmr_config.setback.q && tmr_reg2hw.tmr_config.reload_setback.q && !sp_store_will_be_zero) begin - tmr_setback_d = 3'b111; + setback_o = 3'b111; end end end @@ -176,7 +174,7 @@ module hmr_tmr_ctrl #( 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 - tmr_setback_d = 3'b110; + setback_o = 3'b110; end tmr_red_mode_d = NON_TMR; end @@ -187,7 +185,7 @@ module hmr_tmr_ctrl #( if (cores_synch_i == 1'b1) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin - tmr_setback_d = 3'b111; + setback_o = 3'b111; end end end @@ -197,10 +195,8 @@ module hmr_tmr_ctrl #( always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode if(!rst_ni) begin tmr_red_mode_q <= DefaultTMRMode; - tmr_setback_q <= '0; end else begin tmr_red_mode_q <= tmr_red_mode_d; - tmr_setback_q <= tmr_setback_d; end end From 31fc34f66331202197b863ac5da902c8a3f99fed Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 8 Feb 2023 14:14:57 +0100 Subject: [PATCH 23/66] Making cleaner assignments for main_dmr_out bus. --- rtl/HMR/HMR_wrap.sv | 61 ++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 7d397534..fe6d931a 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -623,7 +623,8 @@ module HMR_wrap import recovery_pkg::*; #( ); assign {tmr_core_busy_out[i], tmr_irq_ack_out[i], tmr_irq_ack_id_out[i], - tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i]} = main_tmr_out[i]; + tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i]} + = main_tmr_out[i][MainConcatWidth-1:MainConcatWidth-CtrlConcatWidth]; assign {tmr_data_add_out[i], tmr_data_wen_out[i], tmr_data_wdata_out[i], tmr_data_be_out[i], tmr_data_user_out[i]} = data_tmr_out[i]; end else begin : gen_data_in_main @@ -757,8 +758,24 @@ module HMR_wrap import recovery_pkg::*; #( .error_o ( dmr_failure_data [i] ) ); assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], - dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] } - = main_dmr_out[i][MainConcatWidth-1:MainConcatWidth-CtrlConcatWidth]; + dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i], + // CSRs signals + dmr_backup_csr[i].csr_mstatus , // 7-bits + dmr_backup_csr[i].csr_mie , // 32-bits + dmr_backup_csr[i].csr_mtvec , // 24-bits + dmr_backup_csr[i].csr_mscratch, // 32-bits + dmr_backup_csr[i].csr_mip , // 32-bits + dmr_backup_csr[i].csr_mepc , // 32-bits + dmr_backup_csr[i].csr_mcause , // 6-bits + // PC signals + dmr_backup_program_counter[i], // 32-bits + dmr_backup_branch_int[i], dmr_backup_branch_addr_int[i], // 1-bits + 32-bits + // RF signals + dmr_backup_regfile_wdata_a[i], // 32-bits + dmr_backup_regfile_waddr_a[i], // 6-bits + dmr_backup_regfile_wdata_b[i], // 32-bits + dmr_backup_regfile_waddr_b[i]} // 6-bits + = main_dmr_out[i]; assign {dmr_data_add_out[i], dmr_data_wen_out[i] , dmr_data_wdata_out[i], dmr_data_be_out[i] , dmr_data_user_out[i] } = data_dmr_out[i]; @@ -767,8 +784,24 @@ module HMR_wrap import recovery_pkg::*; #( assign {dmr_core_busy_out[i], dmr_irq_ack_out[i] , dmr_irq_ack_id_out[i], dmr_instr_req_out[i], dmr_instr_addr_out[i], dmr_data_req_out[i] , dmr_data_add_out[i] , dmr_data_wen_out[i] , dmr_data_wdata_out[i], - dmr_data_be_out[i] , dmr_data_user_out[i]} - = main_dmr_out[i][MainConcatWidth-1:MainConcatWidth-(CtrlConcatWidth+DataConcatWidth)]; + dmr_data_be_out[i] , dmr_data_user_out[i], + // CSRs signals + dmr_backup_csr[i].csr_mstatus , // 7-bits + dmr_backup_csr[i].csr_mie , // 32-bits + dmr_backup_csr[i].csr_mtvec , // 24-bits + dmr_backup_csr[i].csr_mscratch, // 32-bits + dmr_backup_csr[i].csr_mip , // 32-bits + dmr_backup_csr[i].csr_mepc , // 32-bits + dmr_backup_csr[i].csr_mcause , // 6-bits + // PC signals + dmr_backup_program_counter[i], // 32-bits + dmr_backup_branch_int[i], dmr_backup_branch_addr_int[i], // 1-bits + 32-bits + // RF signals + dmr_backup_regfile_wdata_a[i], // 32-bits + dmr_backup_regfile_waddr_a[i], // 6-bits + dmr_backup_regfile_wdata_b[i], // 32-bits + dmr_backup_regfile_waddr_b[i]} // 6-bits + = main_dmr_out[i]; end if (RapidRecovery) begin : gen_rapid_recovery_connection @@ -779,24 +812,6 @@ module HMR_wrap import recovery_pkg::*; #( assign rapid_recovery_backup_enable[i] = tmr_core_rapid_recovery_en[i] ? backup_enable[i] // TMR mode : dmr_core_rapid_recovery_en[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode : 1'b1; // Independent mode - // Building checked singals back from DMR checker - // CSRs - assign dmr_backup_csr[i].csr_mstatus = main_dmr_out[i][305:299]; - assign dmr_backup_csr[i].csr_mie = main_dmr_out[i][298:267]; - assign dmr_backup_csr[i].csr_mtvec = main_dmr_out[i][266:243]; - assign dmr_backup_csr[i].csr_mscratch = main_dmr_out[i][242:211]; - assign dmr_backup_csr[i].csr_mip = main_dmr_out[i][210:179]; - assign dmr_backup_csr[i].csr_mepc = main_dmr_out[i][178:147]; - assign dmr_backup_csr[i].csr_mcause = main_dmr_out[i][146:141]; - // PC - assign dmr_backup_program_counter[i] = main_dmr_out[i][140:109]; - assign dmr_backup_branch_int [i] = main_dmr_out[i][ 108]; - assign dmr_backup_branch_addr_int[i] = main_dmr_out[i][107: 76]; - // RF - assign dmr_backup_regfile_wdata_a[i] = main_dmr_out[i][75:44]; - assign dmr_backup_regfile_waddr_a[i] = main_dmr_out[i][43:38]; - assign dmr_backup_regfile_wdata_b[i] = main_dmr_out[i][37:6]; - assign dmr_backup_regfile_waddr_b[i] = main_dmr_out[i][5:0]; assign dmr_backup_regfile_we_a [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_a & backup_regfile_wport_i[dmr_core_id(i, 1)].we_a From 28440dc20e953c30db0dfb679fdb953da91e045f Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 8 Feb 2023 14:19:34 +0100 Subject: [PATCH 24/66] Adding first support for TMR rapid recovery (to be fixed). --- rtl/HMR/HMR_wrap.sv | 134 ++++++++++++++++++++++++++++++++-------- rtl/HMR/hmr_tmr_ctrl.sv | 23 +++++-- 2 files changed, 126 insertions(+), 31 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index fe6d931a..2cab24d6 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -283,7 +283,18 @@ module HMR_wrap import recovery_pkg::*; #( dmr_backup_regfile_we_a, dmr_backup_regfile_we_b, dmr_recovery_finished; - logic [ NumTMRGroups-1:0][ DataWidth-1:0] tmr_backup_program_counter; + logic [ NumTMRGroups-1:0][RFAddrWidth-1:0] tmr_backup_regfile_waddr_a, + tmr_backup_regfile_waddr_b; + logic [ NumTMRGroups-1:0][ DataWidth-1:0] tmr_backup_program_counter, + tmr_backup_regfile_wdata_a, + tmr_backup_regfile_wdata_b, + tmr_backup_branch_addr_int; + logic [ NumTMRGroups-1:0] tmr_backup_branch_int, + tmr_start_recovery, + tmr_backup_regfile_we_a, + tmr_backup_regfile_we_b, + tmr_recovery_finished; + logic [NumBackupRegfiles-1:0][RFAddrWidth-1:0] backup_regfile_waddr_a, backup_regfile_waddr_b; logic [NumBackupRegfiles-1:0][ DataWidth-1:0] backup_branch_addr_int, @@ -313,7 +324,7 @@ module HMR_wrap import recovery_pkg::*; #( regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; - csrs_intf_t [NumBackupRegfiles-1:0] backup_csr_int, dmr_backup_csr, recovery_csr_out; + csrs_intf_t [NumBackupRegfiles-1:0] backup_csr_int, dmr_backup_csr, tmr_backup_csr, recovery_csr_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin : gen_separate_data @@ -550,7 +561,8 @@ module HMR_wrap import recovery_pkg::*; #( .reg_resp_t ( reg_resp_t ), .TMRFixed ( TMRFixed ), .InterleaveGrps ( InterleaveGrps ), - .DefaultInTMR ( 1'b0 ) + .DefaultInTMR ( 1'b0 ), + .RapidRecovery ( RapidRecovery ) ) i_tmr_ctrl ( .clk_i, .rst_ni, @@ -582,8 +594,12 @@ module HMR_wrap import recovery_pkg::*; #( .tmr_failure_i ( tmr_failure[i] ), .sp_store_is_zero ( sp_store_is_zero[tmr_core_id(i, 0)] ), .sp_store_will_be_zero( sp_store_will_be_zero[tmr_core_id(i, 0)] ), + .fetch_en_i ( sys_fetch_en_i[tmr_core_id(i, 0)] ), - .cores_synch_i ( tmr_cores_synch_i[i] ) + .cores_synch_i ( tmr_cores_synch_i[i] ), + + .recovery_request_o ( tmr_start_recovery [i] ), + .recovery_finished_i ( tmr_recovery_finished [i] ) ); assign tmr_sw_synch_req_o[tmr_core_id(i, 0)] = tmr_sw_synch_req[i]; @@ -623,8 +639,24 @@ module HMR_wrap import recovery_pkg::*; #( ); assign {tmr_core_busy_out[i], tmr_irq_ack_out[i], tmr_irq_ack_id_out[i], - tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i]} - = main_tmr_out[i][MainConcatWidth-1:MainConcatWidth-CtrlConcatWidth]; + tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i], + // CSRs signals + tmr_backup_csr[i].csr_mstatus , // 7-bits + tmr_backup_csr[i].csr_mie , // 32-bits + tmr_backup_csr[i].csr_mtvec , // 24-bits + tmr_backup_csr[i].csr_mscratch, // 32-bits + tmr_backup_csr[i].csr_mip , // 32-bits + tmr_backup_csr[i].csr_mepc , // 32-bits + tmr_backup_csr[i].csr_mcause , // 6-bits + // PC signals + tmr_backup_program_counter[i], // 32-bits + tmr_backup_branch_int[i], tmr_backup_branch_addr_int[i], // 1-bits + 32-bits + // RF signals + tmr_backup_regfile_wdata_a[i], // 32-bits + tmr_backup_regfile_waddr_a[i], // 6-bits + tmr_backup_regfile_wdata_b[i], // 32-bits + tmr_backup_regfile_waddr_b[i]} + = main_tmr_out[i]; assign {tmr_data_add_out[i], tmr_data_wen_out[i], tmr_data_wdata_out[i], tmr_data_be_out[i], tmr_data_user_out[i]} = data_tmr_out[i]; end else begin : gen_data_in_main @@ -633,7 +665,54 @@ module HMR_wrap import recovery_pkg::*; #( assign {tmr_core_busy_out[i], tmr_irq_ack_out[i], tmr_irq_ack_id_out[i], tmr_instr_req_out[i], tmr_instr_addr_out[i], tmr_data_req_out[i], tmr_data_add_out[i], tmr_data_wen_out[i], tmr_data_wdata_out[i], - tmr_data_be_out[i], tmr_data_user_out[i]} = main_tmr_out[i]; + tmr_data_be_out[i], tmr_data_user_out[i], + // CSRs signals + tmr_backup_csr[i].csr_mstatus , // 7-bits + tmr_backup_csr[i].csr_mie , // 32-bits + tmr_backup_csr[i].csr_mtvec , // 24-bits + tmr_backup_csr[i].csr_mscratch, // 32-bits + tmr_backup_csr[i].csr_mip , // 32-bits + tmr_backup_csr[i].csr_mepc , // 32-bits + tmr_backup_csr[i].csr_mcause , // 6-bits + // PC signals + tmr_backup_program_counter[i], // 32-bits + tmr_backup_branch_int[i], tmr_backup_branch_addr_int[i], // 1-bits + 32-bits + // RF signals + tmr_backup_regfile_wdata_a[i], // 32-bits + tmr_backup_regfile_waddr_a[i], // 6-bits + tmr_backup_regfile_wdata_b[i], // 32-bits + tmr_backup_regfile_waddr_b[i]} = main_tmr_out[i]; + end + + if (RapidRecovery) begin : gen_rapid_recovery_connection + + bitwise_TMR_voter #( + .DataWidth( 1 ), + .VoterType( 0 ) + ) i_voter_regfile_we_a ( + .a_i ( backup_regfile_wport_i[tmr_core_id(i, 0)].we_a ), + .b_i ( backup_regfile_wport_i[tmr_core_id(i, 1)].we_a ), + .c_i ( backup_regfile_wport_i[tmr_core_id(i, 2)].we_a ), + .majority_o ( tmr_backup_regfile_we_a [i] ), + .error_o ( ), + .error_cba_o( ) + ); + + bitwise_TMR_voter #( + .DataWidth( 1 ), + .VoterType( 0 ) + ) i_voter_regfile_we_b ( + .a_i ( backup_regfile_wport_i[tmr_core_id(i, 0)].we_b ), + .b_i ( backup_regfile_wport_i[tmr_core_id(i, 1)].we_b ), + .c_i ( backup_regfile_wport_i[tmr_core_id(i, 2)].we_b ), + .majority_o ( tmr_backup_regfile_we_b [i] ), + .error_o ( ), + .error_cba_o( ) + ); + + end else begin : gen_standard_failure + assign tmr_failure [i] = tmr_data_req_out [i] ? (tmr_failure_main[i] | tmr_failure_data[i]) + : tmr_failure_main[i]; end end end else begin : gen_no_tmr_voted @@ -808,10 +887,6 @@ module HMR_wrap import recovery_pkg::*; #( assign dmr_failure [i] = (dmr_data_req_out [i] ? (dmr_failure_main[i] | dmr_failure_data[i]) : dmr_failure_main[i]) ; - // Write Enable signal for backup registers - assign rapid_recovery_backup_enable[i] = tmr_core_rapid_recovery_en[i] ? backup_enable[i] // TMR mode - : dmr_core_rapid_recovery_en[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode - : 1'b1; // Independent mode assign dmr_backup_regfile_we_a [i] = backup_regfile_wport_i[dmr_core_id(i, 0)].we_a & backup_regfile_wport_i[dmr_core_id(i, 1)].we_a @@ -847,6 +922,11 @@ module HMR_wrap import recovery_pkg::*; #( // RapidRecovery output signals if (RapidRecovery) begin : gen_rapid_recovery for (genvar i = 0; i < NumBackupRegfiles; i++) begin : gen_groups + // Write Enable signal for backup registers + assign rapid_recovery_backup_enable[i] = tmr_core_rapid_recovery_en[i] ? backup_enable[i] // TMR mode + : dmr_core_rapid_recovery_en[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent mode + hmr_rapid_recovery_ctrl #( .RFAddrWidth( RFAddrWidth ) ) i_rapid_recovery_ctrl ( @@ -949,6 +1029,7 @@ module HMR_wrap import recovery_pkg::*; #( backup_regfile_waddr_b = '0; start_recovery = '0; dmr_recovery_finished = '0; + tmr_recovery_finished = '0; recovery_debug_halted_in = '0; // Continually backup master cores in interleaved mode for fast entry @@ -988,22 +1069,21 @@ module HMR_wrap import recovery_pkg::*; #( for (int i = 0; i < NumTMRGroups; i++) begin if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin - // backup_csr_int [tmr_shared_id(i)] = tmr_backup_csr [i]; - // backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; - // backup_program_counter_error[tmr_shared_id(i)] = tmr_backup_program_counter_error[i]; - // backup_branch_int [tmr_shared_id(i)] = tmr_backup_branch_int [i]; - // backup_branch_addr_int [tmr_shared_id(i)] = tmr_backup_branch_addr_int [i]; - // backup_regfile_wdata_a [tmr_shared_id(i)] = tmr_backup_regfile_wdata_a [i]; - // backup_regfile_wdata_b [tmr_shared_id(i)] = tmr_backup_regfile_wdata_b [i]; - // backup_regfile_we_a [tmr_shared_id(i)] = tmr_backup_regfile_we_a [i]; - // backup_regfile_we_b [tmr_shared_id(i)] = tmr_backup_regfile_we_b [i]; - // backup_regfile_waddr_a [tmr_shared_id(i)] = tmr_backup_regfile_waddr_a [i]; - // backup_regfile_waddr_b [tmr_shared_id(i)] = tmr_backup_regfile_waddr_b [i]; - // start_recovery [tmr_shared_id(i)] = tmr_start_recovery [i]; - // tmr_recovery_finished[i] = recovery_finished[tmr_shared_id(i)]; - // recovery_debug_halted_in [tmr_shared_id(i)] = core_debug_halted_i [tmr_core_id(tmr_group_id(i), 0)] - // & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 1)]; - // & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 2)]; + backup_csr_int [tmr_shared_id(i)] = tmr_backup_csr [i]; + backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; + backup_branch_int [tmr_shared_id(i)] = tmr_backup_branch_int [i]; + backup_branch_addr_int [tmr_shared_id(i)] = tmr_backup_branch_addr_int [i]; + backup_regfile_wdata_a [tmr_shared_id(i)] = tmr_backup_regfile_wdata_a [i]; + backup_regfile_wdata_b [tmr_shared_id(i)] = tmr_backup_regfile_wdata_b [i]; + backup_regfile_we_a [tmr_shared_id(i)] = tmr_backup_regfile_we_a [i]; + backup_regfile_we_b [tmr_shared_id(i)] = tmr_backup_regfile_we_b [i]; + backup_regfile_waddr_a [tmr_shared_id(i)] = tmr_backup_regfile_waddr_a [i]; + backup_regfile_waddr_b [tmr_shared_id(i)] = tmr_backup_regfile_waddr_b [i]; + start_recovery [tmr_shared_id(i)] = tmr_start_recovery [i]; + tmr_recovery_finished[i] = recovery_finished[tmr_shared_id(i)]; + recovery_debug_halted_in [tmr_shared_id(i)] = core_debug_halted_i [tmr_core_id(tmr_group_id(i), 0)] + & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 1)] + & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 2)]; end end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 8ac9eaaa..7db4f3ec 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -53,10 +53,12 @@ module hmr_tmr_ctrl #( input logic sp_store_is_zero, input logic sp_store_will_be_zero, input logic fetch_en_i, - input logic cores_synch_i + input logic cores_synch_i, + output logic recovery_request_o, + input logic recovery_finished_i ); - typedef enum logic [1:0] {NON_TMR, TMR_RUN, TMR_UNLOAD, TMR_RELOAD} tmr_mode_e; + 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; @@ -101,6 +103,7 @@ module hmr_tmr_ctrl #( setback_o = 3'b000; tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; + recovery_request_o = 1'b0; sw_resynch_req_o = 1'b0; sw_synch_req_o = 1'b0; @@ -111,7 +114,9 @@ module hmr_tmr_ctrl #( // 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.delay_resynch.q == '0) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1) begin + tmr_red_mode_d = TMR_RAPID; + end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin tmr_red_mode_d = TMR_UNLOAD; // TODO: buffer the restoration until delay_resynch is disabled end @@ -124,7 +129,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.delay_resynch == 0) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1) begin + tmr_red_mode_d = TMR_RAPID; + end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin tmr_red_mode_d = TMR_UNLOAD; // TODO: buffer the restoration until delay_resynch is disabled end @@ -156,6 +163,14 @@ module hmr_tmr_ctrl #( end end + TMR_RAPID: begin + recovery_request_o = 1'b1; + if (recovery_finished_i) begin + $display("[HMR-triple] %t - mismatch restored", $realtime); + tmr_red_mode_d = TMR_RUN; + end + end + // Default: do nothing endcase From 5195870c78a6085c2f3613215dfbae28156c7982 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 8 Feb 2023 16:08:16 +0100 Subject: [PATCH 25/66] Ensure sw_synch interrupt stays 0 before boot --- rtl/HMR/hmr_dmr_ctrl.sv | 17 +++++++++-------- rtl/HMR/hmr_tmr_ctrl.sv | 21 +++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 79388963..ffbc5d41 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -127,11 +127,20 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // 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 + sw_synch_req_o = 1'b1; + if (cores_synch_i == 1'b1) begin + dmr_red_mode_d = DMR_RUN; + setback_o = 2'b11; + end + 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 dmr_red_mode_d = NON_DMR; end else begin + sw_synch_req_o = 1'b0; dmr_red_mode_d = DMR_RUN; end end @@ -142,14 +151,6 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( setback_o = 2'b10; end end - // 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 - sw_synch_req_o = 1'b1; - if (cores_synch_i == 1'b1) begin - dmr_red_mode_d = DMR_RUN; - setback_o = 2'b11; - end - end end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 7db4f3ec..998f32db 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -177,12 +177,23 @@ 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 + sw_synch_req_o = 1'b1; + if (cores_synch_i == 1'b1) begin + tmr_red_mode_d = TMR_RELOAD; + if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin + setback_o = 3'b111; + end + end + 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 tmr_red_mode_d = NON_TMR; end else begin tmr_red_mode_d = TMR_RUN; + sw_synch_req_o = 1'b0; end end // split tolerant mode to performance mode anytime (but require correct core state) @@ -194,16 +205,6 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = NON_TMR; end end - // 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 - sw_synch_req_o = 1'b1; - if (cores_synch_i == 1'b1) begin - tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin - setback_o = 3'b111; - end - end - end end end From 83c395c0a7f8eb2eb03c2c2ab7ae0613dd650f3e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 9 Feb 2023 16:20:48 +0100 Subject: [PATCH 26/66] Add response suppress module Add response filter to HMR --- Bender.yml | 1 + rtl/HMR/HMR_wrap.sv | 55 ++++++++++++++++++++++++++++------------ rtl/HMR/resp_suppress.sv | 52 +++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 rtl/HMR/resp_suppress.sv diff --git a/Bender.yml b/Bender.yml index bac0b426..4b0c9155 100644 --- a/Bender.yml +++ b/Bender.yml @@ -28,6 +28,7 @@ sources: - rtl/TMR_voter.sv - rtl/TMR_voter_fail.sv - rtl/TMR_word_voter.sv + - rtl/HMR/resp_suppress.sv # Level 1 - rtl/ODRG_unit/odrg_manager_reg_top.sv - rtl/ecc_wrap/ecc_manager_reg_top.sv diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 2cab24d6..a14118ac 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -372,6 +372,29 @@ module HMR_wrap import recovery_pkg::*; #( end end + logic [NumSysCores-1:0] filt_instr_r_valid, filt_data_r_valid; + + for (genvar i = 0; i < NumSysCores; i++) begin + resp_suppress i_instr_suppress ( + .clk_i, + .rst_ni, + .setback_i (core_setback_o[i]), + .req_i (sys_instr_req_o[i]), + .gnt_i (sys_instr_gnt_i[i]), + .r_valid_i (sys_instr_r_valid_i[i]), + .r_valid_o (filt_instr_r_valid[i]) + ); + resp_suppress i_data_suppress ( + .clk_i, + .rst_ni, + .setback_i (core_setback_o[i]), + .req_i (sys_data_req_o[i]), + .gnt_i (sys_data_gnt_i[i]), + .r_valid_i (sys_data_r_valid_i[i]), + .r_valid_o (filt_data_r_valid[i]) + ); + end + /*************************** * HMR Control Registers * ***************************/ @@ -1244,7 +1267,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [TMRCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[TMRCoreIndex]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[TMRCoreIndex]; + core_instr_r_valid_o[i] = filt_instr_r_valid[TMRCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [TMRCoreIndex]; // DATA @@ -1252,7 +1275,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [TMRCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [TMRCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [TMRCoreIndex]; - core_data_r_valid_o [i] = sys_data_r_valid_i [TMRCoreIndex]; + core_data_r_valid_o [i] = filt_data_r_valid [TMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [TMRCoreIndex]; end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode // CTRL @@ -1278,7 +1301,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [DMRCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[DMRCoreIndex]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[DMRCoreIndex]; + core_instr_r_valid_o[i] = filt_instr_r_valid[DMRCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [DMRCoreIndex]; // DATA @@ -1286,7 +1309,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [DMRCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [DMRCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [DMRCoreIndex]; - core_data_r_valid_o [i] = sys_data_r_valid_i [DMRCoreIndex]; + core_data_r_valid_o [i] = filt_data_r_valid [DMRCoreIndex]; core_data_err_o [i] = sys_data_err_i [DMRCoreIndex]; end else begin : independent_mode // CTRL @@ -1307,7 +1330,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA @@ -1315,7 +1338,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; - core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_r_valid_o [i] = filt_data_r_valid [i]; core_data_err_o [i] = sys_data_err_i [i]; end end @@ -1470,7 +1493,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[SysCoreIndex]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[SysCoreIndex]; + core_instr_r_valid_o[i] = filt_instr_r_valid[SysCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; // DATA @@ -1478,7 +1501,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; - core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + core_data_r_valid_o [i] = filt_data_r_valid [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; end else begin : independent_mode // CTRL @@ -1499,7 +1522,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA @@ -1507,7 +1530,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; - core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_r_valid_o [i] = filt_data_r_valid [i]; core_data_err_o [i] = sys_data_err_i [i]; end end @@ -1664,7 +1687,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i [SysCoreIndex]; + core_instr_r_valid_o[i] = filt_instr_r_valid [SysCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; // DATA @@ -1672,7 +1695,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; - core_data_r_valid_o [i] = sys_data_r_valid_i [SysCoreIndex]; + core_data_r_valid_o [i] = filt_data_r_valid [SysCoreIndex]; core_data_err_o [i] = sys_data_err_i [SysCoreIndex]; end else begin : gen_independent_mode // CTRL @@ -1693,7 +1716,7 @@ module HMR_wrap import recovery_pkg::*; #( // INSTR core_instr_gnt_o [i] = sys_instr_gnt_i [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; - core_instr_r_valid_o[i] = sys_instr_r_valid_i[i]; + core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA @@ -1701,7 +1724,7 @@ module HMR_wrap import recovery_pkg::*; #( core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; - core_data_r_valid_o [i] = sys_data_r_valid_i [i]; + core_data_r_valid_o [i] = filt_data_r_valid [i]; core_data_err_o [i] = sys_data_err_i [i]; end end @@ -1845,7 +1868,7 @@ module HMR_wrap import recovery_pkg::*; #( assign core_instr_gnt_o = sys_instr_gnt_i; assign sys_instr_addr_o = core_instr_addr_i; assign core_instr_r_rdata_o = sys_instr_r_rdata_i; - assign core_instr_r_valid_o = sys_instr_r_valid_i; + assign core_instr_r_valid_o = filt_instr_r_valid; assign core_instr_err_o = sys_instr_err_i; // DATA @@ -1859,7 +1882,7 @@ module HMR_wrap import recovery_pkg::*; #( assign core_data_r_opc_o = sys_data_r_opc_i; assign core_data_r_rdata_o = sys_data_r_rdata_i; assign core_data_r_user_o = sys_data_r_user_i; - assign core_data_r_valid_o = sys_data_r_valid_i; + assign core_data_r_valid_o = filt_data_r_valid; assign core_data_err_o = sys_data_err_i; end diff --git a/rtl/HMR/resp_suppress.sv b/rtl/HMR/resp_suppress.sv new file mode 100644 index 00000000..1144373e --- /dev/null +++ b/rtl/HMR/resp_suppress.sv @@ -0,0 +1,52 @@ +// Copyright 2023 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. +// +// Suppress the r_valid if set back + +module resp_suppress #( + parameter int unsigned NumOutstanding = 2 +) ( + input logic clk_i, + input logic rst_ni, + + input logic setback_i, + input logic req_i, + input logic gnt_i, + input logic r_valid_i, + output logic r_valid_o +); + + logic [$clog2(NumOutstanding)-1:0] outstanding_d, outstanding_q; + logic block_d, block_q; + + assign outstanding_d = outstanding_q + (req_i & gnt_i ? 1 : 0) - (r_valid_i ? 1 : 0); + + assign r_valid_o = block_q ? 1'b0 : r_valid_i; + + always_comb begin + block_d = block_q; + if (setback_i) begin + block_d = 1'b1; + end else if (outstanding_q == 0) begin + block_d = 1'b0; + end + end + + always_ff @( posedge clk_i or negedge rst_ni ) begin : proc_ff + if (!rst_ni) begin + outstanding_q <= '0; + block_q <= '0; + end else begin + outstanding_q <= outstanding_d; + block_q <= block_d; + end + end + +endmodule From 580d4d44323e9ca7581fbf15539a0e8a471515b1 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 9 Feb 2023 17:27:06 +0100 Subject: [PATCH 27/66] TMR: only trigger a single interrupt --- rtl/HMR/HMR_wrap.sv | 2 +- rtl/HMR/hmr_tmr_ctrl.sv | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index a14118ac..9bdfb363 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -652,7 +652,7 @@ module HMR_wrap import recovery_pkg::*; #( bitwise_TMR_voter #( .DataWidth( DataConcatWidth ), .VoterType( 0 ) - ) i_main_voter ( + ) i_data_voter ( .a_i ( data_concat_in[tmr_core_id(i, 0)] ), .b_i ( data_concat_in[tmr_core_id(i, 1)] ), .c_i ( data_concat_in[tmr_core_id(i, 2)] ), diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 998f32db..3a24356d 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -58,6 +58,9 @@ module hmr_tmr_ctrl #( input logic recovery_finished_i ); + logic synch_req, synch_req_sent_d, synch_req_sent_q; + logic resynch_req, resynch_req_sent_d, resynch_req_sent_q; + 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; @@ -70,6 +73,11 @@ module hmr_tmr_ctrl #( 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 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) @@ -104,8 +112,8 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = tmr_red_mode_q; tmr_incr_mismatches_o = '0; recovery_request_o = 1'b0; - sw_resynch_req_o = 1'b0; - sw_synch_req_o = 1'b0; + resynch_req = 1'b0; + synch_req = 1'b0; tmr_hw2reg.tmr_config.force_resynch.de = force_resynch_qe_i; @@ -139,7 +147,7 @@ module hmr_tmr_ctrl #( end TMR_UNLOAD: begin - sw_resynch_req_o = 1'b1; + resynch_req = 1'b1; // If unload complete, go to reload (and reset) if (!sp_store_is_zero) begin tmr_red_mode_d = TMR_RELOAD; @@ -179,7 +187,7 @@ module hmr_tmr_ctrl #( 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 - sw_synch_req_o = 1'b1; + synch_req = 1'b1; if (cores_synch_i == 1'b1) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin @@ -193,7 +201,7 @@ module hmr_tmr_ctrl #( tmr_red_mode_d = NON_TMR; end else begin tmr_red_mode_d = TMR_RUN; - sw_synch_req_o = 1'b0; + synch_req = 1'b0; end end // split tolerant mode to performance mode anytime (but require correct core state) @@ -211,8 +219,12 @@ module hmr_tmr_ctrl #( always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode if(!rst_ni) begin tmr_red_mode_q <= DefaultTMRMode; + synch_req_sent_q <= '0; + resynch_req_sent_q <= '0; end else begin tmr_red_mode_q <= tmr_red_mode_d; + synch_req_sent_q <= synch_req_sent_d; + resynch_req_sent_q <= resynch_req_sent_d; end end From 2496a6dc4f8eaff8867b567539aa5d9cbc136283 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 9 Feb 2023 17:29:50 +0100 Subject: [PATCH 28/66] DMR: only trigger a single interrupt --- rtl/HMR/hmr_dmr_ctrl.sv | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index ffbc5d41..0de7c40f 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -49,6 +49,9 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( input logic cores_synch_i ); + logic synch_req, synch_req_sent_d, synch_req_sent_q; + logic resynch_req, resynch_req_sent_d, resynch_req_sent_q; + 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; @@ -60,6 +63,11 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( 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 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_dmr_regs_reg_top #( .reg_req_t(reg_req_t), .reg_rsp_t(reg_resp_t) @@ -89,8 +97,8 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( dmr_red_mode_d = dmr_red_mode_q; dmr_incr_mismatches_o = '0; recovery_request_o = 1'b0; - sw_resynch_req_o = 1'b0; - sw_synch_req_o = 1'b0; + resynch_req = 1'b0; + synch_req = 1'b0; dmr_hw2reg.dmr_config.force_recovery.de = force_recovery_qe_i; @@ -110,7 +118,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( if (dmr_error_i && (!RapidRecovery || !dmr_reg2hw.dmr_config.rapid_recovery.q)) begin $display("[HMR-dual] %t - mismatch detected, SW trigger", $realtime); - sw_resynch_req_o = 1'b1; + resynch_req = 1'b1; end end @@ -129,7 +137,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( 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 - sw_synch_req_o = 1'b1; + synch_req = 1'b1; if (cores_synch_i == 1'b1) begin dmr_red_mode_d = DMR_RUN; setback_o = 2'b11; @@ -140,7 +148,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( if (dmr_reg2hw.dmr_enable.q == 1'b0) begin dmr_red_mode_d = NON_DMR; end else begin - sw_synch_req_o = 1'b0; + synch_req = 1'b0; dmr_red_mode_d = DMR_RUN; end end @@ -157,8 +165,12 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( always_ff @(posedge clk_i or negedge rst_ni) begin : proc_red_mode if(!rst_ni) begin dmr_red_mode_q <= DefaultDMRMode; + synch_req_sent_q <= '0; + resynch_req_sent_q <= '0; end else begin dmr_red_mode_q <= dmr_red_mode_d; + synch_req_sent_q <= synch_req_sent_d; + resynch_req_sent_q <= resynch_req_sent_d; end end From fe2324f37132df49fe1115d3f28ebcab63414b90 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 9 Feb 2023 19:22:29 +0100 Subject: [PATCH 29/66] TMR: buffer cores_synch signal DMR: buffer cores_synch signal --- rtl/HMR/hmr_dmr_ctrl.sv | 5 ++++- rtl/HMR/hmr_tmr_ctrl.sv | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 0de7c40f..3be7f7b3 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -51,6 +51,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( logic synch_req, synch_req_sent_d, synch_req_sent_q; logic resynch_req, resynch_req_sent_d, resynch_req_sent_q; + logic cores_synch_q; 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; @@ -138,7 +139,7 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( // 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 synch_req = 1'b1; - if (cores_synch_i == 1'b1) begin + if (cores_synch_q == 1'b1) begin dmr_red_mode_d = DMR_RUN; setback_o = 2'b11; end @@ -167,10 +168,12 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( dmr_red_mode_q <= DefaultDMRMode; synch_req_sent_q <= '0; resynch_req_sent_q <= '0; + cores_synch_q <= '0; end else begin dmr_red_mode_q <= dmr_red_mode_d; synch_req_sent_q <= synch_req_sent_d; resynch_req_sent_q <= resynch_req_sent_d; + cores_synch_q <= cores_synch_i; end end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 3a24356d..ef133d46 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -60,6 +60,7 @@ module hmr_tmr_ctrl #( logic synch_req, synch_req_sent_d, synch_req_sent_q; logic resynch_req, resynch_req_sent_d, resynch_req_sent_q; + logic cores_synch_q; 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; @@ -188,7 +189,7 @@ module hmr_tmr_ctrl #( // 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 synch_req = 1'b1; - if (cores_synch_i == 1'b1) begin + if (cores_synch_q == 1'b1) begin tmr_red_mode_d = TMR_RELOAD; if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin setback_o = 3'b111; @@ -221,10 +222,12 @@ module hmr_tmr_ctrl #( tmr_red_mode_q <= DefaultTMRMode; synch_req_sent_q <= '0; resynch_req_sent_q <= '0; + cores_synch_q <= '0; end else begin tmr_red_mode_q <= tmr_red_mode_d; synch_req_sent_q <= synch_req_sent_d; resynch_req_sent_q <= resynch_req_sent_d; + cores_synch_q <= cores_synch_i; end end From 97bb5fc2a49022a4b4e84d74a711cb21d8cb215d Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 10 Feb 2023 11:17:07 +0100 Subject: [PATCH 30/66] Connect rapid recovery synch signals --- rtl/HMR/hmr_dmr_ctrl.sv | 8 ++++++-- rtl/HMR/hmr_tmr_ctrl.sv | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 3be7f7b3..ab7992e9 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -140,8 +140,12 @@ module hmr_dmr_ctrl import recovery_pkg::*; #( if (dmr_red_mode_q == NON_DMR && dmr_reg2hw.dmr_enable.q == 1'b1) begin synch_req = 1'b1; if (cores_synch_q == 1'b1) begin - dmr_red_mode_d = DMR_RUN; - setback_o = 2'b11; + if (dmr_reg2hw.dmr_config.rapid_recovery.q == 1'b1) begin + dmr_red_mode_d = DMR_RESTORE; + end else begin + dmr_red_mode_d = DMR_RUN; + setback_o = 2'b11; + end end end // Before core startup: set DMR mode from reg2hw.dmr_enable diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index ef133d46..e915b9d9 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -190,9 +190,13 @@ module hmr_tmr_ctrl #( if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.q == 1'b1) begin synch_req = 1'b1; if (cores_synch_q == 1'b1) begin - tmr_red_mode_d = TMR_RELOAD; - if (tmr_reg2hw.tmr_config.setback.q == 1'b1) begin - setback_o = 3'b111; + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1) 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 + setback_o = 3'b111; + end end end end From 00e190c539cffc2d935a5428377f08448fd9e40c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 13 Feb 2023 14:16:44 +0100 Subject: [PATCH 31/66] HMR: fix minor DMR naming error --- rtl/HMR/HMR_dmr_regs.hjson | 4 ++-- rtl/HMR/hmr_v1.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/HMR_dmr_regs.hjson b/rtl/HMR/HMR_dmr_regs.hjson index 682c4b5b..12e16d44 100644 --- a/rtl/HMR/HMR_dmr_regs.hjson +++ b/rtl/HMR/HMR_dmr_regs.hjson @@ -19,8 +19,8 @@ resval: "0", fields: [ { bits: "0", - name: "TMR_enable", - desc: "TMR configuration enable." + name: "DMR_enable", + desc: "DMR configuration enable." } ] }, diff --git a/rtl/HMR/hmr_v1.h b/rtl/HMR/hmr_v1.h index ec4f2d7e..7a4e0bfa 100644 --- a/rtl/HMR/hmr_v1.h +++ b/rtl/HMR/hmr_v1.h @@ -137,7 +137,7 @@ extern "C" { // DMR configuration enable. #define HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET 0x0 -#define HMR_DMR_REGS_DMR_ENABLE_TMR_ENABLE_BIT 0 +#define HMR_DMR_REGS_DMR_ENABLE_DMR_ENABLE_BIT 0 // DMR configuration bits. #define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4 From 1f35ee2667ffdb0754f9c30ad5bb71af2166b5ca Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 15 Feb 2023 16:57:25 +0100 Subject: [PATCH 32/66] HMR: Fix DMR setback connections --- rtl/HMR/HMR_wrap.sv | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 9bdfb363..427c1695 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -213,7 +213,7 @@ module HMR_wrap import recovery_pkg::*; #( endfunction function int dmr_offset_id (int core_id); - if (InterleaveGrps) return core_id / NumTMRGroups; + if (InterleaveGrps) return core_id / NumDMRGroups; else return core_id % 2; endfunction @@ -1234,14 +1234,21 @@ module HMR_wrap import recovery_pkg::*; #( // Special signals if (RapidRecovery) begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0)); end else begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; end - if (i >= NumTMRCores && RapidRecovery) begin - core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; - end else if (i >= NumTMRCores) begin - core_setback_o [i] = '0; + if (i >= NumTMRCores && i >= NumDMRCores) begin + core_setback_o [i] = '0; + end else if (i < NumTMRCores && i >= NumDMRCores) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | (RapidRecovery ? (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0) : '0); + end else if (i >= NumTMRCores && i < NumDMRCores) begin + core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (RapidRecovery ? (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : '0) : '0); end if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode // CTRL @@ -1462,7 +1469,7 @@ module HMR_wrap import recovery_pkg::*; #( // Setback if (RapidRecovery) begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] - | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + | recovery_setback_out [tmr_shared_id(tmr_group_id(i))]; end else begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; end @@ -1659,10 +1666,14 @@ module HMR_wrap import recovery_pkg::*; #( always_comb begin // Setback if (RapidRecovery) begin - core_setback_o [i] = recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] + | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; end else begin core_setback_o [i] = '0; end + if (i >= NumDMRCores) begin + core_setback_o [i] = '0; + end if (i < NumDMRCores && (DMRFixed || core_in_dmr[i])) begin : dmr_mode // CTRL core_core_id_o [i] = sys_core_id_i [SysCoreIndex]; From 0d3346782ad832bfd9407a019d726b959ef6cb43 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 16 Feb 2023 17:01:00 +0100 Subject: [PATCH 33/66] Always backup when dmr/tmr is disabled Back up csr when dmr/tmr is disabled --- rtl/HMR/HMR_wrap.sv | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 427c1695..54ab72b4 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -946,9 +946,12 @@ module HMR_wrap import recovery_pkg::*; #( if (RapidRecovery) begin : gen_rapid_recovery for (genvar i = 0; i < NumBackupRegfiles; i++) begin : gen_groups // Write Enable signal for backup registers - assign rapid_recovery_backup_enable[i] = tmr_core_rapid_recovery_en[i] ? backup_enable[i] // TMR mode - : dmr_core_rapid_recovery_en[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode - : 1'b1; // Independent mode + assign rapid_recovery_backup_enable[i] = core_in_tmr[i] ? (i < NumTMRGroups ? backup_enable[i] : 1'b0) // TMR mode + : core_in_dmr[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent mode + // TODO: Only supports interleaved mode!!! + + hmr_rapid_recovery_ctrl #( .RFAddrWidth( RFAddrWidth ) @@ -1058,6 +1061,7 @@ module HMR_wrap import recovery_pkg::*; #( // Continually backup master cores in interleaved mode for fast entry if (InterleaveGrps) begin for (int i = 0; i < NumBackupRegfiles; i++) begin + backup_csr_int [i] = backup_csr_i [i]; backup_program_counter_int [i] = backup_program_counter_i [i]; backup_branch_int [i] = backup_branch_i [i]; backup_branch_addr_int [i] = backup_branch_addr_i [i]; From 0afd35dc4011080dbbfd93ae06f82e6247b597c8 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Sat, 18 Feb 2023 20:10:07 +0100 Subject: [PATCH 34/66] Update response suppression to keep req until gnt --- rtl/HMR/HMR_wrap.sv | 314 ++++++++++++++++++++++----------------- rtl/HMR/resp_suppress.sv | 66 ++++++-- 2 files changed, 232 insertions(+), 148 deletions(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 54ab72b4..4dad449c 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -372,26 +372,64 @@ module HMR_wrap import recovery_pkg::*; #( end end + logic [NumSysCores-1:0] filt_instr_req, filt_data_req; logic [NumSysCores-1:0] filt_instr_r_valid, filt_data_r_valid; + logic [NumSysCores-1:0] filt_instr_gnt, filt_data_gnt; + logic [NumSysCores-1:0] filt_data_we; + logic [NumSysCores-1:0][31:0] filt_instr_addr, filt_data_addr; + logic [NumSysCores-1:0][DataWidth-1:0] filt_data_data; + logic [NumSysCores-1:0][BeWidth-1:0] filt_data_be; for (genvar i = 0; i < NumSysCores; i++) begin - resp_suppress i_instr_suppress ( + resp_suppress #( + .AW (32), + .DW (DataWidth) + ) i_instr_suppress ( .clk_i, .rst_ni, - .setback_i (core_setback_o[i]), - .req_i (sys_instr_req_o[i]), - .gnt_i (sys_instr_gnt_i[i]), + + .ctrl_setback_i (core_setback_o[i]), + + .req_i (filt_instr_req [i]), + .gnt_o (filt_instr_gnt [i]), + .r_valid_o (filt_instr_r_valid[i]), + .we_i ('0), + .addr_i (filt_instr_addr [i]), + .data_i ('0), + .be_i ('0), + + .req_o (sys_instr_req_o[i]), + .gnt_i (sys_instr_gnt_i[i]), .r_valid_i (sys_instr_r_valid_i[i]), - .r_valid_o (filt_instr_r_valid[i]) + .we_o (), + .addr_o (sys_instr_addr_o[i]), + .data_o (), + .be_o () ); - resp_suppress i_data_suppress ( + resp_suppress #( + .AW (32), + .DW (DataWidth) + ) i_data_suppress ( .clk_i, .rst_ni, - .setback_i (core_setback_o[i]), - .req_i (sys_data_req_o[i]), - .gnt_i (sys_data_gnt_i[i]), + + .ctrl_setback_i (core_setback_o[i]), + + .req_i (filt_data_req [i]), + .gnt_o (filt_data_gnt [i]), + .r_valid_o (filt_data_r_valid[i]), + .we_i (filt_data_we [i]), + .addr_i (filt_data_addr [i]), + .data_i (filt_data_data [i]), + .be_i (filt_data_be [i]), + + .req_o (sys_data_req_o [i]), + .gnt_i (sys_data_gnt_i [i]), .r_valid_i (sys_data_r_valid_i[i]), - .r_valid_o (filt_data_r_valid[i]) + .we_o (sys_data_wen_o [i]), + .addr_o (sys_data_add_o [i]), + .data_o (sys_data_wdata_o [i]), + .be_o (sys_data_be_o [i]) ); end @@ -1276,13 +1314,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [TMRCoreIndex]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [TMRCoreIndex]; + core_instr_gnt_o [i] = filt_instr_gnt [TMRCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[TMRCoreIndex]; core_instr_r_valid_o[i] = filt_instr_r_valid[TMRCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [TMRCoreIndex]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [TMRCoreIndex]; + core_data_gnt_o [i] = filt_data_gnt [TMRCoreIndex]; core_data_r_opc_o [i] = sys_data_r_opc_i [TMRCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [TMRCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [TMRCoreIndex]; @@ -1310,13 +1348,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [DMRCoreIndex]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [DMRCoreIndex]; + core_instr_gnt_o [i] = filt_instr_gnt [DMRCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[DMRCoreIndex]; core_instr_r_valid_o[i] = filt_instr_r_valid[DMRCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [DMRCoreIndex]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [DMRCoreIndex]; + core_data_gnt_o [i] = filt_data_gnt [DMRCoreIndex]; core_data_r_opc_o [i] = sys_data_r_opc_i [DMRCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [DMRCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [DMRCoreIndex]; @@ -1339,13 +1377,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [i]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_gnt_o [i] = filt_instr_gnt [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_gnt_o [i] = filt_data_gnt [i]; core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; @@ -1369,16 +1407,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[TMRCoreIndex]; // INSTR - sys_instr_req_o [i] = tmr_instr_req_out [TMRCoreIndex]; - sys_instr_addr_o [i] = tmr_instr_addr_out[TMRCoreIndex]; + filt_instr_req [i] = tmr_instr_req_out [TMRCoreIndex]; + filt_instr_addr [i] = tmr_instr_addr_out[TMRCoreIndex]; // DATA - sys_data_req_o [i] = tmr_data_req_out [TMRCoreIndex]; - sys_data_add_o [i] = tmr_data_add_out [TMRCoreIndex]; - sys_data_wen_o [i] = tmr_data_wen_out [TMRCoreIndex]; - sys_data_wdata_o [i] = tmr_data_wdata_out[TMRCoreIndex]; + filt_data_req [i] = tmr_data_req_out [TMRCoreIndex]; + filt_data_addr [i] = tmr_data_add_out [TMRCoreIndex]; + filt_data_we [i] = tmr_data_wen_out [TMRCoreIndex]; + filt_data_data [i] = tmr_data_wdata_out[TMRCoreIndex]; sys_data_user_o [i] = tmr_data_user_out [TMRCoreIndex]; - sys_data_be_o [i] = tmr_data_be_out [TMRCoreIndex]; + filt_data_be [i] = tmr_data_be_out [TMRCoreIndex]; end else begin : disable_core // Assign disable // CTLR sys_core_busy_o [i] = '0; @@ -1388,16 +1426,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = '0; // INSTR - sys_instr_req_o [i] = '0; - sys_instr_addr_o [i] = '0; + filt_instr_req [i] = '0; + filt_instr_addr [i] = '0; // DATA - sys_data_req_o [i] = '0; - sys_data_add_o [i] = '0; - sys_data_wen_o [i] = '0; - sys_data_wdata_o [i] = '0; + filt_data_req [i] = '0; + filt_data_addr [i] = '0; + filt_data_we [i] = '0; + filt_data_data [i] = '0; sys_data_user_o [i] = '0; - sys_data_be_o [i] = '0; + filt_data_be [i] = '0; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core @@ -1409,16 +1447,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[DMRCoreIndex]; // INSTR - sys_instr_req_o [i] = dmr_instr_req_out [DMRCoreIndex]; - sys_instr_addr_o [i] = dmr_instr_addr_out[DMRCoreIndex]; + filt_instr_req [i] = dmr_instr_req_out [DMRCoreIndex]; + filt_instr_addr [i] = dmr_instr_addr_out[DMRCoreIndex]; // DATA - sys_data_req_o [i] = dmr_data_req_out [DMRCoreIndex]; - sys_data_add_o [i] = dmr_data_add_out [DMRCoreIndex]; - sys_data_wen_o [i] = dmr_data_wen_out [DMRCoreIndex]; - sys_data_wdata_o [i] = dmr_data_wdata_out[DMRCoreIndex]; + filt_data_req [i] = dmr_data_req_out [DMRCoreIndex]; + filt_data_addr [i] = dmr_data_add_out [DMRCoreIndex]; + filt_data_we [i] = dmr_data_wen_out [DMRCoreIndex]; + filt_data_data [i] = dmr_data_wdata_out[DMRCoreIndex]; sys_data_user_o [i] = dmr_data_user_out [DMRCoreIndex]; - sys_data_be_o [i] = dmr_data_be_out [DMRCoreIndex]; + filt_data_be [i] = dmr_data_be_out [DMRCoreIndex]; end else begin : disable_core // Assign disable // CTLR sys_core_busy_o [i] = '0; @@ -1428,16 +1466,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = '0; // INSTR - sys_instr_req_o [i] = '0; - sys_instr_addr_o [i] = '0; + filt_instr_req [i] = '0; + filt_instr_addr [i] = '0; // DATA - sys_data_req_o [i] = '0; - sys_data_add_o [i] = '0; - sys_data_wen_o [i] = '0; - sys_data_wdata_o [i] = '0; + filt_data_req [i] = '0; + filt_data_addr [i] = '0; + filt_data_we [i] = '0; + filt_data_data [i] = '0; sys_data_user_o [i] = '0; - sys_data_be_o [i] = '0; + filt_data_be [i] = '0; end end else begin : independent_mode // CTRL @@ -1448,16 +1486,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; // INSTR - sys_instr_req_o [i] = core_instr_req_i [i]; - sys_instr_addr_o [i] = core_instr_addr_i[i]; + filt_instr_req [i] = core_instr_req_i [i]; + filt_instr_addr [i] = core_instr_addr_i[i]; // DATA - sys_data_req_o [i] = core_data_req_i [i]; - sys_data_add_o [i] = core_data_add_i [i]; - sys_data_wen_o [i] = core_data_wen_i [i]; - sys_data_wdata_o [i] = core_data_wdata_i[i]; + filt_data_req [i] = core_data_req_i [i]; + filt_data_addr [i] = core_data_add_i [i]; + filt_data_we [i] = core_data_wen_i [i]; + filt_data_data [i] = core_data_wdata_i[i]; sys_data_user_o [i] = core_data_user_i [i]; - sys_data_be_o [i] = core_data_be_i [i]; + filt_data_be [i] = core_data_be_i [i]; end end end @@ -1502,13 +1540,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + core_instr_gnt_o [i] = filt_instr_gnt [SysCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[SysCoreIndex]; core_instr_r_valid_o[i] = filt_instr_r_valid[SysCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + core_data_gnt_o [i] = filt_data_gnt [SysCoreIndex]; core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; @@ -1531,13 +1569,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [i]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_gnt_o [i] = filt_instr_gnt [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_gnt_o [i] = filt_data_gnt [i]; core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; @@ -1558,16 +1596,16 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - assign sys_instr_req_o [i] = tmr_instr_req_out [CoreCoreIndex]; - assign sys_instr_addr_o [i] = tmr_instr_addr_out[CoreCoreIndex]; + assign filt_instr_req [i] = tmr_instr_req_out [CoreCoreIndex]; + assign filt_instr_addr [i] = tmr_instr_addr_out[CoreCoreIndex]; // DATA - assign sys_data_req_o [i] = tmr_data_req_out [CoreCoreIndex]; - assign sys_data_add_o [i] = tmr_data_add_out [CoreCoreIndex]; - assign sys_data_wen_o [i] = tmr_data_wen_out [CoreCoreIndex]; - assign sys_data_wdata_o [i] = tmr_data_wdata_out[CoreCoreIndex]; + assign filt_data_req [i] = tmr_data_req_out [CoreCoreIndex]; + assign filt_data_addr [i] = tmr_data_add_out [CoreCoreIndex]; + assign filt_data_we [i] = tmr_data_wen_out [CoreCoreIndex]; + assign filt_data_data [i] = tmr_data_wdata_out[CoreCoreIndex]; assign sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; - assign sys_data_be_o [i] = tmr_data_be_out [CoreCoreIndex]; + assign filt_data_be [i] = tmr_data_be_out [CoreCoreIndex]; end else begin if (i >= NumTMRCores) begin : independent_stragglers // CTRL @@ -1578,16 +1616,16 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // INSTR - assign sys_instr_req_o [i] = core_instr_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_instr_addr_o [i] = core_instr_addr_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_req [i] = core_instr_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_addr [i] = core_instr_addr_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // DATA - assign sys_data_req_o [i] = core_data_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_add_o [i] = core_data_add_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_wen_o [i] = core_data_wen_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_wdata_o [i] = core_data_wdata_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_req [i] = core_data_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_addr [i] = core_data_add_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_we [i] = core_data_wen_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_data [i] = core_data_wdata_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign sys_data_user_o [i] = core_data_user_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_be_o [i] = core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_be [i] = core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; end else begin always_comb begin if (core_in_tmr[i]) begin : tmr_mode @@ -1600,16 +1638,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = tmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - sys_instr_req_o [i] = tmr_instr_req_out [CoreCoreIndex]; - sys_instr_addr_o [i] = tmr_instr_addr_out[CoreCoreIndex]; + filt_instr_req [i] = tmr_instr_req_out [CoreCoreIndex]; + filt_instr_addr [i] = tmr_instr_addr_out[CoreCoreIndex]; // DATA - sys_data_req_o [i] = tmr_data_req_out [CoreCoreIndex]; - sys_data_add_o [i] = tmr_data_add_out [CoreCoreIndex]; - sys_data_wen_o [i] = tmr_data_wen_out [CoreCoreIndex]; - sys_data_wdata_o [i] = tmr_data_wdata_out[CoreCoreIndex]; + filt_data_req [i] = tmr_data_req_out [CoreCoreIndex]; + filt_data_addr [i] = tmr_data_add_out [CoreCoreIndex]; + filt_data_we [i] = tmr_data_wen_out [CoreCoreIndex]; + filt_data_data [i] = tmr_data_wdata_out[CoreCoreIndex]; sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; - sys_data_be_o [i] = tmr_data_be_out [CoreCoreIndex]; + filt_data_be [i] = tmr_data_be_out [CoreCoreIndex]; end else begin : disable_core // Assign disable // CTLR sys_core_busy_o [i] = '0; @@ -1619,16 +1657,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = '0; // INSTR - sys_instr_req_o [i] = '0; - sys_instr_addr_o [i] = '0; + filt_instr_req [i] = '0; + filt_instr_addr [i] = '0; // DATA - sys_data_req_o [i] = '0; - sys_data_add_o [i] = '0; - sys_data_wen_o [i] = '0; - sys_data_wdata_o [i] = '0; + filt_data_req [i] = '0; + filt_data_addr [i] = '0; + filt_data_we [i] = '0; + filt_data_data [i] = '0; sys_data_user_o [i] = '0; - sys_data_be_o [i] = '0; + filt_data_be [i] = '0; end end else begin : independent_mode // CTRL @@ -1639,16 +1677,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; // INSTR - sys_instr_req_o [i] = core_instr_req_i [i]; - sys_instr_addr_o [i] = core_instr_addr_i[i]; + filt_instr_req [i] = core_instr_req_i [i]; + filt_instr_addr [i] = core_instr_addr_i[i]; // DATA - sys_data_req_o [i] = core_data_req_i [i]; - sys_data_add_o [i] = core_data_add_i [i]; - sys_data_wen_o [i] = core_data_wen_i [i]; - sys_data_wdata_o [i] = core_data_wdata_i[i]; + filt_data_req [i] = core_data_req_i [i]; + filt_data_addr [i] = core_data_add_i [i]; + filt_data_we [i] = core_data_wen_i [i]; + filt_data_data [i] = core_data_wdata_i[i]; sys_data_user_o [i] = core_data_user_i [i]; - sys_data_be_o [i] = core_data_be_i [i]; + filt_data_be [i] = core_data_be_i [i]; end end end @@ -1700,13 +1738,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [SysCoreIndex]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [SysCoreIndex]; + core_instr_gnt_o [i] = filt_instr_gnt [SysCoreIndex]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i [SysCoreIndex]; core_instr_r_valid_o[i] = filt_instr_r_valid [SysCoreIndex]; core_instr_err_o [i] = sys_instr_err_i [SysCoreIndex]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [SysCoreIndex]; + core_data_gnt_o [i] = filt_data_gnt [SysCoreIndex]; core_data_r_opc_o [i] = sys_data_r_opc_i [SysCoreIndex]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [SysCoreIndex]; core_data_r_user_o [i] = sys_data_r_user_i [SysCoreIndex]; @@ -1729,13 +1767,13 @@ module HMR_wrap import recovery_pkg::*; #( core_irq_id_o [i] = sys_irq_id_i [i]; // INSTR - core_instr_gnt_o [i] = sys_instr_gnt_i [i]; + core_instr_gnt_o [i] = filt_instr_gnt [i]; core_instr_r_rdata_o[i] = sys_instr_r_rdata_i[i]; core_instr_r_valid_o[i] = filt_instr_r_valid[i]; core_instr_err_o [i] = sys_instr_err_i [i]; // DATA - core_data_gnt_o [i] = sys_data_gnt_i [i]; + core_data_gnt_o [i] = filt_data_gnt [i]; core_data_r_opc_o [i] = sys_data_r_opc_i [i]; core_data_r_rdata_o [i] = sys_data_r_rdata_i [i]; core_data_r_user_o [i] = sys_data_r_user_i [i]; @@ -1756,16 +1794,16 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - assign sys_instr_req_o [i] = dmr_instr_req_out [CoreCoreIndex]; - assign sys_instr_addr_o [i] = dmr_instr_addr_out[CoreCoreIndex]; + assign filt_instr_req [i] = dmr_instr_req_out [CoreCoreIndex]; + assign filt_instr_addr [i] = dmr_instr_addr_out[CoreCoreIndex]; // DATA - assign sys_data_req_o [i] = dmr_data_req_out [CoreCoreIndex]; - assign sys_data_add_o [i] = dmr_data_add_out [CoreCoreIndex]; - assign sys_data_wen_o [i] = dmr_data_wen_out [CoreCoreIndex]; - assign sys_data_wdata_o [i] = dmr_data_wdata_out[CoreCoreIndex]; + assign filt_data_req [i] = dmr_data_req_out [CoreCoreIndex]; + assign filt_data_addr [i] = dmr_data_add_out [CoreCoreIndex]; + assign filt_data_we [i] = dmr_data_wen_out [CoreCoreIndex]; + assign filt_data_data [i] = dmr_data_wdata_out[CoreCoreIndex]; assign sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; - assign sys_data_be_o [i] = dmr_data_be_out [CoreCoreIndex]; + assign filt_data_be [i] = dmr_data_be_out [CoreCoreIndex]; end else begin if (i >= NumDMRCores) begin : independent_stragglers // CTRL @@ -1776,16 +1814,16 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // INSTR - assign sys_instr_req_o [i] = dmr_instr_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_instr_addr_o [i] = dmr_instr_addr_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_req [i] = dmr_instr_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_addr [i] = dmr_instr_addr_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // DATA - assign sys_data_req_o [i] = dmr_data_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_add_o [i] = dmr_data_add_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_wen_o [i] = dmr_data_wen_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_wdata_o [i] = dmr_data_wdata_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_req [i] = dmr_data_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_addr [i] = dmr_data_add_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_we [i] = dmr_data_wen_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_data [i] = dmr_data_wdata_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign sys_data_user_o [i] = dmr_data_user_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_be_o [i] = dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_be [i] = dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; end else begin always_comb begin if (core_in_dmr[i]) begin : dmr_mode @@ -1798,16 +1836,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[CoreCoreIndex]; // INSTR - sys_instr_req_o [i] = dmr_instr_req_out [CoreCoreIndex]; - sys_instr_addr_o [i] = dmr_instr_addr_out[CoreCoreIndex]; + filt_instr_req [i] = dmr_instr_req_out [CoreCoreIndex]; + filt_instr_addr [i] = dmr_instr_addr_out[CoreCoreIndex]; // DATA - sys_data_req_o [i] = dmr_data_req_out [CoreCoreIndex]; - sys_data_add_o [i] = dmr_data_add_out [CoreCoreIndex]; - sys_data_wen_o [i] = dmr_data_wen_out [CoreCoreIndex]; - sys_data_wdata_o [i] = dmr_data_wdata_out[CoreCoreIndex]; + filt_data_req [i] = dmr_data_req_out [CoreCoreIndex]; + filt_data_addr [i] = dmr_data_add_out [CoreCoreIndex]; + filt_data_we [i] = dmr_data_wen_out [CoreCoreIndex]; + filt_data_data [i] = dmr_data_wdata_out[CoreCoreIndex]; sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; - sys_data_be_o [i] = dmr_data_be_out [CoreCoreIndex]; + filt_data_be [i] = dmr_data_be_out [CoreCoreIndex]; end else begin : disable_core // Assign disable // CTLR sys_core_busy_o [i] = '0; @@ -1817,16 +1855,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = '0; // INSTR - sys_instr_req_o [i] = '0; - sys_instr_addr_o [i] = '0; + filt_instr_req [i] = '0; + filt_instr_addr [i] = '0; // DATA - sys_data_req_o [i] = '0; - sys_data_add_o [i] = '0; - sys_data_wen_o [i] = '0; - sys_data_wdata_o [i] = '0; + filt_data_req [i] = '0; + filt_data_addr [i] = '0; + filt_data_we [i] = '0; + filt_data_data [i] = '0; sys_data_user_o [i] = '0; - sys_data_be_o [i] = '0; + filt_data_be [i] = '0; end end else begin : independent_mode // CTRL @@ -1837,16 +1875,16 @@ module HMR_wrap import recovery_pkg::*; #( sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; // INSTR - sys_instr_req_o [i] = core_instr_req_i [i]; - sys_instr_addr_o [i] = core_instr_addr_i[i]; + filt_instr_req [i] = core_instr_req_i [i]; + filt_instr_addr [i] = core_instr_addr_i[i]; // DATA - sys_data_req_o [i] = core_data_req_i [i]; - sys_data_add_o [i] = core_data_add_i [i]; - sys_data_wen_o [i] = core_data_wen_i [i]; - sys_data_wdata_o [i] = core_data_wdata_i[i]; + filt_data_req [i] = core_data_req_i [i]; + filt_data_addr [i] = core_data_add_i [i]; + filt_data_we [i] = core_data_wen_i [i]; + filt_data_data [i] = core_data_wdata_i[i]; sys_data_user_o [i] = core_data_user_i [i]; - sys_data_be_o [i] = core_data_be_i [i]; + filt_data_be [i] = core_data_be_i [i]; end end end @@ -1879,21 +1917,21 @@ module HMR_wrap import recovery_pkg::*; #( assign sys_irq_ack_id_o = core_irq_ack_id_i; // INSTR - assign sys_instr_req_o = core_instr_req_i; - assign core_instr_gnt_o = sys_instr_gnt_i; - assign sys_instr_addr_o = core_instr_addr_i; + assign filt_instr_req = core_instr_req_i; + assign core_instr_gnt_o = filt_instr_gnt; + assign filt_instr_addr = core_instr_addr_i; assign core_instr_r_rdata_o = sys_instr_r_rdata_i; assign core_instr_r_valid_o = filt_instr_r_valid; assign core_instr_err_o = sys_instr_err_i; // DATA - assign sys_data_req_o = core_data_req_i; - assign sys_data_add_o = core_data_add_i; - assign sys_data_wen_o = core_data_wen_i; - assign sys_data_wdata_o = core_data_wdata_i; + assign filt_data_req = core_data_req_i; + assign filt_data_addr = core_data_add_i; + assign filt_data_we = core_data_wen_i; + assign filt_data_data = core_data_wdata_i; assign sys_data_user_o = core_data_user_i; - assign sys_data_be_o = core_data_be_i; - assign core_data_gnt_o = sys_data_gnt_i; + assign filt_data_be = core_data_be_i; + assign core_data_gnt_o = filt_data_gnt; assign core_data_r_opc_o = sys_data_r_opc_i; assign core_data_r_rdata_o = sys_data_r_rdata_i; assign core_data_r_user_o = sys_data_r_user_i; diff --git a/rtl/HMR/resp_suppress.sv b/rtl/HMR/resp_suppress.sv index 1144373e..fa1b8f28 100644 --- a/rtl/HMR/resp_suppress.sv +++ b/rtl/HMR/resp_suppress.sv @@ -11,30 +11,66 @@ // Suppress the r_valid if set back module resp_suppress #( - parameter int unsigned NumOutstanding = 2 + parameter int unsigned NumOutstanding = 2, + parameter int unsigned AW = 32, + parameter int unsigned DW = 32 ) ( input logic clk_i, input logic rst_ni, - input logic setback_i, - input logic req_i, - input logic gnt_i, - input logic r_valid_i, - output logic r_valid_o + input logic ctrl_setback_i, + + input logic req_i, + output logic gnt_o, + output logic r_valid_o, + input logic we_i, + input logic [AW -1:0] addr_i, + input logic [DW -1:0] data_i, + input logic [DW/8-1:0] be_i, + + output logic req_o, + input logic gnt_i, + input logic r_valid_i, + output logic we_o, + output logic [AW -1:0] addr_o, + output logic [DW -1:0] data_o, + output logic [DW/8-1:0] be_o ); logic [$clog2(NumOutstanding)-1:0] outstanding_d, outstanding_q; logic block_d, block_q; + logic latent_req_d, latent_req_q; + logic we_d, we_q; + logic [AW -1:0] addr_d, addr_q; + logic [DW -1:0] data_d, data_q; + logic [DW/8-1:0] be_d, be_q; + + assign outstanding_d = outstanding_q + (req_o & gnt_i ? 1 : 0) - (r_valid_i ? 1 : 0); - assign outstanding_d = outstanding_q + (req_i & gnt_i ? 1 : 0) - (r_valid_i ? 1 : 0); + assign r_valid_o = block_q || latent_req_q ? 1'b0 : r_valid_i; + assign gnt_o = latent_req_q ? 1'b0 : gnt_i; - assign r_valid_o = block_q ? 1'b0 : r_valid_i; + assign req_o = req_i | latent_req_q; + assign we_o = latent_req_q ? we_q : we_i; + assign addr_o = latent_req_q ? addr_q : addr_i; + assign data_o = latent_req_q ? data_q : data_i; + assign be_o = latent_req_q ? be_q : be_i; always_comb begin block_d = block_q; - if (setback_i) begin + latent_req_d = latent_req_q & ~gnt_i; + we_d = we_q; + addr_d = addr_q; + data_d = data_q; + be_d = be_q; + if (ctrl_setback_i) begin block_d = 1'b1; - end else if (outstanding_q == 0) begin + latent_req_d = req_i & ~gnt_i; + we_d = we_i; + addr_d = addr_i; + data_d = data_i; + be_d = be_i; + end else if (outstanding_q == 0 && !latent_req_q) begin block_d = 1'b0; end end @@ -43,9 +79,19 @@ module resp_suppress #( if (!rst_ni) begin outstanding_q <= '0; block_q <= '0; + latent_req_q <= '0; + we_q <= '0; + addr_q <= '0; + data_q <= '0; + be_q <= '0; end else begin outstanding_q <= outstanding_d; block_q <= block_d; + latent_req_q <= latent_req_d; + we_q <= we_d; + addr_q <= addr_d; + data_q <= data_d; + be_q <= be_d; end end From 7c2c61640c311e9619e5e4526a694f726d47e00d Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 10 May 2023 14:35:38 +0200 Subject: [PATCH 35/66] Add modular hmr unit --- Bender.yml | 1 + rtl/HMR/hmr_unit.sv | 774 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 775 insertions(+) create mode 100644 rtl/HMR/hmr_unit.sv diff --git a/Bender.yml b/Bender.yml index 4b0c9155..b7381d11 100644 --- a/Bender.yml +++ b/Bender.yml @@ -125,6 +125,7 @@ sources: - rtl/HMR/hmr_tmr_regs_reg_top.sv - rtl/HMR/hmr_tmr_ctrl.sv - rtl/HMR/HMR_wrap.sv + - rtl/HMR/hmr_unit.sv vendor_package: - name: lowrisc_opentitan diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv new file mode 100644 index 00000000..b8abcbec --- /dev/null +++ b/rtl/HMR/hmr_unit.sv @@ -0,0 +1,774 @@ +// Copyright 2022 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. +// +// Hybrid modular redundancy wrapping unit + +module hmr_unit #( + // Wrapper parameters + /// Number of physical cores + parameter int unsigned NumCores = 0, + /// Enables support for Dual Modular Redundancy + parameter bit DMRSupported = 1'b1, + /// Locks HMR into permanent DMR mode + parameter bit DMRFixed = 1'b0, + /// Enables support for Triple Modular Redundancy + parameter bit TMRSupported = 1'b1, + /// Locks HMR into permanent TMR mode + parameter bit TMRFixed = 1'b0, + /// Interleave DMR/TMR cores, alternatively with sequential grouping + parameter bit InterleaveGrps = 1'b1, + /// rapid recovery - tbd + parameter bit RapidRecovery = 1'b0, + /// Separates voters and checkers for data, which are then only checked if data request is valid + parameter bit SeparateData = 1'b1, + /// Number of separate voters/checkers for individual buses + parameter int unsigned NumBusVoters = 1, + /// General core inputs wrapping struct + parameter type all_inputs_t = logic, + /// General core outputs wrapping struct + parameter type nominal_outputs_t = logic, + /// Bus outputs wrapping struct + parameter type bus_outputs_t = logic, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + // Local parameters depending on the above ones + /// Number of TMR groups (virtual TMR cores) + localparam int unsigned NumTMRGroups = NumCores/3, + /// Number of physical cores used for TMR + localparam int unsigned NumTMRCores = NumTMRGroups * 3, + /// Number of physical cores NOT used for TMR + localparam int unsigned NumTMRLeftover = NumCores - NumTMRCores, + /// Number of DMR groups (virtual DMR cores) + localparam int unsigned NumDMRGroups = NumCores/2, + /// Nubmer of physical cores used for DMR + localparam int unsigned NumDMRCores = NumDMRGroups * 2, + /// Number of physical cores NOT used for DMR + localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, + /// Number of cores visible to the system (Fixed mode removes unneeded system ports) + localparam int unsigned NumSysCores = DMRFixed ? NumDMRGroups : TMRFixed ? NumTMRGroups : NumCores +) ( + input logic clk_i , + input logic rst_ni, + + // Port to configuration unit + input reg_req_t reg_request_i , + output reg_rsp_t reg_response_o, + + // TMR signals + output logic [NumTMRGroups-1:0] tmr_failure_o , + output logic [ NumSysCores-1:0] tmr_error_o , // Should this not be NumTMRCores? or NumCores? + output logic [NumTMRGroups-1:0] tmr_resynch_req_o, + output logic [ NumCores-1:0] tmr_sw_synch_req_o, + input logic [NumTMRGroups-1:0] tmr_cores_synch_i, + + // DMR signals + output logic [NumDMRGroups-1:0] dmr_failure_o , + output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? + output logic [NumDMRGroups-1:0] dmr_resynch_req_o, + output logic [ NumCores-1:0] dmr_sw_synch_req_o, + input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + + input all_inputs_t [NumSysCores-1:0] sys_inputs_i, + output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, + output bus_outputs_t [NumSysCores-1:0][NumBusVoters-1:0] sys_bus_outputs_o, + input logic [NumSysCores-1:0] sys_fetch_en_i, + input logic [NumSysCores-1:0][NumBusVoters-1:0] enable_bus_vote_i, + + output logic [NumCores-1:0] core_setback_o, + output all_inputs_t [NumCores-1:0] core_inputs_o, + input nominal_outputs_t [NumCores-1:0] core_nominal_outputs_i, + input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i +); + function int max(int a, int b); + return (a > b) ? a : b; + endfunction + + function int tmr_group_id (int core_id); + if (InterleaveGrps) return core_id % NumTMRGroups; + else return (core_id/3); + endfunction + + function int tmr_core_id (int group_id, int core_offset); + if (InterleaveGrps) return group_id + core_offset * NumTMRGroups; + else return (group_id * 3) + core_offset; + endfunction + + function int tmr_shared_id (int group_id); + if (InterleaveGrps || !(DMRSupported || DMRFixed)) return group_id; + else return group_id + group_id/2; + endfunction + + function int tmr_offset_id (int core_id); + if (InterleaveGrps) return core_id / NumTMRGroups; + else return core_id % 3; + endfunction + + function int dmr_group_id (int core_id); + if (InterleaveGrps) return core_id % NumDMRGroups; + else return (core_id/2); + endfunction + + function int dmr_core_id (int group_id, int core_offset); + if (InterleaveGrps) return group_id + core_offset * NumDMRGroups; + else return (group_id * 2) + core_offset; + endfunction + + function int dmr_shared_id (int group_id); + return group_id; + endfunction + + function int dmr_offset_id (int core_id); + if (InterleaveGrps) return core_id / NumDMRGroups; + else return core_id % 2; + endfunction + + if (TMRFixed && DMRFixed) $fatal(1, "Cannot fix both TMR and DMR!"); + + nominal_outputs_t [NumTMRGroups-1:0] tmr_nominal_outputs; + bus_outputs_t [NumTMRGroups-1:0][NumBusVoters-1:0] tmr_bus_outputs; + + nominal_outputs_t [NumDMRGroups-1:0] dmr_nominal_outputs; + bus_outputs_t [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_bus_outputs; + + logic [NumTMRGroups-1:0] tmr_failure, tmr_failure_main; + logic [NumTMRGroups-1:0][NumBusVoters-1:0] tmr_failure_data; + logic [NumTMRGroups-1:0][2:0] tmr_error, tmr_error_main; + logic [NumTMRGroups-1:0][NumBusVoters-1:0][2:0] tmr_error_data; + logic [NumTMRGroups-1:0] tmr_single_mismatch; + + logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main; + logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; + + /*************************** + * HMR Control Registers * + ***************************/ + + logic [NumCores-1:0] core_en_as_master; + logic [NumCores-1:0] core_in_independent; + logic [NumCores-1:0] core_in_dmr; + logic [NumCores-1:0] core_in_tmr; + logic [NumCores-1:0] dmr_core_rapid_recovery_en; + logic [NumCores-1:0] tmr_core_rapid_recovery_en; + + logic [NumDMRGroups-1:0][1:0] dmr_setback_q; + logic [NumDMRGroups-1:0] dmr_grp_in_independent; + logic [NumDMRGroups-1:0] dmr_rapid_recovery_en; + + logic [NumTMRGroups-1:0][2:0] tmr_setback_q; + logic [NumTMRGroups-1:0] tmr_grp_in_independent; + logic [NumTMRGroups-1:0] tmr_rapid_recovery_en; + + logic [NumCores-1:0] sp_store_is_zero; + logic [NumCores-1:0] sp_store_will_be_zero; + + for (genvar i = 0; i < NumCores; i++) begin : gen_global_status + assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; + assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; + assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? ~tmr_grp_in_independent[tmr_group_id(i)] : '0; + assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & + ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); + assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && i < NumDMRCores && RapidRecovery ? dmr_rapid_recovery_en[dmr_group_id(i)] : '0; + assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && i < NumTMRCores && RapidRecovery ? tmr_rapid_recovery_en[tmr_group_id(i)] : '0; + end + + reg_req_t [3:0] top_register_reqs; + reg_rsp_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 ) + ) 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 ) + ); + + // 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) + ); + + 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; + 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; + + // Core Config Registers + + reg_req_t [NumCores-1:0] core_register_reqs; + reg_rsp_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 ) + ) 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 ) + ); + + 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; + + 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) + ); + + 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; + end + + + + + /********************************************************** + ******************** TMR Voters & Regs ******************* + **********************************************************/ + + 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; + logic [NumTMRGroups-1:0] tmr_sw_synch_req; + + localparam TMRSelWidth = $clog2(NumTMRGroups); + + /*************** + * Registers * + ***************/ + if (NumTMRGroups == 1) begin + assign tmr_register_reqs[0] = top_register_reqs[3]; + assign top_register_resps[3] = tmr_register_resps[0]; + end else begin + reg_demux #( + .NoPorts ( NumTMRGroups ), + .req_t ( reg_req_t ), + .rsp_t ( reg_rsp_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 ) + ); + end + + for (genvar i = NumTMRCores; i < NumCores; i++) begin : gen_extra_core_assigns + assign tmr_incr_mismatches[i] = '0; + assign tmr_sw_synch_req_o[i] = '0; + end + + 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 ), + .TMRFixed ( TMRFixed ), + .InterleaveGrps ( InterleaveGrps ), + .DefaultInTMR ( 1'b0 ), + .RapidRecovery ( RapidRecovery ) + ) i_tmr_ctrl ( + .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 ), + + .setback_o ( tmr_setback_q[i] ), + .sw_resynch_req_o ( tmr_resynch_req_o[i] ), + .sw_synch_req_o ( tmr_sw_synch_req[i] ), + .grp_in_independent_o ( tmr_grp_in_independent[i] ), + .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), + .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), + .tmr_single_mismatch_i( tmr_single_mismatch[i] ), + .tmr_error_i ( tmr_error[i] ), + .tmr_failure_i ( tmr_failure[i] ), + .sp_store_is_zero ( sp_store_is_zero[tmr_core_id(i, 0)] ), + .sp_store_will_be_zero( sp_store_will_be_zero[tmr_core_id(i, 0)] ), + + .fetch_en_i ( sys_fetch_en_i[tmr_core_id(i, 0)] ), + .cores_synch_i ( tmr_cores_synch_i[i] ), + + .recovery_request_o ( ),//tmr_start_recovery [i] ), + .recovery_finished_i ( '0)//tmr_recovery_finished [i] ) + ); + + assign tmr_sw_synch_req_o[tmr_core_id(i, 0)] = tmr_sw_synch_req[i]; + assign tmr_sw_synch_req_o[tmr_core_id(i, 1)] = tmr_sw_synch_req[i]; + assign tmr_sw_synch_req_o[tmr_core_id(i, 2)] = tmr_sw_synch_req[i]; + + always_comb begin + tmr_failure[i] = tmr_failure_main[i]; + tmr_error [i] = tmr_error_main [i]; + for (int j = 0; j < NumBusVoters; j++) begin + if (enable_bus_vote_i[tmr_core_id(i, 0)][j]) begin + tmr_failure[i] = tmr_failure[i] | tmr_failure_data[i][j]; + tmr_error [i] = tmr_error [i] | tmr_error_data [i][j]; + end + end + end + assign tmr_single_mismatch[i] = tmr_error[i] != 3'b000; + + bitwise_TMR_voter #( + .DataWidth( $bits(nominal_outputs_t) ), + .VoterType( 0 ) + ) i_main_voter ( + .a_i ( core_nominal_outputs_i[tmr_core_id(i, 0)] ), + .b_i ( core_nominal_outputs_i[tmr_core_id(i, 1)] ), + .c_i ( core_nominal_outputs_i[tmr_core_id(i, 2)] ), + .majority_o ( tmr_nominal_outputs [ i ] ), + .error_o ( tmr_failure_main [ i ] ), + .error_cba_o( tmr_error_main [ i ] ) + ); + if (SeparateData) begin : gen_data_voter + for (genvar j = 0; j < NumBusVoters; j++) begin + bitwise_TMR_voter #( + .DataWidth( $bits(bus_outputs_t) ), + .VoterType( 0 ) + ) i_data_voter ( + .a_i ( core_bus_outputs_i[tmr_core_id(i, 0)][j] ), + .b_i ( core_bus_outputs_i[tmr_core_id(i, 1)][j] ), + .c_i ( core_bus_outputs_i[tmr_core_id(i, 2)][j] ), + .majority_o ( tmr_bus_outputs [ i ][j] ), + .error_o ( tmr_failure_data [ i ][j] ), + .error_cba_o( tmr_error_data [ i ][j] ) + ); + end + end + end + end else begin : gen_no_tmr_voted + assign tmr_error_main = '0; + assign tmr_error_data = '0; + assign tmr_error = '0; + assign tmr_failure_main = '0; + assign tmr_failure_data = '0; + assign tmr_failure = '0; + assign tmr_nominal_outputs = '0; + assign tmr_bus_outputs = '0; + assign top_register_resps[3].rdata = '0; + assign top_register_resps[3].error = 1'b1; + assign top_register_resps[3].ready = 1'b1; + assign tmr_incr_mismatches = '0; + assign tmr_grp_in_independent = '0; + assign tmr_setback_q = '0; + assign tmr_resynch_req_o = '0; + assign tmr_sw_synch_req_o = '0; + end + + /************************************************************ + ******************** DMR Voters and Regs ******************* + ************************************************************/ + + 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; + logic [NumDMRGroups-1:0] dmr_sw_synch_req; + + localparam DMRSelWidth = $clog2(NumDMRGroups); + + /*************** + * Registers * + ***************/ + reg_demux #( + .NoPorts ( NumDMRGroups ), + .req_t ( reg_req_t ), + .rsp_t ( reg_rsp_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 ) + ); + + for (genvar i = NumDMRCores; i < NumCores; i++) begin : gen_extra_core_assigns + assign dmr_incr_mismatches[i] = '0; + assign dmr_sw_synch_req_o[i] = '0; + end + + 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 ), + .InterleaveGrps( InterleaveGrps ), + .DMRFixed ( DMRFixed ), + .RapidRecovery ( RapidRecovery ), + .DefaultInDMR ( 1'b0 ) + ) i_dmr_ctrl ( + .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 ), + + .setback_o ( dmr_setback_q [i] ), + .sw_resynch_req_o ( dmr_resynch_req_o [i] ), + .sw_synch_req_o ( dmr_sw_synch_req [i] ), + .grp_in_independent_o ( dmr_grp_in_independent[i] ), + .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), + .dmr_error_i ( dmr_failure [i] ), + + .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), + .cores_synch_i ( dmr_cores_synch_i[i] ), + + .recovery_request_o ( ),//dmr_start_recovery [i] ), + .recovery_finished_i ( '0)//dmr_recovery_finished[i] ) + ); + + assign dmr_sw_synch_req_o[dmr_core_id(i, 0)] = dmr_sw_synch_req[i]; + assign dmr_sw_synch_req_o[dmr_core_id(i, 1)] = dmr_sw_synch_req[i]; + + /********************* + * DMR Core Checkers * + *********************/ + DMR_checker #( + .DataWidth ( $bits(nominal_outputs_t) ) + ) dmr_core_checker_main ( + .inp_a_i ( core_nominal_outputs_i[dmr_core_id(i, 0)] ), + .inp_b_i ( core_nominal_outputs_i[dmr_core_id(i, 1)] ), + .check_o ( dmr_nominal_outputs [ i ] ), + .error_o ( dmr_failure_main [ i ] ) + ); + if (SeparateData) begin : gen_data_checker + for (genvar j = 0; j < NumBusVoters; j++) begin + DMR_checker # ( + .DataWidth ( $bits(bus_outputs_t) ) + ) dmr_core_checker_data ( + .inp_a_i ( core_bus_outputs_i[dmr_core_id(i, 0)][j] ), + .inp_b_i ( core_bus_outputs_i[dmr_core_id(i, 1)][j] ), + .check_o ( dmr_bus_outputs [ i ][j] ), + .error_o ( dmr_failure_data [ i ][j] ) + ); + end + end + + if (RapidRecovery) begin : gen_rapid_recovery_connection + $error("UNIMPLEMENTED"); + end else begin : gen_standard_failure + always_comb begin + dmr_failure[i] = dmr_failure_main[i]; + for (int j = 0; j < NumBusVoters; j++) begin + if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin + dmr_failure[i] = dmr_failure[i] | dmr_failure_data[i][j]; + end + end + end + end + end + end else begin: no_dmr_checkers + assign dmr_failure_main = '0; + assign dmr_failure_data = '0; + assign dmr_failure = '0; + assign dmr_incr_mismatches = '0; + assign dmr_nominal_outputs = '0; + assign dmr_bus_outputs = '0; + assign top_register_resps[2].rdata = '0; + assign top_register_resps[2].error = 1'b1; + assign top_register_resps[2].ready = 1'b1; + assign dmr_sw_synch_req_o = '0; + end + + + // Assign output signals + if (DMRSupported && TMRSupported) begin : gen_full_HMR + /***************** + *** TMR & DMR *** + *****************/ + if (TMRFixed || DMRFixed) $fatal(1, "Cannot support both TMR and DMR and fix one!"); + + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); + localparam DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); + + always_comb begin + // Special signals + if (RapidRecovery) begin + $error("UNIMPLEMENTED"); + // core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + // | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + // | (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : + // (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0)); + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; + end + if (i >= NumTMRCores && i >= NumDMRCores) begin + core_setback_o [i] = '0; + end else if (i < NumTMRCores && i >= NumDMRCores) begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; +// | (RapidRecovery ? (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0) : '0); + end else if (i >= NumTMRCores && i < NumDMRCores) begin + core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; +// | (RapidRecovery ? (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : '0) : '0); + end + if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode + core_inputs_o[i] = sys_inputs_i[TMRCoreIndex]; + end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode + core_inputs_o[i] = sys_inputs_i[DMRCoreIndex]; + end else begin : independent_mode + core_inputs_o[i] = sys_inputs_i[i]; + end + end + end + + for (genvar i = 0; i < NumSysCores/*==NumCores*/; i++) begin : gen_core_outputs + localparam TMRCoreIndex = tmr_group_id(i); + localparam DMRCoreIndex = dmr_group_id(i); + always_comb begin + if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode + if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core + sys_nominal_outputs_o[i] = tmr_nominal_outputs[TMRCoreIndex]; + sys_bus_outputs_o[i] = tmr_bus_outputs[TMRCoreIndex]; + end else begin : disable_core // Assign disable + sys_nominal_outputs_o[i] = '0; + sys_bus_outputs_o[i] = '0; + end + end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode + if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core + sys_nominal_outputs_o[i] = dmr_nominal_outputs[DMRCoreIndex]; + for (int j = 0; j < NumBusVoters; j++) begin + sys_bus_outputs_o[i][j] = dmr_bus_outputs[DMRCoreIndex][j]; + end + end else begin : disable_core // Assign disable + sys_nominal_outputs_o[i] = '0; + sys_bus_outputs_o[i] = '0; + end + end else begin : independent_mode + sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; + sys_bus_outputs_o[i] = core_bus_outputs_i[i]; + end + end + end + + end else if (TMRSupported || TMRFixed) begin : gen_TMR_only + /***************** + *** TMR only *** + *****************/ + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); + always_comb begin + // Special signals + // Setback + if (RapidRecovery) begin + $error("UNIMPLEMENTED"); + // core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + // | recovery_setback_out [tmr_shared_id(tmr_group_id(i))]; + end else begin + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; + end + if (i >= NumTMRCores) begin + core_setback_o [i] = '0; + end + if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode + core_inputs_o[i] = sys_inputs_i[SysCoreIndex]; + end else begin : independent_mode + core_inputs_o[i] = sys_inputs_i[i]; + end + end + end + + for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs + localparam CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); + if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr + assign sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; + assign sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; + end else begin + if (i >= NumTMRCores) begin : independent_stragglers + assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_bus_outputs_o [i] = core_bus_outputs_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + end else begin + always_comb begin + if (core_in_tmr[i]) begin : tmr_mode + if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core + sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; + sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; + end else begin : disable_core // Assign disable + sys_nominal_outputs_o[i] = '0; + sys_bus_outputs_o [i] = '0; + end + end else begin : independent_mode + sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; + sys_bus_outputs_o [i] = core_bus_outputs_i [i]; + end + end + end + end + end + + end else if (DMRSupported || DMRFixed) begin : gen_DMR_only + /***************** + *** DMR only *** + *****************/ + if (DMRFixed && NumCores % 2 != 0) $warning("Extra cores added not properly handled! :)"); + // Binding DMR outputs to zero for now + assign dmr_failure_o = '0; + assign dmr_error_o = '0; + // assign dmr_resynch_req_o = '0; + + for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs + localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); + always_comb begin + // Setback + if (RapidRecovery) begin + $error("UNIMPLEMENTED"); + // core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] + // | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + end else begin + core_setback_o [i] = '0; + end + if (i >= NumDMRCores) begin + core_setback_o [i] = '0; + end + if (i < NumDMRCores && (DMRFixed || core_in_dmr[i])) begin : dmr_mode + core_inputs_o[i] = sys_inputs_i[SysCoreIndex]; + end else begin : gen_independent_mode + core_inputs_o[i] = sys_inputs_i[i]; + end + end + end // gen_core_inputs + + for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs + localparam CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); + if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr + assign sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; + assign sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; + end else begin + if (i >= NumDMRCores) begin : independent_stragglers + assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; + assign sys_bus_outputs_o [i] = core_bus_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; + end else begin + always_comb begin + if (core_in_dmr[i]) begin : dmr_mode + if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core + sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; + sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; + end else begin : disable_core // Assign disable + sys_nominal_outputs_o[i] = '0; + sys_bus_outputs_o [i] = '0; + end + end else begin : independent_mode + sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; + sys_bus_outputs_o [i] = core_bus_outputs_i [i]; + end + end + end + end + end + + end else begin : gen_no_redundancy + /***************** + *** none *** + *****************/ + // Direct assignment, disable all + assign core_setback_o = '0; + assign core_inputs_o = sys_inputs_i; + assign sys_nominal_outputs_o = core_nominal_outputs_i; + assign sys_bus_outputs_o = core_bus_outputs_i; + end + +endmodule From e259fae61df35aa0407af894395a827df73c4e00 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 11 May 2023 10:16:45 +0200 Subject: [PATCH 36/66] Fix lint error --- rtl/HMR/hmr_unit.sv | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index b8abcbec..96a71831 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -1,4 +1,4 @@ -// Copyright 2022 ETH Zurich and University of Bologna. +// Copyright 2023 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 @@ -292,9 +292,6 @@ module hmr_unit #( assign sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.qe && core_register_reqs[i].wdata == '0; end - - - /********************************************************** ******************** TMR Voters & Regs ******************* **********************************************************/ @@ -571,6 +568,7 @@ module hmr_unit #( assign top_register_resps[2].error = 1'b1; assign top_register_resps[2].ready = 1'b1; assign dmr_sw_synch_req_o = '0; + assign dmr_grp_in_independent = '1; end From 2bd1e6e03fe3320a5b72259cf2ae57342483971b Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 22 Jun 2023 17:56:37 +0200 Subject: [PATCH 37/66] Fix ECC Manager configuration --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f119b7..319512bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update `ecc_manager` for configurability - Update secded testbench to use correctors and fix error injection +### Changed +- Replace vendor.py script with bender vendor for ECC modules +- Update `ecc_manager` for configurability + ## 0.5.1 - 2023-04-12 ### Added - Add CI flow for linting From c7aeb582df62868ed22eaf4f0c109fdd1dc2be2e Mon Sep 17 00:00:00 2001 From: Luca Rufer Date: Fri, 2 Dec 2022 12:55:31 +0100 Subject: [PATCH 38/66] Add Corrector to generation script and update testbench --- Bender.yml | 13 ++ CHANGELOG.md | 7 +- rtl/lowrisc_ecc/prim_secded_13_8_cor.sv | 16 +- rtl/lowrisc_ecc/prim_secded_22_16_cor.sv | 44 +++--- rtl/lowrisc_ecc/prim_secded_28_22_cor.sv | 12 +- rtl/lowrisc_ecc/prim_secded_39_32_cor.sv | 76 +++++----- rtl/lowrisc_ecc/prim_secded_72_64_cor.sv | 32 ++-- .../prim_secded_hamming_22_16_cor.sv | 14 +- .../prim_secded_hamming_39_32_cor.sv | 30 ++-- .../prim_secded_hamming_72_64_cor.sv | 60 ++++---- test/tb_ecc_secded.sv | 140 ++++++++++++------ 11 files changed, 254 insertions(+), 190 deletions(-) diff --git a/Bender.yml b/Bender.yml index b7381d11..dea4e4ca 100644 --- a/Bender.yml +++ b/Bender.yml @@ -20,6 +20,19 @@ sources: - rtl/ODRG_unit/odrg_manager_reg_pkg.sv - rtl/ecc_wrap/ecc_manager_reg_pkg.sv - rtl/pulpissimo_tcls/tcls_manager_reg_pkg.sv + - rtl/lowrisc_ecc/prim_secded_13_8_cor.sv + - rtl/lowrisc_ecc/prim_secded_13_8_dec.sv + - rtl/lowrisc_ecc/prim_secded_13_8_enc.sv + - rtl/lowrisc_ecc/prim_secded_22_16_cor.sv + - rtl/lowrisc_ecc/prim_secded_22_16_dec.sv + - rtl/lowrisc_ecc/prim_secded_22_16_enc.sv + - rtl/lowrisc_ecc/prim_secded_39_32_cor.sv + - rtl/lowrisc_ecc/prim_secded_39_32_dec.sv + - rtl/lowrisc_ecc/prim_secded_39_32_enc.sv + - rtl/lowrisc_ecc/prim_secded_72_64_cor.sv + - rtl/lowrisc_ecc/prim_secded_72_64_dec.sv + - rtl/lowrisc_ecc/prim_secded_72_64_enc.sv + - rtl/lowrisc_ecc/prim_secded_pkg.sv - rtl/ODRG_unit/triple_core_barrier.sv - rtl/hsiao_ecc/hsiao_ecc_pkg.sv - rtl/hsiao_ecc/hsiao_ecc_enc.sv diff --git a/CHANGELOG.md b/CHANGELOG.md index 319512bf..074d5acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add ECC correctors -### Changed -- Replace vendor.py script with bender vendor for ECC modules -- Update `ecc_manager` for configurability -- Update secded testbench to use correctors and fix error injection - ### Changed - Replace vendor.py script with bender vendor for ECC modules - Update `ecc_manager` for configurability @@ -33,11 +28,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Expose additional error logging signals - Add scrubber to ECC SRAM wrap - Add testing signals for tapeout +- Add secded ECC corrector ### Changed - Expose `ecc_sram` ecc error signals - Rename cTCLS to ODRG - Hide bus ecc behind bender targets, remove related dependencies +- Update secded testbench to use correctors and fix error injection ## 0.4.0 - 2022-03-31 diff --git a/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv index 644fa91e..b1ba2ff0 100644 --- a/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv @@ -16,20 +16,20 @@ module prim_secded_13_8_cor ( // Syndrome calculation assign syndrome_o[0] = ^(d_i & 13'h016B); - assign syndrome_o[1] = ^(d_i & 13'h02AD); + assign syndrome_o[1] = ^(d_i & 13'h02F8); assign syndrome_o[2] = ^(d_i & 13'h04D5); - assign syndrome_o[3] = ^(d_i & 13'h0836); - assign syndrome_o[4] = ^(d_i & 13'h10DA); + assign syndrome_o[3] = ^(d_i & 13'h08A7); + assign syndrome_o[4] = ^(d_i & 13'h101E); // Corrected output calculation - assign d_o[0] = (syndrome_o == 5'h7) ^ d_i[0]; + assign d_o[0] = (syndrome_o == 5'hd) ^ d_i[0]; assign d_o[1] = (syndrome_o == 5'h19) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 5'he) ^ d_i[2]; + assign d_o[2] = (syndrome_o == 5'h1c) ^ d_i[2]; assign d_o[3] = (syndrome_o == 5'h13) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 5'h1c) ^ d_i[4]; + assign d_o[4] = (syndrome_o == 5'h16) ^ d_i[4]; assign d_o[5] = (syndrome_o == 5'hb) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 5'h15) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 5'h16) ^ d_i[7]; + assign d_o[6] = (syndrome_o == 5'h7) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 5'he) ^ d_i[7]; assign d_o[8] = (syndrome_o == 5'h1) ^ d_i[8]; assign d_o[9] = (syndrome_o == 5'h2) ^ d_i[9]; assign d_o[10] = (syndrome_o == 5'h4) ^ d_i[10]; diff --git a/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv index 96851a5e..b3fd2e4e 100644 --- a/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv @@ -15,30 +15,30 @@ module prim_secded_22_16_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 22'h015555); - assign syndrome_o[1] = ^(d_i & 22'h02AA55); - assign syndrome_o[2] = ^(d_i & 22'h0495A9); - assign syndrome_o[3] = ^(d_i & 22'h0869A6); - assign syndrome_o[4] = ^(d_i & 22'h10669A); - assign syndrome_o[5] = ^(d_i & 22'h209A6A); + assign syndrome_o[0] = ^(d_i & 22'h017B48); + assign syndrome_o[1] = ^(d_i & 22'h0291AB); + assign syndrome_o[2] = ^(d_i & 22'h040E3D); + assign syndrome_o[3] = ^(d_i & 22'h087692); + assign syndrome_o[4] = ^(d_i & 22'h10A547); + assign syndrome_o[5] = ^(d_i & 22'h20C8F4); // Corrected output calculation - assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; - assign d_o[1] = (syndrome_o == 6'h38) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 6'hb) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 6'h34) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 6'h13) ^ d_i[4]; - assign d_o[5] = (syndrome_o == 6'h2c) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 6'h23) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 6'h1c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 6'hd) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 6'h32) ^ d_i[9]; - assign d_o[10] = (syndrome_o == 6'h15) ^ d_i[10]; - assign d_o[11] = (syndrome_o == 6'h2a) ^ d_i[11]; - assign d_o[12] = (syndrome_o == 6'h25) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 6'h1a) ^ d_i[13]; - assign d_o[14] = (syndrome_o == 6'h19) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 6'h26) ^ d_i[15]; + assign d_o[0] = (syndrome_o == 6'h16) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'h1a) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'h34) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'h2c) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h26) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'h31) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h2a) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'h13) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'hd) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'h1c) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h25) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'hb) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h19) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h29) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h32) ^ d_i[15]; assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; diff --git a/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv index d279c716..12908105 100644 --- a/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv @@ -16,11 +16,11 @@ module prim_secded_28_22_cor ( // Syndrome calculation assign syndrome_o[0] = ^(d_i & 28'h07003FF); - assign syndrome_o[1] = ^(d_i & 28'h0B0FC0F); - assign syndrome_o[2] = ^(d_i & 28'h1371C71); + assign syndrome_o[1] = ^(d_i & 28'h0A0FC0F); + assign syndrome_o[2] = ^(d_i & 28'h1171C71); assign syndrome_o[3] = ^(d_i & 28'h23B6592); - assign syndrome_o[4] = ^(d_i & 28'h41DAAA4); - assign syndrome_o[5] = ^(d_i & 28'h82ED348); + assign syndrome_o[4] = ^(d_i & 28'h43DAAA4); + assign syndrome_o[5] = ^(d_i & 28'h83ED348); // Corrected output calculation assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; @@ -43,8 +43,8 @@ module prim_secded_28_22_cor ( assign d_o[17] = (syndrome_o == 6'h2c) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h34) ^ d_i[18]; assign d_o[19] = (syndrome_o == 6'h38) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 6'h1f) ^ d_i[20]; - assign d_o[21] = (syndrome_o == 6'h2f) ^ d_i[21]; + assign d_o[20] = (syndrome_o == 6'h3d) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h3b) ^ d_i[21]; assign d_o[22] = (syndrome_o == 6'h1) ^ d_i[22]; assign d_o[23] = (syndrome_o == 6'h2) ^ d_i[23]; assign d_o[24] = (syndrome_o == 6'h4) ^ d_i[24]; diff --git a/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv index 40e6b005..725b8b61 100644 --- a/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv @@ -15,47 +15,47 @@ module prim_secded_39_32_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 39'h012CA53295); - assign syndrome_o[1] = ^(d_i & 39'h0293492CA5); - assign syndrome_o[2] = ^(d_i & 39'h04552A5329); - assign syndrome_o[3] = ^(d_i & 39'h08A8D294AA); - assign syndrome_o[4] = ^(d_i & 39'h104A2CA54A); - assign syndrome_o[5] = ^(d_i & 39'h2025534952); - assign syndrome_o[6] = ^(d_i & 39'h40D294CA54); + assign syndrome_o[0] = ^(d_i & 39'h013800CDBC); + assign syndrome_o[1] = ^(d_i & 39'h02C439C325); + assign syndrome_o[2] = ^(d_i & 39'h0452D82C63); + assign syndrome_o[3] = ^(d_i & 39'h08A4363856); + assign syndrome_o[4] = ^(d_i & 39'h109B833109); + assign syndrome_o[5] = ^(d_i & 39'h202DCF42C0); + assign syndrome_o[6] = ^(d_i & 39'h404364969A); // Corrected output calculation - assign d_o[0] = (syndrome_o == 7'h7) ^ d_i[0]; - assign d_o[1] = (syndrome_o == 7'h38) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 7'h43) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 7'h1c) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 7'h61) ^ d_i[4]; - assign d_o[5] = (syndrome_o == 7'he) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 7'h70) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 7'hb) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 7'h34) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 7'h45) ^ d_i[9]; - assign d_o[10] = (syndrome_o == 7'h1a) ^ d_i[10]; - assign d_o[11] = (syndrome_o == 7'h62) ^ d_i[11]; - assign d_o[12] = (syndrome_o == 7'hd) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 7'h13) ^ d_i[13]; - assign d_o[14] = (syndrome_o == 7'h64) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 7'h58) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 7'h23) ^ d_i[16]; - assign d_o[17] = (syndrome_o == 7'h2c) ^ d_i[17]; - assign d_o[18] = (syndrome_o == 7'h51) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 7'h16) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 7'h68) ^ d_i[20]; - assign d_o[21] = (syndrome_o == 7'h15) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 7'h2a) ^ d_i[22]; - assign d_o[23] = (syndrome_o == 7'h49) ^ d_i[23]; - assign d_o[24] = (syndrome_o == 7'h26) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 7'h52) ^ d_i[25]; - assign d_o[26] = (syndrome_o == 7'h25) ^ d_i[26]; - assign d_o[27] = (syndrome_o == 7'h19) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 7'h46) ^ d_i[28]; + assign d_o[0] = (syndrome_o == 7'h16) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 7'h4c) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 7'hb) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 7'h51) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 7'h7) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 7'h2c) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 7'h61) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 7'h13) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'h62) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 7'h45) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 7'hd) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 7'h58) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 7'h1c) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 7'h23) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 7'h43) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h32) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 7'h38) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 7'h68) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 7'h26) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'he) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 7'h4a) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 7'h64) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 7'h34) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 7'h70) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 7'h54) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 7'h2a) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 7'h31) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 7'h15) ^ d_i[28]; assign d_o[29] = (syndrome_o == 7'h29) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 7'h54) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 7'h4a) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 7'h46) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h1a) ^ d_i[31]; assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; diff --git a/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv index c1a8d3ea..72c85cf4 100644 --- a/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv @@ -15,14 +15,14 @@ module prim_secded_72_64_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 72'h015B000000001FFFFF); - assign syndrome_o[1] = ^(d_i & 72'h026B00000FFFE0003F); - assign syndrome_o[2] = ^(d_i & 72'h046D003FF003E007C1); - assign syndrome_o[3] = ^(d_i & 72'h08AD0FC0F03C207842); - assign syndrome_o[4] = ^(d_i & 72'h10B571C711C4438884); - assign syndrome_o[5] = ^(d_i & 72'h20B6B65926488C9108); - assign syndrome_o[6] = ^(d_i & 72'h40D6DAAA4A91152210); - assign syndrome_o[7] = ^(d_i & 72'h80DAED348D221A4420); + assign syndrome_o[0] = ^(d_i & 72'h01F8000000001FFFFF); + assign syndrome_o[1] = ^(d_i & 72'h029D00000FFFE0003F); + assign syndrome_o[2] = ^(d_i & 72'h048F003FF003E007C1); + assign syndrome_o[3] = ^(d_i & 72'h08F10FC0F03C207842); + assign syndrome_o[4] = ^(d_i & 72'h106E71C711C4438884); + assign syndrome_o[5] = ^(d_i & 72'h203EB65926488C9108); + assign syndrome_o[6] = ^(d_i & 72'h40D3DAAA4A91152210); + assign syndrome_o[7] = ^(d_i & 72'h8067ED348D221A4420); // Corrected output calculation assign d_o[0] = (syndrome_o == 8'h7) ^ d_i[0]; @@ -81,14 +81,14 @@ module prim_secded_72_64_cor ( assign d_o[53] = (syndrome_o == 8'hb0) ^ d_i[53]; assign d_o[54] = (syndrome_o == 8'hd0) ^ d_i[54]; assign d_o[55] = (syndrome_o == 8'he0) ^ d_i[55]; - assign d_o[56] = (syndrome_o == 8'h1f) ^ d_i[56]; - assign d_o[57] = (syndrome_o == 8'he3) ^ d_i[57]; - assign d_o[58] = (syndrome_o == 8'h7c) ^ d_i[58]; - assign d_o[59] = (syndrome_o == 8'h8f) ^ d_i[59]; - assign d_o[60] = (syndrome_o == 8'hf1) ^ d_i[60]; - assign d_o[61] = (syndrome_o == 8'h3e) ^ d_i[61]; - assign d_o[62] = (syndrome_o == 8'hc7) ^ d_i[62]; - assign d_o[63] = (syndrome_o == 8'hf8) ^ d_i[63]; + assign d_o[56] = (syndrome_o == 8'hce) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 8'hf4) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 8'hb6) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 8'h37) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 8'h6b) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 8'hb9) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'hd9) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 8'h4f) ^ d_i[63]; assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; assign d_o[66] = (syndrome_o == 8'h4) ^ d_i[66]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv index 249a9e7f..e9f47371 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv @@ -19,25 +19,25 @@ module prim_secded_hamming_22_16_cor ( assign syndrome_o[2] = ^(d_i & 22'h04C78E); assign syndrome_o[3] = ^(d_i & 22'h0807F0); assign syndrome_o[4] = ^(d_i & 22'h10F800); - assign syndrome_o[5] = ^(d_i & 22'h205CB7); + assign syndrome_o[5] = ^(d_i & 22'h3FFFFF); // Corrected output calculation assign d_o[0] = (syndrome_o == 6'h23) ^ d_i[0]; assign d_o[1] = (syndrome_o == 6'h25) ^ d_i[1]; assign d_o[2] = (syndrome_o == 6'h26) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 6'h27) ^ d_i[3]; assign d_o[4] = (syndrome_o == 6'h29) ^ d_i[4]; assign d_o[5] = (syndrome_o == 6'h2a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 6'hb) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 6'h2b) ^ d_i[6]; assign d_o[7] = (syndrome_o == 6'h2c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 6'hd) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 6'he) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 6'h2d) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'h2e) ^ d_i[9]; assign d_o[10] = (syndrome_o == 6'h2f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 6'h31) ^ d_i[11]; assign d_o[12] = (syndrome_o == 6'h32) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 6'h13) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 6'h33) ^ d_i[13]; assign d_o[14] = (syndrome_o == 6'h34) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 6'h15) ^ d_i[15]; + assign d_o[15] = (syndrome_o == 6'h35) ^ d_i[15]; assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv index c861663c..2918c058 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv @@ -20,41 +20,41 @@ module prim_secded_hamming_39_32_cor ( assign syndrome_o[3] = ^(d_i & 39'h0803FC07F0); assign syndrome_o[4] = ^(d_i & 39'h1003FFF800); assign syndrome_o[5] = ^(d_i & 39'h20FC000000); - assign syndrome_o[6] = ^(d_i & 39'h402DA65CB7); + assign syndrome_o[6] = ^(d_i & 39'h7FFFFFFFFF); // Corrected output calculation assign d_o[0] = (syndrome_o == 7'h43) ^ d_i[0]; assign d_o[1] = (syndrome_o == 7'h45) ^ d_i[1]; assign d_o[2] = (syndrome_o == 7'h46) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 7'h7) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 7'h47) ^ d_i[3]; assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; assign d_o[5] = (syndrome_o == 7'h4a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 7'hb) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 7'h4b) ^ d_i[6]; assign d_o[7] = (syndrome_o == 7'h4c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 7'hd) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 7'he) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 7'h4d) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'h4e) ^ d_i[9]; assign d_o[10] = (syndrome_o == 7'h4f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 7'h51) ^ d_i[11]; assign d_o[12] = (syndrome_o == 7'h52) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 7'h13) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 7'h53) ^ d_i[13]; assign d_o[14] = (syndrome_o == 7'h54) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 7'h15) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 7'h16) ^ d_i[16]; + assign d_o[15] = (syndrome_o == 7'h55) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h56) ^ d_i[16]; assign d_o[17] = (syndrome_o == 7'h57) ^ d_i[17]; assign d_o[18] = (syndrome_o == 7'h58) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 7'h19) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 7'h1a) ^ d_i[20]; + assign d_o[19] = (syndrome_o == 7'h59) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'h5a) ^ d_i[20]; assign d_o[21] = (syndrome_o == 7'h5b) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 7'h1c) ^ d_i[22]; + assign d_o[22] = (syndrome_o == 7'h5c) ^ d_i[22]; assign d_o[23] = (syndrome_o == 7'h5d) ^ d_i[23]; assign d_o[24] = (syndrome_o == 7'h5e) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 7'h1f) ^ d_i[25]; + assign d_o[25] = (syndrome_o == 7'h5f) ^ d_i[25]; assign d_o[26] = (syndrome_o == 7'h61) ^ d_i[26]; assign d_o[27] = (syndrome_o == 7'h62) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 7'h23) ^ d_i[28]; + assign d_o[28] = (syndrome_o == 7'h63) ^ d_i[28]; assign d_o[29] = (syndrome_o == 7'h64) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 7'h25) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 7'h26) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 7'h65) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h66) ^ d_i[31]; assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv index 896f97ac..e8f2e854 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv @@ -21,72 +21,72 @@ module prim_secded_hamming_72_64_cor ( assign syndrome_o[4] = ^(d_i & 72'h1001FFFE0003FFF800); assign syndrome_o[5] = ^(d_i & 72'h2001FFFFFFFC000000); assign syndrome_o[6] = ^(d_i & 72'h40FE00000000000000); - assign syndrome_o[7] = ^(d_i & 72'h80972CD2D32DA65CB7); + assign syndrome_o[7] = ^(d_i & 72'hFFFFFFFFFFFFFFFFFF); // Corrected output calculation assign d_o[0] = (syndrome_o == 8'h83) ^ d_i[0]; assign d_o[1] = (syndrome_o == 8'h85) ^ d_i[1]; assign d_o[2] = (syndrome_o == 8'h86) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 8'h7) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 8'h87) ^ d_i[3]; assign d_o[4] = (syndrome_o == 8'h89) ^ d_i[4]; assign d_o[5] = (syndrome_o == 8'h8a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 8'hb) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 8'h8b) ^ d_i[6]; assign d_o[7] = (syndrome_o == 8'h8c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 8'hd) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 8'he) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 8'h8d) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 8'h8e) ^ d_i[9]; assign d_o[10] = (syndrome_o == 8'h8f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 8'h91) ^ d_i[11]; assign d_o[12] = (syndrome_o == 8'h92) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 8'h13) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 8'h93) ^ d_i[13]; assign d_o[14] = (syndrome_o == 8'h94) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 8'h15) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 8'h16) ^ d_i[16]; + assign d_o[15] = (syndrome_o == 8'h95) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 8'h96) ^ d_i[16]; assign d_o[17] = (syndrome_o == 8'h97) ^ d_i[17]; assign d_o[18] = (syndrome_o == 8'h98) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 8'h19) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 8'h1a) ^ d_i[20]; + assign d_o[19] = (syndrome_o == 8'h99) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 8'h9a) ^ d_i[20]; assign d_o[21] = (syndrome_o == 8'h9b) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 8'h1c) ^ d_i[22]; + assign d_o[22] = (syndrome_o == 8'h9c) ^ d_i[22]; assign d_o[23] = (syndrome_o == 8'h9d) ^ d_i[23]; assign d_o[24] = (syndrome_o == 8'h9e) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 8'h1f) ^ d_i[25]; + assign d_o[25] = (syndrome_o == 8'h9f) ^ d_i[25]; assign d_o[26] = (syndrome_o == 8'ha1) ^ d_i[26]; assign d_o[27] = (syndrome_o == 8'ha2) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 8'h23) ^ d_i[28]; + assign d_o[28] = (syndrome_o == 8'ha3) ^ d_i[28]; assign d_o[29] = (syndrome_o == 8'ha4) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 8'h25) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 8'h26) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 8'ha5) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 8'ha6) ^ d_i[31]; assign d_o[32] = (syndrome_o == 8'ha7) ^ d_i[32]; assign d_o[33] = (syndrome_o == 8'ha8) ^ d_i[33]; - assign d_o[34] = (syndrome_o == 8'h29) ^ d_i[34]; - assign d_o[35] = (syndrome_o == 8'h2a) ^ d_i[35]; + assign d_o[34] = (syndrome_o == 8'ha9) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 8'haa) ^ d_i[35]; assign d_o[36] = (syndrome_o == 8'hab) ^ d_i[36]; - assign d_o[37] = (syndrome_o == 8'h2c) ^ d_i[37]; + assign d_o[37] = (syndrome_o == 8'hac) ^ d_i[37]; assign d_o[38] = (syndrome_o == 8'had) ^ d_i[38]; assign d_o[39] = (syndrome_o == 8'hae) ^ d_i[39]; - assign d_o[40] = (syndrome_o == 8'h2f) ^ d_i[40]; + assign d_o[40] = (syndrome_o == 8'haf) ^ d_i[40]; assign d_o[41] = (syndrome_o == 8'hb0) ^ d_i[41]; - assign d_o[42] = (syndrome_o == 8'h31) ^ d_i[42]; - assign d_o[43] = (syndrome_o == 8'h32) ^ d_i[43]; + assign d_o[42] = (syndrome_o == 8'hb1) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 8'hb2) ^ d_i[43]; assign d_o[44] = (syndrome_o == 8'hb3) ^ d_i[44]; - assign d_o[45] = (syndrome_o == 8'h34) ^ d_i[45]; + assign d_o[45] = (syndrome_o == 8'hb4) ^ d_i[45]; assign d_o[46] = (syndrome_o == 8'hb5) ^ d_i[46]; assign d_o[47] = (syndrome_o == 8'hb6) ^ d_i[47]; - assign d_o[48] = (syndrome_o == 8'h37) ^ d_i[48]; - assign d_o[49] = (syndrome_o == 8'h38) ^ d_i[49]; + assign d_o[48] = (syndrome_o == 8'hb7) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 8'hb8) ^ d_i[49]; assign d_o[50] = (syndrome_o == 8'hb9) ^ d_i[50]; assign d_o[51] = (syndrome_o == 8'hba) ^ d_i[51]; - assign d_o[52] = (syndrome_o == 8'h3b) ^ d_i[52]; + assign d_o[52] = (syndrome_o == 8'hbb) ^ d_i[52]; assign d_o[53] = (syndrome_o == 8'hbc) ^ d_i[53]; - assign d_o[54] = (syndrome_o == 8'h3d) ^ d_i[54]; - assign d_o[55] = (syndrome_o == 8'h3e) ^ d_i[55]; + assign d_o[54] = (syndrome_o == 8'hbd) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 8'hbe) ^ d_i[55]; assign d_o[56] = (syndrome_o == 8'hbf) ^ d_i[56]; assign d_o[57] = (syndrome_o == 8'hc1) ^ d_i[57]; assign d_o[58] = (syndrome_o == 8'hc2) ^ d_i[58]; - assign d_o[59] = (syndrome_o == 8'h43) ^ d_i[59]; + assign d_o[59] = (syndrome_o == 8'hc3) ^ d_i[59]; assign d_o[60] = (syndrome_o == 8'hc4) ^ d_i[60]; - assign d_o[61] = (syndrome_o == 8'h45) ^ d_i[61]; - assign d_o[62] = (syndrome_o == 8'h46) ^ d_i[62]; + assign d_o[61] = (syndrome_o == 8'hc5) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'hc6) ^ d_i[62]; assign d_o[63] = (syndrome_o == 8'hc7) ^ d_i[63]; assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; diff --git a/test/tb_ecc_secded.sv b/test/tb_ecc_secded.sv index 30793d65..a463b54e 100644 --- a/test/tb_ecc_secded.sv +++ b/test/tb_ecc_secded.sv @@ -193,49 +193,103 @@ module tb_ecc_secded #( prot_t prot_out, prot_in, prot_corrected; logic [1:0] error, error_corrector, error_correcter_decoder; - hsiao_ecc_enc #( - .DataWidth(DataWidth), - .ProtWidth (ProtectBits), - .PrintHsiao(1'b1) - ) i_dut_encode ( - .in (in), - .out(prot_out) - ); - - assign prot_in = prot_out ^ inject; - - hsiao_ecc_dec #( - .DataWidth(DataWidth), - .ProtWidth (ProtectBits), - .PrintHsiao(1'b1) - ) i_dut_decode ( - .in (prot_in), - .out (out), - .syndrome_o(syndrome), - .err_o (error) - ); - - hsiao_ecc_cor #( - .DataWidth(DataWidth), - .ProtWidth (ProtectBits), - .PrintHsiao(1'b1) - ) i_dut_correct ( - .in (prot_in), - .out (prot_corrected), - .syndrome_o(syndrome_corrector), - .err_o (error_corrector) - ); - - hsiao_ecc_dec #( - .DataWidth(DataWidth), - .ProtWidth (ProtectBits), - .PrintHsiao(1'b1) - ) i_dut_correct_decode ( - .in (prot_corrected), - .out (out_corrected), - .syndrome_o(syndrome_corrector_decoder), - .err_o (error_correcter_decoder) - ); + if (DataWidth == 8) begin + prim_secded_13_8_enc i_dut_encode ( + .in (in), + .out(prot_out) + ); + assign prot_in = prot_out ^ inject; + prim_secded_13_8_dec i_dut_decode ( + .in (prot_in), + .d_o (out), + .syndrome_o(syndrome), + .err_o (error) + ); + prim_secded_13_8_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_13_8_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); + end else if (DataWidth == 16) begin + prim_secded_22_16_enc i_dut_encode ( + .in (in), + .out(prot_out) + ); + assign prot_in = prot_out ^ inject; + prim_secded_22_16_dec i_dut_decode ( + .in (prot_in), + .d_o (out), + .syndrome_o(syndrome), + .err_o (error) + ); + prim_secded_22_16_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_22_16_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); + end else if (DataWidth == 32) begin + prim_secded_39_32_enc i_dut_encode ( + .in (in), + .out(prot_out) + ); + assign prot_in = prot_out ^ inject; + prim_secded_39_32_dec i_dut_decode ( + .in (prot_in), + .d_o (out), + .syndrome_o(syndrome), + .err_o (error) + ); + prim_secded_39_32_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_39_32_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); + end else if (DataWidth == 64) begin + prim_secded_72_64_enc i_dut_encode ( + .in (in), + .out(prot_out) + ); + assign prot_in = prot_out ^ inject; + prim_secded_72_64_dec i_dut_decode ( + .in (prot_in), + .d_o (out), + .syndrome_o(syndrome), + .err_o (error) + ); + prim_secded_72_64_cor i_dut_correct ( + .d_i (prot_in), + .d_o (prot_corrected), + .syndrome_o(syndrome_corrector), + .err_o (error_corrector) + ); + prim_secded_72_64_dec i_dut_correct_decode ( + .in (prot_corrected), + .d_o (out_corrected), + .syndrome_o(syndrome_corrector_decoder), + .err_o (error_correcter_decoder) + ); + end /*********************** * Output collection * From e51655736c92b61feb2f6b62d449e191781936e5 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 10 Jul 2023 10:44:26 +0200 Subject: [PATCH 39/66] Simplify sram wrap and add optional cut to RMW path --- rtl/ecc_wrap/ecc_sram_wrap.sv | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/rtl/ecc_wrap/ecc_sram_wrap.sv b/rtl/ecc_wrap/ecc_sram_wrap.sv index d053c11c..f21c9b98 100644 --- a/rtl/ecc_wrap/ecc_sram_wrap.sv +++ b/rtl/ecc_wrap/ecc_sram_wrap.sv @@ -132,14 +132,11 @@ module ecc_sram_wrap #( assign decoder_in = store_state_q == NORMAL ? bank_rdata : rmw_buffer_end; - hsiao_ecc_dec #( - .DataWidth (UnprotectedWidth), - .ProtWidth (ProtectedWidth - UnprotectedWidth) - ) ecc_decode ( - .in ( decoder_in ), - .out ( loaded ), - .syndrome_o(), - .err_o ( ecc_error ) + prim_secded_39_32_dec ecc_decode ( + .in ( decoder_in ), + .d_o ( loaded ), + .syndrome_o (), + .err_o (ecc_error) ); hsiao_ecc_enc #( @@ -152,9 +149,7 @@ module ecc_sram_wrap #( assign tcdm_rdata_o = loaded; - assign to_store = store_state_q == NORMAL ? - tcdm_wdata_i : - (be_selector & input_buffer_q) | (~be_selector & loaded); + assign to_store = store_state_q == NORMAL ? tcdm_wdata_i : (be_selector & input_buffer_q) | (~be_selector & loaded); end else begin : gen_ecc_input @@ -164,12 +159,9 @@ module ecc_sram_wrap #( assign bank_wdata = store_state_q == NORMAL ? tcdm_wdata_i : lns_wdata; assign tcdm_rdata_o = bank_rdata; - hsiao_ecc_dec #( - .DataWidth (UnprotectedWidth), - .ProtWidth (ProtectedWidth - UnprotectedWidth) - ) ld_decode ( - .in ( rmw_buffer_end ), - .out ( intermediate_data_ld ), + prim_secded_39_32_dec ld_decode ( + .in (rmw_buffer_end), + .d_o (intermediate_data_ld), .syndrome_o(), .err_o () ); @@ -191,7 +183,6 @@ module ecc_sram_wrap #( .in ( (be_selector & intermediate_data_st) | (~be_selector & intermediate_data_ld) ), .out ( lns_wdata ) ); - end always_comb begin From c2a42efe5c19e37ec5c4e06818bbd85fc7eb5fbe Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 26 Jul 2023 21:04:10 +0200 Subject: [PATCH 40/66] WIP: integrated rapid recovery unit. --- Bender.yml | 3 +- rtl/HMR/DMR_CSR_checker.sv | 6 +- rtl/HMR/DMR_controller.sv | 4 +- rtl/HMR/HMR_wrap.sv | 4 +- rtl/HMR/hmr_dmr_ctrl.sv | 4 +- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 7 +- rtl/HMR/hmr_unit.sv | 134 ++++++++++++--- ...{recovery_pkg.sv => rapid_recovery_pkg.sv} | 20 ++- rtl/HMR/rapid_recovery_unit.sv | 157 ++++++++++++++++++ rtl/HMR/recovery_csr.sv | 29 ++-- rtl/HMR/recovery_pc.sv | 11 +- rtl/HMR/recovery_rf.sv | 61 +++---- 12 files changed, 360 insertions(+), 80 deletions(-) rename rtl/HMR/{recovery_pkg.sv => rapid_recovery_pkg.sv} (78%) create mode 100644 rtl/HMR/rapid_recovery_unit.sv diff --git a/Bender.yml b/Bender.yml index dea4e4ca..bf14f6f2 100644 --- a/Bender.yml +++ b/Bender.yml @@ -118,10 +118,11 @@ sources: - test/tb_voter_macros.sv - files: - - rtl/HMR/recovery_pkg.sv + - rtl/HMR/rapid_recovery_pkg.sv - rtl/HMR/recovery_csr.sv - rtl/HMR/recovery_pc.sv - rtl/HMR/recovery_rf.sv + - rtl/HMR/rapid_recovery_unit.sv - rtl/HMR/DMR_checker.sv - rtl/HMR/DMR_CSR_checker.sv - rtl/HMR/DMR_address_generator.sv diff --git a/rtl/HMR/DMR_CSR_checker.sv b/rtl/HMR/DMR_CSR_checker.sv index 0bcd067f..c883b18d 100644 --- a/rtl/HMR/DMR_CSR_checker.sv +++ b/rtl/HMR/DMR_CSR_checker.sv @@ -12,9 +12,9 @@ * */ -import recovery_pkg::*; - -module DMR_CSR_checker ( +module DMR_CSR_checker + import rapid_recovery_pkg::*; +( input csrs_intf_t csr_a_i, input csrs_intf_t csr_b_i, output csrs_intf_t check_o, diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index f6c83fd3..9272a769 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -13,7 +13,9 @@ * */ -module DMR_controller import recovery_pkg::*; #( +module DMR_controller + import rapid_recovery_pkg::*; +#( parameter int unsigned NumCores = 0, parameter bit DMRFixed = 1'b0, parameter bit RapidRecovery = 1'b0, diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 4dad449c..ac19fb4a 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -10,7 +10,9 @@ // // Hybrid modular redundancy wrapping unit -module HMR_wrap import recovery_pkg::*; #( +module HMR_wrap + import rapid_recovery_pkg::*; +#( // Wrapper parameters /// Number of physical cores parameter int unsigned NumCores = 0, diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index ab7992e9..1b55311b 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -10,7 +10,9 @@ // // Hybrid modular redundancy DMR control unit -module hmr_dmr_ctrl import recovery_pkg::*; #( +module hmr_dmr_ctrl + import rapid_recovery_pkg::*; +#( parameter bit InterleaveGrps = 1'b0, parameter bit DMRFixed = 1'b0, parameter bit DefaultInDMR = DMRFixed ? 1'b1 : 1'b0, diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv index e1205ea6..4f5b9f2f 100644 --- a/rtl/HMR/hmr_rapid_recovery_ctrl.sv +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -10,8 +10,11 @@ // // Hybrid modular redundancy Rapid Recovery control unit -module hmr_rapid_recovery_ctrl import recovery_pkg::*; #( - parameter int unsigned RFAddrWidth = 6 +module hmr_rapid_recovery_ctrl + import rapid_recovery_pkg::*; +#( + parameter int unsigned RFAddrWidth = 6, + parameter type regfile_write_t = logic ) ( input logic clk_i, input logic rst_ni, diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 96a71831..40daabe9 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -30,6 +30,9 @@ module hmr_unit #( parameter bit SeparateData = 1'b1, /// Number of separate voters/checkers for individual buses parameter int unsigned NumBusVoters = 1, + /// Address width of the core register file (in RISC-V it should be always 6) + parameter int unsigned RfAddrWidth = 6, + parameter int unsigned SysDataWidth = 32, /// General core inputs wrapping struct parameter type all_inputs_t = logic, /// General core outputs wrapping struct @@ -38,6 +41,8 @@ module hmr_unit #( parameter type bus_outputs_t = logic, parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, + /// Rapid recovery structure + parameter type rapid_recovery_t = logic, // Local parameters depending on the above ones /// Number of TMR groups (virtual TMR cores) localparam int unsigned NumTMRGroups = NumCores/3, @@ -75,6 +80,9 @@ module hmr_unit #( output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + // Rapid recovery output bus + output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, + input all_inputs_t [NumSysCores-1:0] sys_inputs_i, output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, output bus_outputs_t [NumSysCores-1:0][NumBusVoters-1:0] sys_bus_outputs_o, @@ -90,6 +98,8 @@ module hmr_unit #( return (a > b) ? a : b; endfunction + localparam int unsigned NumBackupRegs = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); + function int tmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumTMRGroups; else return (core_id/3); @@ -146,6 +156,17 @@ module hmr_unit #( logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main; logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; + /************************** + * Rapid Recovery Signals * + **************************/ + logic [ NumDMRGroups-1:0] dmr_recovery_start, dmr_recovery_finished; + logic [ NumTMRGroups-1:0] tmr_recovery_start, tmr_recovery_finished; + logic [NumBackupRegs-1:0] rapid_recovery_start, rapid_recovery_finished; + logic [NumBackupRegs-1:0] rapid_recovery_backup_en_inp, rapid_recovery_backup_en_oup; + logic [NumBackupRegs-1:0] rapid_recovery_setback; + rapid_recovery_t [NumBackupRegs-1:0] rapid_recovery_bus; + nominal_outputs_t [NumBackupRegs-1:0] rapid_recovery_nominal; + /*************************** * HMR Control Registers * ***************************/ @@ -376,8 +397,8 @@ module hmr_unit #( .fetch_en_i ( sys_fetch_en_i[tmr_core_id(i, 0)] ), .cores_synch_i ( tmr_cores_synch_i[i] ), - .recovery_request_o ( ),//tmr_start_recovery [i] ), - .recovery_finished_i ( '0)//tmr_recovery_finished [i] ) + .recovery_request_o ( tmr_recovery_start [i] ), + .recovery_finished_i ( tmr_recovery_finished [i] ) ); assign tmr_sw_synch_req_o[tmr_core_id(i, 0)] = tmr_sw_synch_req[i]; @@ -513,8 +534,8 @@ module hmr_unit #( .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), .cores_synch_i ( dmr_cores_synch_i[i] ), - .recovery_request_o ( ),//dmr_start_recovery [i] ), - .recovery_finished_i ( '0)//dmr_recovery_finished[i] ) + .recovery_request_o ( dmr_recovery_start [i] ), + .recovery_finished_i ( dmr_recovery_finished [i] ) ); assign dmr_sw_synch_req_o[dmr_core_id(i, 0)] = dmr_sw_synch_req[i]; @@ -544,8 +565,41 @@ module hmr_unit #( end end - if (RapidRecovery) begin : gen_rapid_recovery_connection - $error("UNIMPLEMENTED"); + if (RapidRecovery) begin : gen_rapid_recovery_unit + + assign rapid_recovery_backup_en_inp[i] = core_in_tmr[i] ? (i < NumTMRGroups ? rapid_recovery_backup_en_oup[i] : 1'b0) // TMR mode + : core_in_dmr[i] ? (rapid_recovery_backup_en_oup[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent + rapid_recovery_unit #( + .RfAddrWidth ( RfAddrWidth ), + .DataWidth ( SysDataWidth ), + .regfile_write_t ( rapid_recovery_pkg::regfile_write_t ), + .regfile_raddr_t ( rapid_recovery_pkg::regfile_raddr_t ), + .regfile_rdata_t ( rapid_recovery_pkg::regfile_rdata_t ), + .csr_intf_t ( rapid_recovery_pkg::csrs_intf_t ), + .pc_intf_t ( rapid_recovery_pkg::pc_intf_t ) + ) i_rapid_recovery_unit ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .regfile_write_i ( rapid_recovery_nominal[i].regfile_backup ), + .backup_csr_i ( rapid_recovery_nominal[i].csr_backup ), + .recovery_csr_o ( rapid_recovery_bus[i].csr_recovery ), + .backup_pc_i ( rapid_recovery_nominal[i].pc_backup ), + .recovery_pc_o ( rapid_recovery_bus[i].pc_recovery ), + .backup_enable_i ( rapid_recovery_backup_en_inp[i] ), + .start_recovery_i ( rapid_recovery_start[i] ), + .backup_enable_o ( rapid_recovery_backup_en_oup[i] ), + .recovery_finished_o ( rapid_recovery_finished[i] ), + .setback_o ( rapid_recovery_setback[i] ), + .instr_lock_o ( rapid_recovery_bus[i].instr_lock ), + .enable_pc_recovery_o ( rapid_recovery_bus[i].pc_recovery_en ), + .enable_rf_recovery_o ( rapid_recovery_bus[i].rf_recovery_en ), + .regfile_recovery_wdata_o ( rapid_recovery_bus[i].rf_recovery_wdata ), + .regfile_recovery_rdata_o ( rapid_recovery_bus[i].rf_recovery_rdata ), + .debug_halt_i ( rapid_recovery_nominal[i].debug_halted ), + .debug_req_o ( rapid_recovery_bus[i].debug_req ), + .debug_resume_o ( rapid_recovery_bus[i].debug_resume ) + ); end else begin : gen_standard_failure always_comb begin dmr_failure[i] = dmr_failure_main[i]; @@ -571,6 +625,35 @@ module hmr_unit #( assign dmr_grp_in_independent = '1; end + if (RapidRecovery) begin: gen_rapid_recovery_connection + always_comb begin + rapid_recovery_nominal = '0; + rapid_recovery_start = '0; + dmr_recovery_finished = '0; + tmr_recovery_finished = '0; + if (InterleaveGrps) begin + for (int i = 0; i < NumBackupRegs; i++) begin + rapid_recovery_nominal[i] = dmr_nominal_outputs[i]; + rapid_recovery_start[i] = dmr_recovery_start[i]; + dmr_recovery_finished[i] = rapid_recovery_finished[i]; + end + end + for (int i = 0; i < NumDMRGroups; i++) begin + if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin + rapid_recovery_nominal[dmr_shared_id(i)] = dmr_nominal_outputs[i]; + rapid_recovery_start[dmr_shared_id(i)] = dmr_recovery_start[i]; + dmr_recovery_finished[i] = rapid_recovery_finished[dmr_shared_id(i)]; + end + end + for (int i = 0; i < NumTMRGroups; i++) begin + if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin + rapid_recovery_nominal[tmr_shared_id(i)] = tmr_nominal_outputs[i]; + rapid_recovery_start[tmr_shared_id(i)] = tmr_recovery_start[i]; + tmr_recovery_finished[i] = rapid_recovery_finished[tmr_shared_id(i)]; + end + end + end + end // Assign output signals if (DMRSupported && TMRSupported) begin : gen_full_HMR @@ -586,11 +669,14 @@ module hmr_unit #( always_comb begin // Special signals if (RapidRecovery) begin - $error("UNIMPLEMENTED"); - // core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - // | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] - // | (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : - // (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0)); + // $error("UNIMPLEMENTED"); + rapid_recovery_o [i] = (core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0)); + + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0)); end else begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; @@ -598,11 +684,11 @@ module hmr_unit #( if (i >= NumTMRCores && i >= NumDMRCores) begin core_setback_o [i] = '0; end else if (i < NumTMRCores && i >= NumDMRCores) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)]; -// | (RapidRecovery ? (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0) : '0); + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | (RapidRecovery ? (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0) : '0); end else if (i >= NumTMRCores && i < NumDMRCores) begin - core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; -// | (RapidRecovery ? (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : '0) : '0); + core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (RapidRecovery ? (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : '0) : '0); end if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode core_inputs_o[i] = sys_inputs_i[TMRCoreIndex]; @@ -632,7 +718,7 @@ module hmr_unit #( for (int j = 0; j < NumBusVoters; j++) begin sys_bus_outputs_o[i][j] = dmr_bus_outputs[DMRCoreIndex][j]; end - end else begin : disable_core // Assign disable + end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; end @@ -653,9 +739,11 @@ module hmr_unit #( // Special signals // Setback if (RapidRecovery) begin - $error("UNIMPLEMENTED"); - // core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] - // | recovery_setback_out [tmr_shared_id(tmr_group_id(i))]; + // $error("UNIMPLEMENTED"); + rapid_recovery_o [i] = core_in_tmr[i] ? rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0; + + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] + | rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))]; end else begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)]; end @@ -713,9 +801,11 @@ module hmr_unit #( always_comb begin // Setback if (RapidRecovery) begin - $error("UNIMPLEMENTED"); - // core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] - // | recovery_setback_out [dmr_shared_id(dmr_group_id(i))]; + // $error("UNIMPLEMENTED"); + rapid_recovery_o [i] = core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : '0; + + core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] + | rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))]; end else begin core_setback_o [i] = '0; end diff --git a/rtl/HMR/recovery_pkg.sv b/rtl/HMR/rapid_recovery_pkg.sv similarity index 78% rename from rtl/HMR/recovery_pkg.sv rename to rtl/HMR/rapid_recovery_pkg.sv index 68dfc77a..123f39ef 100644 --- a/rtl/HMR/recovery_pkg.sv +++ b/rtl/HMR/rapid_recovery_pkg.sv @@ -12,7 +12,7 @@ * */ -package recovery_pkg; +package rapid_recovery_pkg; localparam int unsigned DataWidth = 32; localparam int unsigned ProtectedWidth = 39; @@ -64,4 +64,22 @@ typedef struct packed { logic [ProtectedWidth-1:0] csr_mcause; } ecc_csrs_intf_t; +typedef struct packed { + logic [DataWidth-1:0] program_counter; + logic is_branch; + logic [DataWidth-1:0] branch_addr; +} pc_intf_t; + +typedef struct packed { + logic instr_lock; + logic pc_recovery_en; + logic rf_recovery_en; + logic debug_req; + logic debug_resume; + rapid_recovery_pkg::regfile_write_t rf_recovery_wdata; + rapid_recovery_pkg::regfile_rdata_t rf_recovery_rdata; + rapid_recovery_pkg::csrs_intf_t csr_recovery; + rapid_recovery_pkg::pc_intf_t pc_recovery; +} rapid_recovery_t; + endpackage diff --git a/rtl/HMR/rapid_recovery_unit.sv b/rtl/HMR/rapid_recovery_unit.sv new file mode 100644 index 00000000..18661a1d --- /dev/null +++ b/rtl/HMR/rapid_recovery_unit.sv @@ -0,0 +1,157 @@ +// Copyright 2023 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. +// +// Rapid Recovery unit with backup status registers + +module rapid_recovery_unit + import rapid_recovery_pkg::*; +#( + parameter int unsigned RfAddrWidth = 5, + parameter int unsigned DataWidth = 32, + parameter int unsigned EccEnabled = 1, + parameter type regfile_write_t = logic, + parameter type regfile_raddr_t = logic, + parameter type regfile_rdata_t = logic, + parameter type csr_intf_t = logic, + parameter type pc_intf_t = logic +)( + input logic clk_i, + input logic rst_ni, + /* Recovery Register File interface */ + input regfile_write_t regfile_write_i, + /* Recovery Control and Status Registers interface */ + input csr_intf_t backup_csr_i, + output csr_intf_t recovery_csr_o, + /* Recovery Program Counter interface */ + input pc_intf_t backup_pc_i, + output pc_intf_t recovery_pc_o, + /* Rapid Recovery Controller interface */ + /* backup_enable_i: result of comparison between backup_enable_o + (generated by the rapid_recovery_ctrl) and + the DMR/TMR selection mode */ + input logic backup_enable_i, + /* start_recovery_i: software-requested recovery */ + input logic start_recovery_i, + /* backup_enable_o: generated by rapid_recovery_ctrl, asserts that + the core can do the backup of its state */ + output logic backup_enable_o, + /* recovery_finished_o: recovery routine completion */ + output logic recovery_finished_o, + /* setback_o: synchronous clear for the core */ + output logic setback_o, + /* instr_lock_o: blocks the requests toward the instruction cache + during the recovery routine */ + output logic instr_lock_o, + /* enable_pc_recovery_o: allows the program counter to be reloaded + into the core */ + output logic enable_pc_recovery_o, + /* enable_rf_recovery_o: allows the register file to be reloaded + into the core */ + output logic enable_rf_recovery_o, + /* regfile_recovery_wdata_o: used by the address generator in the + rapid_recovery_ctrl to propagate the RF + addresses to the core during the recovery + routine */ + output regfile_write_t regfile_recovery_wdata_o, // To cores RF interface + /* regfile_recovery_rdata_o: propagates the content from the backup RF to + the core RF during the recovery routine */ + output regfile_rdata_t regfile_recovery_rdata_o, + /* debug_halt_i: signals that the cores in recovery are halted */ + input logic debug_halt_i, + /* debug_req_o: sends the cores in debug mode during the recovery routine */ + output logic debug_req_o, + /* debug_resume_o: resumes the cores in recovery from the debug mode */ + output logic debug_resume_o +); + +logic csr_renable; + +hmr_rapid_recovery_ctrl #( + .RFAddrWidth ( RfAddrWidth ), + .regfile_write_t ( regfile_write_t ) +) i_rapid_recovery_ctrl ( + .clk_i, + .rst_ni, + .start_recovery_i, + .recovery_finished_o, + .setback_o, + .instr_lock_o, + .debug_req_o, + .debug_halt_i, + .debug_resume_o, + .recovery_regfile_waddr_o ( regfile_recovery_wdata_o ), + .backup_enable_o ( backup_enable_o ), + .recover_csr_enable_o ( csr_renable ), + .recover_pc_enable_o ( enable_pc_recovery_o ), + .recover_rf_enable_o ( enable_rf_recovery_o ) +); + +recovery_csr #( + .ECCEnabled ( EccEnabled ), + .csr_intf_t ( csr_intf_t ) +) i_recovery_csr ( + .clk_i, + .rst_ni, + .read_enable_i ( csr_renable ), + .write_enable_i ( backup_enable_i ), + .backup_csr_i ( backup_csr_i ), + .recovery_csr_o ( recovery_csr_o ) +); + +recovery_pc #( + .ECCEnabled ( EccEnabled ), + .pc_intf_t ( pc_intf_t ) +) i_recovery_pc ( + // Control Ports + .clk_i, + .rst_ni, + .clear_i ( '0 ), + .read_enable_i ( enable_pc_recovery_o ), + .write_enable_i ( backup_enable_i ), + // Backup Ports + .backup_program_counter_i ( backup_pc_i.program_counter ), + .backup_branch_i ( backup_pc_i.is_branch ), + .backup_branch_addr_i ( backup_pc_i.branch_addr ), + // Recovery Pors + .recovery_program_counter_o ( recovery_pc_o.program_counter ), + .recovery_branch_o ( recovery_pc_o.is_branch ), + .recovery_branch_addr_o ( recovery_pc_o.branch_addr ) +); + +recovery_rf #( + .ECCEnabled ( EccEnabled ), + .ADDR_WIDTH ( RfAddrWidth ), + .regfile_write_t ( regfile_write_t ), + .regfile_raddr_t ( regfile_raddr_t ), + .regfile_rdata_t ( regfile_rdata_t ) +) i_recovery_rf ( + .clk_i, + .rst_ni, + .test_en_i ( '0 ), + //Read port A + .raddr_a_i ( regfile_recovery_wdata_o.waddr_a ), + .rdata_a_o ( regfile_recovery_rdata_o.rdata_a ), + //Read port B + .raddr_b_i ( regfile_recovery_wdata_o.waddr_b ), + .rdata_b_o ( regfile_recovery_rdata_o.rdata_b ), + //Read port C + .raddr_c_i ( '0 ), + .rdata_c_o ( ), + // Write Port A + .waddr_a_i ( regfile_write_i.waddr_a ), + .wdata_a_i ( regfile_write_i.wdata_a ), + .we_a_i ( regfile_write_i.we_a & backup_enable_i ), + // Write Port B + .waddr_b_i ( regfile_write_i.waddr_b ), + .wdata_b_i ( regfile_write_i.wdata_b ), + .we_b_i ( regfile_write_i.we_b & backup_enable_i ) +); + +endmodule: rapid_recovery_unit diff --git a/rtl/HMR/recovery_csr.sv b/rtl/HMR/recovery_csr.sv index 8ef95555..6cf78126 100644 --- a/rtl/HMR/recovery_csr.sv +++ b/rtl/HMR/recovery_csr.sv @@ -13,21 +13,22 @@ * */ -import recovery_pkg::*; - -module recovery_csr #( - parameter ECCEnabled = 0, - parameter NonProtectedWidth = 32, - parameter ProtectedWidth = 39, - localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth - : NonProtectedWidth +module recovery_csr + import rapid_recovery_pkg::*; +#( + parameter int unsigned ECCEnabled = 0, + parameter int unsigned NonProtectedWidth = 32, + parameter int unsigned ProtectedWidth = 39, + parameter type csr_intf_t = logic, + localparam int unsigned DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth ) ( -input logic clk_i , -input logic rst_ni, -input logic read_enable_i, -input logic write_enable_i, -input csrs_intf_t backup_csr_i, -output csrs_intf_t recovery_csr_o + input logic clk_i , + input logic rst_ni, + input logic read_enable_i, + input logic write_enable_i, + input csrs_intf_t backup_csr_i, + output csrs_intf_t recovery_csr_o ); csrs_intf_t csr_inp, diff --git a/rtl/HMR/recovery_pc.sv b/rtl/HMR/recovery_pc.sv index 8b5fdf53..51f62347 100644 --- a/rtl/HMR/recovery_pc.sv +++ b/rtl/HMR/recovery_pc.sv @@ -14,11 +14,12 @@ */ module recovery_pc #( - parameter ECCEnabled = 0, - parameter NonProtectedWidth = 32, - parameter ProtectedWidth = 39, - localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth - : NonProtectedWidth + parameter int unsigned ECCEnabled = 0, + parameter int unsigned NonProtectedWidth = 32, + parameter int unsigned ProtectedWidth = 39, + parameter type pc_intf_t = logic, + localparam int unsigned DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth ) ( // Control Ports input logic clk_i, diff --git a/rtl/HMR/recovery_rf.sv b/rtl/HMR/recovery_rf.sv index 9572d26d..3bc572a7 100644 --- a/rtl/HMR/recovery_rf.sv +++ b/rtl/HMR/recovery_rf.sv @@ -30,42 +30,45 @@ //////////////////////////////////////////////////////////////////////////////// module recovery_rf #( - parameter ECCEnabled = 0, - parameter ADDR_WIDTH = 5, - parameter NonProtectedWidth = 32, - parameter ProtectedWidth = 39, - parameter FPU = 0, - parameter PULP_ZFINX = 0, - localparam DataWidth = ( ECCEnabled ) ? ProtectedWidth - : NonProtectedWidth + parameter int unsigned ECCEnabled = 0, + parameter int unsigned ADDR_WIDTH = 5, + parameter int unsigned NonProtectedWidth = 32, + parameter int unsigned ProtectedWidth = 39, + parameter int unsigned FPU = 0, + parameter int unsigned PULP_ZFINX = 0, + parameter type regfile_write_t = logic, + parameter type regfile_raddr_t = logic, + parameter type regfile_rdata_t = logic, + localparam int unsigned DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth ) ( - // Clock and Reset - input logic clk_i, - input logic rst_ni, + // Clock and Reset + input logic clk_i, + input logic rst_ni, - input logic test_en_i, + input logic test_en_i, - //Read port R1 - input logic [ADDR_WIDTH-1:0] raddr_a_i, - output logic [NonProtectedWidth-1:0] rdata_a_o, + //Read port R1 + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [NonProtectedWidth-1:0] rdata_a_o, - //Read port R2 - input logic [ADDR_WIDTH-1:0] raddr_b_i, - output logic [NonProtectedWidth-1:0] rdata_b_o, + //Read port R2 + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [NonProtectedWidth-1:0] rdata_b_o, - //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [NonProtectedWidth-1:0] rdata_c_o, + //Read port R3 + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [NonProtectedWidth-1:0] rdata_c_o, - // Write port W1 - input logic [ADDR_WIDTH-1:0] waddr_a_i, - input logic [NonProtectedWidth-1:0] wdata_a_i, - input logic we_a_i, + // Write port W1 + input logic [ADDR_WIDTH-1:0] waddr_a_i, + input logic [NonProtectedWidth-1:0] wdata_a_i, + input logic we_a_i, - // Write port W2 - input logic [ADDR_WIDTH-1:0] waddr_b_i, - input logic [NonProtectedWidth-1:0] wdata_b_i, - input logic we_b_i + // Write port W2 + input logic [ADDR_WIDTH-1:0] waddr_b_i, + input logic [NonProtectedWidth-1:0] wdata_b_i, + input logic we_b_i ); // number of integer registers From 3bae1860e00122f7c8955fd7ce463962d451ac68 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 2 Oct 2023 19:26:18 +0200 Subject: [PATCH 41/66] Fix no-RR case --- rtl/HMR/hmr_tmr_ctrl.sv | 6 +++--- rtl/HMR/hmr_unit.sv | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index e915b9d9..6f05db62 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -123,7 +123,7 @@ module hmr_tmr_ctrl #( // 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) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin tmr_red_mode_d = TMR_UNLOAD; @@ -138,7 +138,7 @@ 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) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; end else if (tmr_reg2hw.tmr_config.delay_resynch.q == '0) begin tmr_red_mode_d = TMR_UNLOAD; @@ -190,7 +190,7 @@ module hmr_tmr_ctrl #( if (tmr_red_mode_q == NON_TMR && tmr_reg2hw.tmr_enable.q == 1'b1) begin synch_req = 1'b1; if (cores_synch_q == 1'b1) begin - if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1) begin + if (tmr_reg2hw.tmr_config.rapid_recovery.q == 1'b1 && RapidRecovery) begin tmr_red_mode_d = TMR_RAPID; end else begin tmr_red_mode_d = TMR_RELOAD; diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 40daabe9..7dd16cbc 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -653,6 +653,11 @@ module hmr_unit #( end end end + end else begin + assign rapid_recovery_nominal = '0; + assign rapid_recovery_start = '0; + assign tmr_recovery_finished = '1; + assign dmr_recovery_finished = '1; end // Assign output signals From f83e7d2d758607abca64b8ecadc8b909ca685a6a Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Fri, 6 Oct 2023 16:20:17 +0200 Subject: [PATCH 42/66] Fixed assignment for default status backup if cores are not grouped. --- rtl/HMR/hmr_unit.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 7dd16cbc..49f4281c 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -633,7 +633,7 @@ module hmr_unit #( tmr_recovery_finished = '0; if (InterleaveGrps) begin for (int i = 0; i < NumBackupRegs; i++) begin - rapid_recovery_nominal[i] = dmr_nominal_outputs[i]; + rapid_recovery_nominal[i] = core_nominal_outputs_i[i]; rapid_recovery_start[i] = dmr_recovery_start[i]; dmr_recovery_finished[i] = rapid_recovery_finished[i]; end From d349923d062adf6793b84e5f683b40523bace0ee Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Tue, 10 Oct 2023 07:03:03 +0200 Subject: [PATCH 43/66] Made recovery RF FF-based. --- rtl/HMR/rapid_recovery_unit.sv | 1 - rtl/HMR/recovery_rf.sv | 190 +++++++++--------------- rtl/HMR/recovery_rf_latch.sv | 260 +++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+), 118 deletions(-) create mode 100644 rtl/HMR/recovery_rf_latch.sv diff --git a/rtl/HMR/rapid_recovery_unit.sv b/rtl/HMR/rapid_recovery_unit.sv index 18661a1d..16b89a22 100644 --- a/rtl/HMR/rapid_recovery_unit.sv +++ b/rtl/HMR/rapid_recovery_unit.sv @@ -134,7 +134,6 @@ recovery_rf #( ) i_recovery_rf ( .clk_i, .rst_ni, - .test_en_i ( '0 ), //Read port A .raddr_a_i ( regfile_recovery_wdata_o.waddr_a ), .rdata_a_o ( regfile_recovery_rdata_o.rdata_a ), diff --git a/rtl/HMR/recovery_rf.sv b/rtl/HMR/recovery_rf.sv index 3bc572a7..b546087c 100644 --- a/rtl/HMR/recovery_rf.sv +++ b/rtl/HMR/recovery_rf.sv @@ -9,10 +9,9 @@ // specific language governing permissions and limitations under the License. //////////////////////////////////////////////////////////////////////////////// -// Engineer: Antonio Pullini - pullinia@iis.ee.ethz.ch // +// Engineer: Francesco Conti - f.conti@unibo.it // // // // Additional contributions by: // -// Sven Stucki - svstucki@student.ethz.ch // // Michael Gautschi - gautschi@iis.ee.ethz.ch // // Davide Schiavone - pschiavo@iis.ee.ethz.ch // // // @@ -21,8 +20,7 @@ // Language: SystemVerilog // // // // Description: Register file with 31x 32 bit wide registers. Register 0 // -// is fixed to 0. This register file is based on latches and // -// is thus smaller than the flip-flop based register file. // +// is fixed to 0. This register file is based on flip-flops. // // Also supports the fp-register file now if FPU=1 // // If PULP_ZFINX is 1, floating point operations take values // // from the X register file // @@ -41,13 +39,11 @@ module recovery_rf #( parameter type regfile_rdata_t = logic, localparam int unsigned DataWidth = ( ECCEnabled ) ? ProtectedWidth : NonProtectedWidth -) ( +)( // Clock and Reset input logic clk_i, input logic rst_ni, - input logic test_en_i, - //Read port R1 input logic [ADDR_WIDTH-1:0] raddr_a_i, output logic [NonProtectedWidth-1:0] rdata_a_o, @@ -57,8 +53,8 @@ module recovery_rf #( output logic [NonProtectedWidth-1:0] rdata_b_o, //Read port R3 - input logic [ADDR_WIDTH-1:0] raddr_c_i, - output logic [NonProtectedWidth-1:0] rdata_c_o, + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [NonProtectedWidth:0] rdata_c_o, // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, @@ -78,51 +74,35 @@ module recovery_rf #( localparam NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; // integer register file - logic [NonProtectedWidth-1:0] mem [NUM_WORDS]; - logic [ DataWidth-1:0] ecc_mem [NUM_WORDS]; - logic [NUM_TOT_WORDS-1:1] waddr_onehot_a; - logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , - waddr_onehot_b_q; - logic [NUM_TOT_WORDS-1:1] mem_clocks; - logic [DataWidth-1:0] wdata_a , - wdata_a_q , - wdata_a_ecc; - logic [DataWidth-1:0] wdata_b , - wdata_b_q , - wdata_b_ecc; + logic [NUM_WORDS-1:0][NonProtectedWidth-1:0] mem; + logic [NUM_WORDS-1:0][ DataWidth-1:0] ecc_mem; + // fp register file + logic [NUM_FP_WORDS-1:0][NonProtectedWidth-1:0] mem_fp; + logic [NUM_FP_WORDS-1:0][ DataWidth-1:0] ecc_mem_fp; + + logic [DataWidth-1:0] wdata_a, + wdata_b; // masked write addresses logic [ADDR_WIDTH-1:0] waddr_a; logic [ADDR_WIDTH-1:0] waddr_b; - logic clk_int; - - // fp register file - logic [NonProtectedWidth-1:0] mem_fp [NUM_FP_WORDS]; - logic [ DataWidth-1:0] ecc_mem_fp [NUM_FP_WORDS]; - - int unsigned i; - int unsigned j; - int unsigned k; - int unsigned l; - - genvar x; - genvar y; + // write enable signals for all registers + logic [NUM_TOT_WORDS-1:0] we_a_dec; + logic [NUM_TOT_WORDS-1:0] we_b_dec; generate if (ECCEnabled) begin : gen_ecc_region prim_secded_39_32_enc a_port_ecc_encoder ( - .in ( wdata_a_i ), - .out ( wdata_a_ecc) + .in ( wdata_a_i ), + .out ( wdata_a ) ); - assign wdata_a = wdata_a_ecc; prim_secded_39_32_enc b_port_ecc_encoder ( - .in ( wdata_b_i ), - .out ( wdata_b_ecc) + .in ( wdata_b_i ), + .out ( wdata_b ) ); - assign wdata_b = wdata_b_ecc; for (genvar index = 0; index < NUM_WORDS; index++) begin prim_secded_39_32_dec internal_memory_decoder ( @@ -145,9 +125,7 @@ module recovery_rf #( end end else begin : no_ecc_region assign wdata_a = wdata_a_i; - assign wdata_a_ecc = '0; assign wdata_b = wdata_b_i; - assign wdata_b_ecc = '0; for (genvar index = 0; index < NUM_WORDS; index++) assign mem [index] = ecc_mem [index]; @@ -160,101 +138,79 @@ module recovery_rf #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - if (FPU == 1 && PULP_ZFINX == 0) begin - assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; - assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; - assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - end else begin - assign rdata_a_o = mem[raddr_a_i[4:0]]; - assign rdata_b_o = mem[raddr_b_i[4:0]]; - assign rdata_c_o = mem[raddr_c_i[4:0]]; - end - - //----------------------------------------------------------------------------- - // WRITE : SAMPLE INPUT DATA - //--------------------------------------------------------------------------- - - tc_clk_gating CG_WE_GLOBAL ( - .clk_i ( clk_i ), - .en_i ( we_a_i | we_b_i ), - .test_en_i ( test_en_i ), - .clk_o ( clk_int ) - ); - - // use clk_int here, since otherwise we don't want to write anything anyway - always_ff @(posedge clk_int, negedge rst_ni) begin : sample_waddr - if (~rst_ni) begin - wdata_a_q <= '0; - wdata_b_q <= '0; - waddr_onehot_b_q <= '0; - end else begin - if (we_a_i) wdata_a_q <= wdata_a; - - if (we_b_i) wdata_b_q <= wdata_b; - - waddr_onehot_b_q <= waddr_onehot_b; + generate + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_read + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end else begin : gen_mem_read + assign rdata_a_o = mem[raddr_a_i[4:0]]; + assign rdata_b_o = mem[raddr_b_i[4:0]]; + assign rdata_c_o = mem[raddr_c_i[4:0]]; end - end + endgenerate //----------------------------------------------------------------------------- //-- WRITE : Write Address Decoder (WAD), combinatorial process //----------------------------------------------------------------------------- + // Mask top bit of write address to disable fp regfile assign waddr_a = waddr_a_i; assign waddr_b = waddr_b_i; genvar gidx; generate - for (gidx = 1; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder - assign waddr_onehot_a[gidx] = (we_a_i == 1'b1) && (waddr_a == gidx); - assign waddr_onehot_b[gidx] = (we_b_i == 1'b1) && (waddr_b == gidx); + for (gidx = 0; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder + assign we_a_dec[gidx] = (waddr_a == gidx) ? we_a_i : 1'b0; + assign we_b_dec[gidx] = (waddr_b == gidx) ? we_b_i : 1'b0; end endgenerate - //----------------------------------------------------------------------------- - //-- WRITE : Clock gating (if integrated clock-gating cells are available) - //----------------------------------------------------------------------------- + genvar i, l; generate - for (x = 1; x < NUM_TOT_WORDS; x++) begin : gen_clock_gate - tc_clk_gating clock_gate_i ( - .clk_i ( clk_int ), - .en_i ( waddr_onehot_a[x] | waddr_onehot_b[x] ), - .test_en_i ( test_en_i ), - .clk_o ( mem_clocks[x] ) - ); - end - endgenerate - - //----------------------------------------------------------------------------- - //-- WRITE : Write operation - //----------------------------------------------------------------------------- - //-- Generate M = WORDS sequential processes, each of which describes one - //-- word of the memory. The processes are synchronized with the clocks - //-- ClocksxC(i), i = 0, 1, ..., M-1 - //-- Use active low, i.e. transparent on low latches as storage elements - //-- Data is sampled on rising clock edge - // Integer registers - always_latch begin : latch_wdata - // Note: The assignment has to be done inside this process or Modelsim complains about it - ecc_mem[0] = '0; + //----------------------------------------------------------------------------- + //-- WRITE : Write operation + //----------------------------------------------------------------------------- + // R0 is nil + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + // R0 is nil + ecc_mem[0] <= 32'b0; + end else begin + // R0 is nil + ecc_mem[0] <= 32'b0; + end + end - for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter - if (~rst_ni) ecc_mem[k] = '0; - else if (mem_clocks[k] == 1'b1) ecc_mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + // loop from 1 to NUM_WORDS-1 as R0 is nil + for (i = 1; i < NUM_WORDS; i++) begin : gen_rf + always_ff @(posedge clk_i, negedge rst_ni) begin : register_write_behavioral + if (rst_ni == 1'b0) begin + ecc_mem[i] <= 32'b0; + end else begin + if (we_b_dec[i] == 1'b1) ecc_mem[i] <= wdata_b; + else if (we_a_dec[i] == 1'b1) ecc_mem[i] <= wdata_a; + end + end end - end - if (FPU == 1 && PULP_ZFINX == 0) begin - // Floating point registers - always_latch begin : latch_wdata_fp - if (FPU == 1) begin - for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter - if (~rst_ni) ecc_mem_fp[l] = '0; - else if (mem_clocks[l+NUM_WORDS] == 1'b1) - ecc_mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_write + // Floating point registers + for (l = 0; l < NUM_FP_WORDS; l++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin : fp_regs + if (rst_ni == 1'b0) begin + ecc_mem_fp[l] <= '0; + end else begin + if (we_b_dec[l+NUM_WORDS] == 1'b1) ecc_mem_fp[l] <= wdata_b; + else if (we_a_dec[l+NUM_WORDS] == 1'b1) ecc_mem_fp[l] <= wdata_a; + end end end + end else begin : gen_no_mem_fp_write + assign ecc_mem_fp = 'b0; end - end + + endgenerate + endmodule diff --git a/rtl/HMR/recovery_rf_latch.sv b/rtl/HMR/recovery_rf_latch.sv new file mode 100644 index 00000000..3bc572a7 --- /dev/null +++ b/rtl/HMR/recovery_rf_latch.sv @@ -0,0 +1,260 @@ +// Copyright 2018 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. + +//////////////////////////////////////////////////////////////////////////////// +// Engineer: Antonio Pullini - pullinia@iis.ee.ethz.ch // +// // +// Additional contributions by: // +// Sven Stucki - svstucki@student.ethz.ch // +// Michael Gautschi - gautschi@iis.ee.ethz.ch // +// Davide Schiavone - pschiavo@iis.ee.ethz.ch // +// // +// Design Name: RISC-V register file // +// Project Name: RI5CY // +// Language: SystemVerilog // +// // +// Description: Register file with 31x 32 bit wide registers. Register 0 // +// is fixed to 0. This register file is based on latches and // +// is thus smaller than the flip-flop based register file. // +// Also supports the fp-register file now if FPU=1 // +// If PULP_ZFINX is 1, floating point operations take values // +// from the X register file // +// // +//////////////////////////////////////////////////////////////////////////////// + +module recovery_rf #( + parameter int unsigned ECCEnabled = 0, + parameter int unsigned ADDR_WIDTH = 5, + parameter int unsigned NonProtectedWidth = 32, + parameter int unsigned ProtectedWidth = 39, + parameter int unsigned FPU = 0, + parameter int unsigned PULP_ZFINX = 0, + parameter type regfile_write_t = logic, + parameter type regfile_raddr_t = logic, + parameter type regfile_rdata_t = logic, + localparam int unsigned DataWidth = ( ECCEnabled ) ? ProtectedWidth + : NonProtectedWidth +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, + + input logic test_en_i, + + //Read port R1 + input logic [ADDR_WIDTH-1:0] raddr_a_i, + output logic [NonProtectedWidth-1:0] rdata_a_o, + + //Read port R2 + input logic [ADDR_WIDTH-1:0] raddr_b_i, + output logic [NonProtectedWidth-1:0] rdata_b_o, + + //Read port R3 + input logic [ADDR_WIDTH-1:0] raddr_c_i, + output logic [NonProtectedWidth-1:0] rdata_c_o, + + // Write port W1 + input logic [ADDR_WIDTH-1:0] waddr_a_i, + input logic [NonProtectedWidth-1:0] wdata_a_i, + input logic we_a_i, + + // Write port W2 + input logic [ADDR_WIDTH-1:0] waddr_b_i, + input logic [NonProtectedWidth-1:0] wdata_b_i, + input logic we_b_i +); + + // number of integer registers + localparam NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + // number of floating point registers + localparam NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + + // integer register file + logic [NonProtectedWidth-1:0] mem [NUM_WORDS]; + logic [ DataWidth-1:0] ecc_mem [NUM_WORDS]; + logic [NUM_TOT_WORDS-1:1] waddr_onehot_a; + logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , + waddr_onehot_b_q; + logic [NUM_TOT_WORDS-1:1] mem_clocks; + logic [DataWidth-1:0] wdata_a , + wdata_a_q , + wdata_a_ecc; + logic [DataWidth-1:0] wdata_b , + wdata_b_q , + wdata_b_ecc; + + // masked write addresses + logic [ADDR_WIDTH-1:0] waddr_a; + logic [ADDR_WIDTH-1:0] waddr_b; + + logic clk_int; + + // fp register file + logic [NonProtectedWidth-1:0] mem_fp [NUM_FP_WORDS]; + logic [ DataWidth-1:0] ecc_mem_fp [NUM_FP_WORDS]; + + int unsigned i; + int unsigned j; + int unsigned k; + int unsigned l; + + genvar x; + genvar y; + + generate + if (ECCEnabled) begin : gen_ecc_region + + prim_secded_39_32_enc a_port_ecc_encoder ( + .in ( wdata_a_i ), + .out ( wdata_a_ecc) + ); + assign wdata_a = wdata_a_ecc; + + prim_secded_39_32_enc b_port_ecc_encoder ( + .in ( wdata_b_i ), + .out ( wdata_b_ecc) + ); + assign wdata_b = wdata_b_ecc; + + for (genvar index = 0; index < NUM_WORDS; index++) begin + prim_secded_39_32_dec internal_memory_decoder ( + .in ( ecc_mem [index] ), + .d_o ( mem [index] ), + .syndrome_o ( ), + .err_o ( ) + ); + end + + if (FPU == 1 && PULP_ZFINX == 0) begin + for (genvar index = 0; index < NUM_FP_WORDS; index++) begin + prim_secded_39_32_dec internal_fp_memory_decoder ( + .in ( ecc_mem_fp [index] ), + .d_o ( mem_fp [index] ), + .syndrome_o ( ), + .err_o ( ) + ); + end + end + end else begin : no_ecc_region + assign wdata_a = wdata_a_i; + assign wdata_a_ecc = '0; + assign wdata_b = wdata_b_i; + assign wdata_b_ecc = '0; + + for (genvar index = 0; index < NUM_WORDS; index++) + assign mem [index] = ecc_mem [index]; + + for (genvar index = 0; index < NUM_FP_WORDS; index++) + assign mem_fp [index] = ecc_mem_fp [index]; + end + endgenerate + + //----------------------------------------------------------------------------- + //-- READ : Read address decoder RAD + //----------------------------------------------------------------------------- + if (FPU == 1 && PULP_ZFINX == 0) begin + assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; + assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; + assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; + end else begin + assign rdata_a_o = mem[raddr_a_i[4:0]]; + assign rdata_b_o = mem[raddr_b_i[4:0]]; + assign rdata_c_o = mem[raddr_c_i[4:0]]; + end + + //----------------------------------------------------------------------------- + // WRITE : SAMPLE INPUT DATA + //--------------------------------------------------------------------------- + + tc_clk_gating CG_WE_GLOBAL ( + .clk_i ( clk_i ), + .en_i ( we_a_i | we_b_i ), + .test_en_i ( test_en_i ), + .clk_o ( clk_int ) + ); + + // use clk_int here, since otherwise we don't want to write anything anyway + always_ff @(posedge clk_int, negedge rst_ni) begin : sample_waddr + if (~rst_ni) begin + wdata_a_q <= '0; + wdata_b_q <= '0; + waddr_onehot_b_q <= '0; + end else begin + if (we_a_i) wdata_a_q <= wdata_a; + + if (we_b_i) wdata_b_q <= wdata_b; + + waddr_onehot_b_q <= waddr_onehot_b; + end + end + + //----------------------------------------------------------------------------- + //-- WRITE : Write Address Decoder (WAD), combinatorial process + //----------------------------------------------------------------------------- + + assign waddr_a = waddr_a_i; + assign waddr_b = waddr_b_i; + + genvar gidx; + generate + for (gidx = 1; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder + assign waddr_onehot_a[gidx] = (we_a_i == 1'b1) && (waddr_a == gidx); + assign waddr_onehot_b[gidx] = (we_b_i == 1'b1) && (waddr_b == gidx); + end + endgenerate + + //----------------------------------------------------------------------------- + //-- WRITE : Clock gating (if integrated clock-gating cells are available) + //----------------------------------------------------------------------------- + generate + for (x = 1; x < NUM_TOT_WORDS; x++) begin : gen_clock_gate + tc_clk_gating clock_gate_i ( + .clk_i ( clk_int ), + .en_i ( waddr_onehot_a[x] | waddr_onehot_b[x] ), + .test_en_i ( test_en_i ), + .clk_o ( mem_clocks[x] ) + ); + end + endgenerate + + //----------------------------------------------------------------------------- + //-- WRITE : Write operation + //----------------------------------------------------------------------------- + //-- Generate M = WORDS sequential processes, each of which describes one + //-- word of the memory. The processes are synchronized with the clocks + //-- ClocksxC(i), i = 0, 1, ..., M-1 + //-- Use active low, i.e. transparent on low latches as storage elements + //-- Data is sampled on rising clock edge + + // Integer registers + always_latch begin : latch_wdata + // Note: The assignment has to be done inside this process or Modelsim complains about it + ecc_mem[0] = '0; + + for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter + if (~rst_ni) ecc_mem[k] = '0; + else if (mem_clocks[k] == 1'b1) ecc_mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + end + end + + if (FPU == 1 && PULP_ZFINX == 0) begin + // Floating point registers + always_latch begin : latch_wdata_fp + if (FPU == 1) begin + for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter + if (~rst_ni) ecc_mem_fp[l] = '0; + else if (mem_clocks[l+NUM_WORDS] == 1'b1) + ecc_mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + end + end + end + end +endmodule From 6718ee5a6b9a486e504e143e7a9676efa0e42465 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 11 Oct 2023 22:56:39 +0200 Subject: [PATCH 44/66] Use pipelined checker for core's backup bus. --- rtl/HMR/DMR_checker.sv | 23 ++++++++++-- rtl/HMR/hmr_unit.sv | 79 ++++++++++++++++++++++++++++++------------ 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/rtl/HMR/DMR_checker.sv b/rtl/HMR/DMR_checker.sv index 21842bdb..c28b893d 100644 --- a/rtl/HMR/DMR_checker.sv +++ b/rtl/HMR/DMR_checker.sv @@ -15,8 +15,11 @@ */ module DMR_checker #( - parameter int unsigned DataWidth = 41 + parameter int unsigned DataWidth = 41, + parameter int unsigned Pipeline = 0 )( + input logic clk_i, + input logic rst_ni, input logic [DataWidth-1:0] inp_a_i, input logic [DataWidth-1:0] inp_b_i, output logic [DataWidth-1:0] check_o, @@ -25,10 +28,24 @@ module DMR_checker #( logic error; logic [DataWidth-1:0] compare; +logic [DataWidth-1:0] inp_q; -assign compare = inp_a_i ^ inp_b_i; +if (Pipeline) begin + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + compare <= '0; + inp_q <= '0; + end else begin + compare <= inp_a_i ^ inp_b_i; + inp_q <= inp_a_i; + end + end +end else begin + assign compare = inp_a_i ^ inp_b_i; + assign inp_q = inp_a_i; +end assign error = |compare; -assign check_o = (!error) ? inp_a_i : '0; +assign check_o = (error) ? '0 : inp_q; assign error_o = error; endmodule : DMR_checker diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 49f4281c..5fc22ef6 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -37,6 +37,8 @@ module hmr_unit #( parameter type all_inputs_t = logic, /// General core outputs wrapping struct parameter type nominal_outputs_t = logic, + /// Cores' backup output bus + parameter type core_backup_t = logic, /// Bus outputs wrapping struct parameter type bus_outputs_t = logic, parameter type reg_req_t = logic, @@ -80,8 +82,9 @@ module hmr_unit #( output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, - // Rapid recovery output bus - output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, + // Rapid recovery buses + output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, + input core_backup_t [NumCores-1:0] core_backup_i, input all_inputs_t [NumSysCores-1:0] sys_inputs_i, output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, @@ -146,6 +149,7 @@ module hmr_unit #( nominal_outputs_t [NumDMRGroups-1:0] dmr_nominal_outputs; bus_outputs_t [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_bus_outputs; + core_backup_t [NumDMRGroups-1:0] dmr_backup_outputs; logic [NumTMRGroups-1:0] tmr_failure, tmr_failure_main; logic [NumTMRGroups-1:0][NumBusVoters-1:0] tmr_failure_data; @@ -153,7 +157,7 @@ module hmr_unit #( logic [NumTMRGroups-1:0][NumBusVoters-1:0][2:0] tmr_error_data; logic [NumTMRGroups-1:0] tmr_single_mismatch; - logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main; + logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_backup; logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; /************************** @@ -165,6 +169,7 @@ module hmr_unit #( logic [NumBackupRegs-1:0] rapid_recovery_backup_en_inp, rapid_recovery_backup_en_oup; logic [NumBackupRegs-1:0] rapid_recovery_setback; rapid_recovery_t [NumBackupRegs-1:0] rapid_recovery_bus; + core_backup_t [NumBackupRegs-1:0] rapid_recovery_backup_bus; nominal_outputs_t [NumBackupRegs-1:0] rapid_recovery_nominal; /*************************** @@ -547,6 +552,8 @@ module hmr_unit #( DMR_checker #( .DataWidth ( $bits(nominal_outputs_t) ) ) dmr_core_checker_main ( + .clk_i ( ), + .rst_ni ( ), .inp_a_i ( core_nominal_outputs_i[dmr_core_id(i, 0)] ), .inp_b_i ( core_nominal_outputs_i[dmr_core_id(i, 1)] ), .check_o ( dmr_nominal_outputs [ i ] ), @@ -557,6 +564,8 @@ module hmr_unit #( DMR_checker # ( .DataWidth ( $bits(bus_outputs_t) ) ) dmr_core_checker_data ( + .clk_i ( ), + .rst_ni ( ), .inp_a_i ( core_bus_outputs_i[dmr_core_id(i, 0)][j] ), .inp_b_i ( core_bus_outputs_i[dmr_core_id(i, 1)][j] ), .check_o ( dmr_bus_outputs [ i ][j] ), @@ -567,6 +576,18 @@ module hmr_unit #( if (RapidRecovery) begin : gen_rapid_recovery_unit + DMR_checker #( + .DataWidth ( $bits(core_backup_t) ), + .Pipeline ( 1 ) + ) dmr_core_checker_backup ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .inp_a_i ( core_backup_i [dmr_core_id(i, 0)] ), + .inp_b_i ( core_backup_i [dmr_core_id(i, 1)] ), + .check_o ( dmr_backup_outputs [ i ] ), + .error_o ( dmr_failure_backup [ i ] ) + ); + assign rapid_recovery_backup_en_inp[i] = core_in_tmr[i] ? (i < NumTMRGroups ? rapid_recovery_backup_en_oup[i] : 1'b0) // TMR mode : core_in_dmr[i] ? (rapid_recovery_backup_en_oup[i] & ~dmr_failure[i] ) // DMR mode : 1'b1; // Independent @@ -579,27 +600,36 @@ module hmr_unit #( .csr_intf_t ( rapid_recovery_pkg::csrs_intf_t ), .pc_intf_t ( rapid_recovery_pkg::pc_intf_t ) ) i_rapid_recovery_unit ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .regfile_write_i ( rapid_recovery_nominal[i].regfile_backup ), - .backup_csr_i ( rapid_recovery_nominal[i].csr_backup ), - .recovery_csr_o ( rapid_recovery_bus[i].csr_recovery ), - .backup_pc_i ( rapid_recovery_nominal[i].pc_backup ), - .recovery_pc_o ( rapid_recovery_bus[i].pc_recovery ), - .backup_enable_i ( rapid_recovery_backup_en_inp[i] ), - .start_recovery_i ( rapid_recovery_start[i] ), - .backup_enable_o ( rapid_recovery_backup_en_oup[i] ), - .recovery_finished_o ( rapid_recovery_finished[i] ), - .setback_o ( rapid_recovery_setback[i] ), - .instr_lock_o ( rapid_recovery_bus[i].instr_lock ), - .enable_pc_recovery_o ( rapid_recovery_bus[i].pc_recovery_en ), - .enable_rf_recovery_o ( rapid_recovery_bus[i].rf_recovery_en ), - .regfile_recovery_wdata_o ( rapid_recovery_bus[i].rf_recovery_wdata ), - .regfile_recovery_rdata_o ( rapid_recovery_bus[i].rf_recovery_rdata ), - .debug_halt_i ( rapid_recovery_nominal[i].debug_halted ), - .debug_req_o ( rapid_recovery_bus[i].debug_req ), - .debug_resume_o ( rapid_recovery_bus[i].debug_resume ) + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .regfile_write_i ( rapid_recovery_backup_bus[i].regfile_backup ), + .backup_csr_i ( rapid_recovery_backup_bus[i].csr_backup ), + .recovery_csr_o ( rapid_recovery_bus[i].csr_recovery ), + .backup_pc_i ( rapid_recovery_backup_bus[i].pc_backup ), + .recovery_pc_o ( rapid_recovery_bus[i].pc_recovery ), + .backup_enable_i ( rapid_recovery_backup_en_inp[i] ), + .start_recovery_i ( rapid_recovery_start[i] ), + .backup_enable_o ( rapid_recovery_backup_en_oup[i] ), + .recovery_finished_o ( rapid_recovery_finished[i] ), + .setback_o ( rapid_recovery_setback[i] ), + .instr_lock_o ( rapid_recovery_bus[i].instr_lock ), + .enable_pc_recovery_o ( rapid_recovery_bus[i].pc_recovery_en ), + .enable_rf_recovery_o ( rapid_recovery_bus[i].rf_recovery_en ), + .regfile_recovery_wdata_o ( rapid_recovery_bus[i].rf_recovery_wdata ), + .regfile_recovery_rdata_o ( rapid_recovery_bus[i].rf_recovery_rdata ), + .debug_halt_i ( rapid_recovery_nominal[i].debug_halted ), + .debug_req_o ( rapid_recovery_bus[i].debug_req ), + .debug_resume_o ( rapid_recovery_bus[i].debug_resume ) ); + + always_comb begin + dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i]; + for (int j = 0; j < NumBusVoters; j++) begin + if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin + dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; + end + end + end end else begin : gen_standard_failure always_comb begin dmr_failure[i] = dmr_failure_main[i]; @@ -628,12 +658,14 @@ module hmr_unit #( if (RapidRecovery) begin: gen_rapid_recovery_connection always_comb begin rapid_recovery_nominal = '0; + rapid_recovery_backup_bus = '0; rapid_recovery_start = '0; dmr_recovery_finished = '0; tmr_recovery_finished = '0; if (InterleaveGrps) begin for (int i = 0; i < NumBackupRegs; i++) begin rapid_recovery_nominal[i] = core_nominal_outputs_i[i]; + rapid_recovery_backup_bus[i] = core_backup_i[i]; rapid_recovery_start[i] = dmr_recovery_start[i]; dmr_recovery_finished[i] = rapid_recovery_finished[i]; end @@ -641,6 +673,7 @@ module hmr_unit #( for (int i = 0; i < NumDMRGroups; i++) begin if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin rapid_recovery_nominal[dmr_shared_id(i)] = dmr_nominal_outputs[i]; + rapid_recovery_backup_bus[dmr_shared_id(i)] = dmr_backup_outputs[i]; rapid_recovery_start[dmr_shared_id(i)] = dmr_recovery_start[i]; dmr_recovery_finished[i] = rapid_recovery_finished[dmr_shared_id(i)]; end From 6a3d7e68f65eb23370089abc4ad8b22631dd6981 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Mon, 30 Oct 2023 22:20:18 +0100 Subject: [PATCH 45/66] Store PR coming from IF stage if cores are in independent. --- rtl/HMR/hmr_unit.sv | 1 + rtl/HMR/rapid_recovery_pkg.sv | 1 + rtl/HMR/rapid_recovery_unit.sv | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 5fc22ef6..39d575f7 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -602,6 +602,7 @@ module hmr_unit #( ) i_rapid_recovery_unit ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), + .core_in_independent_i ( core_in_independent[i] ), .regfile_write_i ( rapid_recovery_backup_bus[i].regfile_backup ), .backup_csr_i ( rapid_recovery_backup_bus[i].csr_backup ), .recovery_csr_o ( rapid_recovery_bus[i].csr_recovery ), diff --git a/rtl/HMR/rapid_recovery_pkg.sv b/rtl/HMR/rapid_recovery_pkg.sv index 123f39ef..6a1e1044 100644 --- a/rtl/HMR/rapid_recovery_pkg.sv +++ b/rtl/HMR/rapid_recovery_pkg.sv @@ -65,6 +65,7 @@ typedef struct packed { } ecc_csrs_intf_t; typedef struct packed { + logic [DataWidth-1:0] program_counter_if; logic [DataWidth-1:0] program_counter; logic is_branch; logic [DataWidth-1:0] branch_addr; diff --git a/rtl/HMR/rapid_recovery_unit.sv b/rtl/HMR/rapid_recovery_unit.sv index 16b89a22..77bcf453 100644 --- a/rtl/HMR/rapid_recovery_unit.sv +++ b/rtl/HMR/rapid_recovery_unit.sv @@ -24,6 +24,8 @@ module rapid_recovery_unit )( input logic clk_i, input logic rst_ni, + /* Signals that cores are not grouped */ + input logic core_in_independent_i, /* Recovery Register File interface */ input regfile_write_t regfile_write_i, /* Recovery Control and Status Registers interface */ @@ -105,6 +107,13 @@ recovery_csr #( .recovery_csr_o ( recovery_csr_o ) ); +/* When cores are not grouped, we store as a recovery program counter the instruction + that just eneterd the fetch stage. The reason is that if we switch from independent + to redundant, we do it after a barrier, and if we restart from a barrier instruction + without setting it up properly first, we never continue the execution. */ +logic [DataWidth-1:0] backup_program_counter; +assign backup_program_counter = core_in_independent_i ? backup_pc_i.program_counter_if + : backup_pc_i.program_counter; recovery_pc #( .ECCEnabled ( EccEnabled ), .pc_intf_t ( pc_intf_t ) @@ -116,9 +125,9 @@ recovery_pc #( .read_enable_i ( enable_pc_recovery_o ), .write_enable_i ( backup_enable_i ), // Backup Ports - .backup_program_counter_i ( backup_pc_i.program_counter ), - .backup_branch_i ( backup_pc_i.is_branch ), - .backup_branch_addr_i ( backup_pc_i.branch_addr ), + .backup_program_counter_i ( backup_program_counter ), + .backup_branch_i ( backup_pc_i.is_branch ), + .backup_branch_addr_i ( backup_pc_i.branch_addr ), // Recovery Pors .recovery_program_counter_o ( recovery_pc_o.program_counter ), .recovery_branch_o ( recovery_pc_o.is_branch ), From 3cdeb862091466f4b5a6dd0a09a735b88e3bbc4b Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 15 Nov 2023 17:35:38 +0100 Subject: [PATCH 46/66] [HMR] Fix mismatch count indexing --- rtl/HMR/hmr_unit.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 39d575f7..e6b209de 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -392,7 +392,7 @@ module hmr_unit #( .sw_synch_req_o ( tmr_sw_synch_req[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), - .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), + .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,2)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,0)]} ), .tmr_single_mismatch_i( tmr_single_mismatch[i] ), .tmr_error_i ( tmr_error[i] ), .tmr_failure_i ( tmr_failure[i] ), @@ -533,7 +533,7 @@ module hmr_unit #( .sw_synch_req_o ( dmr_sw_synch_req [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), - .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 1)], dmr_incr_mismatches[dmr_core_id(i, 0)]} ), .dmr_error_i ( dmr_failure [i] ), .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), From 1fd79fcecf6b8285e7d562e3473480dae94f8eb6 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Thu, 23 Nov 2023 21:42:01 +0100 Subject: [PATCH 47/66] Create redundant groups only if redundant modes are supported. --- rtl/HMR/hmr_unit.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index e6b209de..fdaf3410 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -47,13 +47,13 @@ module hmr_unit #( parameter type rapid_recovery_t = logic, // Local parameters depending on the above ones /// Number of TMR groups (virtual TMR cores) - localparam int unsigned NumTMRGroups = NumCores/3, + localparam int unsigned NumTMRGroups = (TMRFixed || TMRSupported) ? NumCores/3 : 1, /// Number of physical cores used for TMR localparam int unsigned NumTMRCores = NumTMRGroups * 3, /// Number of physical cores NOT used for TMR localparam int unsigned NumTMRLeftover = NumCores - NumTMRCores, /// Number of DMR groups (virtual DMR cores) - localparam int unsigned NumDMRGroups = NumCores/2, + localparam int unsigned NumDMRGroups = (DMRFixed || DMRSupported) ? NumCores/2 : 1, /// Nubmer of physical cores used for DMR localparam int unsigned NumDMRCores = NumDMRGroups * 2, /// Number of physical cores NOT used for DMR From 8eb440bb5c64f65f65ac927dba0163d936d9d1ab Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Thu, 30 Nov 2023 15:34:43 +0100 Subject: [PATCH 48/66] Fix out-of-range indices when with a single DMR group. --- rtl/HMR/hmr_unit.sv | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index fdaf3410..42fd9fdd 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -486,19 +486,24 @@ module hmr_unit #( /*************** * Registers * ***************/ - reg_demux #( - .NoPorts ( NumDMRGroups ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_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 ) - ); + if (NumDMRGroups == 1) begin + assign dmr_register_reqs[0] = top_register_reqs[2]; + assign top_register_resps[2] = dmr_register_resps[0]; + end else begin + reg_demux #( + .NoPorts ( NumDMRGroups ), + .req_t ( reg_req_t ), + .rsp_t ( reg_rsp_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 ) + ); + end for (genvar i = NumDMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign dmr_incr_mismatches[i] = '0; From 0695567b9265bddc05ee65e0018e9723855ea200 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Tue, 12 Dec 2023 22:06:12 +0100 Subject: [PATCH 49/66] Enable usage of checkpoint register for DMR synchronization. --- rtl/HMR/hmr_dmr_ctrl.sv | 3 +++ rtl/HMR/hmr_unit.sv | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 1b55311b..47159a3d 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -14,6 +14,7 @@ module hmr_dmr_ctrl import rapid_recovery_pkg::*; #( parameter bit InterleaveGrps = 1'b0, + parameter int unsigned DataWidth = 32, parameter bit DMRFixed = 1'b0, parameter bit DefaultInDMR = DMRFixed ? 1'b1 : 1'b0, parameter bit RapidRecovery = 1'b0, @@ -40,6 +41,7 @@ module hmr_dmr_ctrl output logic [1:0] setback_o, output logic sw_resynch_req_o, output logic sw_synch_req_o, + output logic [DataWidth-1:0] checkpoint_o, output logic grp_in_independent_o, output logic rapid_recovery_en_o, output logic [1:0] dmr_incr_mismatches_o, @@ -70,6 +72,7 @@ module hmr_dmr_ctrl 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), diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 42fd9fdd..b2dd235d 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -86,12 +86,16 @@ module hmr_unit #( output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, input core_backup_t [NumCores-1:0] core_backup_i, + // Boot address is handled apart from other signals + input logic [SysDataWidth-1:0] sys_bootaddress_i, input all_inputs_t [NumSysCores-1:0] sys_inputs_i, output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, output bus_outputs_t [NumSysCores-1:0][NumBusVoters-1:0] sys_bus_outputs_o, input logic [NumSysCores-1:0] sys_fetch_en_i, input logic [NumSysCores-1:0][NumBusVoters-1:0] enable_bus_vote_i, + // Boot address is handled apart from other signals + output logic [NumCores-1:0][SysDataWidth-1:0] core_bootaddress_o, output logic [NumCores-1:0] core_setback_o, output all_inputs_t [NumCores-1:0] core_inputs_o, input nominal_outputs_t [NumCores-1:0] core_nominal_outputs_i, @@ -159,6 +163,7 @@ module hmr_unit #( logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_backup; logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; + logic [NumDMRGroups-1:0][SysDataWidth-1:0] checkpoint_reg_q; /************************** * Rapid Recovery Signals * @@ -515,6 +520,7 @@ module hmr_unit #( hmr_dmr_ctrl #( .reg_req_t ( reg_req_t ), .reg_resp_t ( reg_rsp_t ), + .DataWidth ( SysDataWidth ), .InterleaveGrps( InterleaveGrps ), .DMRFixed ( DMRFixed ), .RapidRecovery ( RapidRecovery ), @@ -536,6 +542,7 @@ module hmr_unit #( .setback_o ( dmr_setback_q [i] ), .sw_resynch_req_o ( dmr_resynch_req_o [i] ), .sw_synch_req_o ( dmr_sw_synch_req [i] ), + .checkpoint_o ( checkpoint_reg_q [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 1)], dmr_incr_mismatches[dmr_core_id(i, 0)]} ), @@ -712,6 +719,8 @@ module hmr_unit #( always_comb begin // Special signals + core_bootaddress_o[i] = (checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] != '0) ? + checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; if (RapidRecovery) begin // $error("UNIMPLEMENTED"); rapid_recovery_o [i] = (core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : @@ -781,6 +790,8 @@ module hmr_unit #( localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin // Special signals + core_bootaddress_o[i] = (checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] != '0) ? + checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; // Setback if (RapidRecovery) begin // $error("UNIMPLEMENTED"); @@ -843,6 +854,8 @@ module hmr_unit #( for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); always_comb begin + core_bootaddress_o[i] = (checkpoint_reg_q[SysCoreIndex] != '0) ? + checkpoint_reg_q[SysCoreIndex] : sys_bootaddress_i; // Setback if (RapidRecovery) begin // $error("UNIMPLEMENTED"); @@ -851,7 +864,7 @@ module hmr_unit #( core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] | rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))]; end else begin - core_setback_o [i] = '0; + core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)]; end if (i >= NumDMRCores) begin core_setback_o [i] = '0; @@ -898,6 +911,7 @@ module hmr_unit #( *****************/ // Direct assignment, disable all assign core_setback_o = '0; + assign core_bootaddress_o = sys_bootaddress_i; assign core_inputs_o = sys_inputs_i; assign sys_nominal_outputs_o = core_nominal_outputs_i; assign sys_bus_outputs_o = core_bus_outputs_i; From e9d76f8d1f493656b864a0372e8e11a09cfc2aa7 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Tue, 12 Dec 2023 22:49:19 +0100 Subject: [PATCH 50/66] Properly rename DMR registers in hmr_dmr_ctrl. --- rtl/HMR/hmr_dmr_ctrl.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 47159a3d..35b638ba 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -77,7 +77,7 @@ module hmr_dmr_ctrl hmr_dmr_regs_reg_top #( .reg_req_t(reg_req_t), .reg_rsp_t(reg_resp_t) - ) i_tmr_regs ( + ) i_dmr_regs ( .clk_i, .rst_ni, .reg_req_i(reg_req_i), From b3883632a3e9999fbe7802574970d9bd22366484 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Tue, 7 May 2024 10:03:00 +0200 Subject: [PATCH 51/66] Extend checker for separate AXI bus. --- rtl/HMR/DMR_checker.sv | 79 ++++++++++++++++++++++++++++++------------ rtl/HMR/hmr_unit.sv | 58 +++++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 33 deletions(-) diff --git a/rtl/HMR/DMR_checker.sv b/rtl/HMR/DMR_checker.sv index c28b893d..7ea6f881 100644 --- a/rtl/HMR/DMR_checker.sv +++ b/rtl/HMR/DMR_checker.sv @@ -15,36 +15,69 @@ */ module DMR_checker #( - parameter int unsigned DataWidth = 41, - parameter int unsigned Pipeline = 0 + parameter type check_bus_t = logic, + parameter int unsigned Pipeline = 0, + parameter bit AxiBus = 1'b0 )( - input logic clk_i, - input logic rst_ni, - input logic [DataWidth-1:0] inp_a_i, - input logic [DataWidth-1:0] inp_b_i, - output logic [DataWidth-1:0] check_o, - output logic error_o + input logic clk_i, + input logic rst_ni, + input check_bus_t inp_a_i, + input check_bus_t inp_b_i, + output check_bus_t check_o, + output logic error_o ); -logic error; -logic [DataWidth-1:0] compare; -logic [DataWidth-1:0] inp_q; +check_bus_t compare; +check_bus_t inp_q; -if (Pipeline) begin - always_ff @(posedge clk_i, negedge rst_ni) begin - if (~rst_ni) begin - compare <= '0; - inp_q <= '0; - end else begin - compare <= inp_a_i ^ inp_b_i; - inp_q <= inp_a_i; +if (AxiBus == 1) begin: gen_axi_checker + logic error, error_aw, error_w, error_ar, error_r, error_b; + if (Pipeline) begin + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + compare <= '0; + inp_q <= '0; + end else begin + compare.aw <= inp_a_i.aw ^ inp_b_i.aw; + compare.w <= inp_a_i.w ^ inp_b_i.w; + compare.ar <= inp_a_i.ar ^ inp_b_i.ar; + compare.r <= inp_a_i.r ^ inp_b_i.r; + compare.b <= inp_a_i.b ^ inp_b_i.b; + inp_q <= inp_a_i; + end end + end else begin + assign compare.aw = inp_a_i.aw ^ inp_b_i.aw; + assign compare.w = inp_a_i.w ^ inp_b_i.w; + assign compare.ar = inp_a_i.ar ^ inp_b_i.ar; + assign compare.r = inp_a_i.r ^ inp_b_i.r; + assign compare.b = inp_a_i.b ^ inp_b_i.b; + assign inp_q = inp_a_i; end -end else begin - assign compare = inp_a_i ^ inp_b_i; - assign inp_q = inp_a_i; + assign error_aw = |compare.aw; + assign error_w = |compare.w; + assign error_ar = |compare.ar; + assign error_r = |compare.r; + assign error_b = |compare.b; + assign error = error_aw | error_w | error_ar | error_r | error_b; +end else begin: gen_generic_checker + logic error; + if (Pipeline) begin + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + compare <= '0; + inp_q <= '0; + end else begin + compare <= inp_a_i ^ inp_b_i; + inp_q <= inp_a_i; + end + end + end else begin + assign compare = inp_a_i ^ inp_b_i; + assign inp_q = inp_a_i; + end + assign error = |compare; end -assign error = |compare; assign check_o = (error) ? '0 : inp_q; assign error_o = error; diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index b2dd235d..bcbb7d3e 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -28,6 +28,8 @@ module hmr_unit #( parameter bit RapidRecovery = 1'b0, /// Separates voters and checkers for data, which are then only checked if data request is valid parameter bit SeparateData = 1'b1, + /// Separates voters and checkers for AXI buses + parameter bit SeparateAxiBus = 1'b0, /// Number of separate voters/checkers for individual buses parameter int unsigned NumBusVoters = 1, /// Address width of the core register file (in RISC-V it should be always 6) @@ -41,6 +43,8 @@ module hmr_unit #( parameter type core_backup_t = logic, /// Bus outputs wrapping struct parameter type bus_outputs_t = logic, + /// AXI output wrapping struct + parameter type axi_req_t = logic, parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, /// Rapid recovery structure @@ -91,6 +95,7 @@ module hmr_unit #( input all_inputs_t [NumSysCores-1:0] sys_inputs_i, output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, output bus_outputs_t [NumSysCores-1:0][NumBusVoters-1:0] sys_bus_outputs_o, + output axi_req_t [NumSysCores-1:0] sys_axi_outputs_o, input logic [NumSysCores-1:0] sys_fetch_en_i, input logic [NumSysCores-1:0][NumBusVoters-1:0] enable_bus_vote_i, @@ -99,7 +104,8 @@ module hmr_unit #( output logic [NumCores-1:0] core_setback_o, output all_inputs_t [NumCores-1:0] core_inputs_o, input nominal_outputs_t [NumCores-1:0] core_nominal_outputs_i, - input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i + input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i, + input axi_req_t [NumCores-1:0] core_axi_outputs_i ); function int max(int a, int b); return (a > b) ? a : b; @@ -153,6 +159,7 @@ module hmr_unit #( nominal_outputs_t [NumDMRGroups-1:0] dmr_nominal_outputs; bus_outputs_t [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_bus_outputs; + axi_req_t [NumDMRGroups-1:0] dmr_axi_outputs; core_backup_t [NumDMRGroups-1:0] dmr_backup_outputs; logic [NumTMRGroups-1:0] tmr_failure, tmr_failure_main; @@ -161,7 +168,7 @@ module hmr_unit #( logic [NumTMRGroups-1:0][NumBusVoters-1:0][2:0] tmr_error_data; logic [NumTMRGroups-1:0] tmr_single_mismatch; - logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_backup; + logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_axi, dmr_failure_backup; logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; logic [NumDMRGroups-1:0][SysDataWidth-1:0] checkpoint_reg_q; @@ -562,7 +569,7 @@ module hmr_unit #( * DMR Core Checkers * *********************/ DMR_checker #( - .DataWidth ( $bits(nominal_outputs_t) ) + .check_bus_t ( nominal_outputs_t ) ) dmr_core_checker_main ( .clk_i ( ), .rst_ni ( ), @@ -571,13 +578,28 @@ module hmr_unit #( .check_o ( dmr_nominal_outputs [ i ] ), .error_o ( dmr_failure_main [ i ] ) ); + if (SeparateAxiBus) begin: gen_axi_checker + DMR_axi_checker #( + .check_bus_t ( axi_req_t ) + ) dmr_core_checker_axi ( + .clk_i ( ), + .rst_ni ( ), + .inp_a_i ( core_axi_outputs_i[dmr_core_id(i, 0)] ), + .inp_b_i ( core_axi_outputs_i[dmr_core_id(i, 1)] ), + .check_o ( dmr_axi_outputs [ i ] ), + .error_o ( dmr_failure_axi [ i ] ) + ); + end else begin: gen_no_axi_checker + assign dmr_axi_outputs = '0; + assign dmr_failure_axi = '0; + end if (SeparateData) begin : gen_data_checker for (genvar j = 0; j < NumBusVoters; j++) begin DMR_checker # ( - .DataWidth ( $bits(bus_outputs_t) ) + .check_bus_t ( bus_outputs_t ) ) dmr_core_checker_data ( - .clk_i ( ), - .rst_ni ( ), + .clk_i ( ), + .rst_ni ( ), .inp_a_i ( core_bus_outputs_i[dmr_core_id(i, 0)][j] ), .inp_b_i ( core_bus_outputs_i[dmr_core_id(i, 1)][j] ), .check_o ( dmr_bus_outputs [ i ][j] ), @@ -589,7 +611,7 @@ module hmr_unit #( if (RapidRecovery) begin : gen_rapid_recovery_unit DMR_checker #( - .DataWidth ( $bits(core_backup_t) ), + .check_bus_t ( core_backup_t ), .Pipeline ( 1 ) ) dmr_core_checker_backup ( .clk_i ( clk_i ), @@ -636,7 +658,7 @@ module hmr_unit #( ); always_comb begin - dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i]; + dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i] | dmr_failure_axi[i]; for (int j = 0; j < NumBusVoters; j++) begin if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; @@ -645,7 +667,7 @@ module hmr_unit #( end end else begin : gen_standard_failure always_comb begin - dmr_failure[i] = dmr_failure_main[i]; + dmr_failure[i] = dmr_failure_main[i] | dmr_failure_axi[i]; for (int j = 0; j < NumBusVoters; j++) begin if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin dmr_failure[i] = dmr_failure[i] | dmr_failure_data[i][j]; @@ -657,10 +679,12 @@ module hmr_unit #( end else begin: no_dmr_checkers assign dmr_failure_main = '0; assign dmr_failure_data = '0; + assign dmr_failure_axi = '0; assign dmr_failure = '0; assign dmr_incr_mismatches = '0; assign dmr_nominal_outputs = '0; assign dmr_bus_outputs = '0; + assign dmr_axi_outputs = '0; assign top_register_resps[2].rdata = '0; assign top_register_resps[2].error = 1'b1; assign top_register_resps[2].ready = 1'b1; @@ -760,24 +784,29 @@ module hmr_unit #( if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core sys_nominal_outputs_o[i] = tmr_nominal_outputs[TMRCoreIndex]; - sys_bus_outputs_o[i] = tmr_bus_outputs[TMRCoreIndex]; + sys_bus_outputs_o[i] = tmr_bus_outputs[TMRCoreIndex]; + sys_axi_outputs_o[i] = '0; end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; + sys_axi_outputs_o[i] = '0; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core sys_nominal_outputs_o[i] = dmr_nominal_outputs[DMRCoreIndex]; + sys_axi_outputs_o[i] = dmr_axi_outputs[DMRCoreIndex]; for (int j = 0; j < NumBusVoters; j++) begin sys_bus_outputs_o[i][j] = dmr_bus_outputs[DMRCoreIndex][j]; end end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; + sys_axi_outputs_o[i] = '0; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; sys_bus_outputs_o[i] = core_bus_outputs_i[i]; + sys_axi_outputs_o[i] = core_axi_outputs_i[i]; end end end @@ -818,12 +847,15 @@ module hmr_unit #( if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr assign sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; + assign sys_axi_outputs_o [i] = '0; end else begin if (i >= NumTMRCores) begin : independent_stragglers assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign sys_bus_outputs_o [i] = core_bus_outputs_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_axi_outputs_o [i] = '0; end else begin always_comb begin + sys_axi_outputs_o [i] = '0; if (core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; @@ -882,23 +914,28 @@ module hmr_unit #( if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr assign sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; + assign sys_axi_outputs_o [i] = dmr_axi_outputs [CoreCoreIndex]; end else begin if (i >= NumDMRCores) begin : independent_stragglers assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; assign sys_bus_outputs_o [i] = core_bus_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; + assign sys_axi_outputs_o [i] = core_axi_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; end else begin always_comb begin if (core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; + sys_axi_outputs_o [i] = dmr_axi_outputs [CoreCoreIndex]; end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o [i] = '0; + sys_axi_outputs_o [i] = '0; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; sys_bus_outputs_o [i] = core_bus_outputs_i [i]; + sys_axi_outputs_o [i] = core_axi_outputs_i [i]; end end end @@ -915,6 +952,7 @@ module hmr_unit #( assign core_inputs_o = sys_inputs_i; assign sys_nominal_outputs_o = core_nominal_outputs_i; assign sys_bus_outputs_o = core_bus_outputs_i; + assign sys_axi_outputs_o = core_axi_outputs_i; end endmodule From a947f5102dbe5b654cba2b7f6a1c57ebaf48b648 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 22 May 2024 13:51:53 +0200 Subject: [PATCH 52/66] Fix AXI DMR checker. --- rtl/HMR/DMR_checker.sv | 42 ++++++++++++++++++++++++------------------ rtl/HMR/hmr_unit.sv | 7 ++++--- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/rtl/HMR/DMR_checker.sv b/rtl/HMR/DMR_checker.sv index 7ea6f881..e8695978 100644 --- a/rtl/HMR/DMR_checker.sv +++ b/rtl/HMR/DMR_checker.sv @@ -29,39 +29,45 @@ module DMR_checker #( check_bus_t compare; check_bus_t inp_q; +logic error; if (AxiBus == 1) begin: gen_axi_checker - logic error, error_aw, error_w, error_ar, error_r, error_b; + logic error_aw, error_w, error_ar, error_r, error_b; if (Pipeline) begin always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin compare <= '0; inp_q <= '0; end else begin - compare.aw <= inp_a_i.aw ^ inp_b_i.aw; - compare.w <= inp_a_i.w ^ inp_b_i.w; - compare.ar <= inp_a_i.ar ^ inp_b_i.ar; - compare.r <= inp_a_i.r ^ inp_b_i.r; - compare.b <= inp_a_i.b ^ inp_b_i.b; - inp_q <= inp_a_i; + compare.aw <= inp_a_i.aw ^ inp_b_i.aw; + compare.aw_valid <= inp_a_i.aw_valid ^ inp_b_i.aw_valid; + compare.w <= inp_a_i.w ^ inp_b_i.w; + compare.w_valid <= inp_a_i.w_valid ^ inp_b_i.w_valid; + compare.ar <= inp_a_i.ar ^ inp_b_i.ar; + compare.ar_valid <= inp_a_i.ar_valid ^ inp_b_i.ar_valid; + compare.r_ready <= inp_a_i.r_ready ^ inp_b_i.r_ready; + compare.b_ready <= inp_a_i.b_ready ^ inp_b_i.b_ready; + inp_q <= inp_a_i; end end end else begin - assign compare.aw = inp_a_i.aw ^ inp_b_i.aw; - assign compare.w = inp_a_i.w ^ inp_b_i.w; - assign compare.ar = inp_a_i.ar ^ inp_b_i.ar; - assign compare.r = inp_a_i.r ^ inp_b_i.r; - assign compare.b = inp_a_i.b ^ inp_b_i.b; + assign compare.aw = inp_a_i.aw ^ inp_b_i.aw; + assign compare.aw_valid = inp_a_i.aw_valid ^ inp_b_i.aw_valid; + assign compare.w = inp_a_i.w ^ inp_b_i.w; + assign compare.w_valid = inp_a_i.w_valid ^ inp_b_i.w_valid; + assign compare.ar = inp_a_i.ar ^ inp_b_i.ar; + assign compare.ar_valid = inp_a_i.ar_valid ^ inp_b_i.ar_valid; + assign compare.r_ready = inp_a_i.r_ready ^ inp_b_i.r_ready; + assign compare.b_ready = inp_a_i.b_ready ^ inp_b_i.b_ready; assign inp_q = inp_a_i; end - assign error_aw = |compare.aw; - assign error_w = |compare.w; - assign error_ar = |compare.ar; - assign error_r = |compare.r; - assign error_b = |compare.b; + assign error_aw = (|compare.aw) | compare.aw_valid; + assign error_w = (|compare.w) | compare.w_valid; + assign error_ar = (|compare.ar) | compare.ar_valid; + assign error_r = compare.r_ready; + assign error_b = compare.b_ready; assign error = error_aw | error_w | error_ar | error_r | error_b; end else begin: gen_generic_checker - logic error; if (Pipeline) begin always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index bcbb7d3e..27988fe6 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -579,7 +579,8 @@ module hmr_unit #( .error_o ( dmr_failure_main [ i ] ) ); if (SeparateAxiBus) begin: gen_axi_checker - DMR_axi_checker #( + DMR_checker #( + .AxiBus ( SeparateAxiBus ), .check_bus_t ( axi_req_t ) ) dmr_core_checker_axi ( .clk_i ( ), @@ -590,8 +591,8 @@ module hmr_unit #( .error_o ( dmr_failure_axi [ i ] ) ); end else begin: gen_no_axi_checker - assign dmr_axi_outputs = '0; - assign dmr_failure_axi = '0; + assign dmr_axi_outputs[i] = '0; + assign dmr_failure_axi[i] = '0; end if (SeparateData) begin : gen_data_checker for (genvar j = 0; j < NumBusVoters; j++) begin From e0cdc31e0b13364b63a6460f8743f43a2935d6d6 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 29 May 2024 14:56:28 +0200 Subject: [PATCH 53/66] Fix undefined assign if bus voters are not there. --- rtl/HMR/hmr_unit.sv | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 27988fe6..e84b944e 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -607,6 +607,9 @@ module hmr_unit #( .error_o ( dmr_failure_data [ i ][j] ) ); end + end else begin: gen_no_data_checker + assign dmr_bus_outputs [i] = '0; + assign dmr_failure_data [i] = '0; end if (RapidRecovery) begin : gen_rapid_recovery_unit From 99af292c6177856efb53755a8337d7aed726baaf Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sat, 8 Jun 2024 16:51:48 +0200 Subject: [PATCH 54/66] Add output signal to manifest that redundancy enabled. --- rtl/HMR/hmr_unit.sv | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index e84b944e..49ad7bf1 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -85,6 +85,7 @@ module hmr_unit #( output logic [NumDMRGroups-1:0] dmr_resynch_req_o, output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, + output logic redundancy_enable_o, // Rapid recovery buses output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, @@ -206,6 +207,8 @@ module hmr_unit #( logic [NumCores-1:0] sp_store_is_zero; logic [NumCores-1:0] sp_store_will_be_zero; + assign redundancy_enable_o = (|core_in_dmr) | (|core_in_tmr); + for (genvar i = 0; i < NumCores; i++) begin : gen_global_status assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; @@ -474,7 +477,7 @@ module hmr_unit #( assign top_register_resps[3].error = 1'b1; assign top_register_resps[3].ready = 1'b1; assign tmr_incr_mismatches = '0; - assign tmr_grp_in_independent = '0; + assign tmr_grp_in_independent = '1; assign tmr_setback_q = '0; assign tmr_resynch_req_o = '0; assign tmr_sw_synch_req_o = '0; From 3e71f0bfee96d6bdcc84e4d603c045cdb3da5ae5 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 9 Jun 2024 00:22:47 +0200 Subject: [PATCH 55/66] Pipeline in independend backup bus whem Rapid Recovery is enabled. --- rtl/HMR/hmr_unit.sv | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 49ad7bf1..39dd7e0b 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -182,7 +182,7 @@ module hmr_unit #( logic [NumBackupRegs-1:0] rapid_recovery_backup_en_inp, rapid_recovery_backup_en_oup; logic [NumBackupRegs-1:0] rapid_recovery_setback; rapid_recovery_t [NumBackupRegs-1:0] rapid_recovery_bus; - core_backup_t [NumBackupRegs-1:0] rapid_recovery_backup_bus; + core_backup_t [NumBackupRegs-1:0] rapid_recovery_backup_bus, core_backup_q; nominal_outputs_t [NumBackupRegs-1:0] rapid_recovery_nominal; /*************************** @@ -671,7 +671,6 @@ module hmr_unit #( dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; end end - end end else begin : gen_standard_failure always_comb begin dmr_failure[i] = dmr_failure_main[i] | dmr_failure_axi[i]; @@ -700,6 +699,17 @@ module hmr_unit #( end if (RapidRecovery) begin: gen_rapid_recovery_connection + + for (genvar i = 0; i < NumBackupRegs; i++) begin + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + core_backup_q[i] <= '0; + end else begin + core_backup_q[i] <= core_backup_i[i]; + end + end + end + always_comb begin rapid_recovery_nominal = '0; rapid_recovery_backup_bus = '0; @@ -708,8 +718,8 @@ module hmr_unit #( tmr_recovery_finished = '0; if (InterleaveGrps) begin for (int i = 0; i < NumBackupRegs; i++) begin - rapid_recovery_nominal[i] = core_nominal_outputs_i[i]; - rapid_recovery_backup_bus[i] = core_backup_i[i]; + rapid_recovery_nominal[i] = dmr_nominal_outputs[i]; + rapid_recovery_backup_bus[i] = core_backup_q[i]; rapid_recovery_start[i] = dmr_recovery_start[i]; dmr_recovery_finished[i] = rapid_recovery_finished[i]; end @@ -731,6 +741,7 @@ module hmr_unit #( end end end else begin + assign core_backup_q = '0; assign rapid_recovery_nominal = '0; assign rapid_recovery_start = '0; assign tmr_recovery_finished = '1; From cdb82dadd2986f095147ea2ae60e25e40569a7e3 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 9 Jun 2024 09:18:57 +0200 Subject: [PATCH 56/66] Fix always comb. --- rtl/HMR/hmr_unit.sv | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 39dd7e0b..fba709ab 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -664,11 +664,12 @@ module hmr_unit #( .debug_resume_o ( rapid_recovery_bus[i].debug_resume ) ); - always_comb begin - dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i] | dmr_failure_axi[i]; - for (int j = 0; j < NumBusVoters; j++) begin - if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin - dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; + always_comb begin + dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i] | dmr_failure_axi[i]; + for (int j = 0; j < NumBusVoters; j++) begin + if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin + dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; + end end end end else begin : gen_standard_failure From d6b13455fc8d0f66226b751fe5c2e3394f503ba1 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 19 Jun 2024 13:49:52 +0200 Subject: [PATCH 57/66] Add ACE buses to DMR checkers. --- rtl/HMR/DMR_checker.sv | 32 ++++++++++++++++++++++++++++---- rtl/HMR/hmr_unit.sv | 2 ++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/rtl/HMR/DMR_checker.sv b/rtl/HMR/DMR_checker.sv index e8695978..ec4d9ceb 100644 --- a/rtl/HMR/DMR_checker.sv +++ b/rtl/HMR/DMR_checker.sv @@ -17,7 +17,8 @@ module DMR_checker #( parameter type check_bus_t = logic, parameter int unsigned Pipeline = 0, - parameter bit AxiBus = 1'b0 + parameter bit AxiBus = 1'b0, + parameter bit AxiHasAce = 1'b0 )( input logic clk_i, input logic rst_ni, @@ -32,7 +33,7 @@ check_bus_t inp_q; logic error; if (AxiBus == 1) begin: gen_axi_checker - logic error_aw, error_w, error_ar, error_r, error_b; + logic error_aw, error_w, error_ar, error_r, error_b, error_ac, error_cr, error_cd; if (Pipeline) begin always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin @@ -47,7 +48,14 @@ if (AxiBus == 1) begin: gen_axi_checker compare.ar_valid <= inp_a_i.ar_valid ^ inp_b_i.ar_valid; compare.r_ready <= inp_a_i.r_ready ^ inp_b_i.r_ready; compare.b_ready <= inp_a_i.b_ready ^ inp_b_i.b_ready; - inp_q <= inp_a_i; + if (AxiHasAce) begin + compare.ac_ready <= inp_a_i.ac_ready ^ inp_b_i.ac_ready; + compare.cr_valid <= inp_a_i.cr_valid ^ inp_b_i.cr_valid; + compare.cr_resp <= inp_a_i.cr_resp ^ inp_b_i.cr_resp; + compare.cd_valid <= inp_a_i.cd_valid ^ inp_b_i.cd_valid; + compare.cd <= inp_a_i.cd ^ inp_b_i.cd; + end + inp_q <= inp_a_i; end end end else begin @@ -59,6 +67,13 @@ if (AxiBus == 1) begin: gen_axi_checker assign compare.ar_valid = inp_a_i.ar_valid ^ inp_b_i.ar_valid; assign compare.r_ready = inp_a_i.r_ready ^ inp_b_i.r_ready; assign compare.b_ready = inp_a_i.b_ready ^ inp_b_i.b_ready; + if (AxiHasAce) begin + assign compare.ac_ready = inp_a_i.ac_ready ^ inp_b_i.ac_ready; + assign compare.cr_valid = inp_a_i.cr_valid ^ inp_b_i.cr_valid; + assign compare.cr_resp = inp_a_i.cr_resp ^ inp_b_i.cr_resp; + assign compare.cd_valid = inp_a_i.cd_valid ^ inp_b_i.cd_valid; + assign compare.cd = inp_a_i.cd ^ inp_b_i.cd; + end assign inp_q = inp_a_i; end assign error_aw = (|compare.aw) | compare.aw_valid; @@ -66,7 +81,16 @@ if (AxiBus == 1) begin: gen_axi_checker assign error_ar = (|compare.ar) | compare.ar_valid; assign error_r = compare.r_ready; assign error_b = compare.b_ready; - assign error = error_aw | error_w | error_ar | error_r | error_b; + if (AxiHasAce) begin + assign error_ac = compare.ac_ready; + assign error_cr = (|compare.cr_resp) | compare.cr_valid; + assign error_cd = (|compare.cd) | compare.cd_valid; + end else begin + assign error_ac = '0; + assign error_cr = '0; + assign error_cd = '0; + end + assign error = error_aw | error_w | error_ar | error_r | error_b | error_ac | error_cr | error_cd; end else begin: gen_generic_checker if (Pipeline) begin always_ff @(posedge clk_i, negedge rst_ni) begin diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index fba709ab..8022fbd4 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -30,6 +30,7 @@ module hmr_unit #( parameter bit SeparateData = 1'b1, /// Separates voters and checkers for AXI buses parameter bit SeparateAxiBus = 1'b0, + parameter bit AxiHasAce = 1'b0, /// Number of separate voters/checkers for individual buses parameter int unsigned NumBusVoters = 1, /// Address width of the core register file (in RISC-V it should be always 6) @@ -584,6 +585,7 @@ module hmr_unit #( if (SeparateAxiBus) begin: gen_axi_checker DMR_checker #( .AxiBus ( SeparateAxiBus ), + .AxiHasAce ( AxiHasAce ), .check_bus_t ( axi_req_t ) ) dmr_core_checker_axi ( .clk_i ( ), From 0b18d315aa152152661e6d9b39350d6c52a10abf Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Wed, 19 Jun 2024 14:10:23 +0200 Subject: [PATCH 58/66] Drive r/b_ready signals to default 1 for helper cores when DMR is enabled. --- rtl/HMR/hmr_unit.sv | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 8022fbd4..a03d997f 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -811,6 +811,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; sys_axi_outputs_o[i] = '0; + sys_axi_outputs_o[i].r_ready = 1'b1; + sys_axi_outputs_o[i].b_ready = 1'b1; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core @@ -823,6 +825,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; sys_axi_outputs_o[i] = '0; + sys_axi_outputs_o[i].r_ready = 1'b1; + sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; @@ -884,6 +888,8 @@ module hmr_unit #( end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o [i] = '0; + sys_axi_outputs_o[i].r_ready = 1'b1; + sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; @@ -952,6 +958,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o [i] = '0; sys_axi_outputs_o [i] = '0; + sys_axi_outputs_o[i].r_ready = 1'b1; + sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; From 13e6adbdb9eace133f575c5c5e22fc812295b1b0 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 4 Aug 2025 19:31:56 +0200 Subject: [PATCH 59/66] Fix hmr_unit --- rtl/HMR/hmr_tmr_ctrl.sv | 21 ++++++++++++++++++--- rtl/HMR/hmr_unit.sv | 18 +++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 6f05db62..2e368a91 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -133,7 +133,7 @@ module hmr_tmr_ctrl #( // If error detected, do resynchronization if (tmr_single_mismatch_i) begin - $display("[HMR-triple] %t - mismatch detected", $realtime); + // $display("[HMR-triple] %t - mismatch detected", $realtime); if (tmr_error_i[0]) tmr_incr_mismatches_o[0] = 1'b1; if (tmr_error_i[1]) tmr_incr_mismatches_o[1] = 1'b1; if (tmr_error_i[2]) tmr_incr_mismatches_o[2] = 1'b1; @@ -161,7 +161,7 @@ module hmr_tmr_ctrl #( TMR_RELOAD: begin // If reload complete, finish (or reset if error happens during reload) if (sp_store_is_zero) begin - $display("[HMR-triple] %t - mismatch restored", $realtime); + // $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 && @@ -175,7 +175,7 @@ module hmr_tmr_ctrl #( TMR_RAPID: begin recovery_request_o = 1'b1; if (recovery_finished_i) begin - $display("[HMR-triple] %t - mismatch restored", $realtime); + // $display("[HMR-triple] %t - mismatch restored", $realtime); tmr_red_mode_d = TMR_RUN; end end @@ -235,4 +235,19 @@ module hmr_tmr_ctrl #( end end + `ifdef TARGET_SIMULATION + // Debug prints + always @(posedge clk_i) begin + if (tmr_red_mode_q == TMR_RUN && tmr_single_mismatch_i) begin + $display("[HMR-triple] %t - mismatch detected", $realtime); + end + if (tmr_red_mode_q == TMR_RELOAD && sp_store_is_zero) begin + $display("[HMR-triple] %t - mismatch restored", $realtime); + end + if (tmr_red_mode_q == TMR_RAPID && recovery_finished_i) begin + $display("[HMR-triple] %t - mismatch restored", $realtime); + end + end + `endif + endmodule diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index a03d997f..871043ee 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -89,8 +89,8 @@ module hmr_unit #( output logic redundancy_enable_o, // Rapid recovery buses - output rapid_recovery_t [NumSysCores-1:0] rapid_recovery_o, - input core_backup_t [NumCores-1:0] core_backup_i, + output rapid_recovery_t [NumCores-1:0] rapid_recovery_o, + input core_backup_t [NumCores-1:0] core_backup_i, // Boot address is handled apart from other signals input logic [SysDataWidth-1:0] sys_bootaddress_i, @@ -208,6 +208,10 @@ module hmr_unit #( logic [NumCores-1:0] sp_store_is_zero; logic [NumCores-1:0] sp_store_will_be_zero; + assign tmr_failure_o = |tmr_failure; + assign tmr_error_o = |tmr_error; + assign dmr_failure_o = |dmr_failure; + assign redundancy_enable_o = (|core_in_dmr) | (|core_in_tmr); for (genvar i = 0; i < NumCores; i++) begin : gen_global_status @@ -859,11 +863,11 @@ module hmr_unit #( if (i >= NumTMRCores) begin core_setback_o [i] = '0; end - if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode - core_inputs_o[i] = sys_inputs_i[SysCoreIndex]; - end else begin : independent_mode - core_inputs_o[i] = sys_inputs_i[i]; - end + end + if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode + assign core_inputs_o[i] = sys_inputs_i[SysCoreIndex]; + end else begin : independent_mode + assign core_inputs_o[i] = sys_inputs_i[i]; end end From f587298e443e94edfac0154bb56b832b19669aac Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 6 Aug 2025 17:55:56 +0200 Subject: [PATCH 60/66] hmr_unit: remove custom AXI ports --- rtl/HMR/hmr_unit.sv | 58 ++++----------------------------------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 871043ee..82cea488 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -28,9 +28,6 @@ module hmr_unit #( parameter bit RapidRecovery = 1'b0, /// Separates voters and checkers for data, which are then only checked if data request is valid parameter bit SeparateData = 1'b1, - /// Separates voters and checkers for AXI buses - parameter bit SeparateAxiBus = 1'b0, - parameter bit AxiHasAce = 1'b0, /// Number of separate voters/checkers for individual buses parameter int unsigned NumBusVoters = 1, /// Address width of the core register file (in RISC-V it should be always 6) @@ -44,8 +41,7 @@ module hmr_unit #( parameter type core_backup_t = logic, /// Bus outputs wrapping struct parameter type bus_outputs_t = logic, - /// AXI output wrapping struct - parameter type axi_req_t = logic, + /// Register bus types parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, /// Rapid recovery structure @@ -97,7 +93,6 @@ module hmr_unit #( input all_inputs_t [NumSysCores-1:0] sys_inputs_i, output nominal_outputs_t [NumSysCores-1:0] sys_nominal_outputs_o, output bus_outputs_t [NumSysCores-1:0][NumBusVoters-1:0] sys_bus_outputs_o, - output axi_req_t [NumSysCores-1:0] sys_axi_outputs_o, input logic [NumSysCores-1:0] sys_fetch_en_i, input logic [NumSysCores-1:0][NumBusVoters-1:0] enable_bus_vote_i, @@ -106,8 +101,7 @@ module hmr_unit #( output logic [NumCores-1:0] core_setback_o, output all_inputs_t [NumCores-1:0] core_inputs_o, input nominal_outputs_t [NumCores-1:0] core_nominal_outputs_i, - input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i, - input axi_req_t [NumCores-1:0] core_axi_outputs_i + input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i ); function int max(int a, int b); return (a > b) ? a : b; @@ -161,7 +155,6 @@ module hmr_unit #( nominal_outputs_t [NumDMRGroups-1:0] dmr_nominal_outputs; bus_outputs_t [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_bus_outputs; - axi_req_t [NumDMRGroups-1:0] dmr_axi_outputs; core_backup_t [NumDMRGroups-1:0] dmr_backup_outputs; logic [NumTMRGroups-1:0] tmr_failure, tmr_failure_main; @@ -170,7 +163,7 @@ module hmr_unit #( logic [NumTMRGroups-1:0][NumBusVoters-1:0][2:0] tmr_error_data; logic [NumTMRGroups-1:0] tmr_single_mismatch; - logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_axi, dmr_failure_backup; + logic [NumDMRGroups-1:0] dmr_failure, dmr_failure_main, dmr_failure_backup; logic [NumDMRGroups-1:0][NumBusVoters-1:0] dmr_failure_data; logic [NumDMRGroups-1:0][SysDataWidth-1:0] checkpoint_reg_q; @@ -586,23 +579,6 @@ module hmr_unit #( .check_o ( dmr_nominal_outputs [ i ] ), .error_o ( dmr_failure_main [ i ] ) ); - if (SeparateAxiBus) begin: gen_axi_checker - DMR_checker #( - .AxiBus ( SeparateAxiBus ), - .AxiHasAce ( AxiHasAce ), - .check_bus_t ( axi_req_t ) - ) dmr_core_checker_axi ( - .clk_i ( ), - .rst_ni ( ), - .inp_a_i ( core_axi_outputs_i[dmr_core_id(i, 0)] ), - .inp_b_i ( core_axi_outputs_i[dmr_core_id(i, 1)] ), - .check_o ( dmr_axi_outputs [ i ] ), - .error_o ( dmr_failure_axi [ i ] ) - ); - end else begin: gen_no_axi_checker - assign dmr_axi_outputs[i] = '0; - assign dmr_failure_axi[i] = '0; - end if (SeparateData) begin : gen_data_checker for (genvar j = 0; j < NumBusVoters; j++) begin DMR_checker # ( @@ -671,7 +647,7 @@ module hmr_unit #( ); always_comb begin - dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i] | dmr_failure_axi[i]; + dmr_failure[i] = dmr_failure_main[i] | dmr_failure_backup[i]; for (int j = 0; j < NumBusVoters; j++) begin if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin dmr_failure[i] = dmr_failure[i] | dmr_failure_backup[i] | dmr_failure_data[i][j]; @@ -680,7 +656,7 @@ module hmr_unit #( end end else begin : gen_standard_failure always_comb begin - dmr_failure[i] = dmr_failure_main[i] | dmr_failure_axi[i]; + dmr_failure[i] = dmr_failure_main[i]; for (int j = 0; j < NumBusVoters; j++) begin if (enable_bus_vote_i[dmr_core_id(i, 0)][j]) begin dmr_failure[i] = dmr_failure[i] | dmr_failure_data[i][j]; @@ -692,12 +668,10 @@ module hmr_unit #( end else begin: no_dmr_checkers assign dmr_failure_main = '0; assign dmr_failure_data = '0; - assign dmr_failure_axi = '0; assign dmr_failure = '0; assign dmr_incr_mismatches = '0; assign dmr_nominal_outputs = '0; assign dmr_bus_outputs = '0; - assign dmr_axi_outputs = '0; assign top_register_resps[2].rdata = '0; assign top_register_resps[2].error = 1'b1; assign top_register_resps[2].ready = 1'b1; @@ -810,32 +784,23 @@ module hmr_unit #( if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core sys_nominal_outputs_o[i] = tmr_nominal_outputs[TMRCoreIndex]; sys_bus_outputs_o[i] = tmr_bus_outputs[TMRCoreIndex]; - sys_axi_outputs_o[i] = '0; end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; - sys_axi_outputs_o[i] = '0; - sys_axi_outputs_o[i].r_ready = 1'b1; - sys_axi_outputs_o[i].b_ready = 1'b1; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core sys_nominal_outputs_o[i] = dmr_nominal_outputs[DMRCoreIndex]; - sys_axi_outputs_o[i] = dmr_axi_outputs[DMRCoreIndex]; for (int j = 0; j < NumBusVoters; j++) begin sys_bus_outputs_o[i][j] = dmr_bus_outputs[DMRCoreIndex][j]; end end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o[i] = '0; - sys_axi_outputs_o[i] = '0; - sys_axi_outputs_o[i].r_ready = 1'b1; - sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; sys_bus_outputs_o[i] = core_bus_outputs_i[i]; - sys_axi_outputs_o[i] = core_axi_outputs_i[i]; end end end @@ -876,15 +841,12 @@ module hmr_unit #( if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr assign sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; - assign sys_axi_outputs_o [i] = '0; end else begin if (i >= NumTMRCores) begin : independent_stragglers assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign sys_bus_outputs_o [i] = core_bus_outputs_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_axi_outputs_o [i] = '0; end else begin always_comb begin - sys_axi_outputs_o [i] = '0; if (core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; @@ -892,8 +854,6 @@ module hmr_unit #( end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o [i] = '0; - sys_axi_outputs_o[i].r_ready = 1'b1; - sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; @@ -945,30 +905,23 @@ module hmr_unit #( if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr assign sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; - assign sys_axi_outputs_o [i] = dmr_axi_outputs [CoreCoreIndex]; end else begin if (i >= NumDMRCores) begin : independent_stragglers assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; assign sys_bus_outputs_o [i] = core_bus_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; - assign sys_axi_outputs_o [i] = core_axi_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; end else begin always_comb begin if (core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; - sys_axi_outputs_o [i] = dmr_axi_outputs [CoreCoreIndex]; end else begin : disable_core // Assign disable sys_nominal_outputs_o[i] = '0; sys_bus_outputs_o [i] = '0; - sys_axi_outputs_o [i] = '0; - sys_axi_outputs_o[i].r_ready = 1'b1; - sys_axi_outputs_o[i].b_ready = 1'b1; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; sys_bus_outputs_o [i] = core_bus_outputs_i [i]; - sys_axi_outputs_o [i] = core_axi_outputs_i [i]; end end end @@ -985,7 +938,6 @@ module hmr_unit #( assign core_inputs_o = sys_inputs_i; assign sys_nominal_outputs_o = core_nominal_outputs_i; assign sys_bus_outputs_o = core_bus_outputs_i; - assign sys_axi_outputs_o = core_axi_outputs_i; end endmodule From 5c9cfbef629a22c0af95863e7a9f42a91b7bf5a2 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 6 Aug 2025 17:59:08 +0200 Subject: [PATCH 61/66] Add default output value parameters to allow non-zero defaults --- rtl/HMR/hmr_unit.sv | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 82cea488..02fdf7db 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -37,10 +37,12 @@ module hmr_unit #( parameter type all_inputs_t = logic, /// General core outputs wrapping struct parameter type nominal_outputs_t = logic, + parameter nominal_outputs_t DefaultNominalOutputs = '{ default: '0 }, /// Cores' backup output bus parameter type core_backup_t = logic, /// Bus outputs wrapping struct parameter type bus_outputs_t = logic, + parameter bus_outputs_t DefaultBusOutputs = '{ default: '0 }, /// Register bus types parameter type reg_req_t = logic, parameter type reg_rsp_t = logic, @@ -460,6 +462,12 @@ module hmr_unit #( .error_cba_o( tmr_error_data [ i ][j] ) ); end + end else begin : gen_no_data_voter + for (genvar j = 0; j < NumBusVoters; j++) begin + assign tmr_bus_outputs[i][j] = DefaultBusOutputs; + assign tmr_failure_data[i][j] = '0; + assign tmr_error_data[i][j] = '0; + end end end end else begin : gen_no_tmr_voted @@ -469,8 +477,8 @@ module hmr_unit #( assign tmr_failure_main = '0; assign tmr_failure_data = '0; assign tmr_failure = '0; - assign tmr_nominal_outputs = '0; - assign tmr_bus_outputs = '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; @@ -593,7 +601,7 @@ module hmr_unit #( ); end end else begin: gen_no_data_checker - assign dmr_bus_outputs [i] = '0; + assign dmr_bus_outputs [i] = DefaultBusOutputs; assign dmr_failure_data [i] = '0; end @@ -670,8 +678,8 @@ module hmr_unit #( assign dmr_failure_data = '0; assign dmr_failure = '0; assign dmr_incr_mismatches = '0; - assign dmr_nominal_outputs = '0; - assign dmr_bus_outputs = '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; @@ -785,8 +793,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = tmr_nominal_outputs[TMRCoreIndex]; sys_bus_outputs_o[i] = tmr_bus_outputs[TMRCoreIndex]; end else begin : disable_core // Assign disable - sys_nominal_outputs_o[i] = '0; - sys_bus_outputs_o[i] = '0; + sys_nominal_outputs_o[i] = DefaultNominalOutputs; + sys_bus_outputs_o[i] = DefaultBusOutputs; end end else if (i < NumDMRCores && core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core @@ -795,8 +803,8 @@ module hmr_unit #( sys_bus_outputs_o[i][j] = dmr_bus_outputs[DMRCoreIndex][j]; end end else begin : disable_core // Assign disable - sys_nominal_outputs_o[i] = '0; - sys_bus_outputs_o[i] = '0; + sys_nominal_outputs_o[i] = DefaultNominalOutputs; + sys_bus_outputs_o[i] = DefaultBusOutputs; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; @@ -852,8 +860,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; end else begin : disable_core // Assign disable - sys_nominal_outputs_o[i] = '0; - sys_bus_outputs_o [i] = '0; + sys_nominal_outputs_o[i] = DefaultNominalOutputs; + sys_bus_outputs_o [i] = DefaultBusOutputs; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; @@ -916,8 +924,8 @@ module hmr_unit #( sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; end else begin : disable_core // Assign disable - sys_nominal_outputs_o[i] = '0; - sys_bus_outputs_o [i] = '0; + sys_nominal_outputs_o[i] = DefaultNominalOutputs; + sys_bus_outputs_o [i] = DefaultBusOutputs; end end else begin : independent_mode sys_nominal_outputs_o[i] = core_nominal_outputs_i[i]; From b6a51434464483396d660a0e01371012ee68c08e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 7 Aug 2025 13:25:10 +0200 Subject: [PATCH 62/66] hmr_unit: Update doc, update status outputs --- rtl/HMR/hmr_unit.sv | 66 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 02fdf7db..51b5079d 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -24,29 +24,32 @@ module hmr_unit #( parameter bit TMRFixed = 1'b0, /// Interleave DMR/TMR cores, alternatively with sequential grouping parameter bit InterleaveGrps = 1'b1, - /// rapid recovery - tbd - parameter bit RapidRecovery = 1'b0, - /// Separates voters and checkers for data, which are then only checked if data request is valid - parameter bit SeparateData = 1'b1, - /// Number of separate voters/checkers for individual buses - parameter int unsigned NumBusVoters = 1, - /// Address width of the core register file (in RISC-V it should be always 6) - parameter int unsigned RfAddrWidth = 6, - parameter int unsigned SysDataWidth = 32, /// General core inputs wrapping struct parameter type all_inputs_t = logic, /// General core outputs wrapping struct parameter type nominal_outputs_t = logic, + /// Default nominal outputs when output ports are disabled parameter nominal_outputs_t DefaultNominalOutputs = '{ default: '0 }, - /// Cores' backup output bus - parameter type core_backup_t = logic, - /// Bus outputs wrapping struct + /// Separates voters and checkers for data, which are then only checked if data request is valid + parameter bit SeparateData = 1'b0, + /// Number of separate voters/checkers for individual buses (requires SeparateData) + parameter int unsigned NumBusVoters = 1, + /// Bus outputs wrapping struct (requires SeparateData) 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, - /// Rapid recovery structure + /// 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) + parameter int unsigned RfAddrWidth = 6, + /// System data width for boot address and checkpoint address (in RISC-V it should be generally be 32) (requires RapidRecovery) + parameter int unsigned SysDataWidth = 32, + /// Cores' backup output bus (requires RapidRecovery) + parameter type core_backup_t = logic, + /// Rapid recovery structure (requires RapidRecovery) parameter type rapid_recovery_t = logic, // Local parameters depending on the above ones /// Number of TMR groups (virtual TMR cores) @@ -67,21 +70,27 @@ module hmr_unit #( input logic clk_i , input logic rst_ni, - // Port to configuration unit + /// Port to configuration unit input reg_req_t reg_request_i , output reg_rsp_t reg_response_o, - // TMR signals + /// TMR signals + /// Indicates if the TMR group has multiple mismatches output logic [NumTMRGroups-1:0] tmr_failure_o , - output logic [ NumSysCores-1:0] tmr_error_o , // Should this not be NumTMRCores? or NumCores? - output logic [NumTMRGroups-1:0] tmr_resynch_req_o, + /// Indicates if the TMR group has a single mismatch + output logic [NumTMRGroups-1:0] tmr_error_o , + /// Resynchronization request interrupt per core, trigger software resynchronization + output logic [ NumCores-1:0] tmr_resynch_req_o, + /// Software synchronization request per core, trigger software to lock independent cores together output logic [ NumCores-1:0] tmr_sw_synch_req_o, + /// External hardware to indicate the cores are synchronized and ready to lock together input logic [NumTMRGroups-1:0] tmr_cores_synch_i, - // DMR signals + /// DMR signals + /// Indicates if the DMR group has multiple mismatches output logic [NumDMRGroups-1:0] dmr_failure_o , - output logic [ NumSysCores-1:0] dmr_error_o , // Should this not be NumDMRCores? or NumCores? - output logic [NumDMRGroups-1:0] dmr_resynch_req_o, + + output logic [ NumCores-1:0] dmr_resynch_req_o, output logic [ NumCores-1:0] dmr_sw_synch_req_o, input logic [NumDMRGroups-1:0] dmr_cores_synch_i, output logic redundancy_enable_o, @@ -342,7 +351,7 @@ module hmr_unit #( reg_req_t [NumTMRGroups-1:0] tmr_register_reqs; reg_rsp_t [NumTMRGroups-1:0] tmr_register_resps; - logic [NumTMRGroups-1:0] tmr_sw_synch_req; + logic [NumTMRGroups-1:0] tmr_sw_resynch_req, tmr_sw_synch_req; localparam TMRSelWidth = $clog2(NumTMRGroups); @@ -371,6 +380,7 @@ module hmr_unit #( for (genvar i = NumTMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign tmr_incr_mismatches[i] = '0; assign tmr_sw_synch_req_o[i] = '0; + assign tmr_resynch_req_o[i] = '0; end for (genvar i = 0; i < NumTMRGroups; i++) begin : gen_tmr_groups @@ -403,7 +413,7 @@ module hmr_unit #( .force_resynch_qe_i ( hmr_reg2hw.tmr_config.force_resynch.qe ), .setback_o ( tmr_setback_q[i] ), - .sw_resynch_req_o ( tmr_resynch_req_o[i] ), + .sw_resynch_req_o ( tmr_sw_resynch_req[i] ), .sw_synch_req_o ( tmr_sw_synch_req[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), @@ -424,6 +434,9 @@ module hmr_unit #( assign tmr_sw_synch_req_o[tmr_core_id(i, 0)] = tmr_sw_synch_req[i]; assign tmr_sw_synch_req_o[tmr_core_id(i, 1)] = tmr_sw_synch_req[i]; assign tmr_sw_synch_req_o[tmr_core_id(i, 2)] = tmr_sw_synch_req[i]; + assign tmr_resynch_req_o[tmr_core_id(i, 0)] = tmr_sw_resynch_req[i]; + assign tmr_resynch_req_o[tmr_core_id(i, 1)] = tmr_sw_resynch_req[i]; + assign tmr_resynch_req_o[tmr_core_id(i, 2)] = tmr_sw_resynch_req[i]; always_comb begin tmr_failure[i] = tmr_failure_main[i]; @@ -501,6 +514,7 @@ module hmr_unit #( reg_req_t [NumDMRGroups-1:0] dmr_register_reqs; reg_rsp_t [NumDMRGroups-1:0] dmr_register_resps; logic [NumDMRGroups-1:0] dmr_sw_synch_req; + logic [NumDMRGroups-1:0] dmr_sw_resynch_req; localparam DMRSelWidth = $clog2(NumDMRGroups); @@ -529,6 +543,7 @@ module hmr_unit #( for (genvar i = NumDMRCores; i < NumCores; i++) begin : gen_extra_core_assigns assign dmr_incr_mismatches[i] = '0; assign dmr_sw_synch_req_o[i] = '0; + assign dmr_resynch_req_o[i] = '0; end for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_dmr_groups @@ -556,7 +571,7 @@ module hmr_unit #( .force_recovery_qe_i ( hmr_reg2hw.dmr_config.force_recovery.qe ), .setback_o ( dmr_setback_q [i] ), - .sw_resynch_req_o ( dmr_resynch_req_o [i] ), + .sw_resynch_req_o ( dmr_sw_resynch_req [i] ), .sw_synch_req_o ( dmr_sw_synch_req [i] ), .checkpoint_o ( checkpoint_reg_q [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), @@ -573,6 +588,8 @@ module hmr_unit #( assign dmr_sw_synch_req_o[dmr_core_id(i, 0)] = dmr_sw_synch_req[i]; assign dmr_sw_synch_req_o[dmr_core_id(i, 1)] = dmr_sw_synch_req[i]; + assign dmr_resynch_req_o[dmr_core_id(i, 0)] = dmr_sw_resynch_req[i]; + assign dmr_resynch_req_o[dmr_core_id(i, 1)] = dmr_sw_resynch_req[i]; /********************* * DMR Core Checkers * @@ -684,6 +701,7 @@ module hmr_unit #( assign top_register_resps[2].error = 1'b1; assign top_register_resps[2].ready = 1'b1; assign dmr_sw_synch_req_o = '0; + assign dmr_resynch_req_o = '0; assign dmr_grp_in_independent = '1; end @@ -879,8 +897,6 @@ module hmr_unit #( if (DMRFixed && NumCores % 2 != 0) $warning("Extra cores added not properly handled! :)"); // Binding DMR outputs to zero for now assign dmr_failure_o = '0; - assign dmr_error_o = '0; - // assign dmr_resynch_req_o = '0; for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); From 7ebfd8449b01f38718e1a4375545094307d7ad1c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 7 Aug 2025 13:37:35 +0200 Subject: [PATCH 63/66] Update ECC correctors --- rtl/lowrisc_ecc/prim_secded_13_8_cor.sv | 16 ++-- rtl/lowrisc_ecc/prim_secded_22_16_cor.sv | 44 +++++------ rtl/lowrisc_ecc/prim_secded_28_22_cor.sv | 12 +-- rtl/lowrisc_ecc/prim_secded_39_32_cor.sv | 76 +++++++++---------- rtl/lowrisc_ecc/prim_secded_72_64_cor.sv | 32 ++++---- .../prim_secded_hamming_22_16_cor.sv | 14 ++-- .../prim_secded_hamming_39_32_cor.sv | 30 ++++---- .../prim_secded_hamming_72_64_cor.sv | 60 +++++++-------- 8 files changed, 142 insertions(+), 142 deletions(-) diff --git a/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv index b1ba2ff0..644fa91e 100644 --- a/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_13_8_cor.sv @@ -16,20 +16,20 @@ module prim_secded_13_8_cor ( // Syndrome calculation assign syndrome_o[0] = ^(d_i & 13'h016B); - assign syndrome_o[1] = ^(d_i & 13'h02F8); + assign syndrome_o[1] = ^(d_i & 13'h02AD); assign syndrome_o[2] = ^(d_i & 13'h04D5); - assign syndrome_o[3] = ^(d_i & 13'h08A7); - assign syndrome_o[4] = ^(d_i & 13'h101E); + assign syndrome_o[3] = ^(d_i & 13'h0836); + assign syndrome_o[4] = ^(d_i & 13'h10DA); // Corrected output calculation - assign d_o[0] = (syndrome_o == 5'hd) ^ d_i[0]; + assign d_o[0] = (syndrome_o == 5'h7) ^ d_i[0]; assign d_o[1] = (syndrome_o == 5'h19) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 5'h1c) ^ d_i[2]; + assign d_o[2] = (syndrome_o == 5'he) ^ d_i[2]; assign d_o[3] = (syndrome_o == 5'h13) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 5'h16) ^ d_i[4]; + assign d_o[4] = (syndrome_o == 5'h1c) ^ d_i[4]; assign d_o[5] = (syndrome_o == 5'hb) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 5'h7) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 5'he) ^ d_i[7]; + assign d_o[6] = (syndrome_o == 5'h15) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 5'h16) ^ d_i[7]; assign d_o[8] = (syndrome_o == 5'h1) ^ d_i[8]; assign d_o[9] = (syndrome_o == 5'h2) ^ d_i[9]; assign d_o[10] = (syndrome_o == 5'h4) ^ d_i[10]; diff --git a/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv index b3fd2e4e..96851a5e 100644 --- a/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_22_16_cor.sv @@ -15,30 +15,30 @@ module prim_secded_22_16_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 22'h017B48); - assign syndrome_o[1] = ^(d_i & 22'h0291AB); - assign syndrome_o[2] = ^(d_i & 22'h040E3D); - assign syndrome_o[3] = ^(d_i & 22'h087692); - assign syndrome_o[4] = ^(d_i & 22'h10A547); - assign syndrome_o[5] = ^(d_i & 22'h20C8F4); + assign syndrome_o[0] = ^(d_i & 22'h015555); + assign syndrome_o[1] = ^(d_i & 22'h02AA55); + assign syndrome_o[2] = ^(d_i & 22'h0495A9); + assign syndrome_o[3] = ^(d_i & 22'h0869A6); + assign syndrome_o[4] = ^(d_i & 22'h10669A); + assign syndrome_o[5] = ^(d_i & 22'h209A6A); // Corrected output calculation - assign d_o[0] = (syndrome_o == 6'h16) ^ d_i[0]; - assign d_o[1] = (syndrome_o == 6'h1a) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 6'h34) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 6'h2c) ^ d_i[4]; - assign d_o[5] = (syndrome_o == 6'h26) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 6'h31) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 6'h2a) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 6'h13) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 6'hd) ^ d_i[9]; - assign d_o[10] = (syndrome_o == 6'h1c) ^ d_i[10]; - assign d_o[11] = (syndrome_o == 6'h25) ^ d_i[11]; - assign d_o[12] = (syndrome_o == 6'hb) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 6'h19) ^ d_i[13]; - assign d_o[14] = (syndrome_o == 6'h29) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 6'h32) ^ d_i[15]; + assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 6'h38) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 6'hb) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 6'h34) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 6'h13) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 6'h2c) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 6'h23) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 6'h1c) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 6'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'h32) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 6'h15) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 6'h2a) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 6'h25) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 6'h1a) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 6'h19) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 6'h26) ^ d_i[15]; assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; diff --git a/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv index 12908105..d279c716 100644 --- a/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_28_22_cor.sv @@ -16,11 +16,11 @@ module prim_secded_28_22_cor ( // Syndrome calculation assign syndrome_o[0] = ^(d_i & 28'h07003FF); - assign syndrome_o[1] = ^(d_i & 28'h0A0FC0F); - assign syndrome_o[2] = ^(d_i & 28'h1171C71); + assign syndrome_o[1] = ^(d_i & 28'h0B0FC0F); + assign syndrome_o[2] = ^(d_i & 28'h1371C71); assign syndrome_o[3] = ^(d_i & 28'h23B6592); - assign syndrome_o[4] = ^(d_i & 28'h43DAAA4); - assign syndrome_o[5] = ^(d_i & 28'h83ED348); + assign syndrome_o[4] = ^(d_i & 28'h41DAAA4); + assign syndrome_o[5] = ^(d_i & 28'h82ED348); // Corrected output calculation assign d_o[0] = (syndrome_o == 6'h7) ^ d_i[0]; @@ -43,8 +43,8 @@ module prim_secded_28_22_cor ( assign d_o[17] = (syndrome_o == 6'h2c) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h34) ^ d_i[18]; assign d_o[19] = (syndrome_o == 6'h38) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 6'h3d) ^ d_i[20]; - assign d_o[21] = (syndrome_o == 6'h3b) ^ d_i[21]; + assign d_o[20] = (syndrome_o == 6'h1f) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 6'h2f) ^ d_i[21]; assign d_o[22] = (syndrome_o == 6'h1) ^ d_i[22]; assign d_o[23] = (syndrome_o == 6'h2) ^ d_i[23]; assign d_o[24] = (syndrome_o == 6'h4) ^ d_i[24]; diff --git a/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv index 725b8b61..40e6b005 100644 --- a/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_39_32_cor.sv @@ -15,47 +15,47 @@ module prim_secded_39_32_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 39'h013800CDBC); - assign syndrome_o[1] = ^(d_i & 39'h02C439C325); - assign syndrome_o[2] = ^(d_i & 39'h0452D82C63); - assign syndrome_o[3] = ^(d_i & 39'h08A4363856); - assign syndrome_o[4] = ^(d_i & 39'h109B833109); - assign syndrome_o[5] = ^(d_i & 39'h202DCF42C0); - assign syndrome_o[6] = ^(d_i & 39'h404364969A); + assign syndrome_o[0] = ^(d_i & 39'h012CA53295); + assign syndrome_o[1] = ^(d_i & 39'h0293492CA5); + assign syndrome_o[2] = ^(d_i & 39'h04552A5329); + assign syndrome_o[3] = ^(d_i & 39'h08A8D294AA); + assign syndrome_o[4] = ^(d_i & 39'h104A2CA54A); + assign syndrome_o[5] = ^(d_i & 39'h2025534952); + assign syndrome_o[6] = ^(d_i & 39'h40D294CA54); // Corrected output calculation - assign d_o[0] = (syndrome_o == 7'h16) ^ d_i[0]; - assign d_o[1] = (syndrome_o == 7'h4c) ^ d_i[1]; - assign d_o[2] = (syndrome_o == 7'hb) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 7'h51) ^ d_i[3]; - assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; - assign d_o[5] = (syndrome_o == 7'h7) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 7'h2c) ^ d_i[6]; - assign d_o[7] = (syndrome_o == 7'h61) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 7'h13) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 7'h62) ^ d_i[9]; - assign d_o[10] = (syndrome_o == 7'h45) ^ d_i[10]; - assign d_o[11] = (syndrome_o == 7'hd) ^ d_i[11]; - assign d_o[12] = (syndrome_o == 7'h58) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 7'h1c) ^ d_i[13]; - assign d_o[14] = (syndrome_o == 7'h23) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 7'h43) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 7'h32) ^ d_i[16]; - assign d_o[17] = (syndrome_o == 7'h38) ^ d_i[17]; - assign d_o[18] = (syndrome_o == 7'h68) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 7'h26) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 7'he) ^ d_i[20]; - assign d_o[21] = (syndrome_o == 7'h4a) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 7'h64) ^ d_i[22]; - assign d_o[23] = (syndrome_o == 7'h34) ^ d_i[23]; - assign d_o[24] = (syndrome_o == 7'h70) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 7'h54) ^ d_i[25]; - assign d_o[26] = (syndrome_o == 7'h2a) ^ d_i[26]; - assign d_o[27] = (syndrome_o == 7'h31) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 7'h15) ^ d_i[28]; + assign d_o[0] = (syndrome_o == 7'h7) ^ d_i[0]; + assign d_o[1] = (syndrome_o == 7'h38) ^ d_i[1]; + assign d_o[2] = (syndrome_o == 7'h43) ^ d_i[2]; + assign d_o[3] = (syndrome_o == 7'h1c) ^ d_i[3]; + assign d_o[4] = (syndrome_o == 7'h61) ^ d_i[4]; + assign d_o[5] = (syndrome_o == 7'he) ^ d_i[5]; + assign d_o[6] = (syndrome_o == 7'h70) ^ d_i[6]; + assign d_o[7] = (syndrome_o == 7'hb) ^ d_i[7]; + assign d_o[8] = (syndrome_o == 7'h34) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'h45) ^ d_i[9]; + assign d_o[10] = (syndrome_o == 7'h1a) ^ d_i[10]; + assign d_o[11] = (syndrome_o == 7'h62) ^ d_i[11]; + assign d_o[12] = (syndrome_o == 7'hd) ^ d_i[12]; + assign d_o[13] = (syndrome_o == 7'h13) ^ d_i[13]; + assign d_o[14] = (syndrome_o == 7'h64) ^ d_i[14]; + assign d_o[15] = (syndrome_o == 7'h58) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h23) ^ d_i[16]; + assign d_o[17] = (syndrome_o == 7'h2c) ^ d_i[17]; + assign d_o[18] = (syndrome_o == 7'h51) ^ d_i[18]; + assign d_o[19] = (syndrome_o == 7'h16) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'h68) ^ d_i[20]; + assign d_o[21] = (syndrome_o == 7'h15) ^ d_i[21]; + assign d_o[22] = (syndrome_o == 7'h2a) ^ d_i[22]; + assign d_o[23] = (syndrome_o == 7'h49) ^ d_i[23]; + assign d_o[24] = (syndrome_o == 7'h26) ^ d_i[24]; + assign d_o[25] = (syndrome_o == 7'h52) ^ d_i[25]; + assign d_o[26] = (syndrome_o == 7'h25) ^ d_i[26]; + assign d_o[27] = (syndrome_o == 7'h19) ^ d_i[27]; + assign d_o[28] = (syndrome_o == 7'h46) ^ d_i[28]; assign d_o[29] = (syndrome_o == 7'h29) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 7'h46) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 7'h1a) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 7'h54) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h4a) ^ d_i[31]; assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; diff --git a/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv index 72c85cf4..c1a8d3ea 100644 --- a/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_72_64_cor.sv @@ -15,14 +15,14 @@ module prim_secded_72_64_cor ( logic single_error; // Syndrome calculation - assign syndrome_o[0] = ^(d_i & 72'h01F8000000001FFFFF); - assign syndrome_o[1] = ^(d_i & 72'h029D00000FFFE0003F); - assign syndrome_o[2] = ^(d_i & 72'h048F003FF003E007C1); - assign syndrome_o[3] = ^(d_i & 72'h08F10FC0F03C207842); - assign syndrome_o[4] = ^(d_i & 72'h106E71C711C4438884); - assign syndrome_o[5] = ^(d_i & 72'h203EB65926488C9108); - assign syndrome_o[6] = ^(d_i & 72'h40D3DAAA4A91152210); - assign syndrome_o[7] = ^(d_i & 72'h8067ED348D221A4420); + assign syndrome_o[0] = ^(d_i & 72'h015B000000001FFFFF); + assign syndrome_o[1] = ^(d_i & 72'h026B00000FFFE0003F); + assign syndrome_o[2] = ^(d_i & 72'h046D003FF003E007C1); + assign syndrome_o[3] = ^(d_i & 72'h08AD0FC0F03C207842); + assign syndrome_o[4] = ^(d_i & 72'h10B571C711C4438884); + assign syndrome_o[5] = ^(d_i & 72'h20B6B65926488C9108); + assign syndrome_o[6] = ^(d_i & 72'h40D6DAAA4A91152210); + assign syndrome_o[7] = ^(d_i & 72'h80DAED348D221A4420); // Corrected output calculation assign d_o[0] = (syndrome_o == 8'h7) ^ d_i[0]; @@ -81,14 +81,14 @@ module prim_secded_72_64_cor ( assign d_o[53] = (syndrome_o == 8'hb0) ^ d_i[53]; assign d_o[54] = (syndrome_o == 8'hd0) ^ d_i[54]; assign d_o[55] = (syndrome_o == 8'he0) ^ d_i[55]; - assign d_o[56] = (syndrome_o == 8'hce) ^ d_i[56]; - assign d_o[57] = (syndrome_o == 8'hf4) ^ d_i[57]; - assign d_o[58] = (syndrome_o == 8'hb6) ^ d_i[58]; - assign d_o[59] = (syndrome_o == 8'h37) ^ d_i[59]; - assign d_o[60] = (syndrome_o == 8'h6b) ^ d_i[60]; - assign d_o[61] = (syndrome_o == 8'hb9) ^ d_i[61]; - assign d_o[62] = (syndrome_o == 8'hd9) ^ d_i[62]; - assign d_o[63] = (syndrome_o == 8'h4f) ^ d_i[63]; + assign d_o[56] = (syndrome_o == 8'h1f) ^ d_i[56]; + assign d_o[57] = (syndrome_o == 8'he3) ^ d_i[57]; + assign d_o[58] = (syndrome_o == 8'h7c) ^ d_i[58]; + assign d_o[59] = (syndrome_o == 8'h8f) ^ d_i[59]; + assign d_o[60] = (syndrome_o == 8'hf1) ^ d_i[60]; + assign d_o[61] = (syndrome_o == 8'h3e) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'hc7) ^ d_i[62]; + assign d_o[63] = (syndrome_o == 8'hf8) ^ d_i[63]; assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; assign d_o[66] = (syndrome_o == 8'h4) ^ d_i[66]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv index e9f47371..249a9e7f 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_22_16_cor.sv @@ -19,25 +19,25 @@ module prim_secded_hamming_22_16_cor ( assign syndrome_o[2] = ^(d_i & 22'h04C78E); assign syndrome_o[3] = ^(d_i & 22'h0807F0); assign syndrome_o[4] = ^(d_i & 22'h10F800); - assign syndrome_o[5] = ^(d_i & 22'h3FFFFF); + assign syndrome_o[5] = ^(d_i & 22'h205CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 6'h23) ^ d_i[0]; assign d_o[1] = (syndrome_o == 6'h25) ^ d_i[1]; assign d_o[2] = (syndrome_o == 6'h26) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 6'h27) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 6'h7) ^ d_i[3]; assign d_o[4] = (syndrome_o == 6'h29) ^ d_i[4]; assign d_o[5] = (syndrome_o == 6'h2a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 6'h2b) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 6'hb) ^ d_i[6]; assign d_o[7] = (syndrome_o == 6'h2c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 6'h2d) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 6'h2e) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 6'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 6'he) ^ d_i[9]; assign d_o[10] = (syndrome_o == 6'h2f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 6'h31) ^ d_i[11]; assign d_o[12] = (syndrome_o == 6'h32) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 6'h33) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 6'h13) ^ d_i[13]; assign d_o[14] = (syndrome_o == 6'h34) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 6'h35) ^ d_i[15]; + assign d_o[15] = (syndrome_o == 6'h15) ^ d_i[15]; assign d_o[16] = (syndrome_o == 6'h1) ^ d_i[16]; assign d_o[17] = (syndrome_o == 6'h2) ^ d_i[17]; assign d_o[18] = (syndrome_o == 6'h4) ^ d_i[18]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv index 2918c058..c861663c 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_39_32_cor.sv @@ -20,41 +20,41 @@ module prim_secded_hamming_39_32_cor ( assign syndrome_o[3] = ^(d_i & 39'h0803FC07F0); assign syndrome_o[4] = ^(d_i & 39'h1003FFF800); assign syndrome_o[5] = ^(d_i & 39'h20FC000000); - assign syndrome_o[6] = ^(d_i & 39'h7FFFFFFFFF); + assign syndrome_o[6] = ^(d_i & 39'h402DA65CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 7'h43) ^ d_i[0]; assign d_o[1] = (syndrome_o == 7'h45) ^ d_i[1]; assign d_o[2] = (syndrome_o == 7'h46) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 7'h47) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 7'h7) ^ d_i[3]; assign d_o[4] = (syndrome_o == 7'h49) ^ d_i[4]; assign d_o[5] = (syndrome_o == 7'h4a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 7'h4b) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 7'hb) ^ d_i[6]; assign d_o[7] = (syndrome_o == 7'h4c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 7'h4d) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 7'h4e) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 7'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 7'he) ^ d_i[9]; assign d_o[10] = (syndrome_o == 7'h4f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 7'h51) ^ d_i[11]; assign d_o[12] = (syndrome_o == 7'h52) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 7'h53) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 7'h13) ^ d_i[13]; assign d_o[14] = (syndrome_o == 7'h54) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 7'h55) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 7'h56) ^ d_i[16]; + assign d_o[15] = (syndrome_o == 7'h15) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 7'h16) ^ d_i[16]; assign d_o[17] = (syndrome_o == 7'h57) ^ d_i[17]; assign d_o[18] = (syndrome_o == 7'h58) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 7'h59) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 7'h5a) ^ d_i[20]; + assign d_o[19] = (syndrome_o == 7'h19) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 7'h1a) ^ d_i[20]; assign d_o[21] = (syndrome_o == 7'h5b) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 7'h5c) ^ d_i[22]; + assign d_o[22] = (syndrome_o == 7'h1c) ^ d_i[22]; assign d_o[23] = (syndrome_o == 7'h5d) ^ d_i[23]; assign d_o[24] = (syndrome_o == 7'h5e) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 7'h5f) ^ d_i[25]; + assign d_o[25] = (syndrome_o == 7'h1f) ^ d_i[25]; assign d_o[26] = (syndrome_o == 7'h61) ^ d_i[26]; assign d_o[27] = (syndrome_o == 7'h62) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 7'h63) ^ d_i[28]; + assign d_o[28] = (syndrome_o == 7'h23) ^ d_i[28]; assign d_o[29] = (syndrome_o == 7'h64) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 7'h65) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 7'h66) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 7'h25) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 7'h26) ^ d_i[31]; assign d_o[32] = (syndrome_o == 7'h1) ^ d_i[32]; assign d_o[33] = (syndrome_o == 7'h2) ^ d_i[33]; assign d_o[34] = (syndrome_o == 7'h4) ^ d_i[34]; diff --git a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv index e8f2e854..896f97ac 100644 --- a/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv +++ b/rtl/lowrisc_ecc/prim_secded_hamming_72_64_cor.sv @@ -21,72 +21,72 @@ module prim_secded_hamming_72_64_cor ( assign syndrome_o[4] = ^(d_i & 72'h1001FFFE0003FFF800); assign syndrome_o[5] = ^(d_i & 72'h2001FFFFFFFC000000); assign syndrome_o[6] = ^(d_i & 72'h40FE00000000000000); - assign syndrome_o[7] = ^(d_i & 72'hFFFFFFFFFFFFFFFFFF); + assign syndrome_o[7] = ^(d_i & 72'h80972CD2D32DA65CB7); // Corrected output calculation assign d_o[0] = (syndrome_o == 8'h83) ^ d_i[0]; assign d_o[1] = (syndrome_o == 8'h85) ^ d_i[1]; assign d_o[2] = (syndrome_o == 8'h86) ^ d_i[2]; - assign d_o[3] = (syndrome_o == 8'h87) ^ d_i[3]; + assign d_o[3] = (syndrome_o == 8'h7) ^ d_i[3]; assign d_o[4] = (syndrome_o == 8'h89) ^ d_i[4]; assign d_o[5] = (syndrome_o == 8'h8a) ^ d_i[5]; - assign d_o[6] = (syndrome_o == 8'h8b) ^ d_i[6]; + assign d_o[6] = (syndrome_o == 8'hb) ^ d_i[6]; assign d_o[7] = (syndrome_o == 8'h8c) ^ d_i[7]; - assign d_o[8] = (syndrome_o == 8'h8d) ^ d_i[8]; - assign d_o[9] = (syndrome_o == 8'h8e) ^ d_i[9]; + assign d_o[8] = (syndrome_o == 8'hd) ^ d_i[8]; + assign d_o[9] = (syndrome_o == 8'he) ^ d_i[9]; assign d_o[10] = (syndrome_o == 8'h8f) ^ d_i[10]; assign d_o[11] = (syndrome_o == 8'h91) ^ d_i[11]; assign d_o[12] = (syndrome_o == 8'h92) ^ d_i[12]; - assign d_o[13] = (syndrome_o == 8'h93) ^ d_i[13]; + assign d_o[13] = (syndrome_o == 8'h13) ^ d_i[13]; assign d_o[14] = (syndrome_o == 8'h94) ^ d_i[14]; - assign d_o[15] = (syndrome_o == 8'h95) ^ d_i[15]; - assign d_o[16] = (syndrome_o == 8'h96) ^ d_i[16]; + assign d_o[15] = (syndrome_o == 8'h15) ^ d_i[15]; + assign d_o[16] = (syndrome_o == 8'h16) ^ d_i[16]; assign d_o[17] = (syndrome_o == 8'h97) ^ d_i[17]; assign d_o[18] = (syndrome_o == 8'h98) ^ d_i[18]; - assign d_o[19] = (syndrome_o == 8'h99) ^ d_i[19]; - assign d_o[20] = (syndrome_o == 8'h9a) ^ d_i[20]; + assign d_o[19] = (syndrome_o == 8'h19) ^ d_i[19]; + assign d_o[20] = (syndrome_o == 8'h1a) ^ d_i[20]; assign d_o[21] = (syndrome_o == 8'h9b) ^ d_i[21]; - assign d_o[22] = (syndrome_o == 8'h9c) ^ d_i[22]; + assign d_o[22] = (syndrome_o == 8'h1c) ^ d_i[22]; assign d_o[23] = (syndrome_o == 8'h9d) ^ d_i[23]; assign d_o[24] = (syndrome_o == 8'h9e) ^ d_i[24]; - assign d_o[25] = (syndrome_o == 8'h9f) ^ d_i[25]; + assign d_o[25] = (syndrome_o == 8'h1f) ^ d_i[25]; assign d_o[26] = (syndrome_o == 8'ha1) ^ d_i[26]; assign d_o[27] = (syndrome_o == 8'ha2) ^ d_i[27]; - assign d_o[28] = (syndrome_o == 8'ha3) ^ d_i[28]; + assign d_o[28] = (syndrome_o == 8'h23) ^ d_i[28]; assign d_o[29] = (syndrome_o == 8'ha4) ^ d_i[29]; - assign d_o[30] = (syndrome_o == 8'ha5) ^ d_i[30]; - assign d_o[31] = (syndrome_o == 8'ha6) ^ d_i[31]; + assign d_o[30] = (syndrome_o == 8'h25) ^ d_i[30]; + assign d_o[31] = (syndrome_o == 8'h26) ^ d_i[31]; assign d_o[32] = (syndrome_o == 8'ha7) ^ d_i[32]; assign d_o[33] = (syndrome_o == 8'ha8) ^ d_i[33]; - assign d_o[34] = (syndrome_o == 8'ha9) ^ d_i[34]; - assign d_o[35] = (syndrome_o == 8'haa) ^ d_i[35]; + assign d_o[34] = (syndrome_o == 8'h29) ^ d_i[34]; + assign d_o[35] = (syndrome_o == 8'h2a) ^ d_i[35]; assign d_o[36] = (syndrome_o == 8'hab) ^ d_i[36]; - assign d_o[37] = (syndrome_o == 8'hac) ^ d_i[37]; + assign d_o[37] = (syndrome_o == 8'h2c) ^ d_i[37]; assign d_o[38] = (syndrome_o == 8'had) ^ d_i[38]; assign d_o[39] = (syndrome_o == 8'hae) ^ d_i[39]; - assign d_o[40] = (syndrome_o == 8'haf) ^ d_i[40]; + assign d_o[40] = (syndrome_o == 8'h2f) ^ d_i[40]; assign d_o[41] = (syndrome_o == 8'hb0) ^ d_i[41]; - assign d_o[42] = (syndrome_o == 8'hb1) ^ d_i[42]; - assign d_o[43] = (syndrome_o == 8'hb2) ^ d_i[43]; + assign d_o[42] = (syndrome_o == 8'h31) ^ d_i[42]; + assign d_o[43] = (syndrome_o == 8'h32) ^ d_i[43]; assign d_o[44] = (syndrome_o == 8'hb3) ^ d_i[44]; - assign d_o[45] = (syndrome_o == 8'hb4) ^ d_i[45]; + assign d_o[45] = (syndrome_o == 8'h34) ^ d_i[45]; assign d_o[46] = (syndrome_o == 8'hb5) ^ d_i[46]; assign d_o[47] = (syndrome_o == 8'hb6) ^ d_i[47]; - assign d_o[48] = (syndrome_o == 8'hb7) ^ d_i[48]; - assign d_o[49] = (syndrome_o == 8'hb8) ^ d_i[49]; + assign d_o[48] = (syndrome_o == 8'h37) ^ d_i[48]; + assign d_o[49] = (syndrome_o == 8'h38) ^ d_i[49]; assign d_o[50] = (syndrome_o == 8'hb9) ^ d_i[50]; assign d_o[51] = (syndrome_o == 8'hba) ^ d_i[51]; - assign d_o[52] = (syndrome_o == 8'hbb) ^ d_i[52]; + assign d_o[52] = (syndrome_o == 8'h3b) ^ d_i[52]; assign d_o[53] = (syndrome_o == 8'hbc) ^ d_i[53]; - assign d_o[54] = (syndrome_o == 8'hbd) ^ d_i[54]; - assign d_o[55] = (syndrome_o == 8'hbe) ^ d_i[55]; + assign d_o[54] = (syndrome_o == 8'h3d) ^ d_i[54]; + assign d_o[55] = (syndrome_o == 8'h3e) ^ d_i[55]; assign d_o[56] = (syndrome_o == 8'hbf) ^ d_i[56]; assign d_o[57] = (syndrome_o == 8'hc1) ^ d_i[57]; assign d_o[58] = (syndrome_o == 8'hc2) ^ d_i[58]; - assign d_o[59] = (syndrome_o == 8'hc3) ^ d_i[59]; + assign d_o[59] = (syndrome_o == 8'h43) ^ d_i[59]; assign d_o[60] = (syndrome_o == 8'hc4) ^ d_i[60]; - assign d_o[61] = (syndrome_o == 8'hc5) ^ d_i[61]; - assign d_o[62] = (syndrome_o == 8'hc6) ^ d_i[62]; + assign d_o[61] = (syndrome_o == 8'h45) ^ d_i[61]; + assign d_o[62] = (syndrome_o == 8'h46) ^ d_i[62]; assign d_o[63] = (syndrome_o == 8'hc7) ^ d_i[63]; assign d_o[64] = (syndrome_o == 8'h1) ^ d_i[64]; assign d_o[65] = (syndrome_o == 8'h2) ^ d_i[65]; From c41bfbe7ca8eb7340851dac97cc4e557311b44d5 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 7 Aug 2025 14:39:42 +0200 Subject: [PATCH 64/66] Fix lint --- .github/waiver.verible | 1 + .github/workflows/ci.yml | 8 + rtl/HMR/DMR_CSR_checker.sv | 4 +- rtl/HMR/DMR_address_generator.sv | 10 +- rtl/HMR/DMR_checker.sv | 18 +- rtl/HMR/DMR_controller.sv | 27 +-- rtl/HMR/HMR_wrap.sv | 329 +++++++++++++++++------------ rtl/HMR/hmr_dmr_ctrl.sv | 4 +- rtl/HMR/hmr_rapid_recovery_ctrl.sv | 3 + rtl/HMR/hmr_tmr_ctrl.sv | 3 +- rtl/HMR/hmr_unit.sv | 161 ++++++++------ rtl/HMR/rapid_recovery_pkg.sv | 4 +- rtl/HMR/rapid_recovery_unit.sv | 4 +- rtl/HMR/recovery_csr.sv | 4 +- rtl/HMR/recovery_pc.sv | 4 +- rtl/HMR/recovery_rf.sv | 26 +-- rtl/HMR/recovery_rf_latch.sv | 30 +-- rtl/HMR/resp_suppress.sv | 4 +- rtl/ecc_wrap/ecc_sram_wrap.sv | 4 +- 19 files changed, 380 insertions(+), 268 deletions(-) diff --git a/.github/waiver.verible b/.github/waiver.verible index 4729585f..d8852ab1 100644 --- a/.github/waiver.verible +++ b/.github/waiver.verible @@ -3,3 +3,4 @@ # SPDX-License-Identifier: SHL-0.51 waive --rule=explicit-parameter-storage-type --location="./rtl/ecc_wrap/ecc_sram.sv" +waive --rule=module-filename --location="./rtl/HMR/recovery_rf_latch.sv" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52ed8c37..043732ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,14 @@ jobs: ./rtl/ecc_wrap/ecc_manager_reg_top.sv ./rtl/ODRG_unit/odrg_manager_reg_pkg.sv ./rtl/ODRG_unit/odrg_manager_reg_top.sv + ./rtl/HMR/hmr_core_regs_reg_pkg.sv + ./rtl/HMR/hmr_core_regs_reg_top.sv + ./rtl/HMR/hmr_dmr_regs_reg_pkg.sv + ./rtl/HMR/hmr_dmr_regs_reg_top.sv + ./rtl/HMR/hmr_registers_reg_pkg.sv + ./rtl/HMR/hmr_registers_reg_top.sv + ./rtl/HMR/hmr_tmr_regs_reg_pkg.sv + ./rtl/HMR/hmr_tmr_regs_reg_top.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/rtl/HMR/DMR_CSR_checker.sv b/rtl/HMR/DMR_CSR_checker.sv index c883b18d..cb30c2ee 100644 --- a/rtl/HMR/DMR_CSR_checker.sv +++ b/rtl/HMR/DMR_CSR_checker.sv @@ -7,9 +7,9 @@ * 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. - * + * * CS Registers Checker - * + * */ module DMR_CSR_checker diff --git a/rtl/HMR/DMR_address_generator.sv b/rtl/HMR/DMR_address_generator.sv index e832de28..255d1366 100644 --- a/rtl/HMR/DMR_address_generator.sv +++ b/rtl/HMR/DMR_address_generator.sv @@ -7,14 +7,14 @@ * 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. - * + * * Dual Modular Address Generator - * Generates addresses for RF refill - * + * Generates addresses for RF refill + * */ module DMR_address_generator #( - parameter AddrWidth = 5 + parameter int unsigned AddrWidth = 5 )( input logic clk_i , input logic rst_ni , @@ -35,7 +35,7 @@ logic [NumVotingSignals-1:0] addr_count_rst; logic [ArrayWidth-1:0][AddrWidth-1:0] addr_count; generate - for (genvar i = 0; i < NumVotingSignals; i++) begin + for (genvar i = 0; i < NumVotingSignals; i++) begin : gen_addr_ffs always_ff @(posedge clk_i, negedge rst_ni) begin : address_generator_counter if (~rst_ni) addr_count [i] <= '1; diff --git a/rtl/HMR/DMR_checker.sv b/rtl/HMR/DMR_checker.sv index ec4d9ceb..d7a049af 100644 --- a/rtl/HMR/DMR_checker.sv +++ b/rtl/HMR/DMR_checker.sv @@ -7,11 +7,11 @@ * 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. - * + * * Dual Modular Redundancy Checker * Compares the outputs generated by two IPs and returns error signals * in case of mismatch - * + * */ module DMR_checker #( @@ -34,7 +34,7 @@ logic error; if (AxiBus == 1) begin: gen_axi_checker logic error_aw, error_w, error_ar, error_r, error_b, error_ac, error_cr, error_cd; - if (Pipeline) begin + if (Pipeline) begin : gen_pipelined_checker always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin compare <= '0; @@ -58,7 +58,7 @@ if (AxiBus == 1) begin: gen_axi_checker inp_q <= inp_a_i; end end - end else begin + end else begin : gen_combined_checker assign compare.aw = inp_a_i.aw ^ inp_b_i.aw; assign compare.aw_valid = inp_a_i.aw_valid ^ inp_b_i.aw_valid; assign compare.w = inp_a_i.w ^ inp_b_i.w; @@ -67,7 +67,7 @@ if (AxiBus == 1) begin: gen_axi_checker assign compare.ar_valid = inp_a_i.ar_valid ^ inp_b_i.ar_valid; assign compare.r_ready = inp_a_i.r_ready ^ inp_b_i.r_ready; assign compare.b_ready = inp_a_i.b_ready ^ inp_b_i.b_ready; - if (AxiHasAce) begin + if (AxiHasAce) begin : gen_ace_signalling assign compare.ac_ready = inp_a_i.ac_ready ^ inp_b_i.ac_ready; assign compare.cr_valid = inp_a_i.cr_valid ^ inp_b_i.cr_valid; assign compare.cr_resp = inp_a_i.cr_resp ^ inp_b_i.cr_resp; @@ -81,18 +81,18 @@ if (AxiBus == 1) begin: gen_axi_checker assign error_ar = (|compare.ar) | compare.ar_valid; assign error_r = compare.r_ready; assign error_b = compare.b_ready; - if (AxiHasAce) begin + if (AxiHasAce) begin : gen_ace_error_signalling assign error_ac = compare.ac_ready; assign error_cr = (|compare.cr_resp) | compare.cr_valid; assign error_cd = (|compare.cd) | compare.cd_valid; - end else begin + end else begin : gen_no_ace_signalling assign error_ac = '0; assign error_cr = '0; assign error_cd = '0; end assign error = error_aw | error_w | error_ar | error_r | error_b | error_ac | error_cr | error_cd; end else begin: gen_generic_checker - if (Pipeline) begin + if (Pipeline) begin : gen_pipelined_checker always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin compare <= '0; @@ -102,7 +102,7 @@ end else begin: gen_generic_checker inp_q <= inp_a_i; end end - end else begin + end else begin : gen_combined_checker assign compare = inp_a_i ^ inp_b_i; assign inp_q = inp_a_i; end diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index 9272a769..004f113f 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -7,10 +7,10 @@ * 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. - * + * * Dual Modular Redundancy Controller - * Handles the occurrence of errors and starts recovery routine - * + * Handles the occurrence of errors and starts recovery routine + * */ module DMR_controller @@ -123,7 +123,7 @@ end * Routine start signal. * Checks if there are any errors from external checkers to start the FSM Recovery Routine. */ -assign routine_start = (|dmr_rf_checker_error_port_a_i) | +assign routine_start = (|dmr_rf_checker_error_port_a_i) | (|dmr_rf_checker_error_port_a_i) | (|dmr_core_checker_error_main_i) | (|dmr_core_checker_error_data_i) ; @@ -153,7 +153,7 @@ end * inexistent instruction requests towards iCache while the cores are in debug mode (halted). */ generate - for (genvar i = 0; i < NumDMRGroups; i++) begin + for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_core_instr_lock always_ff @(posedge clk_i, negedge rst_ni) begin : instruction_lock_registers if (~rst_ni) begin dmr_ctrl_core_instr_lock_q [i] <= 1'b0; @@ -172,7 +172,7 @@ endgenerate * Clock gate the cores that do not need to recover during the recovery routine. */ generate - for (genvar i = 0; i < NumDMRGroups; i++) begin + for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_clk_en always_ff @(posedge clk_i, negedge rst_ni) begin : core_clock_enable if (~rst_ni) begin dmr_ctrl_core_clk_en_q [i] <= 1'b1; @@ -192,7 +192,7 @@ endgenerate * allow their register files to be reloaded with the RRF content. */ generate - for (genvar i = 0; i < NumDMRGroups; i++) begin + for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_core_recover always_ff @(posedge clk_i, negedge rst_ni) begin : core_recover_registers if (~rst_ni) begin dmr_ctrl_core_recover_q [i] <= 1'b0; @@ -212,7 +212,7 @@ endgenerate * from sampling new values from the cores. */ generate - for (genvar i = 0; i < NumDMRGroups; i++) begin + for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_pc_write_enable always_ff @(posedge clk_i, negedge rst_ni) begin : program_counter_write_enable if (~rst_ni) begin dmr_ctrl_pc_write_enable_q [i] <= 1'b1; @@ -310,7 +310,7 @@ always_comb begin : recovery_routine_fsm end else next = current; end - + RESET: begin dmr_ctrl_core_setback_out [error_index_q] = 1'b1; dmr_ctrl_core_instr_lock_d [error_index_q] = 1'b1; @@ -321,7 +321,7 @@ always_comb begin : recovery_routine_fsm end next = HALT_REQ; end - + HALT_REQ: begin dmr_ctrl_core_debug_req_out [error_index_q] = 1'b1; next = HALT_WAIT; @@ -343,7 +343,7 @@ always_comb begin : recovery_routine_fsm end else next = current; end - + RESTORE_RF: begin dmr_ctrl_core_recover_d [error_index_q] = 1'b1; addr_gen_start = 1'b1; @@ -354,7 +354,7 @@ always_comb begin : recovery_routine_fsm end else next = current; end - + RESTORE_CSR: begin end @@ -362,6 +362,9 @@ always_comb begin : recovery_routine_fsm clear = 1'b1; next = IDLE; end + + // Default: do nothing + default: ; endcase end : recovery_routine_fsm diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index ac19fb4a..75e7dda8 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -51,7 +51,8 @@ module HMR_wrap /// Number of physical cores NOT used for DMR localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, /// Number of cores visible to the system (Fixed mode removes unneeded system ports) - localparam int unsigned NumSysCores = DMRFixed ? NumDMRCores : TMRFixed ? NumTMRCores : NumCores + localparam int unsigned NumSysCores = DMRFixed ? NumDMRCores : + TMRFixed ? NumTMRCores : NumCores ) ( input logic clk_i , input logic rst_ni, @@ -130,7 +131,7 @@ module HMR_wrap input logic [NumSysCores-1:0][ UserWidth-1:0] sys_data_r_user_i , input logic [NumSysCores-1:0] sys_data_r_valid_i , input logic [NumSysCores-1:0] sys_data_err_i , - + input logic [NumSysCores-1:0][NumExtPerf-1:0] sys_perf_counters_i, // Ports connecting to the cores @@ -174,47 +175,47 @@ module HMR_wrap // APU/SHARED_FPU not implemented ); - function int max(int a, int b); + function automatic int max(int a, int b); return (a > b) ? a : b; endfunction localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); - function int tmr_group_id (int core_id); + function automatic int tmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumTMRGroups; else return (core_id/3); endfunction - function int tmr_core_id (int group_id, int core_offset); + function automatic int tmr_core_id (int group_id, int core_offset); if (InterleaveGrps) return group_id + core_offset * NumTMRGroups; else return (group_id * 3) + core_offset; endfunction - function int tmr_shared_id (int group_id); + function automatic int tmr_shared_id (int group_id); if (InterleaveGrps || !(DMRSupported || DMRFixed)) return group_id; else return group_id + group_id/2; endfunction - function int tmr_offset_id (int core_id); + function automatic int tmr_offset_id (int core_id); if (InterleaveGrps) return core_id / NumTMRGroups; else return core_id % 3; endfunction - function int dmr_group_id (int core_id); + function automatic int dmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumDMRGroups; else return (core_id/2); endfunction - function int dmr_core_id (int group_id, int core_offset); + function automatic int dmr_core_id (int group_id, int core_offset); if (InterleaveGrps) return group_id + core_offset * NumDMRGroups; else return (group_id * 2) + core_offset; endfunction - function int dmr_shared_id (int group_id); + function automatic int dmr_shared_id (int group_id); return group_id; endfunction - function int dmr_offset_id (int core_id); + function automatic int dmr_offset_id (int core_id); if (InterleaveGrps) return core_id / NumDMRGroups; else return core_id % 2; endfunction @@ -296,7 +297,7 @@ module HMR_wrap tmr_backup_regfile_we_a, tmr_backup_regfile_we_b, tmr_recovery_finished; - + logic [NumBackupRegfiles-1:0][RFAddrWidth-1:0] backup_regfile_waddr_a, backup_regfile_waddr_b; logic [NumBackupRegfiles-1:0][ DataWidth-1:0] backup_branch_addr_int, @@ -326,7 +327,8 @@ module HMR_wrap regfile_raddr_t [NumBackupRegfiles-1:0] core_regfile_raddr_out; regfile_rdata_t [NumBackupRegfiles-1:0] core_recovery_regfile_rdata_out; regfile_write_t [NumBackupRegfiles-1:0] core_recovery_regfile_wport_out; - csrs_intf_t [NumBackupRegfiles-1:0] backup_csr_int, dmr_backup_csr, tmr_backup_csr, recovery_csr_out; + csrs_intf_t [NumBackupRegfiles-1:0] backup_csr_int, dmr_backup_csr, + tmr_backup_csr, recovery_csr_out; for (genvar i = 0; i < NumCores; i++) begin : gen_concat if (SeparateData) begin : gen_separate_data @@ -352,8 +354,9 @@ module HMR_wrap core_data_be_i[i], core_data_user_i[i]}; end else begin : gen_single_group assign main_concat_in[i] = {core_core_busy_i[i], core_irq_ack_i[i], core_irq_ack_id_i[i], - core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], core_data_add_i[i], - core_data_wen_i[i], core_data_wdata_i[i], core_data_be_i[i], core_data_user_i[i], + core_instr_req_i[i], core_instr_addr_i[i], core_data_req_i[i], + core_data_add_i[i], core_data_wen_i[i], core_data_wdata_i[i], + core_data_be_i[i], core_data_user_i[i], // CSRs signals backup_csr_i[i].csr_mstatus , // 7-bits backup_csr_i[i].csr_mie , // 32-bits @@ -382,7 +385,7 @@ module HMR_wrap logic [NumSysCores-1:0][DataWidth-1:0] filt_data_data; logic [NumSysCores-1:0][BeWidth-1:0] filt_data_be; - for (genvar i = 0; i < NumSysCores; i++) begin + for (genvar i = 0; i < NumSysCores; i++) begin : gen_resp_suppress resp_suppress #( .AW (32), .DW (DataWidth) @@ -459,12 +462,24 @@ module HMR_wrap for (genvar i = 0; i < NumCores; i++) begin : gen_global_status assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; - assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; - assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? ~tmr_grp_in_independent[tmr_group_id(i)] : '0; - assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & - ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); - assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && i < NumDMRCores && RapidRecovery ? dmr_rapid_recovery_en[dmr_group_id(i)] : '0; - assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && i < NumTMRCores && RapidRecovery ? tmr_rapid_recovery_en[tmr_group_id(i)] : '0; + assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? + ~dmr_grp_in_independent[dmr_group_id(i)] : '0; + assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? + ~tmr_grp_in_independent[tmr_group_id(i)] : '0; + assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? + 1'b1 : ~core_in_tmr[i]) & + ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? + 1'b1 : ~core_in_dmr[i]); + assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && + i < NumDMRCores && + RapidRecovery ? + dmr_rapid_recovery_en[dmr_group_id(i)] : + '0; + assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && + i < NumTMRCores && + RapidRecovery ? + tmr_rapid_recovery_en[tmr_group_id(i)] : + '0; end reg_req_t [3:0] top_register_reqs; @@ -578,7 +593,8 @@ module HMR_wrap 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 sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.qe && + core_register_reqs[i].wdata == '0; end @@ -593,7 +609,7 @@ module HMR_wrap reg_resp_t [NumTMRGroups-1:0] tmr_register_resps; logic [NumTMRGroups-1:0] tmr_sw_synch_req; - localparam TMRSelWidth = $clog2(NumTMRGroups); + localparam int unsigned TMRSelWidth = $clog2(NumTMRGroups); /*************** * Registers * @@ -651,7 +667,9 @@ module HMR_wrap .sw_synch_req_o ( tmr_sw_synch_req[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), - .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,2)]} ), + .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,0)], + tmr_incr_mismatches[tmr_core_id(i,1)], + tmr_incr_mismatches[tmr_core_id(i,2)]} ), .tmr_single_mismatch_i( tmr_single_mismatch[i] ), .tmr_error_i ( tmr_error[i] ), .tmr_failure_i ( tmr_failure[i] ), @@ -814,7 +832,7 @@ module HMR_wrap reg_resp_t [NumDMRGroups-1:0] dmr_register_resps; logic [NumDMRGroups-1:0] dmr_sw_synch_req; - localparam DMRSelWidth = $clog2(NumDMRGroups); + localparam int unsigned DMRSelWidth = $clog2(NumDMRGroups); /*************** * Registers * @@ -866,7 +884,8 @@ module HMR_wrap .sw_synch_req_o ( dmr_sw_synch_req [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), - .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], dmr_incr_mismatches[dmr_core_id(i, 1)]} ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 0)], + dmr_incr_mismatches[dmr_core_id(i, 1)]} ), .dmr_error_i ( dmr_failure [i] ), .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), @@ -964,7 +983,7 @@ module HMR_wrap : dmr_failure_main[i]; end end - end else begin: no_dmr_checkers + end else begin: gen_no_dmr_checkers assign dmr_failure_main = '0; assign dmr_failure_data = '0; assign dmr_failure = '0; @@ -986,9 +1005,10 @@ module HMR_wrap if (RapidRecovery) begin : gen_rapid_recovery for (genvar i = 0; i < NumBackupRegfiles; i++) begin : gen_groups // Write Enable signal for backup registers - assign rapid_recovery_backup_enable[i] = core_in_tmr[i] ? (i < NumTMRGroups ? backup_enable[i] : 1'b0) // TMR mode - : core_in_dmr[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode - : 1'b1; // Independent mode + assign rapid_recovery_backup_enable[i] = + core_in_tmr[i] ? (i < NumTMRGroups ? backup_enable[i] : 1'b0) // TMR mode + : core_in_dmr[i] ? (backup_enable[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent mode // TODO: Only supports interleaved mode!!! @@ -1115,7 +1135,8 @@ module HMR_wrap end for (int i = 0; i < NumDMRGroups; i++) begin - if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin + if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && + dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin backup_csr_int [dmr_shared_id(i)] = dmr_backup_csr [i]; backup_program_counter_int [dmr_shared_id(i)] = dmr_backup_program_counter [i]; // backup_program_counter_error[dmr_shared_id(i)] = dmr_backup_program_counter_error[i]; @@ -1129,13 +1150,15 @@ module HMR_wrap backup_regfile_waddr_b [dmr_shared_id(i)] = dmr_backup_regfile_waddr_b [i]; start_recovery [dmr_shared_id(i)] = dmr_start_recovery [i]; dmr_recovery_finished[i] = recovery_finished[dmr_shared_id(i)]; - recovery_debug_halted_in [dmr_shared_id(i)] = core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] - & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; + recovery_debug_halted_in [dmr_shared_id(i)] = + core_debug_halted_i [dmr_core_id(dmr_group_id(i), 0)] + & core_debug_halted_i [dmr_core_id(dmr_group_id(i), 1)]; end end for (int i = 0; i < NumTMRGroups; i++) begin - if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin + if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && + tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin backup_csr_int [tmr_shared_id(i)] = tmr_backup_csr [i]; backup_program_counter_int [tmr_shared_id(i)] = tmr_backup_program_counter [i]; backup_branch_int [tmr_shared_id(i)] = tmr_backup_branch_int [i]; @@ -1148,9 +1171,10 @@ module HMR_wrap backup_regfile_waddr_b [tmr_shared_id(i)] = tmr_backup_regfile_waddr_b [i]; start_recovery [tmr_shared_id(i)] = tmr_start_recovery [i]; tmr_recovery_finished[i] = recovery_finished[tmr_shared_id(i)]; - recovery_debug_halted_in [tmr_shared_id(i)] = core_debug_halted_i [tmr_core_id(tmr_group_id(i), 0)] - & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 1)] - & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 2)]; + recovery_debug_halted_in [tmr_shared_id(i)] = + core_debug_halted_i [tmr_core_id(tmr_group_id(i), 0)] + & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 1)] + & core_debug_halted_i [tmr_core_id(tmr_group_id(i), 2)]; end end end @@ -1159,53 +1183,67 @@ module HMR_wrap always_comb begin if ((DMRFixed || (DMRSupported && core_in_dmr[i])) && dmr_core_rapid_recovery_en[i]) begin - core_debug_resume_o [i] = recovery_debug_resume_out [dmr_shared_id(dmr_group_id(i))]; - + core_debug_resume_o [i] = recovery_debug_resume_out [dmr_shared_id(dmr_group_id(i))]; + // Setback - core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; - core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; + core_recover_o [i] = recovery_trigger_out [dmr_shared_id(dmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [dmr_shared_id(dmr_group_id(i))]; // CSRs - recovery_csr_o [i] = recovery_csr_out [dmr_shared_id(dmr_group_id(i))]; + recovery_csr_o [i] = recovery_csr_out [dmr_shared_id(dmr_group_id(i))]; // PC - pc_recover_o [i] = recovery_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; - recovery_program_counter_o [i] = recovery_program_counter_out [dmr_shared_id(dmr_group_id(i))]; - recovery_branch_o [i] = recovery_branch_out [dmr_shared_id(dmr_group_id(i))]; - recovery_branch_addr_o [i] = recovery_branch_addr_out [dmr_shared_id(dmr_group_id(i))]; + pc_recover_o [i] = recovery_pc_enable_out [dmr_shared_id(dmr_group_id(i))]; + recovery_program_counter_o [i] = + recovery_program_counter_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [dmr_shared_id(dmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [dmr_shared_id(dmr_group_id(i))]; // RF - core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_a; - core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_a; - core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_a; - core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_b; - core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_b; - core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_b; - - end else if ((TMRFixed || (TMRSupported && core_in_tmr[i])) && tmr_core_rapid_recovery_en[i]) begin - core_debug_resume_o [i] = recovery_debug_resume_out [tmr_shared_id(tmr_group_id(i))]; + core_recovery_regfile_wport_o[i].we_a = + core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_a; + core_recovery_regfile_wport_o[i].waddr_a = + core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_a; + core_recovery_regfile_wport_o[i].wdata_a = + core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_a; + core_recovery_regfile_wport_o[i].we_b = + core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].we_b; + core_recovery_regfile_wport_o[i].waddr_b = + core_recovery_regfile_wport_out[dmr_shared_id(dmr_group_id(i))].waddr_b; + core_recovery_regfile_wport_o[i].wdata_b = + core_recovery_regfile_rdata_out[dmr_shared_id(dmr_group_id(i))].rdata_b; + + end else if ((TMRFixed || (TMRSupported && core_in_tmr[i])) && + tmr_core_rapid_recovery_en[i]) begin + core_debug_resume_o [i] = recovery_debug_resume_out [tmr_shared_id(tmr_group_id(i))]; // Setback - core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; - core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; + core_recover_o [i] = recovery_trigger_out [tmr_shared_id(tmr_group_id(i))]; + core_instr_lock_o [i] = recovery_instr_lock_out [tmr_shared_id(tmr_group_id(i))]; // CSRs - recovery_csr_o [i] = recovery_csr_out [tmr_shared_id(tmr_group_id(i))]; + recovery_csr_o [i] = recovery_csr_out [tmr_shared_id(tmr_group_id(i))]; // PC - pc_recover_o [i] = recovery_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; - recovery_program_counter_o [i] = recovery_program_counter_out [tmr_shared_id(tmr_group_id(i))]; - recovery_branch_o [i] = recovery_branch_out [tmr_shared_id(tmr_group_id(i))]; - recovery_branch_addr_o [i] = recovery_branch_addr_out [tmr_shared_id(tmr_group_id(i))]; + pc_recover_o [i] = recovery_pc_enable_out [tmr_shared_id(tmr_group_id(i))]; + recovery_program_counter_o [i] = + recovery_program_counter_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_o [i] = recovery_branch_out [tmr_shared_id(tmr_group_id(i))]; + recovery_branch_addr_o [i] = recovery_branch_addr_out [tmr_shared_id(tmr_group_id(i))]; // RF - // core_regfile_raddr_o [i] = core_regfile_raddr_out [tmr_shared_id(tmr_group_id(i))]; - core_recovery_regfile_wport_o[i].we_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_a; - core_recovery_regfile_wport_o[i].waddr_a = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_a; - core_recovery_regfile_wport_o[i].wdata_a = core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_a; - core_recovery_regfile_wport_o[i].we_b = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_b; - core_recovery_regfile_wport_o[i].waddr_b = core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_b; - core_recovery_regfile_wport_o[i].wdata_b = core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_b; + core_recovery_regfile_wport_o[i].we_a = + core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_a; + core_recovery_regfile_wport_o[i].waddr_a = + core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_a; + core_recovery_regfile_wport_o[i].wdata_a = + core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_a; + core_recovery_regfile_wport_o[i].we_b = + core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].we_b; + core_recovery_regfile_wport_o[i].waddr_b = + core_recovery_regfile_wport_out[tmr_shared_id(tmr_group_id(i))].waddr_b; + core_recovery_regfile_wport_o[i].wdata_b = + core_recovery_regfile_rdata_out[tmr_shared_id(tmr_group_id(i))].rdata_b; end else begin // Disable RapidRecovery @@ -1271,16 +1309,17 @@ module HMR_wrap if (TMRFixed || DMRFixed) $fatal(1, "Cannot support both TMR and DMR and fix one!"); for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); - localparam DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); + localparam int unsigned TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); + localparam int unsigned DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); always_comb begin // Special signals if (RapidRecovery) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] - | (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : - (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0)); + core_setback_o [i] = + tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0)); end else begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; @@ -1288,11 +1327,13 @@ module HMR_wrap if (i >= NumTMRCores && i >= NumDMRCores) begin core_setback_o [i] = '0; end else if (i < NumTMRCores && i >= NumDMRCores) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | (RapidRecovery ? (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0) : '0); + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | + (RapidRecovery ? + (core_in_tmr[i] ? recovery_setback_out [tmr_shared_id(tmr_group_id(i))] : '0) : '0); end else if (i >= NumTMRCores && i < NumDMRCores) begin - core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] - | (RapidRecovery ? (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : '0) : '0); + core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] | + (RapidRecovery ? + (core_in_dmr[i] ? recovery_setback_out [dmr_shared_id(dmr_group_id(i))] : '0) : '0); end if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode // CTRL @@ -1304,7 +1345,7 @@ module HMR_wrap core_boot_addr_o [i] = sys_boot_addr_i [TMRCoreIndex]; if (RapidRecovery) begin - core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex] + core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex] | recovery_debug_req_out [tmr_shared_id(tmr_group_id(i))]; end else begin core_debug_req_o [i] = sys_debug_req_i [TMRCoreIndex]; @@ -1338,7 +1379,7 @@ module HMR_wrap core_boot_addr_o [i] = sys_boot_addr_i [DMRCoreIndex]; if (RapidRecovery) begin - core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex] + core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex] | recovery_debug_req_out [dmr_shared_id(dmr_group_id(i))]; end else begin core_debug_req_o [i] = sys_debug_req_i [DMRCoreIndex]; @@ -1396,8 +1437,8 @@ module HMR_wrap end for (genvar i = 0; i < NumSysCores/*==NumCores*/; i++) begin : gen_core_outputs - localparam TMRCoreIndex = tmr_group_id(i); - localparam DMRCoreIndex = dmr_group_id(i); + localparam int unsigned TMRCoreIndex = tmr_group_id(i); + localparam int unsigned DMRCoreIndex = dmr_group_id(i); always_comb begin if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core @@ -1507,7 +1548,7 @@ module HMR_wrap *** TMR only *** *****************/ for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); + localparam int unsigned SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin // Special signals // Setback @@ -1530,7 +1571,7 @@ module HMR_wrap core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; if (RapidRecovery) begin - core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] | recovery_debug_req_out [tmr_shared_id(tmr_group_id(i))]; end else begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; @@ -1588,7 +1629,7 @@ module HMR_wrap end for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs - localparam CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); + localparam int unsigned CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr // CTRL assign sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; @@ -1611,23 +1652,34 @@ module HMR_wrap end else begin if (i >= NumTMRCores) begin : independent_stragglers // CTRL - assign sys_core_busy_o [i] = core_core_busy_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_core_busy_o [i] = + core_core_busy_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // IRQ - assign sys_irq_ack_o [i] = core_irq_ack_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_irq_ack_id_o [i] = core_irq_ack_id_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_o [i] = + core_irq_ack_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_id_o [i] = + core_irq_ack_id_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // INSTR - assign filt_instr_req [i] = core_instr_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_instr_addr [i] = core_instr_addr_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_req [i] = + core_instr_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_addr [i] = + core_instr_addr_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // DATA - assign filt_data_req [i] = core_data_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_addr [i] = core_data_add_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_we [i] = core_data_wen_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_data [i] = core_data_wdata_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_user_o [i] = core_data_user_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_be [i] = core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_req [i] = + core_data_req_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_addr [i] = + core_data_add_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_we [i] = + core_data_wen_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_data [i] = + core_data_wdata_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_user_o [i] = + core_data_user_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_be [i] = + core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; end else begin always_comb begin if (core_in_tmr[i]) begin : tmr_mode @@ -1645,10 +1697,10 @@ module HMR_wrap // DATA filt_data_req [i] = tmr_data_req_out [CoreCoreIndex]; - filt_data_addr [i] = tmr_data_add_out [CoreCoreIndex]; - filt_data_we [i] = tmr_data_wen_out [CoreCoreIndex]; - filt_data_data [i] = tmr_data_wdata_out[CoreCoreIndex]; - sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; + filt_data_addr [i] = tmr_data_add_out [CoreCoreIndex]; + filt_data_we [i] = tmr_data_wen_out [CoreCoreIndex]; + filt_data_data [i] = tmr_data_wdata_out[CoreCoreIndex]; + sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; filt_data_be [i] = tmr_data_be_out [CoreCoreIndex]; end else begin : disable_core // Assign disable // CTLR @@ -1679,16 +1731,16 @@ module HMR_wrap sys_irq_ack_id_o [i] = core_irq_ack_id_i[i]; // INSTR - filt_instr_req [i] = core_instr_req_i [i]; - filt_instr_addr [i] = core_instr_addr_i[i]; + filt_instr_req [i] = core_instr_req_i [i]; + filt_instr_addr [i] = core_instr_addr_i[i]; // DATA - filt_data_req [i] = core_data_req_i [i]; + filt_data_req [i] = core_data_req_i [i]; filt_data_addr [i] = core_data_add_i [i]; - filt_data_we [i] = core_data_wen_i [i]; - filt_data_data [i] = core_data_wdata_i[i]; + filt_data_we [i] = core_data_wen_i [i]; + filt_data_data [i] = core_data_wdata_i[i]; sys_data_user_o [i] = core_data_user_i [i]; - filt_data_be [i] = core_data_be_i [i]; + filt_data_be [i] = core_data_be_i [i]; end end end @@ -1706,7 +1758,7 @@ module HMR_wrap // assign dmr_resynch_req_o = '0; for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); + localparam int unsigned SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); always_comb begin // Setback if (RapidRecovery) begin @@ -1728,7 +1780,7 @@ module HMR_wrap core_boot_addr_o [i] = sys_boot_addr_i [SysCoreIndex]; if (RapidRecovery) begin - core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] + core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex] | recovery_debug_req_out [dmr_shared_id(dmr_group_id(i))]; end else begin core_debug_req_o [i] = sys_debug_req_i [SysCoreIndex]; @@ -1809,23 +1861,34 @@ module HMR_wrap end else begin if (i >= NumDMRCores) begin : independent_stragglers // CTRL - assign sys_core_busy_o [i] = dmr_core_busy_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_core_busy_o [i] = + dmr_core_busy_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // IRQ - assign sys_irq_ack_o [i] = dmr_irq_ack_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_irq_ack_id_o [i] = dmr_irq_ack_id_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_o [i] = + dmr_irq_ack_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_irq_ack_id_o [i] = + dmr_irq_ack_id_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // INSTR - assign filt_instr_req [i] = dmr_instr_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_instr_addr [i] = dmr_instr_addr_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_req [i] = + dmr_instr_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_instr_addr [i] = + dmr_instr_addr_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; // DATA - assign filt_data_req [i] = dmr_data_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_addr [i] = dmr_data_add_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_we [i] = dmr_data_wen_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_data [i] = dmr_data_wdata_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_data_user_o [i] = dmr_data_user_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign filt_data_be [i] = dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_req [i] = + dmr_data_req_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_addr [i] = + dmr_data_add_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_we [i] = + dmr_data_wen_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_data [i] = + dmr_data_wdata_out[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_data_user_o [i] = + dmr_data_user_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign filt_data_be [i] = + dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; end else begin always_comb begin if (core_in_dmr[i]) begin : dmr_mode @@ -1843,10 +1906,10 @@ module HMR_wrap // DATA filt_data_req [i] = dmr_data_req_out [CoreCoreIndex]; - filt_data_addr [i] = dmr_data_add_out [CoreCoreIndex]; - filt_data_we [i] = dmr_data_wen_out [CoreCoreIndex]; - filt_data_data [i] = dmr_data_wdata_out[CoreCoreIndex]; - sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; + filt_data_addr [i] = dmr_data_add_out [CoreCoreIndex]; + filt_data_we [i] = dmr_data_wen_out [CoreCoreIndex]; + filt_data_data [i] = dmr_data_wdata_out[CoreCoreIndex]; + sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; filt_data_be [i] = dmr_data_be_out [CoreCoreIndex]; end else begin : disable_core // Assign disable // CTLR @@ -1862,10 +1925,10 @@ module HMR_wrap // DATA filt_data_req [i] = '0; - filt_data_addr [i] = '0; - filt_data_we [i] = '0; - filt_data_data [i] = '0; - sys_data_user_o [i] = '0; + filt_data_addr [i] = '0; + filt_data_we [i] = '0; + filt_data_data [i] = '0; + sys_data_user_o [i] = '0; filt_data_be [i] = '0; end end else begin : independent_mode @@ -1882,10 +1945,10 @@ module HMR_wrap // DATA filt_data_req [i] = core_data_req_i [i]; - filt_data_addr [i] = core_data_add_i [i]; - filt_data_we [i] = core_data_wen_i [i]; - filt_data_data [i] = core_data_wdata_i[i]; - sys_data_user_o [i] = core_data_user_i [i]; + filt_data_addr [i] = core_data_add_i [i]; + filt_data_we [i] = core_data_wen_i [i]; + filt_data_data [i] = core_data_wdata_i[i]; + sys_data_user_o [i] = core_data_user_i [i]; filt_data_be [i] = core_data_be_i [i]; end end diff --git a/rtl/HMR/hmr_dmr_ctrl.sv b/rtl/HMR/hmr_dmr_ctrl.sv index 35b638ba..ad74eab0 100644 --- a/rtl/HMR/hmr_dmr_ctrl.sv +++ b/rtl/HMR/hmr_dmr_ctrl.sv @@ -111,7 +111,8 @@ module hmr_dmr_ctrl 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 + 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; dmr_red_mode_d = DMR_RESTORE; end @@ -137,6 +138,7 @@ module hmr_dmr_ctrl end // Default: do nothing + default: ; endcase // Logic to switch in and out of DMR diff --git a/rtl/HMR/hmr_rapid_recovery_ctrl.sv b/rtl/HMR/hmr_rapid_recovery_ctrl.sv index 4f5b9f2f..b461680a 100644 --- a/rtl/HMR/hmr_rapid_recovery_ctrl.sv +++ b/rtl/HMR/hmr_rapid_recovery_ctrl.sv @@ -125,6 +125,9 @@ module hmr_rapid_recovery_ctrl recovery_finished_o = 1'b1; end end + + // Default: do nothing + default: ; endcase end diff --git a/rtl/HMR/hmr_tmr_ctrl.sv b/rtl/HMR/hmr_tmr_ctrl.sv index 2e368a91..f23512f3 100644 --- a/rtl/HMR/hmr_tmr_ctrl.sv +++ b/rtl/HMR/hmr_tmr_ctrl.sv @@ -39,7 +39,7 @@ module hmr_tmr_ctrl #( input logic rapid_recovery_qe_i, input logic force_resynch_q_i, input logic force_resynch_qe_i, - + // TMR control signals output logic [2:0] setback_o, output logic sw_resynch_req_o, @@ -181,6 +181,7 @@ module hmr_tmr_ctrl #( end // Default: do nothing + default: ; endcase diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index 51b5079d..bbf0d66e 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -65,7 +65,8 @@ module hmr_unit #( /// Number of physical cores NOT used for DMR localparam int unsigned NumDMRLeftover = NumCores - NumDMRCores, /// Number of cores visible to the system (Fixed mode removes unneeded system ports) - localparam int unsigned NumSysCores = DMRFixed ? NumDMRGroups : TMRFixed ? NumTMRGroups : NumCores + localparam int unsigned NumSysCores = DMRFixed ? NumDMRGroups : + TMRFixed ? NumTMRGroups : NumCores ) ( input logic clk_i , input logic rst_ni, @@ -114,47 +115,48 @@ module hmr_unit #( input nominal_outputs_t [NumCores-1:0] core_nominal_outputs_i, input bus_outputs_t [NumCores-1:0][NumBusVoters-1:0] core_bus_outputs_i ); - function int max(int a, int b); + function automatic int max(int a, int b); return (a > b) ? a : b; endfunction - localparam int unsigned NumBackupRegs = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); + localparam int unsigned NumBackupRegs = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, + TMRSupported || TMRFixed ? NumTMRGroups : 0); - function int tmr_group_id (int core_id); + function automatic int tmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumTMRGroups; else return (core_id/3); endfunction - function int tmr_core_id (int group_id, int core_offset); + function automatic int tmr_core_id (int group_id, int core_offset); if (InterleaveGrps) return group_id + core_offset * NumTMRGroups; else return (group_id * 3) + core_offset; endfunction - function int tmr_shared_id (int group_id); + function automatic int tmr_shared_id (int group_id); if (InterleaveGrps || !(DMRSupported || DMRFixed)) return group_id; else return group_id + group_id/2; endfunction - function int tmr_offset_id (int core_id); + function automatic int tmr_offset_id (int core_id); if (InterleaveGrps) return core_id / NumTMRGroups; else return core_id % 3; endfunction - function int dmr_group_id (int core_id); + function automatic int dmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumDMRGroups; else return (core_id/2); endfunction - function int dmr_core_id (int group_id, int core_offset); + function automatic int dmr_core_id (int group_id, int core_offset); if (InterleaveGrps) return group_id + core_offset * NumDMRGroups; else return (group_id * 2) + core_offset; endfunction - function int dmr_shared_id (int group_id); + function automatic int dmr_shared_id (int group_id); return group_id; endfunction - function int dmr_offset_id (int core_id); + function automatic int dmr_offset_id (int core_id); if (InterleaveGrps) return core_id / NumDMRGroups; else return core_id % 2; endfunction @@ -220,12 +222,23 @@ module hmr_unit #( for (genvar i = 0; i < NumCores; i++) begin : gen_global_status assign core_in_independent[i] = ~core_in_dmr[i] & ~core_in_tmr[i]; - assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? ~dmr_grp_in_independent[dmr_group_id(i)] : '0; - assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? ~tmr_grp_in_independent[tmr_group_id(i)] : '0; - assign core_en_as_master[i] = ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & - ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); - assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && i < NumDMRCores && RapidRecovery ? dmr_rapid_recovery_en[dmr_group_id(i)] : '0; - assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && i < NumTMRCores && RapidRecovery ? tmr_rapid_recovery_en[tmr_group_id(i)] : '0; + assign core_in_dmr[i] = (DMRSupported || DMRFixed) && i < NumDMRCores ? + ~dmr_grp_in_independent[dmr_group_id(i)] : '0; + assign core_in_tmr[i] = (TMRSupported || TMRFixed) && i < NumTMRCores ? + ~tmr_grp_in_independent[tmr_group_id(i)] : '0; + assign core_en_as_master[i] = + ((tmr_core_id(tmr_group_id(i), 0) == i || i>=NumTMRCores) ? 1'b1 : ~core_in_tmr[i]) & + ((dmr_core_id(dmr_group_id(i), 0) == i || i>=NumDMRCores) ? 1'b1 : ~core_in_dmr[i]); + assign dmr_core_rapid_recovery_en[i] = (DMRSupported || DMRFixed) && + i < NumDMRCores && + RapidRecovery ? + dmr_rapid_recovery_en[dmr_group_id(i)] : + '0; + assign tmr_core_rapid_recovery_en[i] = (TMRSupported || TMRFixed) && + i < NumTMRCores && + RapidRecovery ? + tmr_rapid_recovery_en[tmr_group_id(i)] : + '0; end reg_req_t [3:0] top_register_reqs; @@ -339,7 +352,8 @@ module hmr_unit #( 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 sp_store_will_be_zero[i] = core_config_reg2hw[i].sp_store.qe && + core_register_reqs[i].wdata == '0; end /********************************************************** @@ -353,15 +367,15 @@ module hmr_unit #( reg_rsp_t [NumTMRGroups-1:0] tmr_register_resps; logic [NumTMRGroups-1:0] tmr_sw_resynch_req, tmr_sw_synch_req; - localparam TMRSelWidth = $clog2(NumTMRGroups); + localparam int unsigned TMRSelWidth = $clog2(NumTMRGroups); /*************** * Registers * ***************/ - if (NumTMRGroups == 1) begin + if (NumTMRGroups == 1) begin : gen_single_tmr_group_reg_connect assign tmr_register_reqs[0] = top_register_reqs[3]; assign top_register_resps[3] = tmr_register_resps[0]; - end else begin + end else begin : gen_multi_tmr_group_reg_connect reg_demux #( .NoPorts ( NumTMRGroups ), .req_t ( reg_req_t ), @@ -417,7 +431,9 @@ module hmr_unit #( .sw_synch_req_o ( tmr_sw_synch_req[i] ), .grp_in_independent_o ( tmr_grp_in_independent[i] ), .rapid_recovery_en_o ( tmr_rapid_recovery_en[i] ), - .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,2)], tmr_incr_mismatches[tmr_core_id(i,1)], tmr_incr_mismatches[tmr_core_id(i,0)]} ), + .tmr_incr_mismatches_o( {tmr_incr_mismatches[tmr_core_id(i,2)], + tmr_incr_mismatches[tmr_core_id(i,1)], + tmr_incr_mismatches[tmr_core_id(i,0)]} ), .tmr_single_mismatch_i( tmr_single_mismatch[i] ), .tmr_error_i ( tmr_error[i] ), .tmr_failure_i ( tmr_failure[i] ), @@ -462,7 +478,7 @@ module hmr_unit #( .error_cba_o( tmr_error_main [ i ] ) ); if (SeparateData) begin : gen_data_voter - for (genvar j = 0; j < NumBusVoters; j++) begin + for (genvar j = 0; j < NumBusVoters; j++) begin : gen_bus_voter bitwise_TMR_voter #( .DataWidth( $bits(bus_outputs_t) ), .VoterType( 0 ) @@ -476,7 +492,7 @@ module hmr_unit #( ); end end else begin : gen_no_data_voter - for (genvar j = 0; j < NumBusVoters; j++) begin + for (genvar j = 0; j < NumBusVoters; j++) begin : gen_tieoffs assign tmr_bus_outputs[i][j] = DefaultBusOutputs; assign tmr_failure_data[i][j] = '0; assign tmr_error_data[i][j] = '0; @@ -516,15 +532,15 @@ module hmr_unit #( logic [NumDMRGroups-1:0] dmr_sw_synch_req; logic [NumDMRGroups-1:0] dmr_sw_resynch_req; - localparam DMRSelWidth = $clog2(NumDMRGroups); + localparam int unsigned DMRSelWidth = $clog2(NumDMRGroups); /*************** * Registers * ***************/ - if (NumDMRGroups == 1) begin + if (NumDMRGroups == 1) begin : gen_single_dmr_group_reg_connect assign dmr_register_reqs[0] = top_register_reqs[2]; assign top_register_resps[2] = dmr_register_resps[0]; - end else begin + end else begin : gen_multi_dmr_group_reg_connect reg_demux #( .NoPorts ( NumDMRGroups ), .req_t ( reg_req_t ), @@ -576,7 +592,8 @@ module hmr_unit #( .checkpoint_o ( checkpoint_reg_q [i] ), .grp_in_independent_o ( dmr_grp_in_independent[i] ), .rapid_recovery_en_o ( dmr_rapid_recovery_en [i] ), - .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 1)], dmr_incr_mismatches[dmr_core_id(i, 0)]} ), + .dmr_incr_mismatches_o ( {dmr_incr_mismatches[dmr_core_id(i, 1)], + dmr_incr_mismatches[dmr_core_id(i, 0)]} ), .dmr_error_i ( dmr_failure [i] ), .fetch_en_i ( sys_fetch_en_i[dmr_core_id(i, 0)] ), @@ -605,7 +622,7 @@ module hmr_unit #( .error_o ( dmr_failure_main [ i ] ) ); if (SeparateData) begin : gen_data_checker - for (genvar j = 0; j < NumBusVoters; j++) begin + for (genvar j = 0; j < NumBusVoters; j++) begin : gen_bus_checker DMR_checker # ( .check_bus_t ( bus_outputs_t ) ) dmr_core_checker_data ( @@ -636,9 +653,10 @@ module hmr_unit #( .error_o ( dmr_failure_backup [ i ] ) ); - assign rapid_recovery_backup_en_inp[i] = core_in_tmr[i] ? (i < NumTMRGroups ? rapid_recovery_backup_en_oup[i] : 1'b0) // TMR mode - : core_in_dmr[i] ? (rapid_recovery_backup_en_oup[i] & ~dmr_failure[i] ) // DMR mode - : 1'b1; // Independent + assign rapid_recovery_backup_en_inp[i] = + core_in_tmr[i] ? (i < NumTMRGroups ? rapid_recovery_backup_en_oup[i] : 1'b0)// TMR mode + : core_in_dmr[i] ? (rapid_recovery_backup_en_oup[i] & ~dmr_failure[i] ) // DMR mode + : 1'b1; // Independent rapid_recovery_unit #( .RfAddrWidth ( RfAddrWidth ), .DataWidth ( SysDataWidth ), @@ -707,7 +725,7 @@ module hmr_unit #( if (RapidRecovery) begin: gen_rapid_recovery_connection - for (genvar i = 0; i < NumBackupRegs; i++) begin + for (genvar i = 0; i < NumBackupRegs; i++) begin : gen_core_backup_regs always_ff @(posedge clk_i, negedge rst_ni) begin if (~rst_ni) begin core_backup_q[i] <= '0; @@ -732,7 +750,8 @@ module hmr_unit #( end end for (int i = 0; i < NumDMRGroups; i++) begin - if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin + if ((DMRFixed || (DMRSupported && ~dmr_grp_in_independent[i])) && + dmr_core_rapid_recovery_en[dmr_core_id(i, 0)]) begin rapid_recovery_nominal[dmr_shared_id(i)] = dmr_nominal_outputs[i]; rapid_recovery_backup_bus[dmr_shared_id(i)] = dmr_backup_outputs[i]; rapid_recovery_start[dmr_shared_id(i)] = dmr_recovery_start[i]; @@ -740,7 +759,8 @@ module hmr_unit #( end end for (int i = 0; i < NumTMRGroups; i++) begin - if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin + if ((TMRFixed || (TMRSupported && ~tmr_grp_in_independent[i])) && + tmr_core_rapid_recovery_en[tmr_core_id(i, 0)]) begin rapid_recovery_nominal[tmr_shared_id(i)] = tmr_nominal_outputs[i]; rapid_recovery_start[tmr_shared_id(i)] = tmr_recovery_start[i]; tmr_recovery_finished[i] = rapid_recovery_finished[tmr_shared_id(i)]; @@ -763,22 +783,23 @@ module hmr_unit #( if (TMRFixed || DMRFixed) $fatal(1, "Cannot support both TMR and DMR and fix one!"); for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); - localparam DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); + localparam int unsigned TMRCoreIndex = tmr_core_id(tmr_group_id(i), 0); + localparam int unsigned DMRCoreIndex = dmr_core_id(dmr_group_id(i), 0); always_comb begin // Special signals core_bootaddress_o[i] = (checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] != '0) ? - checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; + checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; if (RapidRecovery) begin // $error("UNIMPLEMENTED"); - rapid_recovery_o [i] = (core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : - (core_in_tmr[i] ? rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0)); + rapid_recovery_o [i] = + (core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0)); core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] - | (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : - (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0)); + | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] + | (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : + (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0)); end else begin core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)]; @@ -786,11 +807,13 @@ module hmr_unit #( if (i >= NumTMRCores && i >= NumDMRCores) begin core_setback_o [i] = '0; end else if (i < NumTMRCores && i >= NumDMRCores) begin - core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] - | (RapidRecovery ? (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0) : '0); + core_setback_o [i] = tmr_setback_q [tmr_group_id(i)][tmr_offset_id(i)] | + (RapidRecovery ? + (core_in_tmr[i] ? rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))] : '0) : '0); end else if (i >= NumTMRCores && i < NumDMRCores) begin - core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] - | (RapidRecovery ? (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : '0) : '0); + core_setback_o [i] = dmr_setback_q [dmr_group_id(i)][dmr_offset_id(i)] | + (RapidRecovery ? + (core_in_dmr[i] ? rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))] : '0) : '0); end if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode core_inputs_o[i] = sys_inputs_i[TMRCoreIndex]; @@ -803,8 +826,8 @@ module hmr_unit #( end for (genvar i = 0; i < NumSysCores/*==NumCores*/; i++) begin : gen_core_outputs - localparam TMRCoreIndex = tmr_group_id(i); - localparam DMRCoreIndex = dmr_group_id(i); + localparam int unsigned TMRCoreIndex = tmr_group_id(i); + localparam int unsigned DMRCoreIndex = dmr_group_id(i); always_comb begin if (i < NumTMRCores && core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core @@ -836,15 +859,16 @@ module hmr_unit #( *** TMR only *** *****************/ for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); + localparam int unsigned SysCoreIndex = TMRFixed ? i/3 : tmr_core_id(tmr_group_id(i), 0); always_comb begin // Special signals core_bootaddress_o[i] = (checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] != '0) ? - checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; + checkpoint_reg_q[dmr_shared_id(dmr_group_id(i))] : sys_bootaddress_i; // Setback if (RapidRecovery) begin // $error("UNIMPLEMENTED"); - rapid_recovery_o [i] = core_in_tmr[i] ? rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0; + rapid_recovery_o [i] = core_in_tmr[i] ? + rapid_recovery_bus [tmr_shared_id(tmr_group_id(i))] : '0; core_setback_o [i] = tmr_setback_q [tmr_group_id(i)] | rapid_recovery_setback [tmr_shared_id(tmr_group_id(i))]; @@ -863,15 +887,17 @@ module hmr_unit #( end for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs - localparam CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); + localparam int unsigned CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr assign sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; - end else begin - if (i >= NumTMRCores) begin : independent_stragglers - assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - assign sys_bus_outputs_o [i] = core_bus_outputs_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - end else begin + end else begin : gen_not_fixed_tmr + if (i >= NumTMRCores) begin : gen_independent_stragglers + assign sys_nominal_outputs_o[i] = + core_nominal_outputs_i[TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + assign sys_bus_outputs_o [i] = + core_bus_outputs_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; + end else begin : gen_normal_tmr always_comb begin if (core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core @@ -899,14 +925,15 @@ module hmr_unit #( assign dmr_failure_o = '0; for (genvar i = 0; i < NumCores; i++) begin : gen_core_inputs - localparam SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); + localparam int unsigned SysCoreIndex = DMRFixed ? i/2 : dmr_core_id(dmr_group_id(i), 0); always_comb begin core_bootaddress_o[i] = (checkpoint_reg_q[SysCoreIndex] != '0) ? checkpoint_reg_q[SysCoreIndex] : sys_bootaddress_i; // Setback if (RapidRecovery) begin // $error("UNIMPLEMENTED"); - rapid_recovery_o [i] = core_in_dmr[i] ? rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : '0; + rapid_recovery_o [i] = core_in_dmr[i] ? + rapid_recovery_bus [dmr_shared_id(dmr_group_id(i))] : '0; core_setback_o [i] = dmr_setback_q[dmr_group_id(i)][dmr_offset_id(i)] | rapid_recovery_setback [dmr_shared_id(dmr_group_id(i))]; @@ -925,15 +952,17 @@ module hmr_unit #( end // gen_core_inputs for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs - localparam CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); + localparam int unsigned CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr assign sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; - end else begin - if (i >= NumDMRCores) begin : independent_stragglers - assign sys_nominal_outputs_o[i] = core_nominal_outputs_i[DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; - assign sys_bus_outputs_o [i] = core_bus_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; - end else begin + end else begin : gen_not_fixed_dmr + if (i >= NumDMRCores) begin : gen_independent_stragglers + assign sys_nominal_outputs_o[i] = + core_nominal_outputs_i[DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; + assign sys_bus_outputs_o [i] = + core_bus_outputs_i [DMRFixed ? i-NumDMRGroups+NumDMRCores : i]; + end else begin : gen_normal_dmr always_comb begin if (core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core diff --git a/rtl/HMR/rapid_recovery_pkg.sv b/rtl/HMR/rapid_recovery_pkg.sv index 6a1e1044..71d300bd 100644 --- a/rtl/HMR/rapid_recovery_pkg.sv +++ b/rtl/HMR/rapid_recovery_pkg.sv @@ -7,9 +7,9 @@ * 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. - * + * * Recovery Region Package - * + * */ package rapid_recovery_pkg; diff --git a/rtl/HMR/rapid_recovery_unit.sv b/rtl/HMR/rapid_recovery_unit.sv index 77bcf453..8290e572 100644 --- a/rtl/HMR/rapid_recovery_unit.sv +++ b/rtl/HMR/rapid_recovery_unit.sv @@ -57,9 +57,9 @@ module rapid_recovery_unit /* enable_rf_recovery_o: allows the register file to be reloaded into the core */ output logic enable_rf_recovery_o, - /* regfile_recovery_wdata_o: used by the address generator in the + /* regfile_recovery_wdata_o: used by the address generator in the rapid_recovery_ctrl to propagate the RF - addresses to the core during the recovery + addresses to the core during the recovery routine */ output regfile_write_t regfile_recovery_wdata_o, // To cores RF interface /* regfile_recovery_rdata_o: propagates the content from the backup RF to diff --git a/rtl/HMR/recovery_csr.sv b/rtl/HMR/recovery_csr.sv index 6cf78126..446c93e6 100644 --- a/rtl/HMR/recovery_csr.sv +++ b/rtl/HMR/recovery_csr.sv @@ -7,10 +7,10 @@ * 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. - * + * * Recovery Control Status Registers * ECC-protected register that stores the CSRs values from the cores - * + * */ module recovery_csr diff --git a/rtl/HMR/recovery_pc.sv b/rtl/HMR/recovery_pc.sv index 51f62347..9be09344 100644 --- a/rtl/HMR/recovery_pc.sv +++ b/rtl/HMR/recovery_pc.sv @@ -7,10 +7,10 @@ * 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. - * + * * Recovery Program Counter * ECC-protected register that stores the Program Counter value from the cores - * + * */ module recovery_pc #( diff --git a/rtl/HMR/recovery_rf.sv b/rtl/HMR/recovery_rf.sv index b546087c..58015312 100644 --- a/rtl/HMR/recovery_rf.sv +++ b/rtl/HMR/recovery_rf.sv @@ -68,10 +68,10 @@ module recovery_rf #( ); // number of integer registers - localparam NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NUM_WORDS = 2 ** (ADDR_WIDTH - 1); // number of floating point registers - localparam NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); - localparam NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + localparam int unsigned NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; // integer register file logic [NUM_WORDS-1:0][NonProtectedWidth-1:0] mem; @@ -93,18 +93,18 @@ module recovery_rf #( generate if (ECCEnabled) begin : gen_ecc_region - + prim_secded_39_32_enc a_port_ecc_encoder ( .in ( wdata_a_i ), .out ( wdata_a ) ); - + prim_secded_39_32_enc b_port_ecc_encoder ( .in ( wdata_b_i ), .out ( wdata_b ) ); - - for (genvar index = 0; index < NUM_WORDS; index++) begin + + for (genvar index = 0; index < NUM_WORDS; index++) begin : gen_internal_decoder prim_secded_39_32_dec internal_memory_decoder ( .in ( ecc_mem [index] ), .d_o ( mem [index] ), @@ -112,9 +112,9 @@ module recovery_rf #( .err_o ( ) ); end - - if (FPU == 1 && PULP_ZFINX == 0) begin - for (genvar index = 0; index < NUM_FP_WORDS; index++) begin + + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_fp_decoders + for (genvar index = 0; index < NUM_FP_WORDS; index++) begin : gen_internal_fp_decoder prim_secded_39_32_dec internal_fp_memory_decoder ( .in ( ecc_mem_fp [index] ), .d_o ( mem_fp [index] ), @@ -123,13 +123,13 @@ module recovery_rf #( ); end end - end else begin : no_ecc_region + end else begin : gen_no_ecc_region assign wdata_a = wdata_a_i; assign wdata_b = wdata_b_i; for (genvar index = 0; index < NUM_WORDS; index++) assign mem [index] = ecc_mem [index]; - + for (genvar index = 0; index < NUM_FP_WORDS; index++) assign mem_fp [index] = ecc_mem_fp [index]; end @@ -197,7 +197,7 @@ module recovery_rf #( if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_write // Floating point registers - for (l = 0; l < NUM_FP_WORDS; l++) begin + for (l = 0; l < NUM_FP_WORDS; l++) begin : gen_fp_regs always_ff @(posedge clk_i, negedge rst_ni) begin : fp_regs if (rst_ni == 1'b0) begin ecc_mem_fp[l] <= '0; diff --git a/rtl/HMR/recovery_rf_latch.sv b/rtl/HMR/recovery_rf_latch.sv index 3bc572a7..4a108ef4 100644 --- a/rtl/HMR/recovery_rf_latch.sv +++ b/rtl/HMR/recovery_rf_latch.sv @@ -72,16 +72,16 @@ module recovery_rf #( ); // number of integer registers - localparam NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NUM_WORDS = 2 ** (ADDR_WIDTH - 1); // number of floating point registers - localparam NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); - localparam NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + localparam int unsigned NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; // integer register file logic [NonProtectedWidth-1:0] mem [NUM_WORDS]; logic [ DataWidth-1:0] ecc_mem [NUM_WORDS]; logic [NUM_TOT_WORDS-1:1] waddr_onehot_a; - logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , + logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , waddr_onehot_b_q; logic [NUM_TOT_WORDS-1:1] mem_clocks; logic [DataWidth-1:0] wdata_a , @@ -111,20 +111,20 @@ module recovery_rf #( generate if (ECCEnabled) begin : gen_ecc_region - + prim_secded_39_32_enc a_port_ecc_encoder ( .in ( wdata_a_i ), .out ( wdata_a_ecc) ); assign wdata_a = wdata_a_ecc; - + prim_secded_39_32_enc b_port_ecc_encoder ( .in ( wdata_b_i ), .out ( wdata_b_ecc) ); assign wdata_b = wdata_b_ecc; - - for (genvar index = 0; index < NUM_WORDS; index++) begin + + for (genvar index = 0; index < NUM_WORDS; index++) begin : gen_internal_decoder prim_secded_39_32_dec internal_memory_decoder ( .in ( ecc_mem [index] ), .d_o ( mem [index] ), @@ -132,9 +132,9 @@ module recovery_rf #( .err_o ( ) ); end - - if (FPU == 1 && PULP_ZFINX == 0) begin - for (genvar index = 0; index < NUM_FP_WORDS; index++) begin + + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_fp_decoders + for (genvar index = 0; index < NUM_FP_WORDS; index++) begin : gen_internal_fp_decoder prim_secded_39_32_dec internal_fp_memory_decoder ( .in ( ecc_mem_fp [index] ), .d_o ( mem_fp [index] ), @@ -151,7 +151,7 @@ module recovery_rf #( for (genvar index = 0; index < NUM_WORDS; index++) assign mem [index] = ecc_mem [index]; - + for (genvar index = 0; index < NUM_FP_WORDS; index++) assign mem_fp [index] = ecc_mem_fp [index]; end @@ -160,11 +160,11 @@ module recovery_rf #( //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- - if (FPU == 1 && PULP_ZFINX == 0) begin + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_read assign rdata_a_o = raddr_a_i[5] ? mem_fp[raddr_a_i[4:0]] : mem[raddr_a_i[4:0]]; assign rdata_b_o = raddr_b_i[5] ? mem_fp[raddr_b_i[4:0]] : mem[raddr_b_i[4:0]]; assign rdata_c_o = raddr_c_i[5] ? mem_fp[raddr_c_i[4:0]] : mem[raddr_c_i[4:0]]; - end else begin + end else begin : gen_standard_read assign rdata_a_o = mem[raddr_a_i[4:0]]; assign rdata_b_o = mem[raddr_b_i[4:0]]; assign rdata_c_o = mem[raddr_c_i[4:0]]; @@ -245,7 +245,7 @@ module recovery_rf #( end end - if (FPU == 1 && PULP_ZFINX == 0) begin + if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_latch // Floating point registers always_latch begin : latch_wdata_fp if (FPU == 1) begin diff --git a/rtl/HMR/resp_suppress.sv b/rtl/HMR/resp_suppress.sv index fa1b8f28..9e9c185b 100644 --- a/rtl/HMR/resp_suppress.sv +++ b/rtl/HMR/resp_suppress.sv @@ -17,7 +17,7 @@ module resp_suppress #( ) ( input logic clk_i, input logic rst_ni, - + input logic ctrl_setback_i, input logic req_i, @@ -94,5 +94,5 @@ module resp_suppress #( be_q <= be_d; end end - + endmodule diff --git a/rtl/ecc_wrap/ecc_sram_wrap.sv b/rtl/ecc_wrap/ecc_sram_wrap.sv index f21c9b98..b28aa6e7 100644 --- a/rtl/ecc_wrap/ecc_sram_wrap.sv +++ b/rtl/ecc_wrap/ecc_sram_wrap.sv @@ -149,7 +149,9 @@ module ecc_sram_wrap #( assign tcdm_rdata_o = loaded; - assign to_store = store_state_q == NORMAL ? tcdm_wdata_i : (be_selector & input_buffer_q) | (~be_selector & loaded); + assign to_store = store_state_q == NORMAL ? + tcdm_wdata_i : + (be_selector & input_buffer_q) | (~be_selector & loaded); end else begin : gen_ecc_input From ac3ecafd2e7230760adc6f6702f6b401d80b8d17 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 7 Aug 2025 14:49:47 +0200 Subject: [PATCH 65/66] Fix lint --- rtl/HMR/DMR_controller.sv | 2 +- rtl/HMR/HMR_wrap.sv | 19 ++++++++-------- rtl/HMR/hmr_unit.sv | 12 +++++----- rtl/HMR/recovery_rf.sv | 39 ++++++++++++++++---------------- rtl/HMR/recovery_rf_latch.sv | 43 ++++++++++++++++++------------------ 5 files changed, 59 insertions(+), 56 deletions(-) diff --git a/rtl/HMR/DMR_controller.sv b/rtl/HMR/DMR_controller.sv index 004f113f..0af4fdb2 100644 --- a/rtl/HMR/DMR_controller.sv +++ b/rtl/HMR/DMR_controller.sv @@ -87,7 +87,7 @@ logic [$clog2(NumDMRGroups)-1:0] error_index_d, /****************** * Output Assigns * ******************/ -for (genvar i = 0; i < NumDMRGroups; i++) begin +for (genvar i = 0; i < NumDMRGroups; i++) begin : gen_assigns assign dmr_ctrl_core_setback_o [i] = dmr_ctrl_core_setback_out [i]; assign dmr_ctrl_core_clk_en_o [i] = dmr_ctrl_core_clk_en_out [i]; assign dmr_ctrl_pc_read_enable_o [i] = dmr_ctrl_pc_read_enable_out [i]; diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 75e7dda8..979483ed 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -179,7 +179,8 @@ module HMR_wrap return (a > b) ? a : b; endfunction - localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, TMRSupported || TMRFixed ? NumTMRGroups : 0); + localparam int unsigned NumBackupRegfiles = max(DMRSupported || DMRFixed ? NumDMRGroups : 0, + TMRSupported || TMRFixed ? NumTMRGroups : 0); function automatic int tmr_group_id (int core_id); if (InterleaveGrps) return core_id % NumTMRGroups; @@ -1630,7 +1631,7 @@ module HMR_wrap for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs localparam int unsigned CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); - if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr + if (TMRFixed && i < NumTMRGroups) begin : gen_fixed_tmr // CTRL assign sys_core_busy_o [i] = tmr_core_busy_out[CoreCoreIndex]; @@ -1649,8 +1650,8 @@ module HMR_wrap assign filt_data_data [i] = tmr_data_wdata_out[CoreCoreIndex]; assign sys_data_user_o [i] = tmr_data_user_out [CoreCoreIndex]; assign filt_data_be [i] = tmr_data_be_out [CoreCoreIndex]; - end else begin - if (i >= NumTMRCores) begin : independent_stragglers + end else begin : gen_normal_tmr + if (i >= NumTMRCores) begin : gen_independent_stragglers // CTRL assign sys_core_busy_o [i] = core_core_busy_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; @@ -1680,7 +1681,7 @@ module HMR_wrap core_data_user_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign filt_data_be [i] = core_data_be_i [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - end else begin + end else begin : gen_tmr_normal always_comb begin if (core_in_tmr[i]) begin : tmr_mode if (tmr_core_id(tmr_group_id(i), 0) == i) begin : is_tmr_main_core @@ -1839,7 +1840,7 @@ module HMR_wrap for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs localparam CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); - if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr + if (DMRFixed && i < NumDMRGroups) begin : gen_fixed_dmr // CTRL assign sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex]; @@ -1858,8 +1859,8 @@ module HMR_wrap assign filt_data_data [i] = dmr_data_wdata_out[CoreCoreIndex]; assign sys_data_user_o [i] = dmr_data_user_out [CoreCoreIndex]; assign filt_data_be [i] = dmr_data_be_out [CoreCoreIndex]; - end else begin - if (i >= NumDMRCores) begin : independent_stragglers + end else begin : gen_normal_dmr + if (i >= NumDMRCores) begin : gen_independent_stragglers // CTRL assign sys_core_busy_o [i] = dmr_core_busy_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; @@ -1889,7 +1890,7 @@ module HMR_wrap dmr_data_user_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; assign filt_data_be [i] = dmr_data_be_out [TMRFixed ? i-NumTMRGroups+NumTMRCores : i]; - end else begin + end else begin : gen_dmr_normal always_comb begin if (core_in_dmr[i]) begin : dmr_mode if (dmr_core_id(dmr_group_id(i), 0) == i) begin : is_dmr_main_core diff --git a/rtl/HMR/hmr_unit.sv b/rtl/HMR/hmr_unit.sv index bbf0d66e..bbabbce5 100644 --- a/rtl/HMR/hmr_unit.sv +++ b/rtl/HMR/hmr_unit.sv @@ -708,7 +708,7 @@ module hmr_unit #( end end end - end else begin: no_dmr_checkers + end else begin: gen_no_dmr_checkers assign dmr_failure_main = '0; assign dmr_failure_data = '0; assign dmr_failure = '0; @@ -767,7 +767,7 @@ module hmr_unit #( end end end - end else begin + end else begin : gen_no_recovery assign core_backup_q = '0; assign rapid_recovery_nominal = '0; assign rapid_recovery_start = '0; @@ -879,16 +879,16 @@ module hmr_unit #( core_setback_o [i] = '0; end end - if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : tmr_mode + if (i < NumTMRCores && (TMRFixed || core_in_tmr[i])) begin : gen_tmr_mode assign core_inputs_o[i] = sys_inputs_i[SysCoreIndex]; - end else begin : independent_mode + end else begin : gen_independent_mode assign core_inputs_o[i] = sys_inputs_i[i]; end end for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs localparam int unsigned CoreCoreIndex = TMRFixed ? i : tmr_group_id(i); - if (TMRFixed && i < NumTMRGroups) begin : fixed_tmr + if (TMRFixed && i < NumTMRGroups) begin : gen_fixed_tmr assign sys_nominal_outputs_o[i] = tmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = tmr_bus_outputs [CoreCoreIndex]; end else begin : gen_not_fixed_tmr @@ -953,7 +953,7 @@ module hmr_unit #( for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs localparam int unsigned CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); - if (DMRFixed && i < NumDMRGroups) begin : fixed_dmr + if (DMRFixed && i < NumDMRGroups) begin : gen_fixed_dmr assign sys_nominal_outputs_o[i] = dmr_nominal_outputs[CoreCoreIndex]; assign sys_bus_outputs_o [i] = dmr_bus_outputs [CoreCoreIndex]; end else begin : gen_not_fixed_dmr diff --git a/rtl/HMR/recovery_rf.sv b/rtl/HMR/recovery_rf.sv index 58015312..c4d4c166 100644 --- a/rtl/HMR/recovery_rf.sv +++ b/rtl/HMR/recovery_rf.sv @@ -68,17 +68,18 @@ module recovery_rf #( ); // number of integer registers - localparam int unsigned NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NumWords = 2 ** (ADDR_WIDTH - 1); // number of floating point registers - localparam int unsigned NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); - localparam int unsigned NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + localparam int unsigned NumFpWords = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NumTotWords = + FPU ? (PULP_ZFINX ? NumWords : NumWords + NumFpWords) : NumWords; // integer register file - logic [NUM_WORDS-1:0][NonProtectedWidth-1:0] mem; - logic [NUM_WORDS-1:0][ DataWidth-1:0] ecc_mem; + logic [NumWords-1:0][NonProtectedWidth-1:0] mem; + logic [NumWords-1:0][ DataWidth-1:0] ecc_mem; // fp register file - logic [NUM_FP_WORDS-1:0][NonProtectedWidth-1:0] mem_fp; - logic [NUM_FP_WORDS-1:0][ DataWidth-1:0] ecc_mem_fp; + logic [NumFpWords-1:0][NonProtectedWidth-1:0] mem_fp; + logic [NumFpWords-1:0][ DataWidth-1:0] ecc_mem_fp; logic [DataWidth-1:0] wdata_a, wdata_b; @@ -88,8 +89,8 @@ module recovery_rf #( logic [ADDR_WIDTH-1:0] waddr_b; // write enable signals for all registers - logic [NUM_TOT_WORDS-1:0] we_a_dec; - logic [NUM_TOT_WORDS-1:0] we_b_dec; + logic [NumTotWords-1:0] we_a_dec; + logic [NumTotWords-1:0] we_b_dec; generate if (ECCEnabled) begin : gen_ecc_region @@ -104,7 +105,7 @@ module recovery_rf #( .out ( wdata_b ) ); - for (genvar index = 0; index < NUM_WORDS; index++) begin : gen_internal_decoder + for (genvar index = 0; index < NumWords; index++) begin : gen_internal_decoder prim_secded_39_32_dec internal_memory_decoder ( .in ( ecc_mem [index] ), .d_o ( mem [index] ), @@ -114,7 +115,7 @@ module recovery_rf #( end if (FPU == 1 && PULP_ZFINX == 0) begin : gen_fp_decoders - for (genvar index = 0; index < NUM_FP_WORDS; index++) begin : gen_internal_fp_decoder + for (genvar index = 0; index < NumFpWords; index++) begin : gen_internal_fp_decoder prim_secded_39_32_dec internal_fp_memory_decoder ( .in ( ecc_mem_fp [index] ), .d_o ( mem_fp [index] ), @@ -127,10 +128,10 @@ module recovery_rf #( assign wdata_a = wdata_a_i; assign wdata_b = wdata_b_i; - for (genvar index = 0; index < NUM_WORDS; index++) + for (genvar index = 0; index < NumWords; index++) assign mem [index] = ecc_mem [index]; - for (genvar index = 0; index < NUM_FP_WORDS; index++) + for (genvar index = 0; index < NumFpWords; index++) assign mem_fp [index] = ecc_mem_fp [index]; end endgenerate @@ -160,7 +161,7 @@ module recovery_rf #( genvar gidx; generate - for (gidx = 0; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder + for (gidx = 0; gidx < NumTotWords; gidx++) begin : gen_we_decoder assign we_a_dec[gidx] = (waddr_a == gidx) ? we_a_i : 1'b0; assign we_b_dec[gidx] = (waddr_b == gidx) ? we_b_i : 1'b0; end @@ -183,8 +184,8 @@ module recovery_rf #( end end - // loop from 1 to NUM_WORDS-1 as R0 is nil - for (i = 1; i < NUM_WORDS; i++) begin : gen_rf + // loop from 1 to NumWords-1 as R0 is nil + for (i = 1; i < NumWords; i++) begin : gen_rf always_ff @(posedge clk_i, negedge rst_ni) begin : register_write_behavioral if (rst_ni == 1'b0) begin ecc_mem[i] <= 32'b0; @@ -197,13 +198,13 @@ module recovery_rf #( if (FPU == 1 && PULP_ZFINX == 0) begin : gen_mem_fp_write // Floating point registers - for (l = 0; l < NUM_FP_WORDS; l++) begin : gen_fp_regs + for (l = 0; l < NumFpWords; l++) begin : gen_fp_regs always_ff @(posedge clk_i, negedge rst_ni) begin : fp_regs if (rst_ni == 1'b0) begin ecc_mem_fp[l] <= '0; end else begin - if (we_b_dec[l+NUM_WORDS] == 1'b1) ecc_mem_fp[l] <= wdata_b; - else if (we_a_dec[l+NUM_WORDS] == 1'b1) ecc_mem_fp[l] <= wdata_a; + if (we_b_dec[l+NumWords] == 1'b1) ecc_mem_fp[l] <= wdata_b; + else if (we_a_dec[l+NumWords] == 1'b1) ecc_mem_fp[l] <= wdata_a; end end end diff --git a/rtl/HMR/recovery_rf_latch.sv b/rtl/HMR/recovery_rf_latch.sv index 4a108ef4..99240581 100644 --- a/rtl/HMR/recovery_rf_latch.sv +++ b/rtl/HMR/recovery_rf_latch.sv @@ -72,18 +72,19 @@ module recovery_rf #( ); // number of integer registers - localparam int unsigned NUM_WORDS = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NumWords = 2 ** (ADDR_WIDTH - 1); // number of floating point registers - localparam int unsigned NUM_FP_WORDS = 2 ** (ADDR_WIDTH - 1); - localparam int unsigned NUM_TOT_WORDS = FPU ? (PULP_ZFINX ? NUM_WORDS : NUM_WORDS + NUM_FP_WORDS) : NUM_WORDS; + localparam int unsigned NumFpWords = 2 ** (ADDR_WIDTH - 1); + localparam int unsigned NumTotWords = + FPU ? (PULP_ZFINX ? NumWords : NumWords + NumFpWords) : NumWords; // integer register file - logic [NonProtectedWidth-1:0] mem [NUM_WORDS]; - logic [ DataWidth-1:0] ecc_mem [NUM_WORDS]; - logic [NUM_TOT_WORDS-1:1] waddr_onehot_a; - logic [NUM_TOT_WORDS-1:1] waddr_onehot_b , + logic [NonProtectedWidth-1:0] mem [NumWords]; + logic [ DataWidth-1:0] ecc_mem [NumWords]; + logic [NumTotWords-1:1] waddr_onehot_a; + logic [NumTotWords-1:1] waddr_onehot_b , waddr_onehot_b_q; - logic [NUM_TOT_WORDS-1:1] mem_clocks; + logic [NumTotWords-1:1] mem_clocks; logic [DataWidth-1:0] wdata_a , wdata_a_q , wdata_a_ecc; @@ -98,8 +99,8 @@ module recovery_rf #( logic clk_int; // fp register file - logic [NonProtectedWidth-1:0] mem_fp [NUM_FP_WORDS]; - logic [ DataWidth-1:0] ecc_mem_fp [NUM_FP_WORDS]; + logic [NonProtectedWidth-1:0] mem_fp [NumFpWords]; + logic [ DataWidth-1:0] ecc_mem_fp [NumFpWords]; int unsigned i; int unsigned j; @@ -124,7 +125,7 @@ module recovery_rf #( ); assign wdata_b = wdata_b_ecc; - for (genvar index = 0; index < NUM_WORDS; index++) begin : gen_internal_decoder + for (genvar index = 0; index < NumWords; index++) begin : gen_internal_decoder prim_secded_39_32_dec internal_memory_decoder ( .in ( ecc_mem [index] ), .d_o ( mem [index] ), @@ -134,7 +135,7 @@ module recovery_rf #( end if (FPU == 1 && PULP_ZFINX == 0) begin : gen_fp_decoders - for (genvar index = 0; index < NUM_FP_WORDS; index++) begin : gen_internal_fp_decoder + for (genvar index = 0; index < NumFpWords; index++) begin : gen_internal_fp_decoder prim_secded_39_32_dec internal_fp_memory_decoder ( .in ( ecc_mem_fp [index] ), .d_o ( mem_fp [index] ), @@ -143,16 +144,16 @@ module recovery_rf #( ); end end - end else begin : no_ecc_region + end else begin : gen_no_ecc_region assign wdata_a = wdata_a_i; assign wdata_a_ecc = '0; assign wdata_b = wdata_b_i; assign wdata_b_ecc = '0; - for (genvar index = 0; index < NUM_WORDS; index++) + for (genvar index = 0; index < NumWords; index++) assign mem [index] = ecc_mem [index]; - for (genvar index = 0; index < NUM_FP_WORDS; index++) + for (genvar index = 0; index < NumFpWords; index++) assign mem_fp [index] = ecc_mem_fp [index]; end endgenerate @@ -205,7 +206,7 @@ module recovery_rf #( genvar gidx; generate - for (gidx = 1; gidx < NUM_TOT_WORDS; gidx++) begin : gen_we_decoder + for (gidx = 1; gidx < NumTotWords; gidx++) begin : gen_we_decoder assign waddr_onehot_a[gidx] = (we_a_i == 1'b1) && (waddr_a == gidx); assign waddr_onehot_b[gidx] = (we_b_i == 1'b1) && (waddr_b == gidx); end @@ -215,7 +216,7 @@ module recovery_rf #( //-- WRITE : Clock gating (if integrated clock-gating cells are available) //----------------------------------------------------------------------------- generate - for (x = 1; x < NUM_TOT_WORDS; x++) begin : gen_clock_gate + for (x = 1; x < NumTotWords; x++) begin : gen_clock_gate tc_clk_gating clock_gate_i ( .clk_i ( clk_int ), .en_i ( waddr_onehot_a[x] | waddr_onehot_b[x] ), @@ -239,7 +240,7 @@ module recovery_rf #( // Note: The assignment has to be done inside this process or Modelsim complains about it ecc_mem[0] = '0; - for (k = 1; k < NUM_WORDS; k++) begin : w_WordIter + for (k = 1; k < NumWords; k++) begin : w_WordIter if (~rst_ni) ecc_mem[k] = '0; else if (mem_clocks[k] == 1'b1) ecc_mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; end @@ -249,10 +250,10 @@ module recovery_rf #( // Floating point registers always_latch begin : latch_wdata_fp if (FPU == 1) begin - for (l = 0; l < NUM_FP_WORDS; l++) begin : w_WordIter + for (l = 0; l < NumFpWords; l++) begin : w_WordIter if (~rst_ni) ecc_mem_fp[l] = '0; - else if (mem_clocks[l+NUM_WORDS] == 1'b1) - ecc_mem_fp[l] = waddr_onehot_b_q[l+NUM_WORDS] ? wdata_b_q : wdata_a_q; + else if (mem_clocks[l+NumWords] == 1'b1) + ecc_mem_fp[l] = waddr_onehot_b_q[l+NumWords] ? wdata_b_q : wdata_a_q; end end end From 7a5bf5b4ad6d077d16e7fda7a75620e09c7e43b1 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 7 Aug 2025 14:55:43 +0200 Subject: [PATCH 66/66] Fix lint --- rtl/HMR/HMR_wrap.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/HMR/HMR_wrap.sv b/rtl/HMR/HMR_wrap.sv index 979483ed..3fb2e183 100644 --- a/rtl/HMR/HMR_wrap.sv +++ b/rtl/HMR/HMR_wrap.sv @@ -1839,7 +1839,7 @@ module HMR_wrap end // gen_core_inputs for (genvar i = 0; i < NumSysCores; i++) begin : gen_core_outputs - localparam CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); + localparam int unsigned CoreCoreIndex = DMRFixed ? i : dmr_group_id(i); if (DMRFixed && i < NumDMRGroups) begin : gen_fixed_dmr // CTRL assign sys_core_busy_o [i] = dmr_core_busy_out[CoreCoreIndex];