From 03220334d2d42092f9669665414904339ec1f253 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Sat, 18 May 2024 16:59:36 +0200 Subject: [PATCH 01/48] Add relOBI encoding and decoding modules --- Bender.lock | 36 ++++++++++++++ Bender.yml | 1 + include/obi/typedef.svh | 40 +++++++++++++++ src/relobi_decoder.sv | 108 ++++++++++++++++++++++++++++++++++++++++ src/relobi_encoder.sv | 105 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 290 insertions(+) create mode 100644 src/relobi_decoder.sv create mode 100644 src/relobi_encoder.sv diff --git a/Bender.lock b/Bender.lock index 67dd6ef..07c10b9 100644 --- a/Bender.lock +++ b/Bender.lock @@ -1,4 +1,20 @@ packages: + apb: + revision: 77ddf073f194d44b9119949d2421be59789e69ae + version: 0.2.4 + source: + Git: https://github.com/pulp-platform/apb.git + dependencies: + - common_cells + axi: + revision: 9402c8a9ce0a7b5253c3c29e788612d771e8b5d6 + version: 0.39.3 + source: + Git: https://github.com/pulp-platform/axi.git + dependencies: + - common_cells + - common_verification + - tech_cells_generic common_cells: revision: 9afda9abb565971649c2aa0985639c096f351171 version: 1.38.0 @@ -13,6 +29,26 @@ packages: source: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] + redundancy_cells: + revision: 49a1b8ce7f6a468891e196297a789b36d1e8ff9d + version: null + source: + Git: https://github.com/pulp-platform/redundancy_cells.git + dependencies: + - common_cells + - common_verification + - register_interface + - tech_cells_generic + register_interface: + revision: ae616e5a1ec2b41e72d200e5ab09c65e94aebd3d + version: 0.4.4 + source: + Git: https://github.com/pulp-platform/register_interface.git + dependencies: + - apb + - axi + - common_cells + - common_verification tech_cells_generic: revision: 7968dd6e6180df2c644636bc6d2908a49f2190cf version: 0.2.13 diff --git a/Bender.yml b/Bender.yml index 5d4f84d..47aba8f 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,6 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 49a1b8ce7f6a468891e196297a789b36d1e8ff9d } export_include_dirs: - include diff --git a/include/obi/typedef.svh b/include/obi/typedef.svh index 9bbe65a..9ab0006 100644 --- a/include/obi/typedef.svh +++ b/include/obi/typedef.svh @@ -127,4 +127,44 @@ `OBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, obi_t``_r_optional_t) \ `OBI_TYPEDEF_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) +`define RELOBI_TYPEDEF_A_CHAN_T(a_chan_t, ADDR_WIDTH, DATA_WIDTH, ID_WIDTH, a_optional_t) \ + typedef struct packed { \ + logic [ ADDR_WIDTH+hsiao_ecc_pkg::min_ecc(ADDR_WIDTH)-1:0] addr; \ + logic we; \ + logic [ DATA_WIDTH/8-1:0] be; \ + logic [ DATA_WIDTH+hsiao_ecc_pkg::min_ecc(DATA_WIDTH)-1:0] wdata; \ + logic [ ID_WIDTH-1:0] aid; \ + a_optional_t a_optional; \ + logic [hsiao_ecc_pkg::min_ecc(1+DATA_WIDTH/8+ID_WIDTH+$bits(a_optional_t))-1:0] other_ecc; \ + } a_chan_t; + +`define RELOBI_TYEPDEF_DEFAULT_REQ_T(req_t, a_chan_t) \ + typedef struct packed { \ + a_chan_t a; \ + logic [2:0] req; \ + } req_t; + +`define RELOBI_TYEPDEF_REQ_T(req_t, a_chan_t) \ + typedef struct packed { \ + a_chan_t a; \ + logic [2:0] req; \ + logic [2:0] rready; \ + } req_t; + +`define OBI_TYPEDEF_R_CHAN_T(r_chan_t, RDATA_WIDTH, ID_WIDTH, r_optional_t) \ + typedef struct packed { \ + logic [ RDATA_WIDTH+hsiao_ecc_pkg::min_ecc(RDATA_WIDTH)-1:0] rdata; \ + logic [ ID_WIDTH-1:0] rid; \ + logic err; \ + r_optional_t r_optional; \ + logic [hsiao_ecc_pkg::min_ecc(ID_WIDTH+1+$bits(r_optional_t))-1:0] other_ecc; \ + } r_chan_t; + +`define RELOBI_TYPEDEF_RSP_T(rsp_t, r_chan_t) \ + typedef struct packed { \ + r_chan_t r; \ + logic [2:0] gnt; \ + logic [2:0] rvalid; \ + } rsp_t; + `endif // OBI_TYPEDEF_SVH diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv new file mode 100644 index 0000000..ab88c27 --- /dev/null +++ b/src/relobi_decoder.sv @@ -0,0 +1,108 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +/// An encoder for reliable OBI +module relobi_decoder import hsiao_ecc_pkg::*; #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter relobi_req_t = logic, + parameter relobi_rsp_t = logic, + parameter obi_req_t = logic, + parameter obi_rsp_t = logic, + parameter a_optional_t = logic, + parameter r_optional_t = logic +) ( + input relobi_req_t rel_req_i, + output relobi_rsp_t rel_rsp_o, + + output obi_req_t req_o, + input obi_rsp_t rsp_i + + // TODO: error output!!! +); + + TMR_voter_detect i_req_valid_vote ( + .a_i (rel_req_i.req[0]), + .b_i (rel_req_i.req[1]), + .c_i (rel_req_i.req[2]), + .majority_o (req_o.req), + .error_cba_o() + ); + + assign rel_rsp_o.gnt = {3{rsp_i.gnt}}; + + if (Cfg.UseRReady) begin : gen_rready_vote + TMR_voter_detect i_rsp_ready_vote ( + .a_i (rel_req_i.rready[0]), + .b_i (rel_req_i.rready[1]), + .c_i (rel_req_i.rready[2]), + .majority_o (req_o.rready), + .error_cba_o() + ); + end + + assign rel_rsp_o.rvalid = {3{rsp_i.rvalid}}; + + hsiao_ecc_dec #( + .DataWidth ( Cfg.AddrWidth ) + ) i_addr_dec ( + .in ( rel_req_i.a.addr ), + .out ( req_o.a.addr ), + .syndrome_o(), + .err_o () + ); + + hsiao_ecc_dec #( + .DataWidth ( Cfg.DataWidth ) + ) i_wdata_dec ( + .in ( rel_req_i.a.wdata ), + .out ( req_o.a.wdata ), + .syndrome_o(), + .err_o () + ); + + hsiao_ecc_dec #( + .DataWidth ( 1 /* we */ + + Cfg.DataWidth/8 /* be */ + + Cfg.IdWidth /* aid */ + + $bits(a_optional_t) /* optional */ ) + ) i_a_remaining_dec ( + .in ( {rel_req_i.a.other_ecc, + rel_req_i.a.we, + rel_req_i.a.be, + rel_req_i.a.aid, + rel_req_i.a.a_optional} ), + .out ( {req_o.a.we, + req_o.a.be, + req_o.a.aid, + req_o.a.a_optional} ), + .syndrome_o(), + .err_o () + ); + + hsiao_ecc_enc #( + .DataWidth ( Cfg.DataWidth ) + ) i_rdata_enc ( + .in ( rsp_i.r.rdata ), + .out( rsp_o.r.rdata ) + ); + + hsiao_ecc_enc #( + .DataWidth ( Cfg.IdWidth /* rid */ + + 1 /* err */ + + $bits(r_optional_t) /* optional */ ) + ) i_r_remaining_enc ( + .in ( {rsp_i.r.rid, + rsp_i.r.err, + rsp_i.r.r_optional} ), + .out( {rel_rsp_o.r.other_ecc, + rel_rsp_o.r.rid, + rel_rsp_o.r.err, + rel_rsp_o.r.r_optional} ) + ); + +endmodule diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv new file mode 100644 index 0000000..2ff5507 --- /dev/null +++ b/src/relobi_encoder.sv @@ -0,0 +1,105 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_encoder #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter relobi_req_t = logic, + parameter relobi_rsp_t = logic, + parameter obi_req_t = logic, + parameter obi_rsp_t = logic, + parameter a_optional_t = logic, + parameter r_optional_t = logic +) ( + input obi_req_t req_i, + output obi_rsp_t rsp_o, + + output relobi_req_t rel_req_o, + input relobi_rsp_t rel_rsp_i + + // TODO: error output!!! +); + + assign rel_req_o.req = {3{req_i.req}}; + + TMR_voter_detect i_req_gnt_vote ( + .a_i (rel_rsp_i.gnt[0]), + .b_i (rel_rsp_i.gnt[1]), + .c_i (rel_rsp_i.gnt[2]), + .majority_o (rsp_o.gnt), + .error_cba_o() + ); + + if (Cfg.UseRReady) begin : gen_rready_multiply + assign rel_req_o.rready = {3{req_i.rready}}; + end + + TMR_voter_detect i_rsp_valid_vote ( + .a_i (rel_rsp_i.rvalid[0]), + .b_i (rel_rsp_i.rvalid[1]), + .c_i (rel_rsp_i.rvalid[2]), + .majority_o (rsp_o.rvalid), + .error_cba_o() + ); + + hsiao_ecc_enc #( + .DataWidth ( Cfg.AddrWidth ) + ) i_addr_enc ( + .in ( req_i.a.addr ), + .out( rel_req_o.a.addr ), + ); + + hsiao_ecc_enc #( + .DataWidth ( Cfg.DataWidth ) + ) i_wdata_enc ( + .in ( req_i.a.wdata ), + .out( rel_req_o.a.wdata ), + ); + + hsiao_ecc_enc #( + .DataWidth ( 1 /* we */ + + Cfg.DataWidth/8 /* be */ + + Cfg.IdWidth /* aid */ + + $bits(a_optional_t) /* optional */ ) + ) i_a_remaining_enc ( + .in ( {req_i.a.we, + req_i.a.be, + req_i.a.aid, + req_i.a.a_optional} ), + .out ( {rel_req_o.a.other_ecc, + rel_req_o.a.we, + rel_req_o.a.be, + rel_req_o.a.aid, + rel_req_o.a.a_optional} ) + ); + + hsiao_ecc_dec #( + .DataWidth ( Cfg.DataWidth ) + ) i_rdata_dec ( + .in ( rel_rsp_i.r.rdata ), + .out ( rsp_o.r.rdata ), + .syndrome_o(), + .err_o () + ); + + hsiao_ecc_dec #( + .DataWidth ( Cfg.IdWidth /* rid */ + + 1 /* err */ + + $bits(r_optional_t) /* optional */ ) + ) i_r_remaining_dec ( + .in ( {rel_rsp_i.r.other_ecc, + rel_rsp_i.r.rid, + rel_rsp_i.r.err, + rel_rsp_i.r.r_optional} ), + .out( {rsp_o.r.rid, + rsp_o.r.err, + rsp_o.r.r_optional} ), + .syndrome_o(), + .err_o () + ); + +endmodule From e4846587fe78d7968e03395592b1c821e284689e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 14 Aug 2024 19:38:46 +0200 Subject: [PATCH 02/48] Add relobi demux --- Bender.yml | 9 +++ src/relobi_demux.sv | 164 ++++++++++++++++++++++++++++++++++++++++++++ src/relobi_tmr_r.sv | 93 +++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 src/relobi_demux.sv create mode 100644 src/relobi_tmr_r.sv diff --git a/Bender.yml b/Bender.yml index 47aba8f..fedc49c 100644 --- a/Bender.yml +++ b/Bender.yml @@ -39,3 +39,12 @@ sources: - src/test/tb_obi_xbar.sv - src/test/atop_golden_mem_pkg.sv - src/test/tb_obi_atop_resolver.sv + + - target: relOBI + files: + # Level 1 + - src/relobi_decoder.sv + - src/relobi_encoder.sv + - src/relobi_tmr_r.sv + # Level 2 + - src/relobi_demux.sv diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv new file mode 100644 index 0000000..009cb87 --- /dev/null +++ b/src/relobi_demux.sv @@ -0,0 +1,164 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_demux #( + /// The OBI configuration for all ports. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The request struct for all ports. + parameter type obi_req_t = logic, + /// The response struct for all ports. + parameter type obi_rsp_t = logic, + /// The r_chan struct for all ports. + parameter type obi_r_chan_t = logic, + /// The number of manager ports. + parameter int unsigned NumMgrPorts = 32'd0, + /// The maximum number of outstanding transactions. + parameter int unsigned NumMaxTrans = 32'd0, + /// Use TMR for select signal + parameter bit TmrSelect = 1'b1, + /// The type of the port select signal. + parameter type select_t = logic [$clog2(NumMgrPorts)-1:0], + parameter int unsigned SelWidth = TmrSelect ? 3 : 1 +) ( + input logic clk_i, + input logic rst_ni, + + input select_t [ SelWidth-1:0] sbr_port_select_i, + input obi_req_t sbr_port_req_i, + output obi_rsp_t sbr_port_rsp_o, + + output obi_req_t [NumMgrPorts-1:0] mgr_ports_req_o, + input obi_rsp_t [NumMgrPorts-1:0] mgr_ports_rsp_i +); + + if (ObiCfg.Integrity) begin : gen_integrity_err + $fatal(1, "unimplemented"); + end + + // stall requests to ensure in-order behavior (could be handled differently with rready) + localparam int unsigned CounterWidth = cf_math_pkg::idx_width(NumMaxTrans); + + // Internals TMR'd + + logic [2:0] cnt_up, cnt_down, overflow; + logic [2:0][CounterWidth-1:0] in_flight; + logic [2:0] sbr_port_gnt; + logic [2:0] sbr_port_rready; + + select_t [2:0] select_d, select_d_voted, select_q, select_i_tmr; + + logic [NumMgrPorts-1:0][2:0] mgr_ports_req; + + for (genvar i = 0; i < 3; i++) begin : gen_tmr + assign select_i_tmr[i] = TmrSelect ? sbr_port_select_i[i] : sbr_port_select_i[0]; + + always_comb begin : proc_req + select_d[i] = select_q[i]; + cnt_up[i] = 1'b0; + for (int j = 0; j < NumMgrPorts; j++) begin + mgr_ports_req[j][i] = 1'b0; + end + sbr_port_gnt[i] = 1'b0; + + if (!overflow[i]) begin + if (select_i_tmr[i] == select_q[i] || in_flight[i] == '0 || (in_flight[i] == 1 && cnt_down[i])) begin + mgr_ports_req[select_i_tmr[i]][i] = sbr_port_req_i.req[i]; + sbr_port_gnt[i] = mgr_ports_rsp_i[select_i_tmr[i]].gnt[i]; + end + end + + if (mgr_ports_req[select_i_tmr[i]][i] && mgr_ports_rsp_i[select_i_tmr[i]].gnt[i]) begin + select_d[i] = select_i_tmr[i]; + cnt_up[i] = 1'b1; + end + end + end + + for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_mgr_req + assign mgr_ports_req_o[i].req = mgr_ports_req[i]; + assign mgr_ports_req_o[i].a = sbr_port_req_i.a; + end + + assign sbr_port_rsp_o.gnt = sbr_port_gnt; + + relobi_tmr_r #( + .ObiCfg (ObiCfg), + .obi_r_chan_t(obi_r_chan_t) + ) i_r_vote ( + .three_r_i({mgr_ports_rsp_i[select_q[2]].r, + mgr_ports_rsp_i[select_q[1]].r, + mgr_ports_rsp_i[select_q[0]].r}), + .voted_r_o(sbr_port_rsp_o.r) + ); + + for (genvar i = 0; i < 3; i++) begin : gen_rvalid + // Could be voted, but with only one error source (either select_q or rvalid) should suffice + assign sbr_port_rsp_o.rvalid[i] = mgr_ports_rsp_i[select_q[i]].rvalid[i]; + end + + if (ObiCfg.UseRReady) begin : gen_rready + assign sbr_port_rready = sbr_port_req_i.rready; + for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_rready + assign mgr_ports_req_o[i].rready = sbr_port_req_i.rready; + end + end else begin : gen_no_rready + assign sbr_port_rready = 3'b111; + end + + logic [2:0][CounterWidth:0] counter_q, counter_d_voted, counter_d; + + for (genvar i = 0; i < 3; i++) begin : gen_counter + // Could be voted, but with only one error source (either select_q or rvalid) should suffice + assign cnt_down[i] = mgr_ports_rsp_i[select_q[i]].rvalid[i] && sbr_port_rready[i]; + + assign overflow[i] = counter_q[CounterWidth]; + assign in_flight[i] = counter_q[CounterWidth-1:0]; + + always_comb begin + counter_d[i] = counter_q[i]; + + if (cnt_up & ~cnt_down) begin + counter_d[i] = counter_q[i] + {{CounterWidth-1{1'b0}}, 1'b1}; + end else if (cnt_down & ~cnt_up) begin + coutner_d[i] = counter_q[i] - {{CounterWidth-1{1'b0}}, 1'b1}; + end + end + end + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_state + bitwise_TMR_voter #( + .DataWidth( $clog2(NumMgrPorts) ) + ) i_select_vote ( + .a_i (select_d[0]), + .b_i (select_d[1]), + .c_i (select_d[2]), + .majority_o (select_d_voted[i]), + .error_o (), + .error_cba_o() + ); + bitwise_TMR_voter #( + .DataWidth( CounterWidth+1 ) + ) i_select_vote ( + .a_i (counter_d[0]), + .b_i (counter_d[1]), + .c_i (counter_d[2]), + .majority_o (counter_d_voted[i]), + .error_o (), + .error_cba_o() + ); + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_select + if(!rst_ni) begin + counter_q <= '0; + select_q <= '0; + end else begin + counter_q <= counter_d_voted; + select_q <= select_d_voted; + end + end + +endmodule diff --git a/src/relobi_tmr_r.sv b/src/relobi_tmr_r.sv new file mode 100644 index 0000000..b078fd5 --- /dev/null +++ b/src/relobi_tmr_r.sv @@ -0,0 +1,93 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_tmr_r #( + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + parameter type obi_r_chan_t = logic, + parameter type r_optional_t = logic +) ( + input obi_r_chan_t [2:0] three_r_i, + output obi_r_chan_t voted_r_o +); + + bitwise_TMR_voter #( + .DataWidth(ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)) + ) i_r_data ( + .a_i (three_r_i[0].rdata), + .b_i (three_r_i[1].rdata), + .c_i (three_r_i[2].rdata), + .majority_o (voted_r_o.rdata), + .error_o (), + .error_cba_o() + ); + bitwise_TMR_voter #( + .DataWidth(ObiCfg.IdWidth) + ) i_r_id ( + .a_i (three_r_i[0].rid), + .b_i (three_r_i[1].rid), + .c_i (three_r_i[2].rid), + .majority_o (voted_r_o.rid), + .error_o (), + .error_cba_o() + ); + TMR_voter i_r_err ( + .a_i (three_r_i[0].err), + .b_i (three_r_i[1].err), + .c_i (three_r_i[2].err), + .majority_o (voted_r_o.err) + ); + + if (ObiCfg.OptionalCfg.RUserWidth) begin : gen_ruser + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.RUserWidth) + ) i_r_id ( + .a_i (three_r_i[0].r_optional.user), + .b_i (three_r_i[1].r_optional.user), + .c_i (three_r_i[2].r_optional.user), + .majority_o (voted_r_o.r_optional.user), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.RChkWidth) begin : gen_rchk + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.RChkWidth) + ) i_r_id ( + .a_i (three_r_i[0].r_optional.rchk), + .b_i (three_r_i[1].r_optional.rchk), + .c_i (three_r_i[2].r_optional.rchk), + .majority_o (voted_r_o.r_optional.rchk), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.UseAtop) begin : gen_exokay + TMR_voter i_r_err ( + .a_i (three_r_i[0].r_optional.exokay), + .b_i (three_r_i[1].r_optional.exokay), + .c_i (three_r_i[2].r_optional.exokay), + .majority_o (voted_r_o.r_optional.exokay) + ); + end + if (!ObiCfg.OptionalCfg.RUserWidth && + !ObiCfg.OptionalCfg.RChkWidth && + !ObiCfg.OptionalCfg.UseAtop ) begin : gen_optional_tie + assign voted_r_o.r_optional = '0; + end + + bitwise_TMR_voter #( + .DataWidth(hsiao_ecc_pkg::min_ecc(ObiCfg.IdWidth+1+$bits(r_optional_t))) + ) i_r_id ( + .a_i (three_r_i[0].other_ecc), + .b_i (three_r_i[1].other_ecc), + .c_i (three_r_i[2].other_ecc), + .majority_o (voted_r_o.other_ecc), + .error_o (), + .error_cba_o() + ); + + +endmodule From 884ccd5e1869a9e2fd1898fc124bd32151f648b6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 30 Sep 2024 19:58:26 +0200 Subject: [PATCH 03/48] Update redundancy_cells --- .gitignore | 1 + Bender.lock | 2 +- Bender.yml | 2 +- include/obi/typedef.svh | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 092a4fa..87a730a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .bender +working_dir diff --git a/Bender.lock b/Bender.lock index 07c10b9..c3176b1 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 49a1b8ce7f6a468891e196297a789b36d1e8ff9d + revision: d924bd6a2ffa48f0e6d26e6c66725012cf677abe version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index fedc49c..cfd3ebf 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 49a1b8ce7f6a468891e196297a789b36d1e8ff9d } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: d924bd6a2ffa48f0e6d26e6c66725012cf677abe } export_include_dirs: - include diff --git a/include/obi/typedef.svh b/include/obi/typedef.svh index 9ab0006..5772cda 100644 --- a/include/obi/typedef.svh +++ b/include/obi/typedef.svh @@ -151,7 +151,7 @@ logic [2:0] rready; \ } req_t; -`define OBI_TYPEDEF_R_CHAN_T(r_chan_t, RDATA_WIDTH, ID_WIDTH, r_optional_t) \ +`define RELOBI_TYPEDEF_R_CHAN_T(r_chan_t, RDATA_WIDTH, ID_WIDTH, r_optional_t) \ typedef struct packed { \ logic [ RDATA_WIDTH+hsiao_ecc_pkg::min_ecc(RDATA_WIDTH)-1:0] rdata; \ logic [ ID_WIDTH-1:0] rid; \ From 8a03311aedb6a7c02225efbfa3bd00900394d2e3 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 30 Sep 2024 19:58:49 +0200 Subject: [PATCH 04/48] Add explanatory comments to OBI IPs. --- src/obi_mux.sv | 2 ++ src/obi_pkg.sv | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/obi_mux.sv b/src/obi_mux.sv index 5e17b5c..6c44cd8 100644 --- a/src/obi_mux.sv +++ b/src/obi_mux.sv @@ -35,9 +35,11 @@ module obi_mux #( input logic rst_ni, input logic testmode_i, + /// Subordinate ports (input) input sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req_i, output sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp_o, + /// Manager ports (output) output mgr_port_obi_req_t mgr_port_req_o, input mgr_port_obi_rsp_t mgr_port_rsp_i ); diff --git a/src/obi_pkg.sv b/src/obi_pkg.sv index 32bb1d1..8ff947d 100644 --- a/src/obi_pkg.sv +++ b/src/obi_pkg.sv @@ -15,8 +15,11 @@ package obi_pkg; /// The OBI prot type, to be expanded. typedef logic [2:0] prot_t; + /// Default ATOP has no atomic/exclusive operation, i.e., standard transaction. localparam atop_t DefaultAtop = 6'b000000; + /// Default Memory type is non-bufferable and non-cacheable. localparam memtype_t DefaultMemtype = 2'b00; + /// Default Prot is Data access in machine mode. localparam prot_t DefaultProt = 3'b111; /// The config type for OBI bus optional fields. @@ -33,6 +36,7 @@ package obi_pkg; int unsigned RChkWidth; } obi_optional_cfg_t; + /// The minimal optional configuration disables all optional features. localparam obi_optional_cfg_t ObiMinimalOptionalConfig = '{ UseAtop: 1'b0, UseMemtype: 1'b0, @@ -46,6 +50,7 @@ package obi_pkg; RChkWidth: 0 }; + /// The atop optional config only enables atomics, everything else is disabled. localparam obi_optional_cfg_t ObiAtopOptionalConfig = '{ UseAtop: 1'b1, UseMemtype: 1'b0, @@ -59,6 +64,7 @@ package obi_pkg; RChkWidth: 0 }; + /// Returns a config enabling all optional features with specified user, mid, and chk widths. function automatic obi_optional_cfg_t obi_all_optional_config(int unsigned AUserWidth, int unsigned WUserWidth, int unsigned RUserWidth, int unsigned MidWidth, int unsigned AChkWidth, int unsigned RChkWidth); @@ -88,6 +94,7 @@ package obi_pkg; obi_optional_cfg_t OptionalCfg; } obi_cfg_t; + /// Returns a default configuration with specified address, data, and ID widths, and a specified optional configuration. function automatic obi_cfg_t obi_default_cfg(int unsigned AddrWidth, int unsigned DataWidth, int unsigned IdWidth, obi_optional_cfg_t OptionalCfg); obi_default_cfg = '{ @@ -102,9 +109,10 @@ package obi_pkg; }; endfunction - /// The default OBI bus config. + /// The default OBI bus config (32-bit address and data, 1-bit ID width, no optional features. localparam obi_cfg_t ObiDefaultConfig = obi_default_cfg(32, 32, 1, ObiMinimalOptionalConfig); + /// Returns an OBI bus config increasing the ID width for a multiplexer/crossbar with NumManagers. function automatic obi_cfg_t mux_grow_cfg(obi_cfg_t ObiCfgIn, int unsigned NumManagers); mux_grow_cfg = '{ UseRReady: ObiCfgIn.UseRReady, @@ -118,6 +126,7 @@ package obi_pkg; }; endfunction + /// OBI Atomic operations. typedef enum atop_t { ATOPLR = 6'h22, ATOPSC = 6'h23, From 19ab1deeeb0e90bddc6db352360a80295184929c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 30 Sep 2024 20:07:45 +0200 Subject: [PATCH 05/48] Extract a_other enc/dec --- Bender.yml | 9 +++++-- src/relobi_a_other_decoder.sv | 44 +++++++++++++++++++++++++++++++ src/relobi_a_other_encoder.sv | 34 ++++++++++++++++++++++++ src/relobi_decoder.sv | 28 +++++++++----------- src/relobi_encoder.sv | 26 +++++++++---------- src/relobi_pkg.sv | 49 +++++++++++++++++++++++++++++++++++ 6 files changed, 158 insertions(+), 32 deletions(-) create mode 100644 src/relobi_a_other_decoder.sv create mode 100644 src/relobi_a_other_encoder.sv create mode 100644 src/relobi_pkg.sv diff --git a/Bender.yml b/Bender.yml index cfd3ebf..1b9a2b8 100644 --- a/Bender.yml +++ b/Bender.yml @@ -43,8 +43,13 @@ sources: - target: relOBI files: # Level 1 - - src/relobi_decoder.sv - - src/relobi_encoder.sv + - src/relobi_pkg.sv - src/relobi_tmr_r.sv # Level 2 + - src/relobi_a_other_decoder.sv + - src/relobi_a_other_encoder.sv + # Level 3 + - src/relobi_decoder.sv + - src/relobi_encoder.sv + # Level 4 - src/relobi_demux.sv diff --git a/src/relobi_a_other_decoder.sv b/src/relobi_a_other_decoder.sv new file mode 100644 index 0000000..6945d7a --- /dev/null +++ b/src/relobi_a_other_decoder.sv @@ -0,0 +1,44 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_a_other_decoder #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type a_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_a_other_ecc_width(Cfg) +) ( + input logic we_i, + input logic [Cfg.DataWidth/8-1:0] be_i, + input logic [Cfg.IdWidth -1:0] aid_i, + input a_optional_t a_optional_i, + input logic [ OtherEccWidth-1:0] other_ecc_i, + + output logic we_o, + output logic [Cfg.DataWidth/8-1:0] be_o, + output logic [Cfg.IdWidth -1:0] aid_o, + output a_optional_t a_optional_o + + // TODO: error +); + + hsiao_ecc_dec #( + .DataWidth (relobi_pkg::relobi_a_other_width(Cfg)) + ) i_a_remaining_dec ( + .in ( {other_ecc_i, + we_i, + be_i, + aid_i, + a_optional_i} ), + .out ( {we_o, + be_o, + aid_o, + a_optional_o} ), + .syndrome_o(), + .err_o () + ); + +endmodule diff --git a/src/relobi_a_other_encoder.sv b/src/relobi_a_other_encoder.sv new file mode 100644 index 0000000..7c722c4 --- /dev/null +++ b/src/relobi_a_other_encoder.sv @@ -0,0 +1,34 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_a_other_encoder #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type a_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_a_other_ecc_width(Cfg) +) ( + input logic we_i, + input logic [Cfg.DataWidth/8-1:0] be_i, + input logic [Cfg.IdWidth -1:0] aid_i, + input a_optional_t a_optional_i, + + output logic [ OtherEccWidth-1:0] other_ecc_o +); + + logic [relobi_pkg::relobi_a_other_width(Cfg)-1:0] unused; + + hsiao_ecc_enc #( + .DataWidth (relobi_pkg::relobi_a_other_width(Cfg)) + ) i_a_remaining_enc ( + .in ( {we_i, + be_i, + aid_i, + a_optional_i} ), + .out ( {other_ecc, unused} ) + ); + +endmodule diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index ab88c27..dbe47b4 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -65,23 +65,19 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .err_o () ); - hsiao_ecc_dec #( - .DataWidth ( 1 /* we */ + - Cfg.DataWidth/8 /* be */ + - Cfg.IdWidth /* aid */ + - $bits(a_optional_t) /* optional */ ) + relobi_a_other_decoder #( + .Cfg (Cfg), + .a_optional_t (a_optional_t) ) i_a_remaining_dec ( - .in ( {rel_req_i.a.other_ecc, - rel_req_i.a.we, - rel_req_i.a.be, - rel_req_i.a.aid, - rel_req_i.a.a_optional} ), - .out ( {req_o.a.we, - req_o.a.be, - req_o.a.aid, - req_o.a.a_optional} ), - .syndrome_o(), - .err_o () + .we_i (rel_req_i.a.we), + .be_i (rel_req_i.a.be), + .aid_i (rel_req_i.a.aid), + .a_optional_i(rel_req_i.a.a_optional), + .other_ecc (rel_req_i.a.other_ecc), + .we_o (req_o.a.we), + .be_o (req_o.a.be), + .aid_o (req_o.a.aid), + .a_optional_o(req_o.a.a_optional ) ); hsiao_ecc_enc #( diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index 2ff5507..0c7386a 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -60,22 +60,20 @@ module relobi_encoder #( .out( rel_req_o.a.wdata ), ); - hsiao_ecc_enc #( - .DataWidth ( 1 /* we */ + - Cfg.DataWidth/8 /* be */ + - Cfg.IdWidth /* aid */ + - $bits(a_optional_t) /* optional */ ) + relobi_a_other_encoder #( + .Cfg (Cfg), + .a_optional_t (a_optional_t) ) i_a_remaining_enc ( - .in ( {req_i.a.we, - req_i.a.be, - req_i.a.aid, - req_i.a.a_optional} ), - .out ( {rel_req_o.a.other_ecc, - rel_req_o.a.we, - rel_req_o.a.be, - rel_req_o.a.aid, - rel_req_o.a.a_optional} ) + .we_i (req_i.a.we), + .be_i (req_i.a.be), + .aid_i (req_i.a.aid), + .a_optional_i(req_i.a.a_optional), + .other_ecc_o (rel_req_o.a.other_ecc) ); + assign rel_req_o.a.we = req_i.a.we; + assign rel_req_o.a.be = req_i.a.be; + assign rel_req_o.a.aid = req_i.a.aid; + assign rel_req_o.a.a_optional = req_i.a.a_optional; hsiao_ecc_dec #( .DataWidth ( Cfg.DataWidth ) diff --git a/src/relobi_pkg.sv b/src/relobi_pkg.sv new file mode 100644 index 0000000..df06ebb --- /dev/null +++ b/src/relobi_pkg.sv @@ -0,0 +1,49 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +package relobi_pkg; + + let max(a,b) = (a > b) ? a : b; + + function automatic int unsigned relobi_a_other_width(obi_pkg::obi_cfg_t Cfg); + + relobi_a_other_width = 1 /* we */ + + Cfg.DataWidth/8 /* be */ + + Cfg.IdWidth /* aid */ + +/* a_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 6 : 0) + + (Cfg.OptionalCfg.UseMemtype ? 2 : 0) + + (Cfg.OptionalCfg.UseProt ? 3 : 0) + + (Cfg.OptionalCfg.UseDbg ? 1 : 0) + + Cfg.OptionalCfg.AUserWidth + + Cfg.OptionalCfg.WUserWidth + + Cfg.OptionalCfg.MidWidth + + Cfg.OptionalCfg.AChkWidth )); + + endfunction + + function automatic int unsigned relobi_a_other_ecc_width(obi_pkg::obi_cfg_t Cfg); + + relobi_a_other_ecc_width = hsiao_ecc_pkg::min_ecc(relobi_a_other_width(Cfg)); + + endfunction + + function automatic int unsigned relobi_r_other_width(obi_pkg::obi_cfg_t Cfg); + + relobi_r_other_width = 1 /* err */ + + Cfg.IdWidth /* rid */ + +/* a_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 1 : 0) + + Cfg.OptionalCfg.RUserWidth + + Cfg.OptionalCfg.RChkWidth )); + + endfunction + + function automatic int unsigned relobi_r_other_ecc_width(obi_pkg::obi_cfg_t Cfg); + + relobi_r_other_ecc_width = hsiao_ecc_pkg::min_ecc(relobi_r_other_width(Cfg)); + + endfunction + +endpackage \ No newline at end of file From 5a2e9eda92a31435a900b73aa957ab45b77b7fc5 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 6 May 2025 17:47:11 +0200 Subject: [PATCH 06/48] WIP: Add relobi mux --- src/relobi_decoder.sv | 4 +- src/relobi_mux.sv | 232 ++++++++++++++++++++++++++++++++++++++++++ src/relobi_tmr_a.sv | 182 +++++++++++++++++++++++++++++++++ 3 files changed, 416 insertions(+), 2 deletions(-) create mode 100644 src/relobi_mux.sv create mode 100644 src/relobi_tmr_a.sv diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index dbe47b4..0354ecc 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -73,11 +73,11 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .be_i (rel_req_i.a.be), .aid_i (rel_req_i.a.aid), .a_optional_i(rel_req_i.a.a_optional), - .other_ecc (rel_req_i.a.other_ecc), + .other_ecc_i (rel_req_i.a.other_ecc), .we_o (req_o.a.we), .be_o (req_o.a.be), .aid_o (req_o.a.aid), - .a_optional_o(req_o.a.a_optional ) + .a_optional_o(req_o.a.a_optional) ); hsiao_ecc_enc #( diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv new file mode 100644 index 0000000..2c98487 --- /dev/null +++ b/src/relobi_mux.sv @@ -0,0 +1,232 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +`include "obi/assign.svh" + +/// An OBI multiplexer. +module obi_mux #( + /// The configuration of the subordinate ports (input ports). + parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + /// The configuration of the manager port (output port). + parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + /// The request struct for the subordinate ports (input ports). + parameter type sbr_port_obi_req_t = logic, + /// The A channel struct for the subordinate ports (input ports). + parameter type sbr_port_a_chan_t = logic, + /// The response struct for the subordinate ports (input ports). + parameter type sbr_port_obi_rsp_t = logic, + /// The R channel struct for the subordinate ports (input ports). + parameter type sbr_port_r_chan_t = logic, + /// The request struct for the manager port (output port). + parameter type mgr_port_obi_req_t = sbr_port_obi_req_t, + /// The response struct for the manager port (output port). + parameter type mgr_port_obi_rsp_t = sbr_port_obi_rsp_t, + /// The A channel struct for the manager port (output port). + parameter type mgr_port_a_chan_t = logic, + /// The A channel optionals struct for all ports. + parameter type a_optional_t = logic, + /// The number of subordinate ports (input ports). + parameter int unsigned NumSbrPorts = 32'd0, + /// The maximum number of outstanding transactions. + parameter int unsigned NumMaxTrans = 32'd0, + /// Use the extended ID field (aid & rid) to route the response + parameter bit UseIdForRouting = 1'b0 +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + + input sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req_i, + output sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp_o, + + output mgr_port_obi_req_t mgr_port_req_o, + input mgr_port_obi_rsp_t mgr_port_rsp_i +); + if (NumSbrPorts <= 1) begin : gen_NumSbrPorts_err + $fatal(1, "unimplemented"); + end + if (MgrPortObiCfg.IdWidth < SbrPortObiCfg.IdWidth) begin : gen_IdWidthDecreasing_err + $fatal(1, "relobi_mux: IdWidth not allowed to decrease"); + end + if (MgrPortObiCfg.UseRReady != SbrPortObiCfg.UseRReady || + MgrPortObiCfg.CombGnt != SbrPortObiCfg.CombGnt || + MgrPortObiCfg.AddrWidth != SbrPortObiCfg.DataWidth || + MgrPortObiCfg.DataWidth != SbrPortObiCfg.DataWidth || + MgrPortObiCfg.Integrity != SbrPortObiCfg.Integrity || + MgrPortObiCfg.BeFull != SbrPortObiCfg.BeFull || + MgrPortObiCfg.OptionalCfg != SbrPortObiCfg.OptionalCfg ) begin : gen_ConfigDiff_err + $fatal(1, "relobi_mux: Configuration needs to be identical for mgr & sbr except IdWidth"); + end + + localparam int unsigned RequiredExtraIdWidth = $clog2(NumSbrPorts); + + logic [NumSbrPorts-1:0][2:0] sbr_ports_req, sbr_ports_gnt; + sbr_port_a_chan_t [NumSbrPorts-1:0] sbr_ports_a; + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_assign + assign sbr_ports_req[i] = sbr_ports_req_i[i].req; + assign sbr_ports_a[i] = sbr_ports_req_i[i].a; + assign sbr_ports_rsp_o[i].gnt = sbr_ports_gnt[i]; + end + + sbr_port_a_chan_t [2:0] mgr_port_a_in_sbr; + mgr_port_a_chan_t [2:0] mgr_port_a_tmr; + logic [2:0][RequiredExtraIdWidth-1:0] selected_id, response_id; + logic [2:0] mgr_port_req, fifo_full, fifo_pop; + + assign mgr_port_req_o.req = mgr_port_req & ~fifo_full; + + // rr_arb_tree #( + // .NumIn ( NumSbrPorts ), + // .DataType ( sbr_port_a_chan_t ), + // .AxiVldRdy ( 1'b1 ), + // .LockIn ( 1'b1 ) + // ) i_rr_arb ( + // .clk_i, + // .rst_ni, + + // .flush_i ( 1'b0 ), + // .rr_i ( '0 ), + + // .req_i ( sbr_ports_req ), + // .gnt_o ( sbr_ports_gnt ), + // .data_i ( sbr_ports_a ), + + // .req_o ( mgr_port_req ), + // .gnt_i ( mgr_port_rsp_i.gnt && ~fifo_full ), + // .data_o ( mgr_port_a_in_sbr ), + + // .idx_o ( selected_id ) + // ); + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_aid + if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical + always_comb begin + `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr[i]) + mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr[i].other_ecc; + end + end else begin : gen_aid_extend + logic we; + logic [MgrPortObiCfg.DataWidth/8-1:0] be; + logic [SbrPortObiCfg.IdWidth-1:0] sbr_aid; + logic [MgrPortObiCfg.IdWidth-1:0] mgr_aid; + a_optional_t a_optional; + logic [relobi_pkg::relobi_a_other_ecc_width(MgrPortObiCfg)-1:0] other_ecc; + relobi_a_other_decoder #( + .Cfg (SbrPortObiCfg), + .a_optional_t (a_optional_t) + ) i_other_decode ( + .we_i (mgr_port_a_in_sbr[i].we), + .be_i (mgr_port_a_in_sbr[i].be), + .aid_i (mgr_port_a_in_sbr[i].aid), + .a_optional_i(mgr_port_a_in_sbr[i].a_optional), + .other_ecc_i (mgr_port_a_in_sbr[i].other_ecc), + .we_o (we), + .be_o (be), + .aid_o (sbr_aid), + .a_optional_o(a_optional) + ); + if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + + RequiredExtraIdWidth ) begin + always_comb begin + mgr_aid = '0; + mgr_aid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0] = {selected_id[i], sbr_aid}; + end + end else begin + always_comb begin + mgr_aid = '0; + mgr_aid[SbrPortObiCfg.IdWidth-1:0] = sbr_aid; + end + end + relobi_a_other_encoder #( + .Cfg (MgrPortObiCfg), + .a_optional_t (a_optional_t) + ) i_other_encode ( + .we_i (we), + .be_i (be), + .aid_i (mgr_aid), + .a_optional_i(a_optional), + .other_ecc_o (other_ecc), + ); + + always_comb begin + `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr[i]) + mgr_port_a_tmr[i].we = we; + mgr_port_a_tmr[i].be = be; + mgr_port_a_tmr[i].aid = mgr_aid; + mgr_port_a_tmr[i].a_optional = a_optional; + mgr_port_a_tmr[i].other_ecc = other_ecc; + end + + end + end + + logic [2:0][SbrPortObiCfg.IdWidth-1:0] rsp_rid; + + if (UseIdForRouting) begin : gen_id_assign + if (!(MgrPortObiCfg.IdWidth > 0 && + (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + + RequiredExtraIdWidth ))) begin : gen_IdWidth_err + $fatal(1, "UseIdForRouting requires MgrPort IdWidth to increase with log2(NumSbrPorts)"); + end + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_rid + // TODO: ecc + + assign {response_id[i], rsp_rid[i]} = + mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0]; + assign fifo_full[i] = 1'b0; + end + + end else begin : gen_no_id_assign + + // fifo_v3 #( + // .FALL_THROUGH( 1'b0 ), + // .DATA_WIDTH ( RequiredExtraIdWidth ), + // .DEPTH ( NumMaxTrans ) + // ) i_fifo ( + // .clk_i, + // .rst_ni, + // .flush_i ('0), + // .testmode_i, + + // .full_o ( fifo_full ), + // .empty_o (), + // .usage_o (), + // .data_i ( selected_id ), + // .push_i ( mgr_port_req_o.req && mgr_port_rsp_i.gnt ), + + // .data_o ( response_id ), + // .pop_i ( fifo_pop ) + // ); + + end + + // if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect + // assign mgr_port_req_o.rready = sbr_ports_req_i[response_id].rready; + // end + // logic [NumSbrPorts-1:0] sbr_rsp_rvalid; + // sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; + // always_comb begin : proc_sbr_rsp + // for (int i = 0; i < NumSbrPorts; i++) begin + // sbr_rsp_r[i] = '0; + // sbr_rsp_rvalid[i] = '0; + // end + // `OBI_SET_R_STRUCT(sbr_rsp_r[response_id], mgr_port_rsp_i.r); + // sbr_rsp_rvalid[response_id] = mgr_port_rsp_i.rvalid; + // end + + // for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_rsp_assign + // assign sbr_ports_rsp_o[i].r = sbr_rsp_r[i]; + // assign sbr_ports_rsp_o[i].rvalid = sbr_rsp_rvalid[i]; + // end + + if (MgrPortObiCfg.UseRReady) begin : gen_fifo_pop + assign fifo_pop = mgr_port_rsp_i.rvalid & mgr_port_req_o.rready; + end else begin : gen_fifo_pop + assign fifo_pop = mgr_port_rsp_i.rvalid; + end + +endmodule diff --git a/src/relobi_tmr_a.sv b/src/relobi_tmr_a.sv new file mode 100644 index 0000000..2f56835 --- /dev/null +++ b/src/relobi_tmr_a.sv @@ -0,0 +1,182 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_tmr_a #( + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + parameter type obi_a_chan_t = logic, + parameter type a_optional_t = logic +) ( + input obi_a_chan_t [2:0] three_a_i, + output obi_a_chan_t voted_a_o +); + + bitwise_TMR_voter #( + .DataWidth(ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)) + ) i_r_data ( + .a_i (three_a_i[0].addr), + .b_i (three_a_i[1].addr), + .c_i (three_a_i[2].addr), + .majority_o (voted_a_o.addr), + .error_o (), + .error_cba_o() + ); + TMR_voter i_r_we ( + .a_i (three_a_i[0].we), + .b_i (three_a_i[1].we), + .c_i (three_a_i[2].we), + .majority_o (voted_a_o.we) + ); + bitwise_TMR_voter #( + .DataWidth(ObiCfg.DataWidth/8) + ) i_r_data ( + .a_i (three_a_i[0].be), + .b_i (three_a_i[1].be), + .c_i (three_a_i[2].be), + .majority_o (voted_a_o.be), + .error_o (), + .error_cba_o() + ); + bitwise_TMR_voter #( + .DataWidth(ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)) + ) i_r_data ( + .a_i (three_a_i[0].wdata), + .b_i (three_a_i[1].wdata), + .c_i (three_a_i[2].wdata), + .majority_o (voted_a_o.wdata), + .error_o (), + .error_cba_o() + ); + bitwise_TMR_voter #( + .DataWidth(ObiCfg.IdWidth) + ) i_r_id ( + .a_i (three_a_i[0].aid), + .b_i (three_a_i[1].aid), + .c_i (three_a_i[2].aid), + .majority_o (voted_a_o.aid), + .error_o (), + .error_cba_o() + ); + TMR_voter i_r_err ( + .a_i (three_r_i[0].err), + .b_i (three_r_i[1].err), + .c_i (three_r_i[2].err), + .majority_o (voted_r_o.err) + ); + + if (ObiCfg.OptionalCfg.AUserWidth) begin : gen_auser + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.RUserWidth) + ) i_r_id ( + .a_i (three_a_i[0].a_optional.auser), + .b_i (three_a_i[1].a_optional.auser), + .c_i (three_a_i[2].a_optional.auser), + .majority_o (voted_a_o.a_optional.auser), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.WUserWidth) begin : gen_wuser + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.RUserWidth) + ) i_r_id ( + .a_i (three_a_i[0].a_optional.wuser), + .b_i (three_a_i[1].a_optional.wuser), + .c_i (three_a_i[2].a_optional.wuser), + .majority_o (voted_a_o.a_optional.wuser), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.UseAtop) begin : gen_atop + bitwise_TMR_voter #( + .DataWidth(6) + ) i_r_err ( + .a_i (three_a_i[0].a_optional.atop), + .b_i (three_a_i[1].a_optional.atop), + .c_i (three_a_i[2].a_optional.atop), + .majority_o (voted_a_o.a_optional.atop), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.UseMemtype) begin : gen_memtype + bitwise_TMR_voter #( + .DataWidth(2) + ) i_r_err ( + .a_i (three_a_i[0].a_optional.memtype), + .b_i (three_a_i[1].a_optional.memtype), + .c_i (three_a_i[2].a_optional.memtype), + .majority_o (voted_a_o.a_optional.memtype), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.MidWidth) begin : gen_mid + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.MidWidth) + ) i_r_err ( + .a_i (three_a_i[0].a_optional.mid), + .b_i (three_a_i[1].a_optional.mid), + .c_i (three_a_i[2].a_optional.mid), + .majority_o (voted_a_o.a_optional.mid), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.UseProt) begin : gen_prot + bitwise_TMR_voter #( + .DataWidth(3) + ) i_r_err ( + .a_i (three_a_i[0].a_optional.prot), + .b_i (three_a_i[1].a_optional.prot), + .c_i (three_a_i[2].a_optional.prot), + .majority_o (voted_a_o.a_optional.prot), + .error_o (), + .error_cba_o() + ); + end + if (ObiCfg.OptionalCfg.UseDbg) begin : gen_dbg + TMR_voter i_r_err ( + .a_i (three_a_i[0].a_optional.dbg), + .b_i (three_a_i[1].a_optional.dbg), + .c_i (three_a_i[2].a_optional.dbg), + .majority_o (voted_a_o.a_optional.dbg) + ); + end + if (ObiCfg.OptionalCfg.AChkWidth) begin : gen_achk + bitwise_TMR_voter #( + .DataWidth(ObiCfg.OptionalCfg.AChkWidth) + ) i_r_id ( + .a_i (three_a_i[0].a_optional.achk), + .b_i (three_a_i[1].a_optional.achk), + .c_i (three_a_i[2].a_optional.achk), + .majority_o (voted_a_o.a_optional.achk), + .error_o (), + .error_cba_o() + ); + end + if (!ObiCfg.OptionalCfg.AUserWidth && + !ObiCfg.OptionalCfg.WUserWidth && + !ObiCfg.OptionalCfg.UseAtop && + !ObiCfg.OptionalCfg.UseMemtype && + !ObiCfg.OptionalCfg.MidWidth && + !ObiCfg.OptionalCfg.UseProt && + !ObiCfg.OptionalCfg.UseDbg && + !ObiCfg.OptionalCfg.AChkWidth ) begin : gen_optional_tie + assign voted_a_o.a_optional = '0; + end + bitwise_TMR_voter #( + .DataWidth(hsiao_ecc_pkg::min_ecc(1+ObiCfg.DataWidth/8+ObiCfg.IdWidth+$bits(a_optional_t))) + ) i_r_id ( + .a_i (three_a_i[0].other_ecc), + .b_i (three_a_i[1].other_ecc), + .c_i (three_a_i[2].other_ecc), + .majority_o (voted_a_o.other_ecc), + .error_o (), + .error_cba_o() + ); + +endmodule From c0719adcad30e1d87d2c08497043cf53d419d0ab Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 8 May 2025 13:46:16 +0200 Subject: [PATCH 07/48] Add r_other_enc/dec --- Bender.yml | 2 ++ src/relobi_a_other_encoder.sv | 2 +- src/relobi_decoder.sv | 21 +++++++++--------- src/relobi_encoder.sv | 23 +++++++++----------- src/relobi_pkg.sv | 4 ++-- src/relobi_r_other_decoder.sv | 41 +++++++++++++++++++++++++++++++++++ src/relobi_r_other_encoder.sv | 32 +++++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 src/relobi_r_other_decoder.sv create mode 100644 src/relobi_r_other_encoder.sv diff --git a/Bender.yml b/Bender.yml index 1b9a2b8..5a4a8ea 100644 --- a/Bender.yml +++ b/Bender.yml @@ -48,6 +48,8 @@ sources: # Level 2 - src/relobi_a_other_decoder.sv - src/relobi_a_other_encoder.sv + - src/relobi_r_other_decoder.sv + - src/relobi_r_other_encoder.sv # Level 3 - src/relobi_decoder.sv - src/relobi_encoder.sv diff --git a/src/relobi_a_other_encoder.sv b/src/relobi_a_other_encoder.sv index 7c722c4..f34482d 100644 --- a/src/relobi_a_other_encoder.sv +++ b/src/relobi_a_other_encoder.sv @@ -28,7 +28,7 @@ module relobi_a_other_encoder #( be_i, aid_i, a_optional_i} ), - .out ( {other_ecc, unused} ) + .out ( {other_ecc_o, unused} ) ); endmodule diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index 0354ecc..6aaa998 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -87,18 +87,17 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .out( rsp_o.r.rdata ) ); - hsiao_ecc_enc #( - .DataWidth ( Cfg.IdWidth /* rid */ + - 1 /* err */ + - $bits(r_optional_t) /* optional */ ) + relobi_r_other_encoder #( + .Cfg (Cfg), + .r_optional_t (r_optional_t) ) i_r_remaining_enc ( - .in ( {rsp_i.r.rid, - rsp_i.r.err, - rsp_i.r.r_optional} ), - .out( {rel_rsp_o.r.other_ecc, - rel_rsp_o.r.rid, - rel_rsp_o.r.err, - rel_rsp_o.r.r_optional} ) + .rid_i (rsp_i.r.rid), + .err_i (rsp_i.r.err), + .r_optional_i(rsp_i.r.r_optional), + .other_ecc_o (rel_rsp_o.r.other_ecc) ); + assign rel_rsp_o.r.rid = rsp_i.r.rid; + assign rel_rsp_o.r.err = rsp_i.r.err; + assign rel_rsp_o.r.r_optional = rsp_i.r.r_optional; endmodule diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index 0c7386a..44bc1dc 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -84,20 +84,17 @@ module relobi_encoder #( .err_o () ); - hsiao_ecc_dec #( - .DataWidth ( Cfg.IdWidth /* rid */ + - 1 /* err */ + - $bits(r_optional_t) /* optional */ ) + relobi_r_other_decoder #( + .Cfg (Cfg), + .r_optional_t (r_optional_t) ) i_r_remaining_dec ( - .in ( {rel_rsp_i.r.other_ecc, - rel_rsp_i.r.rid, - rel_rsp_i.r.err, - rel_rsp_i.r.r_optional} ), - .out( {rsp_o.r.rid, - rsp_o.r.err, - rsp_o.r.r_optional} ), - .syndrome_o(), - .err_o () + .rid_i (rel_rsp_i.r.rid), + .err_i (rel_rsp_i.r.err), + .r_optional_i(rel_rsp_i.r.r_optional), + .other_ecc_i (rel_rsp_i.r.other_ecc), + .rid_o (rsp_o.r.rid), + .err_o (rsp_o.r.err), + .r_optional_o(rsp_o.r.r_optional) ); endmodule diff --git a/src/relobi_pkg.sv b/src/relobi_pkg.sv index df06ebb..e073a5b 100644 --- a/src/relobi_pkg.sv +++ b/src/relobi_pkg.sv @@ -34,7 +34,7 @@ package relobi_pkg; relobi_r_other_width = 1 /* err */ + Cfg.IdWidth /* rid */ + -/* a_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 1 : 0) + +/* r_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 1 : 0) + Cfg.OptionalCfg.RUserWidth + Cfg.OptionalCfg.RChkWidth )); @@ -46,4 +46,4 @@ package relobi_pkg; endfunction -endpackage \ No newline at end of file +endpackage diff --git a/src/relobi_r_other_decoder.sv b/src/relobi_r_other_decoder.sv new file mode 100644 index 0000000..5b035fb --- /dev/null +++ b/src/relobi_r_other_decoder.sv @@ -0,0 +1,41 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_r_other_decoder #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type r_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_r_other_ecc_width(Cfg) +) ( + input logic [Cfg.IdWidth -1:0] rid_i, + input logic err_i, + input r_optional_t r_optional_i, + input logic [OtherEccWidth-1:0] other_ecc_i, + + output logic [Cfg.IdWidth -1:0] rid_o, + output logic err_o, + output r_optional_t r_optional_o + + // TODO: error +); + + + hsiao_ecc_dec #( + .DataWidth ( relobi_pkg::relobi_r_other_width(Cfg) ) + ) i_r_remaining_dec ( + .in ( {other_ecc_i, + rid_i, + err_i, + r_optional_i} ), + .out( {rid_o, + err_o, + r_optional_o} ), + .syndrome_o(), + .err_o () + ); + +endmodule diff --git a/src/relobi_r_other_encoder.sv b/src/relobi_r_other_encoder.sv new file mode 100644 index 0000000..71bb801 --- /dev/null +++ b/src/relobi_r_other_encoder.sv @@ -0,0 +1,32 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_r_other_encoder #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type r_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_r_other_ecc_width(Cfg) +) ( + input logic rid_i, + input logic [Cfg.DataWidth/8-1:0] err_i, + input r_optional_t r_optional_i, + + output logic [ OtherEccWidth-1:0] other_ecc_o +); + + logic [relobi_pkg::relobi_r_other_width(Cfg)-1:0] unused; + + hsiao_ecc_enc #( + .DataWidth (relobi_pkg::relobi_r_other_width(Cfg)) + ) i_a_remaining_enc ( + .in ( {rid_i, + err_i, + r_optional_i} ), + .out ( {other_ecc_o, unused} ) + ); + +endmodule From 2522c2437c4b1e8bd38230cc970322a3988e8eb3 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 8 May 2025 13:55:02 +0200 Subject: [PATCH 08/48] Update relobi mux --- src/relobi_mux.sv | 162 ++++++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 57 deletions(-) diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 2c98487..880b37f 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -7,7 +7,7 @@ `include "obi/assign.svh" /// An OBI multiplexer. -module obi_mux #( +module relobi_mux #( /// The configuration of the subordinate ports (input ports). parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, /// The configuration of the manager port (output port). @@ -28,6 +28,8 @@ module obi_mux #( parameter type mgr_port_a_chan_t = logic, /// The A channel optionals struct for all ports. parameter type a_optional_t = logic, + /// The R channel optionals struct for all ports. + parameter type r_optional_t = logic, /// The number of subordinate ports (input ports). parameter int unsigned NumSbrPorts = 32'd0, /// The maximum number of outstanding transactions. @@ -78,28 +80,35 @@ module obi_mux #( assign mgr_port_req_o.req = mgr_port_req & ~fifo_full; - // rr_arb_tree #( - // .NumIn ( NumSbrPorts ), - // .DataType ( sbr_port_a_chan_t ), - // .AxiVldRdy ( 1'b1 ), - // .LockIn ( 1'b1 ) - // ) i_rr_arb ( - // .clk_i, - // .rst_ni, + logic [2:0] rr_arb_mgr_port_gnt; - // .flush_i ( 1'b0 ), - // .rr_i ( '0 ), + for (genvar i = 0; i < 3; i++) begin : gen_mgr_port_gnt + assign rr_arb_mgr_port_gnt[i] = mgr_port_rsp_i.gnt[i] && ~fifo_full[i]; + end + + rel_rr_arb_tree #( + .NumIn ( NumSbrPorts ), + .DataType ( sbr_port_a_chan_t ), + .AxiVldRdy ( 1'b1 ), + .LockIn ( 1'b1 ), + .TmrStatus ( 1'b1 ) + ) i_rr_arb ( + .clk_i, + .rst_ni, + + .flush_i ( 1'b0 ), + .rr_i ( '0 ), - // .req_i ( sbr_ports_req ), - // .gnt_o ( sbr_ports_gnt ), - // .data_i ( sbr_ports_a ), + .req_i ( sbr_ports_req ), + .gnt_o ( sbr_ports_gnt ), + .data_i ( sbr_ports_a ), - // .req_o ( mgr_port_req ), - // .gnt_i ( mgr_port_rsp_i.gnt && ~fifo_full ), - // .data_o ( mgr_port_a_in_sbr ), + .req_o ( mgr_port_req ), + .gnt_i ( rr_arb_mgr_port_gnt ), + .data_o ( mgr_port_a_in_sbr ), - // .idx_o ( selected_id ) - // ); + .idx_o ( selected_id ) + ); for (genvar i = 0; i < 3; i++) begin : gen_tmr_aid if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical @@ -173,7 +182,18 @@ module obi_mux #( end for (genvar i = 0; i < 3; i++) begin : gen_tmr_rid - // TODO: ecc + relobi_r_other_decoder #( + .Cfg (SbrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_decode ( + .rid_i (mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth-1:0]), + .err_i (mgr_port_rsp_i.r.err), + .r_optional_i(mgr_port_rsp_i.r.r_optional), + .other_ecc_i (mgr_port_rsp_i.r.other_ecc), + .rid_o (rsp_rid[i]), + .err_o (), + .r_optional_o() + ); assign {response_id[i], rsp_rid[i]} = mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0]; @@ -181,47 +201,75 @@ module obi_mux #( end end else begin : gen_no_id_assign + logic [2:0][hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three; + logic [hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr, response_id_encoded; + + for (genvar i = 0; i < 3; i++) begin : gen_extra_id_tmr + hsiao_ecc_enc #( + .DataWidth (RequiredExtraIdWidth) + ) i_ecc ( + .in (selected_id[i]), + .out (selected_id_tmr_three[i]) + ); + + hsiao_ecc_dec #( + .DataWidth (RequiredExtraIdWidth) + ) i_ecc_dec ( + .in (response_id_encoded), + .out (response_id[i]), + .syndrome_o(), + .err_o () // TODO + ); + end - // fifo_v3 #( - // .FALL_THROUGH( 1'b0 ), - // .DATA_WIDTH ( RequiredExtraIdWidth ), - // .DEPTH ( NumMaxTrans ) - // ) i_fifo ( - // .clk_i, - // .rst_ni, - // .flush_i ('0), - // .testmode_i, - - // .full_o ( fifo_full ), - // .empty_o (), - // .usage_o (), - // .data_i ( selected_id ), - // .push_i ( mgr_port_req_o.req && mgr_port_rsp_i.gnt ), - - // .data_o ( response_id ), - // .pop_i ( fifo_pop ) - // ); + `VOTE31F(selected_id, selected_id_tmr, TODO) + + rel_fifo #( + .FallThrough( 1'b0 ), + .DataWidth ( hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth) ), + .Depth ( NumMaxTrans ), + .TmrStatus ( 1'b1 ), + .DataHasECC ( 1'b1 ), + .StatusFF ( 1'b0 ) + ) i_fifo ( + .clk_i, + .rst_ni, + .flush_i ('0), + .testmode_i, + + .full_o ( fifo_full ), + .empty_o (), + .usage_o (), + .data_i ( selected_id_tmr ), + .push_i ( mgr_port_req_o.req & mgr_port_rsp_i.gnt ), + .data_o ( response_id_encoded ), + .pop_i ( fifo_pop ) + ); end - // if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect - // assign mgr_port_req_o.rready = sbr_ports_req_i[response_id].rready; - // end - // logic [NumSbrPorts-1:0] sbr_rsp_rvalid; - // sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; - // always_comb begin : proc_sbr_rsp - // for (int i = 0; i < NumSbrPorts; i++) begin - // sbr_rsp_r[i] = '0; - // sbr_rsp_rvalid[i] = '0; - // end - // `OBI_SET_R_STRUCT(sbr_rsp_r[response_id], mgr_port_rsp_i.r); - // sbr_rsp_rvalid[response_id] = mgr_port_rsp_i.rvalid; - // end - - // for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_rsp_assign - // assign sbr_ports_rsp_o[i].r = sbr_rsp_r[i]; - // assign sbr_ports_rsp_o[i].rvalid = sbr_rsp_rvalid[i]; - // end + if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect + for (genvar i = 0; i < 3; i++) begin : gen_rready_connect_tmr + assign mgr_port_req_o.rready[i] = sbr_ports_req_i[response_id[i]].rready[i]; + end + end + logic [NumSbrPorts-1:0][2:0] sbr_rsp_rvalid; + sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; + always_comb begin : proc_sbr_rsp + for (int i = 0; i < NumSbrPorts; i++) begin + // Always assign r struct to avoid triplication overhead + `OBI_SET_R_STRUCT(sbr_rsp_r[i], mgr_port_rsp_i.r); + sbr_rsp_rvalid[i] = '0; + end + for (genvar i = 0; i < 3; i++) begin + sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; + end + end + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_rsp_assign + assign sbr_ports_rsp_o[i].r = sbr_rsp_r[i]; + assign sbr_ports_rsp_o[i].rvalid = sbr_rsp_rvalid[i]; + end if (MgrPortObiCfg.UseRReady) begin : gen_fifo_pop assign fifo_pop = mgr_port_rsp_i.rvalid & mgr_port_req_o.rready; From b84b6203be4d740df3b58837fca13ceaa469555c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 8 May 2025 13:55:26 +0200 Subject: [PATCH 09/48] Add relobi xbar --- Bender.yml | 4 ++ src/relobi_err_sbr.sv | 107 ++++++++++++++++++++++++++++ src/relobi_xbar.sv | 162 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+) create mode 100644 src/relobi_err_sbr.sv create mode 100644 src/relobi_xbar.sv diff --git a/Bender.yml b/Bender.yml index 5a4a8ea..0934065 100644 --- a/Bender.yml +++ b/Bender.yml @@ -55,3 +55,7 @@ sources: - src/relobi_encoder.sv # Level 4 - src/relobi_demux.sv + - src/relobi_err_sbr.sv + - src/relobi_mux.sv + # Level 5 + - src/relobi_xbar.sv diff --git a/src/relobi_err_sbr.sv b/src/relobi_err_sbr.sv new file mode 100644 index 0000000..62f7781 --- /dev/null +++ b/src/relobi_err_sbr.sv @@ -0,0 +1,107 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module obi_err_sbr #( + /// The OBI configuration for all ports. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The request struct. + parameter type obi_req_t = logic, + /// The response struct. + parameter type obi_rsp_t = logic, + /// Numper of transactions accepted before stalling if UseRReady + parameter int unsigned NumMaxTrans = 1, + /// Data to respond with from error subordinate + parameter logic [ObiCfg.DataWidth-1:0] RspData = 32'hBADCAB1E +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + + input obi_req_t obi_req_i, + output obi_rsp_t obi_rsp_o +); + + logic [ObiCfg.IdWidth-1:0] rid; + logic fifo_full, fifo_empty, fifo_pop; + + always_comb begin + obi_rsp_o.r.rdata = '0; + obi_rsp_o.r.rdata = RspData; + obi_rsp_o.r.rid = rid; + obi_rsp_o.r.err = 1'b1; + obi_rsp_o.r.r_optional = '0; + obi_rsp_o.gnt = ~fifo_full; + obi_rsp_o.rvalid = ~fifo_empty; + end + + if (ObiCfg.UseRReady) begin : gen_pop_rready + assign fifo_pop = obi_rsp_o.rvalid && obi_req_i.rready; + end else begin : gen_pop_default + assign fifo_pop = obi_rsp_o.rvalid; + end + + fifo_v3 #( + .DEPTH ( ObiCfg.UseRReady ? NumMaxTrans : 1 ), + .FALL_THROUGH ( 1'b0 ), + .DATA_WIDTH ( ObiCfg.IdWidth ) + ) i_id_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( '0 ), + .full_o ( fifo_full ), + .empty_o ( fifo_empty ), + .usage_o (), + .data_i ( obi_req_i.a.aid ), + .push_i ( obi_req_i.req && obi_rsp_o.gnt ), + .data_o ( rid ), + .pop_i ( fifo_pop ) + ); + +endmodule + +`include "obi/typedef.svh" +`include "obi/assign.svh" + +module obi_err_sbr_intf #( + /// The OBI configuration for all ports. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// Numper of transactions accepted before stalling if UseRReady + parameter int unsigned NumMaxTrans = 1, + /// Data to respond with from error subordinate + parameter logic [ObiCfg.DataWidth-1:0] RspData = 32'hBADCAB1E +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + + OBI_BUS.Subordinate sbr_port +); + + `OBI_TYPEDEF_ALL(obi, ObiCfg) + + obi_req_t obi_req; + obi_rsp_t obi_rsp; + + `OBI_ASSIGN_TO_REQ(obi_req, sbr_port, ObiCfg) + `OBI_ASSIGN_FROM_RSP(sbr_port, obi_rsp, ObiCfg) + + obi_err_sbr #( + .ObiCfg ( ObiCfg ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .NumMaxTrans ( NumMaxTrans ), + .RspData ( RspData ) + ) i_err_sbr ( + .clk_i, + .rst_ni, + .testmode_i, + + .obi_req_i ( obi_req ), + .obi_rsp_o ( obi_rsp ) + ); + +endmodule diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv new file mode 100644 index 0000000..00a1a3c --- /dev/null +++ b/src/relobi_xbar.sv @@ -0,0 +1,162 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +/// An OBI crossbar interconnect. +module relobi_xbar #( + /// The OBI configuration for the subordinate ports (input ports). + parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + /// The OBI configuration for the manager ports (ouput ports). + parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + /// The request struct for the subordinate ports (input ports). + parameter type sbr_port_obi_req_t = logic, + /// The A channel struct for the subordinate ports (input ports). + parameter type sbr_port_a_chan_t = logic, + /// The response struct for the subordinate ports (input ports). + parameter type sbr_port_obi_rsp_t = logic, + /// The R channel struct for the subordinate ports (input ports). + parameter type sbr_port_r_chan_t = logic, + /// The request struct for the manager ports (output ports). + parameter type mgr_port_obi_req_t = sbr_port_obi_req_t, + /// The response struct for the manager ports (output ports). + parameter type mgr_port_obi_rsp_t = sbr_port_obi_rsp_t, + /// The number of subordinate ports (input ports). + parameter int unsigned NumSbrPorts = 32'd0, + /// The number of manager ports (output ports). + parameter int unsigned NumMgrPorts = 32'd0, + /// The maximum number of outstanding transactions. + parameter int unsigned NumMaxTrans = 32'd0, + /// The number of address rules. + parameter int unsigned NumAddrRules = 32'd0, + /// The address map rule type. + parameter type addr_map_rule_t = logic, + /// Use the extended ID field (aid & rid) to route the response + parameter bit UseIdForRouting = 1'b0, + /// Connectivity matrix to disable certain paths. + parameter bit [NumSbrPorts-1:0][NumMgrPorts-1:0] Connectivity = '1, + /// Use TMR for addr map signal + parameter bit TmrMap = 1'b1, + parameter int unsigned MapWidth = TmrSelect ? 3 : 1 +) ( + input logic clk_i, + input logic rst_ni, + input logic testmode_i, + + input sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req_i, + output sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp_o, + + output mgr_port_obi_req_t [NumMgrPorts-1:0] mgr_ports_req_o, + input mgr_port_obi_rsp_t [NumMgrPorts-1:0] mgr_ports_rsp_i, + + input addr_map_rule_t [MapWidth-1:0][NumAddrRules-1:0] addr_map_i, + input logic [MapWidth-1:0][NumSbrPorts-1:0] en_default_idx_i, + input logic [MapWidth-1:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] default_idx_i +); + + logic [NumSbrPorts-1:0][2:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; + + // Signals from the demuxes + sbr_port_obi_req_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_reqs; + sbr_port_obi_rsp_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_rsps; + + // Signals to the muxes + sbr_port_obi_req_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_reqs; + sbr_port_obi_rsp_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_rsps; + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_demux + for (genvar j = 0; j < 3; j++) begin : gen_tmr + addr_decode #( + .NoIndices ( NumMgrPorts ), + .NoRules ( NumAddrRules ), + .addr_t ( logic [MgrPortObiCfg.AddrWidth-1:0] ), + .rule_t ( addr_map_rule_t ) + ) i_addr_decode ( + .addr_i ( sbr_ports_req_i[i].a.addr ), // TODO ecc + .addr_map_i ( TmrMap ? addr_map_i[j] : addr_map_i[0] ), + .idx_o ( sbr_port_select[i][j] ), + .dec_valid_o (), + .dec_error_o (), + .en_default_idx_i( TmrMap ? en_default_idx_i[j][i] : en_default_idx_i[0][i] ), + .default_idx_i ( TmrMap ? default_idx_i[j][i] : default_idx_i[0][i] ) + ); + end + + relobi_demux #( + .ObiCfg ( SbrPortObiCfg ), + .obi_req_t ( sbr_port_obi_req_t ), + .obi_rsp_t ( sbr_port_obi_rsp_t ), + .NumMgrPorts ( NumMgrPorts ), + .NumMaxTrans ( NumMaxTrans ), + .TmrSelect ( 1'b1 ) + ) i_demux ( + .clk_i, + .rst_ni, + .sbr_port_select_i ( sbr_port_select[i] ), + .sbr_port_req_i ( sbr_ports_req_i[i] ), + .sbr_port_rsp_o ( sbr_ports_rsp_o[i] ), + .mgr_ports_req_o ( sbr_reqs[i] ), + .mgr_ports_rsp_i ( sbr_rsps[i] ) + ); + end + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_interco_sbr + for (genvar j = 0; j < NumMgrPorts; j++) begin : gen_interco_mgr + if (Connectivity[i][j]) begin : gen_connected + assign mgr_reqs[j][i] = sbr_reqs[i][j]; + assign sbr_rsps[i][j] = mgr_rsps[j][i]; + end else begin : gen_err_sbr + assign mgr_reqs[j][i].req = '0'; + if (MgrPortObiCfg.UseRReady) begin : gen_rready + assign mgr_reqs[j][i].rready = '0; + end + assign mgr_reqs[j][i].a = '0; + if (MgrPortObiCfg.Integrity) begin : gen_integrity + assign mgr_reqs[j][i].reqpar = '1; + if (MgrPortObiCfg.UseRReady) begin : gen_int_rready + assign mgr_reqs[j][i].rreadypar = '1; + end + end + relobi_err_sbr #( + .ObiCfg ( SbrPortObiCfg ), + .obi_req_t ( sbr_port_obi_req_t ), + .obi_rsp_t ( sbr_port_obi_rsp_t ), + .NumMaxTrans ( NumMaxTrans ), + .RspData ( 32'hBADCAB1E ) + ) i_err_sbr ( + .clk_i, + .rst_ni, + .testmode_i, + .obi_req_i (sbr_reqs[i][j]), + .obi_rsp_o (sbr_rsps[i][j]) + ); + end + end + end + + for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_mux + relobi_mux #( + .SbrPortObiCfg ( SbrPortObiCfg ), + .MgrPortObiCfg ( MgrPortObiCfg ), + .sbr_port_obi_req_t ( sbr_port_obi_req_t ), + .sbr_port_a_chan_t ( sbr_port_a_chan_t ), + .sbr_port_obi_rsp_t ( sbr_port_obi_rsp_t ), + .sbr_port_r_chan_t ( sbr_port_r_chan_t ), + .mgr_port_obi_req_t ( mgr_port_obi_req_t ), + .mgr_port_obi_rsp_t ( mgr_port_obi_rsp_t ), + .NumSbrPorts ( NumSbrPorts ), + .NumMaxTrans ( NumMaxTrans ), + .UseIdForRouting ( UseIdForRouting ) + ) i_mux ( + .clk_i, + .rst_ni, + .testmode_i, + .sbr_ports_req_i ( mgr_reqs[i] ), + .sbr_ports_rsp_o ( mgr_rsps[i] ), + .mgr_port_req_o ( mgr_ports_req_o[i] ), + .mgr_port_rsp_i ( mgr_ports_rsp_i[i] ) + ); + end + +endmodule From 3de4596cbd0802d7112ca5b6c54bd1544b79b277 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 8 May 2025 23:02:35 +0200 Subject: [PATCH 10/48] Fix relobi, add xbar test --- Bender.lock | 14 +- Bender.yml | 5 +- Makefile | 7 +- include/obi/assign.svh | 69 +------- include/obi/typedef.svh | 31 +++- src/relobi_a_other_decoder.sv | 6 +- src/relobi_decoder.sv | 44 +++-- src/relobi_demux.sv | 19 +- src/relobi_encoder.sv | 42 +++-- src/relobi_mux.sv | 74 ++++---- src/relobi_r_other_decoder.sv | 6 +- src/relobi_r_other_encoder.sv | 4 +- src/relobi_tmr_r.sv | 14 +- src/relobi_xbar.sv | 29 +++- src/test/obi_test.sv | 15 +- src/test/tb_obi_xbar.sv | 4 +- src/test/tb_relobi_xbar.sv | 314 ++++++++++++++++++++++++++++++++++ 17 files changed, 529 insertions(+), 168 deletions(-) create mode 100644 src/test/tb_relobi_xbar.sv diff --git a/Bender.lock b/Bender.lock index c3176b1..c609380 100644 --- a/Bender.lock +++ b/Bender.lock @@ -7,8 +7,8 @@ packages: dependencies: - common_cells axi: - revision: 9402c8a9ce0a7b5253c3c29e788612d771e8b5d6 - version: 0.39.3 + revision: 39f5f2d51c5e524f6fc5cf8b6e901f7dcc5622d7 + version: 0.39.6 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -24,13 +24,13 @@ packages: - common_verification - tech_cells_generic common_verification: - revision: 9c07fa860593b2caabd9b5681740c25fac04b878 - version: 0.2.3 + revision: fb1885f48ea46164a10568aeff51884389f67ae3 + version: 0.2.5 source: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: d924bd6a2ffa48f0e6d26e6c66725012cf677abe + revision: b23577c955b392f5661c6fd7bbda710a6a752377 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git @@ -40,8 +40,8 @@ packages: - register_interface - tech_cells_generic register_interface: - revision: ae616e5a1ec2b41e72d200e5ab09c65e94aebd3d - version: 0.4.4 + revision: 5daa85d164cf6b54ad061ea1e4c6f3624556e467 + version: 0.4.5 source: Git: https://github.com/pulp-platform/register_interface.git dependencies: diff --git a/Bender.yml b/Bender.yml index 0934065..b2f2cbc 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: d924bd6a2ffa48f0e6d26e6c66725012cf677abe } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: b23577c955b392f5661c6fd7bbda710a6a752377 } export_include_dirs: - include @@ -59,3 +59,6 @@ sources: - src/relobi_mux.sv # Level 5 - src/relobi_xbar.sv + - target: test + files: + - src/test/tb_relobi_xbar.sv diff --git a/Makefile b/Makefile index f065071..4df8c59 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,14 @@ BENDER ?= bender VSIM ?= vsim -AVAILABLE_TESTBENCHES = tb_obi_xbar tb_obi_atop_resolver +BENDER_TARGETS := -t test +BENDER_TARGETS += -t relOBI + +AVAILABLE_TESTBENCHES = tb_obi_xbar tb_obi_atop_resolver tb_relobi_xbar scripts/compile.tcl: mkdir -p scripts - $(BENDER) script vsim -t test --vlog-arg="-svinputport=compat" > $@ + $(BENDER) script vsim $(BENDER_TARGETS) --vlog-arg="-svinputport=compat" > $@ .PHONY: build build: scripts/compile.tcl diff --git a/include/obi/assign.svh b/include/obi/assign.svh index a5395e2..e8dd4db 100644 --- a/include/obi/assign.svh +++ b/include/obi/assign.svh @@ -27,46 +27,11 @@ __opt_as __lhs``__lhs_sep``r_optional = __rhs``__rhs_sep``r_optional; `define __OBI_TO_REQ(__opt_as, __lhs, __lhs_sep, __rhs, __rhs_sep, __lhscfg, __rhscfg) \ `__OBI_TO_A(__opt_as, __lhs, __lhs_sep, __rhs, __rhs_sep) \ - __opt_as __lhs.req = __rhs.req; \ - if (__lhscfg.UseRReady) begin \ - if (__rhscfg.UseRReady) begin \ - __opt_as __lhs.rready = __rhs.rready; \ - if (__lhscfg.Integrity) begin \ - if (__rhscfg.Integrity) begin \ - __opt_as __lhs.rreadypar = __rhs.rreadypar; \ - end else begin \ - __opt_as __lhs.rreadypar = ~__rhs.rready; \ - end \ - end \ - end else begin \ - __opt_as __lhs.rready = 1'b1; \ - if (__lhscfg.Integrity) begin \ - __opt_as __lhs.rreadypar = 1'b0; \ - end \ - end \ - end else if (__rhscfg.UseRReady) begin \ - $error("Incompatible Configs! Please assign manually!"); \ - end \ - if (__lhscfg.Integrity) begin \ - if (__rhscfg.Integrity) begin \ - __opt_as __lhs.reqpar = __rhs.reqpar; \ - end else begin \ - __opt_as __lhs.reqpar = ~__rhs.req; \ - end \ - end + __opt_as __lhs.req = __rhs.req; `define __OBI_TO_RSP(__opt_as, __lhs, __lhs_sep, __rhs, __rhs_sep, __lhscfg, __rhscfg) \ `__OBI_TO_R(__opt_as, __lhs, __lhs_sep, __rhs, __rhs_sep) \ __opt_as __lhs.gnt = __rhs.gnt; \ - __opt_as __lhs.rvalid = __rhs.rvalid; \ - if (__lhscfg.Integrity) begin \ - if (__rhscfg.Integrity) begin \ - __opt_as __lhs.gntpar = __rhs.gntpar; \ - __opt_as __lhs.rvalidpar = __rhs.rvalidpar; \ - end else begin \ - __opt_as __lhs.gntpar = ~__rhs.gnt; \ - __opt_as __lhs.rvalidpar = ~__rhs.rvalid; \ - end \ - end + __opt_as __lhs.rvalid = __rhs.rvalid; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -86,36 +51,10 @@ `define OBI_ASSIGN_A(dst, src, dstcfg, srccfg) \ `__OBI_TO_A(assign, dst, ., src, .) \ assign dst.req = src.req; \ - assign src.gnt = dst.gnt; \ - if (dstcfg.Integrity && srccfg.Integrity) begin \ - assign dst.reqpar = src.reqpar; \ - assign src.gntpar = dst.gntpar; \ - end else if (dstcfg.Integrity ^ srccfg.Integrity) begin \ - $error("Incompatible Configs! Please assign manually!"); \ - end + assign src.gnt = dst.gnt; `define OBI_ASSIGN_R(dst, src, dstcfg, srccfg) \ `__OBI_TO_R(assign, dst, ., src, .) \ - assign dst.rvalid = src.rvalid; \ - if (dstcfg.Integrity && srccfg.Integrity) begin \ - assign dst.rvalidpar = src.rvalidpar; \ - end else if (dstcfg.Integrity ^ srccfg.Integrity) begin \ - $error("Incompatible Configs! Please assign manually!"); \ - end \ - if (srccfg.UseRReady) begin \ - if (dstcfg.UseRReady) begin \ - assign src.rready = dst.rready; \ - if (srccfg.Integrity && dstcfg.Integrity) begin \ - assign src.rreadypar = dst.rreadypar; \ - end \ - end else begin \ - assign src.rready = 1'b1; \ - if (srccfg.Integrity) begin \ - assign src.rreadypar = 1'b0; \ - end \ - end \ - end else if (dstcfg.UseRReady) begin \ - $error("Incompatible Configs! Please assign manually!"); \ - end + assign dst.rvalid = src.rvalid; `define OBI_ASSIGN(sbr, mgr, sbrcfg, mgrcfg) \ `OBI_ASSIGN_A(sbr, mgr, sbrcfg, mgrcfg) \ `OBI_ASSIGN_R(mgr, sbr, mgrcfg, sbrcfg) diff --git a/include/obi/typedef.svh b/include/obi/typedef.svh index 5772cda..4d76840 100644 --- a/include/obi/typedef.svh +++ b/include/obi/typedef.svh @@ -127,6 +127,18 @@ `OBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, obi_t``_r_optional_t) \ `OBI_TYPEDEF_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) +`define OBI_TYPEDEF_ALL_WITH_OPTIONAL(obi_t, cfg, a_optional_t, r_optional_t) \ + `OBI_TYPEDEF_A_CHAN_T(obi_t``_a_chan_t, cfg.AddrWidth, cfg.DataWidth, cfg.IdWidth, a_optional_t) \ + `OBI_TYPEDEF_INTEGRITY_REQ_T(obi_t``_req_t, obi_t``_a_chan_t) \ + `OBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, r_optional_t) \ + `OBI_TYPEDEF_INTEGRITY_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) + +`define OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(obi_t, cfg, a_optional_t, r_optional_t) \ + `OBI_TYPEDEF_A_CHAN_T(obi_t``_a_chan_t, cfg.AddrWidth, cfg.DataWidth, cfg.IdWidth, a_optional_t) \ + `OBI_TYPEDEF_DEFAULT_REQ_T(obi_t``_req_t, obi_t``_a_chan_t) \ + `OBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, r_optional_t) \ + `OBI_TYPEDEF_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) + `define RELOBI_TYPEDEF_A_CHAN_T(a_chan_t, ADDR_WIDTH, DATA_WIDTH, ID_WIDTH, a_optional_t) \ typedef struct packed { \ logic [ ADDR_WIDTH+hsiao_ecc_pkg::min_ecc(ADDR_WIDTH)-1:0] addr; \ @@ -138,13 +150,13 @@ logic [hsiao_ecc_pkg::min_ecc(1+DATA_WIDTH/8+ID_WIDTH+$bits(a_optional_t))-1:0] other_ecc; \ } a_chan_t; -`define RELOBI_TYEPDEF_DEFAULT_REQ_T(req_t, a_chan_t) \ +`define RELOBI_TYPEDEF_DEFAULT_REQ_T(req_t, a_chan_t) \ typedef struct packed { \ a_chan_t a; \ logic [2:0] req; \ } req_t; -`define RELOBI_TYEPDEF_REQ_T(req_t, a_chan_t) \ +`define RELOBI_TYPEDEF_REQ_T(req_t, a_chan_t) \ typedef struct packed { \ a_chan_t a; \ logic [2:0] req; \ @@ -167,4 +179,19 @@ logic [2:0] rvalid; \ } rsp_t; +`define RELOBI_TYPEDEF_ALL(obi_t, cfg) \ + `OBI_TYPEDEF_ALL_A_OPTIONAL(obi_t``_a_optional_t, cfg.OptionalCfg.AUserWidth, cfg.OptionalCfg.WUserWidth, cfg.OptionalCfg.MidWidth, cfg.OptionalCfg.AChkWidth) \ + `RELOBI_TYPEDEF_A_CHAN_T(obi_t``_a_chan_t, cfg.AddrWidth, cfg.DataWidth, cfg.IdWidth, obi_t``_a_optional_t) \ + `RELOBI_TYPEDEF_DEFAULT_REQ_T(obi_t``_req_t, obi_t``_a_chan_t) \ + `OBI_TYPEDEF_ALL_R_OPTIONAL(obi_t``_r_optional_t, cfg.OptionalCfg.RUserWidth, cfg.OptionalCfg.RChkWidth) \ + `RELOBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, obi_t``_r_optional_t) \ + `RELOBI_TYPEDEF_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) + +`define RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(obi_t, cfg, a_optional_t, r_optional_t) \ + `RELOBI_TYPEDEF_A_CHAN_T(obi_t``_a_chan_t, cfg.AddrWidth, cfg.DataWidth, cfg.IdWidth, a_optional_t) \ + `RELOBI_TYPEDEF_DEFAULT_REQ_T(obi_t``_req_t, obi_t``_a_chan_t) \ + `RELOBI_TYPEDEF_R_CHAN_T(obi_t``_r_chan_t, cfg.DataWidth, cfg.IdWidth, r_optional_t) \ + `RELOBI_TYPEDEF_RSP_T(obi_t``_rsp_t, obi_t``_r_chan_t) + + `endif // OBI_TYPEDEF_SVH diff --git a/src/relobi_a_other_decoder.sv b/src/relobi_a_other_decoder.sv index 6945d7a..8aee97e 100644 --- a/src/relobi_a_other_decoder.sv +++ b/src/relobi_a_other_decoder.sv @@ -20,9 +20,9 @@ module relobi_a_other_decoder #( output logic we_o, output logic [Cfg.DataWidth/8-1:0] be_o, output logic [Cfg.IdWidth -1:0] aid_o, - output a_optional_t a_optional_o + output a_optional_t a_optional_o, - // TODO: error + output logic [1:0] relerr_o ); hsiao_ecc_dec #( @@ -38,7 +38,7 @@ module relobi_a_other_decoder #( aid_o, a_optional_o} ), .syndrome_o(), - .err_o () + .err_o (relerr_o) ); endmodule diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index 6aaa998..6fdeba7 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -9,28 +9,41 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( /// Configuration of the bus parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, - parameter relobi_req_t = logic, - parameter relobi_rsp_t = logic, - parameter obi_req_t = logic, - parameter obi_rsp_t = logic, - parameter a_optional_t = logic, - parameter r_optional_t = logic + parameter type relobi_req_t = logic, + parameter type relobi_rsp_t = logic, + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic ) ( input relobi_req_t rel_req_i, output relobi_rsp_t rel_rsp_o, output obi_req_t req_o, - input obi_rsp_t rsp_i + input obi_rsp_t rsp_i, - // TODO: error output!!! + output logic [1:0] relerr_o ); + logic [1:0][2:0] voter_errs; + logic [2:0][1:0] hsiao_errs; + logic [1:0][2:0] hsiao_errs_transpose; + + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs + for (genvar j = 0; j < 3; j++) begin + assign hsiao_errs_transpose[i][j] = hsiao_errs_transpose[j][i]; + end + end + + assign relerr_o[0] = |voter_errs | |hsiao_errs_transpose[0]; + assign relerr_o[1] = |hsiao_errs_transpose[1]; + TMR_voter_detect i_req_valid_vote ( .a_i (rel_req_i.req[0]), .b_i (rel_req_i.req[1]), .c_i (rel_req_i.req[2]), .majority_o (req_o.req), - .error_cba_o() + .error_cba_o(voter_errs[0]) ); assign rel_rsp_o.gnt = {3{rsp_i.gnt}}; @@ -41,8 +54,10 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .b_i (rel_req_i.rready[1]), .c_i (rel_req_i.rready[2]), .majority_o (req_o.rready), - .error_cba_o() + .error_cba_o(voter_errs[1]) ); + end else begin : gen_no_rready + assign voter_errs[1] = '0; end assign rel_rsp_o.rvalid = {3{rsp_i.rvalid}}; @@ -53,7 +68,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .in ( rel_req_i.a.addr ), .out ( req_o.a.addr ), .syndrome_o(), - .err_o () + .err_o (hsiao_errs[0]) ); hsiao_ecc_dec #( @@ -62,7 +77,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .in ( rel_req_i.a.wdata ), .out ( req_o.a.wdata ), .syndrome_o(), - .err_o () + .err_o (hsiao_errs[1]) ); relobi_a_other_decoder #( @@ -77,14 +92,15 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .we_o (req_o.a.we), .be_o (req_o.a.be), .aid_o (req_o.a.aid), - .a_optional_o(req_o.a.a_optional) + .a_optional_o(req_o.a.a_optional), + .relerr_o (hsiao_errs[2]) ); hsiao_ecc_enc #( .DataWidth ( Cfg.DataWidth ) ) i_rdata_enc ( .in ( rsp_i.r.rdata ), - .out( rsp_o.r.rdata ) + .out( rel_rsp_o.r.rdata ) ); relobi_r_other_encoder #( diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index 009cb87..b32ce0f 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -13,6 +13,8 @@ module relobi_demux #( parameter type obi_rsp_t = logic, /// The r_chan struct for all ports. parameter type obi_r_chan_t = logic, + /// The optional r_chan struct for all ports. + parameter type obi_r_optional_t = logic, /// The number of manager ports. parameter int unsigned NumMgrPorts = 32'd0, /// The maximum number of outstanding transactions. @@ -52,10 +54,10 @@ module relobi_demux #( logic [NumMgrPorts-1:0][2:0] mgr_ports_req; - for (genvar i = 0; i < 3; i++) begin : gen_tmr - assign select_i_tmr[i] = TmrSelect ? sbr_port_select_i[i] : sbr_port_select_i[0]; + always_comb begin : proc_req + for (int i = 0; i < 3; i++) begin : gen_tmr + select_i_tmr[i] = TmrSelect ? sbr_port_select_i[i] : sbr_port_select_i[0]; - always_comb begin : proc_req select_d[i] = select_q[i]; cnt_up[i] = 1'b0; for (int j = 0; j < NumMgrPorts; j++) begin @@ -86,7 +88,8 @@ module relobi_demux #( relobi_tmr_r #( .ObiCfg (ObiCfg), - .obi_r_chan_t(obi_r_chan_t) + .obi_r_chan_t(obi_r_chan_t), + .r_optional_t (obi_r_optional_t) ) i_r_vote ( .three_r_i({mgr_ports_rsp_i[select_q[2]].r, mgr_ports_rsp_i[select_q[1]].r, @@ -114,8 +117,8 @@ module relobi_demux #( // Could be voted, but with only one error source (either select_q or rvalid) should suffice assign cnt_down[i] = mgr_ports_rsp_i[select_q[i]].rvalid[i] && sbr_port_rready[i]; - assign overflow[i] = counter_q[CounterWidth]; - assign in_flight[i] = counter_q[CounterWidth-1:0]; + assign overflow[i] = counter_q[i][CounterWidth]; + assign in_flight[i] = counter_q[i][CounterWidth-1:0]; always_comb begin counter_d[i] = counter_q[i]; @@ -123,7 +126,7 @@ module relobi_demux #( if (cnt_up & ~cnt_down) begin counter_d[i] = counter_q[i] + {{CounterWidth-1{1'b0}}, 1'b1}; end else if (cnt_down & ~cnt_up) begin - coutner_d[i] = counter_q[i] - {{CounterWidth-1{1'b0}}, 1'b1}; + counter_d[i] = counter_q[i] - {{CounterWidth-1{1'b0}}, 1'b1}; end end end @@ -141,7 +144,7 @@ module relobi_demux #( ); bitwise_TMR_voter #( .DataWidth( CounterWidth+1 ) - ) i_select_vote ( + ) i_counter_vote ( .a_i (counter_d[0]), .b_i (counter_d[1]), .c_i (counter_d[2]), diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index 44bc1dc..a659aa5 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -8,22 +8,35 @@ module relobi_encoder #( /// Configuration of the bus parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, - parameter relobi_req_t = logic, - parameter relobi_rsp_t = logic, - parameter obi_req_t = logic, - parameter obi_rsp_t = logic, - parameter a_optional_t = logic, - parameter r_optional_t = logic + parameter type relobi_req_t = logic, + parameter type relobi_rsp_t = logic, + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic ) ( input obi_req_t req_i, output obi_rsp_t rsp_o, output relobi_req_t rel_req_o, - input relobi_rsp_t rel_rsp_i + input relobi_rsp_t rel_rsp_i, - // TODO: error output!!! + logic [1:0] relerr_o ); + logic [1:0][2:0] voter_errs; + logic [1:0][1:0] hsiao_errs; + logic [1:0][1:0] hsiao_errs_transpose; + + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs + for (genvar j = 0; j < 2; j++) begin + assign hsiao_errs_transpose[i][j] = hsiao_errs_transpose[j][i]; + end + end + + assign relerr_o[0] = |voter_errs | |(hsiao_errs_transpose[0]); + assign relerr_o[1] = |(hsiao_errs_transpose[1]); + assign rel_req_o.req = {3{req_i.req}}; TMR_voter_detect i_req_gnt_vote ( @@ -31,7 +44,7 @@ module relobi_encoder #( .b_i (rel_rsp_i.gnt[1]), .c_i (rel_rsp_i.gnt[2]), .majority_o (rsp_o.gnt), - .error_cba_o() + .error_cba_o(voter_errs[0]) ); if (Cfg.UseRReady) begin : gen_rready_multiply @@ -43,21 +56,21 @@ module relobi_encoder #( .b_i (rel_rsp_i.rvalid[1]), .c_i (rel_rsp_i.rvalid[2]), .majority_o (rsp_o.rvalid), - .error_cba_o() + .error_cba_o(voter_errs[1]) ); hsiao_ecc_enc #( .DataWidth ( Cfg.AddrWidth ) ) i_addr_enc ( .in ( req_i.a.addr ), - .out( rel_req_o.a.addr ), + .out( rel_req_o.a.addr ) ); hsiao_ecc_enc #( .DataWidth ( Cfg.DataWidth ) ) i_wdata_enc ( .in ( req_i.a.wdata ), - .out( rel_req_o.a.wdata ), + .out( rel_req_o.a.wdata ) ); relobi_a_other_encoder #( @@ -81,7 +94,7 @@ module relobi_encoder #( .in ( rel_rsp_i.r.rdata ), .out ( rsp_o.r.rdata ), .syndrome_o(), - .err_o () + .err_o (hsiao_errs[0]) ); relobi_r_other_decoder #( @@ -94,7 +107,8 @@ module relobi_encoder #( .other_ecc_i (rel_rsp_i.r.other_ecc), .rid_o (rsp_o.r.rid), .err_o (rsp_o.r.err), - .r_optional_o(rsp_o.r.r_optional) + .r_optional_o(rsp_o.r.r_optional), + .relerr_o (hsiao_errs[1]) ); endmodule diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 880b37f..99263ed 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -5,6 +5,7 @@ // Michael Rogenmoser `include "obi/assign.svh" +`include "redundancy_cells/voters.svh" /// An OBI multiplexer. module relobi_mux #( @@ -67,21 +68,22 @@ module relobi_mux #( logic [NumSbrPorts-1:0][2:0] sbr_ports_req, sbr_ports_gnt; sbr_port_a_chan_t [NumSbrPorts-1:0] sbr_ports_a; + + sbr_port_a_chan_t mgr_port_a_in_sbr; + mgr_port_a_chan_t [2:0] mgr_port_a_tmr; + logic [2:0][RequiredExtraIdWidth-1:0] selected_id, response_id; + logic [2:0] mgr_port_req, fifo_full, fifo_pop; + + logic [2:0] rr_arb_mgr_port_gnt; + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_assign assign sbr_ports_req[i] = sbr_ports_req_i[i].req; assign sbr_ports_a[i] = sbr_ports_req_i[i].a; assign sbr_ports_rsp_o[i].gnt = sbr_ports_gnt[i]; end - sbr_port_a_chan_t [2:0] mgr_port_a_in_sbr; - mgr_port_a_chan_t [2:0] mgr_port_a_tmr; - logic [2:0][RequiredExtraIdWidth-1:0] selected_id, response_id; - logic [2:0] mgr_port_req, fifo_full, fifo_pop; - assign mgr_port_req_o.req = mgr_port_req & ~fifo_full; - logic [2:0] rr_arb_mgr_port_gnt; - for (genvar i = 0; i < 3; i++) begin : gen_mgr_port_gnt assign rr_arb_mgr_port_gnt[i] = mgr_port_rsp_i.gnt[i] && ~fifo_full[i]; end @@ -107,14 +109,16 @@ module relobi_mux #( .gnt_i ( rr_arb_mgr_port_gnt ), .data_o ( mgr_port_a_in_sbr ), - .idx_o ( selected_id ) + .idx_o ( selected_id ), + + .relerr_o () ); for (genvar i = 0; i < 3; i++) begin : gen_tmr_aid if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical always_comb begin - `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr[i]) - mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr[i].other_ecc; + `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr) + mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr.other_ecc; end end else begin : gen_aid_extend logic we; @@ -127,15 +131,17 @@ module relobi_mux #( .Cfg (SbrPortObiCfg), .a_optional_t (a_optional_t) ) i_other_decode ( - .we_i (mgr_port_a_in_sbr[i].we), - .be_i (mgr_port_a_in_sbr[i].be), - .aid_i (mgr_port_a_in_sbr[i].aid), - .a_optional_i(mgr_port_a_in_sbr[i].a_optional), - .other_ecc_i (mgr_port_a_in_sbr[i].other_ecc), + .we_i (mgr_port_a_in_sbr.we), + .be_i (mgr_port_a_in_sbr.be), + .aid_i (mgr_port_a_in_sbr.aid), + .a_optional_i(mgr_port_a_in_sbr.a_optional), + .other_ecc_i (mgr_port_a_in_sbr.other_ecc), .we_o (we), .be_o (be), .aid_o (sbr_aid), - .a_optional_o(a_optional) + .a_optional_o(a_optional), + + .relerr_o () ); if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + RequiredExtraIdWidth ) begin @@ -157,21 +163,22 @@ module relobi_mux #( .be_i (be), .aid_i (mgr_aid), .a_optional_i(a_optional), - .other_ecc_o (other_ecc), + .other_ecc_o (other_ecc) ); - always_comb begin - `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr[i]) - mgr_port_a_tmr[i].we = we; - mgr_port_a_tmr[i].be = be; - mgr_port_a_tmr[i].aid = mgr_aid; - mgr_port_a_tmr[i].a_optional = a_optional; - mgr_port_a_tmr[i].other_ecc = other_ecc; - end + assign mgr_port_a_tmr[i].addr = mgr_port_a_in_sbr.addr; + assign mgr_port_a_tmr[i].wdata = mgr_port_a_in_sbr.wdata; + assign mgr_port_a_tmr[i].we = we; + assign mgr_port_a_tmr[i].be = be; + assign mgr_port_a_tmr[i].aid = mgr_aid; + assign mgr_port_a_tmr[i].a_optional = a_optional; + assign mgr_port_a_tmr[i].other_ecc = other_ecc; end end + `VOTE31F(mgr_port_a_tmr, mgr_port_req_o.a, ) + logic [2:0][SbrPortObiCfg.IdWidth-1:0] rsp_rid; if (UseIdForRouting) begin : gen_id_assign @@ -201,8 +208,8 @@ module relobi_mux #( end end else begin : gen_no_id_assign - logic [2:0][hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three; - logic [hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr, response_id_encoded; + logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three; + logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr, response_id_encoded; for (genvar i = 0; i < 3; i++) begin : gen_extra_id_tmr hsiao_ecc_enc #( @@ -222,14 +229,14 @@ module relobi_mux #( ); end - `VOTE31F(selected_id, selected_id_tmr, TODO) + `VOTE31F(selected_id_tmr_three, selected_id_tmr, ) rel_fifo #( .FallThrough( 1'b0 ), - .DataWidth ( hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth) ), + .DataWidth ( RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth) ), .Depth ( NumMaxTrans ), .TmrStatus ( 1'b1 ), - .DataHasECC ( 1'b1 ), + .DataHasEcc ( 1'b1 ), .StatusFF ( 1'b0 ) ) i_fifo ( .clk_i, @@ -243,7 +250,9 @@ module relobi_mux #( .data_i ( selected_id_tmr ), .push_i ( mgr_port_req_o.req & mgr_port_rsp_i.gnt ), .data_o ( response_id_encoded ), - .pop_i ( fifo_pop ) + .pop_i ( fifo_pop ), + + .fault_o () ); end @@ -259,9 +268,10 @@ module relobi_mux #( for (int i = 0; i < NumSbrPorts; i++) begin // Always assign r struct to avoid triplication overhead `OBI_SET_R_STRUCT(sbr_rsp_r[i], mgr_port_rsp_i.r); + sbr_rsp_r[i].other_ecc = mgr_port_rsp_i.r.other_ecc; sbr_rsp_rvalid[i] = '0; end - for (genvar i = 0; i < 3; i++) begin + for (int i = 0; i < 3; i++) begin sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; end end diff --git a/src/relobi_r_other_decoder.sv b/src/relobi_r_other_decoder.sv index 5b035fb..1407b9f 100644 --- a/src/relobi_r_other_decoder.sv +++ b/src/relobi_r_other_decoder.sv @@ -18,9 +18,9 @@ module relobi_r_other_decoder #( output logic [Cfg.IdWidth -1:0] rid_o, output logic err_o, - output r_optional_t r_optional_o + output r_optional_t r_optional_o, - // TODO: error + output logic [1:0] relerr_o ); @@ -35,7 +35,7 @@ module relobi_r_other_decoder #( err_o, r_optional_o} ), .syndrome_o(), - .err_o () + .err_o (relerr_o) ); endmodule diff --git a/src/relobi_r_other_encoder.sv b/src/relobi_r_other_encoder.sv index 71bb801..07ea2bb 100644 --- a/src/relobi_r_other_encoder.sv +++ b/src/relobi_r_other_encoder.sv @@ -11,8 +11,8 @@ module relobi_r_other_encoder #( parameter type r_optional_t = logic, parameter int unsigned OtherEccWidth = relobi_pkg::relobi_r_other_ecc_width(Cfg) ) ( - input logic rid_i, - input logic [Cfg.DataWidth/8-1:0] err_i, + input logic [Cfg.IdWidth -1:0] rid_i, + input logic err_i, input r_optional_t r_optional_i, output logic [ OtherEccWidth-1:0] other_ecc_o diff --git a/src/relobi_tmr_r.sv b/src/relobi_tmr_r.sv index b078fd5..d5534fe 100644 --- a/src/relobi_tmr_r.sv +++ b/src/relobi_tmr_r.sv @@ -43,11 +43,11 @@ module relobi_tmr_r #( if (ObiCfg.OptionalCfg.RUserWidth) begin : gen_ruser bitwise_TMR_voter #( .DataWidth(ObiCfg.OptionalCfg.RUserWidth) - ) i_r_id ( - .a_i (three_r_i[0].r_optional.user), - .b_i (three_r_i[1].r_optional.user), - .c_i (three_r_i[2].r_optional.user), - .majority_o (voted_r_o.r_optional.user), + ) i_r_user ( + .a_i (three_r_i[0].r_optional.ruser), + .b_i (three_r_i[1].r_optional.ruser), + .c_i (three_r_i[2].r_optional.ruser), + .majority_o (voted_r_o.r_optional.ruser), .error_o (), .error_cba_o() ); @@ -55,7 +55,7 @@ module relobi_tmr_r #( if (ObiCfg.OptionalCfg.RChkWidth) begin : gen_rchk bitwise_TMR_voter #( .DataWidth(ObiCfg.OptionalCfg.RChkWidth) - ) i_r_id ( + ) i_r_rchk ( .a_i (three_r_i[0].r_optional.rchk), .b_i (three_r_i[1].r_optional.rchk), .c_i (three_r_i[2].r_optional.rchk), @@ -80,7 +80,7 @@ module relobi_tmr_r #( bitwise_TMR_voter #( .DataWidth(hsiao_ecc_pkg::min_ecc(ObiCfg.IdWidth+1+$bits(r_optional_t))) - ) i_r_id ( + ) i_r_other_ecc ( .a_i (three_r_i[0].other_ecc), .b_i (three_r_i[1].other_ecc), .c_i (three_r_i[2].other_ecc), diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index 00a1a3c..66dd758 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -22,6 +22,12 @@ module relobi_xbar #( parameter type mgr_port_obi_req_t = sbr_port_obi_req_t, /// The response struct for the manager ports (output ports). parameter type mgr_port_obi_rsp_t = sbr_port_obi_rsp_t, + /// The A channel struct for the manager port (output port). + parameter type mgr_port_a_chan_t = logic, + /// The A channel optionals struct for all ports. + parameter type a_optional_t = logic, + /// The R channel optionals struct for all ports. + parameter type r_optional_t = logic, /// The number of subordinate ports (input ports). parameter int unsigned NumSbrPorts = 32'd0, /// The number of manager ports (output ports). @@ -38,7 +44,7 @@ module relobi_xbar #( parameter bit [NumSbrPorts-1:0][NumMgrPorts-1:0] Connectivity = '1, /// Use TMR for addr map signal parameter bit TmrMap = 1'b1, - parameter int unsigned MapWidth = TmrSelect ? 3 : 1 + parameter int unsigned MapWidth = TmrMap ? 3 : 1 ) ( input logic clk_i, input logic rst_ni, @@ -67,13 +73,25 @@ module relobi_xbar #( for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_demux for (genvar j = 0; j < 3; j++) begin : gen_tmr + + logic [MgrPortObiCfg.AddrWidth-1:0] addr; + + hsiao_ecc_dec #( + .DataWidth ( MgrPortObiCfg.AddrWidth ) + ) i_addr_dec ( + .in ( sbr_ports_req_i[i].a.addr ), + .out ( addr ), + .syndrome_o(), + .err_o () + ); + addr_decode #( .NoIndices ( NumMgrPorts ), .NoRules ( NumAddrRules ), .addr_t ( logic [MgrPortObiCfg.AddrWidth-1:0] ), .rule_t ( addr_map_rule_t ) ) i_addr_decode ( - .addr_i ( sbr_ports_req_i[i].a.addr ), // TODO ecc + .addr_i ( addr ), .addr_map_i ( TmrMap ? addr_map_i[j] : addr_map_i[0] ), .idx_o ( sbr_port_select[i][j] ), .dec_valid_o (), @@ -87,6 +105,8 @@ module relobi_xbar #( .ObiCfg ( SbrPortObiCfg ), .obi_req_t ( sbr_port_obi_req_t ), .obi_rsp_t ( sbr_port_obi_rsp_t ), + .obi_r_chan_t( sbr_port_r_chan_t ), + .obi_r_optional_t ( r_optional_t ), .NumMgrPorts ( NumMgrPorts ), .NumMaxTrans ( NumMaxTrans ), .TmrSelect ( 1'b1 ) @@ -107,7 +127,7 @@ module relobi_xbar #( assign mgr_reqs[j][i] = sbr_reqs[i][j]; assign sbr_rsps[i][j] = mgr_rsps[j][i]; end else begin : gen_err_sbr - assign mgr_reqs[j][i].req = '0'; + assign mgr_reqs[j][i].req = '0; if (MgrPortObiCfg.UseRReady) begin : gen_rready assign mgr_reqs[j][i].rready = '0; end @@ -145,6 +165,9 @@ module relobi_xbar #( .sbr_port_r_chan_t ( sbr_port_r_chan_t ), .mgr_port_obi_req_t ( mgr_port_obi_req_t ), .mgr_port_obi_rsp_t ( mgr_port_obi_rsp_t ), + .mgr_port_a_chan_t ( mgr_port_a_chan_t ), + .a_optional_t ( a_optional_t ), + .r_optional_t ( r_optional_t ), .NumSbrPorts ( NumSbrPorts ), .NumMaxTrans ( NumMaxTrans ), .UseIdForRouting ( UseIdForRouting ) diff --git a/src/test/obi_test.sv b/src/test/obi_test.sv index 90a49ef..fc3a1c0 100644 --- a/src/test/obi_test.sv +++ b/src/test/obi_test.sv @@ -50,6 +50,7 @@ package obi_test; obi.rvalidpar <= '1; obi.rdata <= '0; obi.rid <= '0; + obi.err <= '0; obi.r_optional <= '0; endfunction @@ -93,12 +94,15 @@ package obi_test; task send_r ( input logic [ObiCfg.DataWidth-1:0] rdata, input logic [ ObiCfg.IdWidth-1:0] rid, + input logic err, input obi_r_optional_t r_optional ); + obi.rvalid <= #TA 1'b1; obi.rvalidpar <= #TA 1'b0; obi.rdata <= #TA rdata; obi.rid <= #TA rid; + obi.err <= #TA err; obi.r_optional <= #TA r_optional; cycle_start(); if (ObiCfg.UseRReady) begin @@ -109,6 +113,7 @@ package obi_test; obi.rvalidpar <= #TA 1'b1; obi.rdata <= #TA '0; obi.rid <= #TA '0; + obi.rid <= #TA '0; obi.r_optional <= #TA '0; endtask @@ -232,7 +237,7 @@ package obi_test; a_addr = addr_t'($urandom_range(MinAddr, MaxAddr)); a_we = $urandom() % 2; a_be = $urandom() % (1 << (ObiCfg.DataWidth/8)); - a_wdata = $urandom() % (1 << ObiCfg.DataWidth); + a_wdata = $urandom() % (1 << ObiCfg.DataWidth-1); a_aid = $urandom() % (1 << ObiCfg.IdWidth); a_optional = obi_a_optional_t'($urandom()); @@ -250,7 +255,9 @@ package obi_test; repeat (n_rsps) begin wait (a_queue.size() > 0); a_addr = this.a_queue.pop_front(); - rand_wait(RMinWaitCycles, RMaxWaitCycles); + if (ObiCfg.UseRReady) begin + rand_wait(RMinWaitCycles, RMaxWaitCycles); + end drv.recv_r(r_rdata, r_rid, r_err, r_optional); end endtask @@ -373,6 +380,7 @@ package obi_test; automatic addr_t a_addr; automatic logic [ObiCfg.DataWidth-1:0] r_rdata; automatic logic [ ObiCfg.IdWidth-1:0] r_rid; + automatic logic r_err; automatic obi_r_optional_t r_optional; wait (a_queue.size() > 0); @@ -380,9 +388,10 @@ package obi_test; a_addr = this.a_queue.pop_front(); r_rid = this.id_queue.pop_front(); + r_err = '0; rand_success = std::randomize(r_rdata); assert(rand_success); rand_success = std::randomize(r_optional); assert(rand_success); - this.drv.send_r(r_rdata, r_rid, r_optional); + this.drv.send_r(r_rdata, r_rid, r_err, r_optional); end endtask diff --git a/src/test/tb_obi_xbar.sv b/src/test/tb_obi_xbar.sv index 9586050..c89d634 100644 --- a/src/test/tb_obi_xbar.sv +++ b/src/test/tb_obi_xbar.sv @@ -31,7 +31,7 @@ module tb_obi_xbar; localparam time TestTime = 8ns; localparam obi_pkg::obi_cfg_t MgrConfig = '{ - UseRReady: 1'b1, + UseRReady: 1'b0, CombGnt: 1'b0, AddrWidth: AddrWidth, DataWidth: DataWidth, @@ -64,7 +64,7 @@ module tb_obi_xbar; ) rand_manager_t; localparam obi_pkg::obi_cfg_t SbrConfig = '{ - UseRReady: 1'b1, + UseRReady: 1'b0, CombGnt: 1'b0, AddrWidth: AddrWidth, DataWidth: DataWidth, diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv new file mode 100644 index 0000000..67db23e --- /dev/null +++ b/src/test/tb_relobi_xbar.sv @@ -0,0 +1,314 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +`include "obi/typedef.svh" +`include "obi/assign.svh" + +module tb_relobi_xbar; + import obi_pkg::*; + + localparam int unsigned NumManagers = 32'd6; + localparam int unsigned NumSubordinates = 32'd8; + localparam bit UseIdForRouting = 1'b0; + + localparam int unsigned NumMaxTrans = 32'd8; + localparam int unsigned AddrWidth = 32; + localparam int unsigned DataWidth = 32; + localparam int unsigned MgrIdWidth = 5; + localparam int unsigned SbrIdWidth = MgrIdWidth+$clog2(NumManagers); + localparam int unsigned AUserWidth = 4; + localparam int unsigned WUserWidth = 2; + localparam int unsigned RUserWidth = 3; + + // TODO CHK! + + localparam int unsigned NumRequests = 32'd1000; + + localparam time CyclTime = 10ns; + localparam time ApplTime = 2ns; + localparam time TestTime = 8ns; + + localparam obi_pkg::obi_cfg_t MgrConfig = '{ + UseRReady: 1'b0, + CombGnt: 1'b0, + AddrWidth: AddrWidth, + DataWidth: DataWidth, + IdWidth: MgrIdWidth, + Integrity: 1'b0, + BeFull: 1'b1, + OptionalCfg: '{ + UseAtop: 1'b1, + UseMemtype: 1'b1, + UseProt: 1'b1, + UseDbg: 1'b1, + AUserWidth: AUserWidth, + WUserWidth: WUserWidth, + RUserWidth: RUserWidth, + MidWidth: 0, + AChkWidth: 0, + RChkWidth: 0 + } + }; + + typedef struct packed { + logic [ AUserWidth-1:0] auser; + logic [ WUserWidth-1:0] wuser; + obi_pkg::atop_t atop; + obi_pkg::memtype_t memtype; + obi_pkg::prot_t prot; + logic dbg; + } mgr_a_optional_t; + typedef struct packed { + logic [RUserWidth-1:0] ruser; + logic exokay; + } mgr_r_optional_t; + typedef obi_test::obi_rand_manager #( + .ObiCfg ( MgrConfig ), + .obi_a_optional_t ( mgr_a_optional_t ), + .obi_r_optional_t ( mgr_r_optional_t ), + .TA ( ApplTime ), + .TT ( TestTime ), + .MinAddr (32'h0000_0000), + .MaxAddr (32'h0001_3000) + ) rand_manager_t; + + localparam obi_pkg::obi_cfg_t SbrConfig = '{ + UseRReady: 1'b0, + CombGnt: 1'b0, + AddrWidth: AddrWidth, + DataWidth: DataWidth, + IdWidth: SbrIdWidth, + Integrity: 1'b0, + BeFull: 1'b1, + OptionalCfg: '{ + UseAtop: 1'b1, + UseMemtype: 1'b1, + UseProt: 1'b1, + UseDbg: 1'b1, + AUserWidth: AUserWidth, + WUserWidth: WUserWidth, + RUserWidth: RUserWidth, + MidWidth: 0, + AChkWidth: 0, + RChkWidth: 0 + } + }; + + typedef mgr_a_optional_t sbr_a_optional_t; + typedef mgr_r_optional_t sbr_r_optional_t; + + typedef obi_test::obi_rand_subordinate #( + .ObiCfg ( SbrConfig ), + .obi_a_optional_t ( sbr_a_optional_t ), + .obi_r_optional_t ( sbr_r_optional_t ), + .TA ( ApplTime ), + .TT ( TestTime ) + ) rand_subordinate_t; + + localparam int unsigned NumRules = 8; + typedef struct packed { + int unsigned idx; + logic [AddrWidth-1:0] start_addr; + logic [AddrWidth:0] end_addr; + } rule_t; + + localparam rule_t [NumRules-1:0] AddrMap = '{ + '{idx: 32'd7, start_addr: 32'h0001_0000, end_addr: 32'h0001_1000}, + '{idx: 32'd6, start_addr: 32'h0000_9000, end_addr: 32'h0001_0000}, + '{idx: 32'd5, start_addr: 32'h0000_8000, end_addr: 32'h0000_9000}, + '{idx: 32'd4, start_addr: 32'h0000_7000, end_addr: 32'h0000_8000}, + '{idx: 32'd3, start_addr: 32'h0000_6300, end_addr: 32'h0000_7000}, + '{idx: 32'd2, start_addr: 32'h0000_4000, end_addr: 32'h0000_6300}, + '{idx: 32'd1, start_addr: 32'h0000_3000, end_addr: 32'h0000_4000}, + '{idx: 32'd0, start_addr: 32'h0000_0000, end_addr: 32'h0000_3000} + }; + + logic clk, rst_n; + logic [NumManagers-1:0] end_of_sim; + + OBI_BUS_DV #( + .OBI_CFG ( MgrConfig ), + .obi_a_optional_t ( mgr_a_optional_t ), + .obi_r_optional_t ( mgr_r_optional_t ) + ) mgr_bus_dv [NumManagers] ( + .clk_i ( clk ), + .rst_ni ( rst_n ) + ); + OBI_BUS #( + .OBI_CFG ( MgrConfig ), + .obi_a_optional_t ( mgr_a_optional_t ), + .obi_r_optional_t ( mgr_r_optional_t ) + ) mgr_bus [NumManagers] (); + + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_drivers + initial begin + automatic rand_manager_t obi_rand_manager = new ( mgr_bus_dv[i], $sformatf("MGR_%0d",i)); + automatic logic [ MgrConfig.DataWidth-1:0] r_rdata = '0; + automatic logic [ MgrConfig.IdWidth-1:0] r_rid = '0; + automatic logic r_err = '0; + automatic mgr_r_optional_t r_optional = '0; + end_of_sim[i] <= 1'b0; + obi_rand_manager.reset(); + @(posedge rst_n); + obi_rand_manager.write(32'h0000_1100, 4'hF, 32'hDEAD_BEEF, 2, + '{auser: '0, + wuser: '0, + atop: '0, + memtype: obi_pkg::memtype_t'('0), + prot: obi_pkg::prot_t'('0), + dbg: '0}, r_rdata, r_rid, r_err, r_optional); + obi_rand_manager.read(32'h0000_e100, 2, '{auser: '0, + wuser: '0, + atop: '0, + memtype: obi_pkg::memtype_t'('0), + prot: obi_pkg::prot_t'('0), + dbg: '0}, r_rdata, r_rid, r_err, r_optional); + obi_rand_manager.run(NumRequests); + end_of_sim[i] <= 1'b1; + end + + `OBI_ASSIGN(mgr_bus[i], mgr_bus_dv[i], MgrConfig, MgrConfig) + end + + OBI_BUS_DV #( + .OBI_CFG ( SbrConfig ), + .obi_a_optional_t ( sbr_a_optional_t ), + .obi_r_optional_t ( sbr_r_optional_t ) + ) sbr_bus_dv [NumSubordinates] ( + .clk_i ( clk ), + .rst_ni ( rst_n ) + ); + OBI_BUS #( + .OBI_CFG ( SbrConfig ), + .obi_a_optional_t ( sbr_a_optional_t ), + .obi_r_optional_t ( sbr_r_optional_t ) + ) sbr_bus [NumSubordinates] (); + + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_drivers + initial begin + automatic rand_subordinate_t obi_rand_subordinate = + new ( sbr_bus_dv[i], $sformatf("SBR_%0d",i)); + obi_rand_subordinate.reset(); + @(posedge rst_n); + obi_rand_subordinate.run(); + end + + `OBI_ASSIGN(sbr_bus_dv[i], sbr_bus[i], SbrConfig, SbrConfig) + end + + clk_rst_gen #( + .ClkPeriod ( CyclTime ), + .RstClkCycles ( 5 ) + ) i_clk_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + // DUT + `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(mgr_bus, MgrConfig, mgr_a_optional_t, mgr_r_optional_t) + `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) + `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_mgr_bus, MgrConfig, mgr_a_optional_t, mgr_r_optional_t) + `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) + mgr_bus_req_t [NumManagers-1:0] mgr_bus_req; + mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp; + sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req; + sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp; + rel_mgr_bus_req_t [NumManagers-1:0] rel_mgr_bus_req; + rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp; + rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req; + rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp; + + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_encode + + `OBI_ASSIGN_TO_REQ(mgr_bus_req[i], mgr_bus[i], MgrConfig) + `OBI_ASSIGN_FROM_RSP(mgr_bus[i], mgr_bus_rsp[i], MgrConfig) + + relobi_encoder #( + .Cfg ( MgrConfig ), + .relobi_req_t ( rel_mgr_bus_req_t ), + .relobi_rsp_t ( rel_mgr_bus_rsp_t ), + .obi_req_t ( mgr_bus_req_t ), + .obi_rsp_t ( mgr_bus_rsp_t ), + .a_optional_t ( mgr_a_optional_t ), + .r_optional_t ( mgr_r_optional_t ) + ) i_enc_mgr ( + .req_i (mgr_bus_req[i]), + .rsp_o (mgr_bus_rsp[i]), + + .rel_req_o (rel_mgr_bus_req[i]), + .rel_rsp_i (rel_mgr_bus_rsp[i]), + + .relerr_o () + ); + end + + relobi_xbar #( + .SbrPortObiCfg ( MgrConfig ), + .MgrPortObiCfg ( SbrConfig ), + .sbr_port_obi_req_t ( rel_mgr_bus_req_t ), + .sbr_port_a_chan_t ( rel_mgr_bus_a_chan_t ), + .sbr_port_obi_rsp_t ( rel_mgr_bus_rsp_t ), + .sbr_port_r_chan_t ( rel_mgr_bus_r_chan_t ), + .mgr_port_obi_req_t ( rel_sbr_bus_req_t ), + .mgr_port_obi_rsp_t ( rel_sbr_bus_rsp_t ), + .mgr_port_a_chan_t ( rel_sbr_bus_a_chan_t ), + .a_optional_t ( mgr_a_optional_t ), + .r_optional_t ( mgr_r_optional_t ), + .NumSbrPorts ( NumManagers ), + .NumMgrPorts ( NumSubordinates ), + .NumMaxTrans ( NumMaxTrans ), + .NumAddrRules ( NumRules ), + .addr_map_rule_t ( rule_t ), + .UseIdForRouting ( UseIdForRouting ), + .TmrMap (1'b1) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .testmode_i ( 1'b0 ), + + .sbr_ports_req_i ( rel_mgr_bus_req ), + .sbr_ports_rsp_o ( rel_mgr_bus_rsp ), + + .mgr_ports_req_o ( rel_sbr_bus_req ), + .mgr_ports_rsp_i ( rel_sbr_bus_rsp ), + + .addr_map_i ( {3{AddrMap}} ), + .en_default_idx_i ( '0 ), + .default_idx_i ( '0 ) + ); + + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode + relobi_decoder #( + .Cfg ( SbrConfig ), + .relobi_req_t ( rel_sbr_bus_req_t ), + .relobi_rsp_t ( rel_sbr_bus_rsp_t ), + .obi_req_t ( sbr_bus_req_t ), + .obi_rsp_t ( sbr_bus_rsp_t ), + .a_optional_t ( sbr_a_optional_t ), + .r_optional_t ( sbr_r_optional_t ) + ) i_dec_sbr ( + .req_o (sbr_bus_req[i]), + .rsp_i (sbr_bus_rsp[i]), + + .rel_req_i (rel_sbr_bus_req[i]), + .rel_rsp_o (rel_sbr_bus_rsp[i]), + + .relerr_o () + ); + + `OBI_ASSIGN_FROM_REQ(sbr_bus[i], sbr_bus_req[i], SbrConfig) + `OBI_ASSIGN_TO_RSP(sbr_bus_rsp[i], sbr_bus[i], SbrConfig) + + end + + initial begin + wait(&end_of_sim); + repeat (1000) @(posedge clk); + $display("Simulation stopped as all Masters transferred their data, Success.",); + $stop(); + end + +endmodule From 9126de79c9acae459ba4c868b6f155d47d5f80a9 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 9 May 2025 11:19:23 +0200 Subject: [PATCH 11/48] Add fault signalling --- Bender.lock | 2 +- Bender.yml | 2 +- src/relobi_a_other_decoder.sv | 4 +- src/relobi_decoder.sv | 18 +++---- src/relobi_demux.sv | 21 +++++--- src/relobi_encoder.sv | 8 +-- src/relobi_mux.sv | 33 +++++++++--- src/relobi_r_other_decoder.sv | 4 +- src/relobi_tmr_a.sv | 96 ++++++++++++++++++++--------------- src/relobi_tmr_r.sv | 48 ++++++++++-------- src/relobi_xbar.sv | 22 ++++++-- src/test/tb_relobi_xbar.sv | 8 +-- 12 files changed, 162 insertions(+), 104 deletions(-) diff --git a/Bender.lock b/Bender.lock index c609380..f176334 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: b23577c955b392f5661c6fd7bbda710a6a752377 + revision: 6b179fa05f40a9a3e1ca3d027e54f724d50e26e0 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index b2f2cbc..21b1abf 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: b23577c955b392f5661c6fd7bbda710a6a752377 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 6b179fa05f40a9a3e1ca3d027e54f724d50e26e0 } export_include_dirs: - include diff --git a/src/relobi_a_other_decoder.sv b/src/relobi_a_other_decoder.sv index 8aee97e..1ce100d 100644 --- a/src/relobi_a_other_decoder.sv +++ b/src/relobi_a_other_decoder.sv @@ -22,7 +22,7 @@ module relobi_a_other_decoder #( output logic [Cfg.IdWidth -1:0] aid_o, output a_optional_t a_optional_o, - output logic [1:0] relerr_o + output logic [1:0] fault_o ); hsiao_ecc_dec #( @@ -38,7 +38,7 @@ module relobi_a_other_decoder #( aid_o, a_optional_o} ), .syndrome_o(), - .err_o (relerr_o) + .err_o (fault_o) ); endmodule diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index 6fdeba7..e3f0708 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -22,10 +22,10 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( output obi_req_t req_o, input obi_rsp_t rsp_i, - output logic [1:0] relerr_o + output logic [1:0] fault_o ); - logic [1:0][2:0] voter_errs; + logic [1:0] voter_errs; logic [2:0][1:0] hsiao_errs; logic [1:0][2:0] hsiao_errs_transpose; @@ -35,26 +35,26 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( end end - assign relerr_o[0] = |voter_errs | |hsiao_errs_transpose[0]; - assign relerr_o[1] = |hsiao_errs_transpose[1]; + assign fault_o[0] = |voter_errs | |hsiao_errs_transpose[0]; + assign fault_o[1] = |hsiao_errs_transpose[1]; - TMR_voter_detect i_req_valid_vote ( + TMR_voter_fail i_req_valid_vote ( .a_i (rel_req_i.req[0]), .b_i (rel_req_i.req[1]), .c_i (rel_req_i.req[2]), .majority_o (req_o.req), - .error_cba_o(voter_errs[0]) + .fault_detected_o(voter_errs[0]) ); assign rel_rsp_o.gnt = {3{rsp_i.gnt}}; if (Cfg.UseRReady) begin : gen_rready_vote - TMR_voter_detect i_rsp_ready_vote ( + TMR_voter_fail i_rsp_ready_vote ( .a_i (rel_req_i.rready[0]), .b_i (rel_req_i.rready[1]), .c_i (rel_req_i.rready[2]), .majority_o (req_o.rready), - .error_cba_o(voter_errs[1]) + .fault_detected_o(voter_errs[1]) ); end else begin : gen_no_rready assign voter_errs[1] = '0; @@ -93,7 +93,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .be_o (req_o.a.be), .aid_o (req_o.a.aid), .a_optional_o(req_o.a.a_optional), - .relerr_o (hsiao_errs[2]) + .fault_o (hsiao_errs[2]) ); hsiao_ecc_enc #( diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index b32ce0f..1015b58 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -33,13 +33,19 @@ module relobi_demux #( output obi_rsp_t sbr_port_rsp_o, output obi_req_t [NumMgrPorts-1:0] mgr_ports_req_o, - input obi_rsp_t [NumMgrPorts-1:0] mgr_ports_rsp_i + input obi_rsp_t [NumMgrPorts-1:0] mgr_ports_rsp_i, + + output logic [1:0] fault_o ); if (ObiCfg.Integrity) begin : gen_integrity_err $fatal(1, "unimplemented"); end + logic [7:0] faults; + assign fault_o[0] = |faults; + assign fault_o[1] = 1'b0; // reserved for future use + // stall requests to ensure in-order behavior (could be handled differently with rready) localparam int unsigned CounterWidth = cf_math_pkg::idx_width(NumMaxTrans); @@ -94,7 +100,8 @@ module relobi_demux #( .three_r_i({mgr_ports_rsp_i[select_q[2]].r, mgr_ports_rsp_i[select_q[1]].r, mgr_ports_rsp_i[select_q[0]].r}), - .voted_r_o(sbr_port_rsp_o.r) + .voted_r_o(sbr_port_rsp_o.r), + .fault_o (faults[0]) ); for (genvar i = 0; i < 3; i++) begin : gen_rvalid @@ -132,25 +139,23 @@ module relobi_demux #( end for (genvar i = 0; i < 3; i++) begin : gen_tmr_state - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth( $clog2(NumMgrPorts) ) ) i_select_vote ( .a_i (select_d[0]), .b_i (select_d[1]), .c_i (select_d[2]), .majority_o (select_d_voted[i]), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[1+2*i]) ); - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth( CounterWidth+1 ) ) i_counter_vote ( .a_i (counter_d[0]), .b_i (counter_d[1]), .c_i (counter_d[2]), .majority_o (counter_d_voted[i]), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[2+2*i]) ); end diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index a659aa5..be6db99 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -21,7 +21,7 @@ module relobi_encoder #( output relobi_req_t rel_req_o, input relobi_rsp_t rel_rsp_i, - logic [1:0] relerr_o + logic [1:0] fault_o ); logic [1:0][2:0] voter_errs; @@ -34,8 +34,8 @@ module relobi_encoder #( end end - assign relerr_o[0] = |voter_errs | |(hsiao_errs_transpose[0]); - assign relerr_o[1] = |(hsiao_errs_transpose[1]); + assign fault_o[0] = |voter_errs | |(hsiao_errs_transpose[0]); + assign fault_o[1] = |(hsiao_errs_transpose[1]); assign rel_req_o.req = {3{req_i.req}}; @@ -108,7 +108,7 @@ module relobi_encoder #( .rid_o (rsp_o.r.rid), .err_o (rsp_o.r.err), .r_optional_o(rsp_o.r.r_optional), - .relerr_o (hsiao_errs[1]) + .fault_o (hsiao_errs[1]) ); endmodule diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 99263ed..b9cf323 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -46,7 +46,9 @@ module relobi_mux #( output sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp_o, output mgr_port_obi_req_t mgr_port_req_o, - input mgr_port_obi_rsp_t mgr_port_rsp_i + input mgr_port_obi_rsp_t mgr_port_rsp_i, + + output logic [1:0] fault_o ); if (NumSbrPorts <= 1) begin : gen_NumSbrPorts_err $fatal(1, "unimplemented"); @@ -66,6 +68,17 @@ module relobi_mux #( localparam int unsigned RequiredExtraIdWidth = $clog2(NumSbrPorts); + logic [5:0][1:0] hsiao_faults; + logic [1:0][5:0] hsiao_faults_transpose; + logic [3:0] voter_faults; + for (genvar i = 0; i < 6; i++) begin : gen_hsiao_faults + for (genvar j = 0; j < 2; j++) begin + assign hsiao_faults_transpose[j][i] = hsiao_faults[i][j]; + end + end + assign fault_o[0] = |voter_faults | |hsiao_faults_transpose[0]; + assign fault_o[1] = |hsiao_faults_transpose[1]; + logic [NumSbrPorts-1:0][2:0] sbr_ports_req, sbr_ports_gnt; sbr_port_a_chan_t [NumSbrPorts-1:0] sbr_ports_a; @@ -111,7 +124,7 @@ module relobi_mux #( .idx_o ( selected_id ), - .relerr_o () + .fault_o ( voter_faults[0] ) ); for (genvar i = 0; i < 3; i++) begin : gen_tmr_aid @@ -120,6 +133,7 @@ module relobi_mux #( `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr) mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr.other_ecc; end + assign hsiao_faults[i] = '0; end else begin : gen_aid_extend logic we; logic [MgrPortObiCfg.DataWidth/8-1:0] be; @@ -141,7 +155,7 @@ module relobi_mux #( .aid_o (sbr_aid), .a_optional_o(a_optional), - .relerr_o () + .fault_o (hsiao_faults[i]) ); if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + RequiredExtraIdWidth ) begin @@ -177,7 +191,7 @@ module relobi_mux #( end end - `VOTE31F(mgr_port_a_tmr, mgr_port_req_o.a, ) + `VOTE31F(mgr_port_a_tmr, mgr_port_req_o.a, voter_faults[1]) logic [2:0][SbrPortObiCfg.IdWidth-1:0] rsp_rid; @@ -199,7 +213,8 @@ module relobi_mux #( .other_ecc_i (mgr_port_rsp_i.r.other_ecc), .rid_o (rsp_rid[i]), .err_o (), - .r_optional_o() + .r_optional_o(), + .fault_o (hsiao_faults[3+i]) ); assign {response_id[i], rsp_rid[i]} = @@ -207,6 +222,8 @@ module relobi_mux #( assign fifo_full[i] = 1'b0; end + assign voter_faults[3:2] = '0; + end else begin : gen_no_id_assign logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three; logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr, response_id_encoded; @@ -225,11 +242,11 @@ module relobi_mux #( .in (response_id_encoded), .out (response_id[i]), .syndrome_o(), - .err_o () // TODO + .err_o (hsiao_faults[3+i]) ); end - `VOTE31F(selected_id_tmr_three, selected_id_tmr, ) + `VOTE31F(selected_id_tmr_three, selected_id_tmr, voter_faults[2]) rel_fifo #( .FallThrough( 1'b0 ), @@ -252,7 +269,7 @@ module relobi_mux #( .data_o ( response_id_encoded ), .pop_i ( fifo_pop ), - .fault_o () + .fault_o (voter_faults[3]) ); end diff --git a/src/relobi_r_other_decoder.sv b/src/relobi_r_other_decoder.sv index 1407b9f..a3d2a4b 100644 --- a/src/relobi_r_other_decoder.sv +++ b/src/relobi_r_other_decoder.sv @@ -20,7 +20,7 @@ module relobi_r_other_decoder #( output logic err_o, output r_optional_t r_optional_o, - output logic [1:0] relerr_o + output logic [1:0] fault_o ); @@ -35,7 +35,7 @@ module relobi_r_other_decoder #( err_o, r_optional_o} ), .syndrome_o(), - .err_o (relerr_o) + .err_o (fault_o) ); endmodule diff --git a/src/relobi_tmr_a.sv b/src/relobi_tmr_a.sv index 2f56835..9b7159a 100644 --- a/src/relobi_tmr_a.sv +++ b/src/relobi_tmr_a.sv @@ -10,85 +10,90 @@ module relobi_tmr_a #( parameter type a_optional_t = logic ) ( input obi_a_chan_t [2:0] three_a_i, - output obi_a_chan_t voted_a_o + output obi_a_chan_t voted_a_o, + output logic fault_o ); - bitwise_TMR_voter #( + logic [14:0] faults; + + assign fault_o = |faults; + + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)) ) i_r_data ( .a_i (three_a_i[0].addr), .b_i (three_a_i[1].addr), .c_i (three_a_i[2].addr), .majority_o (voted_a_o.addr), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[0]) ); - TMR_voter i_r_we ( + TMR_voter_fail i_r_we ( .a_i (three_a_i[0].we), .b_i (three_a_i[1].we), .c_i (three_a_i[2].we), - .majority_o (voted_a_o.we) + .majority_o (voted_a_o.we), + .fault_detected_o (faults[1]) ); - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.DataWidth/8) ) i_r_data ( .a_i (three_a_i[0].be), .b_i (three_a_i[1].be), .c_i (three_a_i[2].be), .majority_o (voted_a_o.be), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[2]) ); - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)) ) i_r_data ( .a_i (three_a_i[0].wdata), .b_i (three_a_i[1].wdata), .c_i (three_a_i[2].wdata), .majority_o (voted_a_o.wdata), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[3]) ); - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.IdWidth) ) i_r_id ( .a_i (three_a_i[0].aid), .b_i (three_a_i[1].aid), .c_i (three_a_i[2].aid), .majority_o (voted_a_o.aid), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[4]) ); - TMR_voter i_r_err ( + TMR_voter_fail i_r_err ( .a_i (three_r_i[0].err), .b_i (three_r_i[1].err), .c_i (three_r_i[2].err), - .majority_o (voted_r_o.err) + .majority_o (voted_r_o.err), + .fault_detected_o (faults[5]) ); if (ObiCfg.OptionalCfg.AUserWidth) begin : gen_auser - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.RUserWidth) ) i_r_id ( .a_i (three_a_i[0].a_optional.auser), .b_i (three_a_i[1].a_optional.auser), .c_i (three_a_i[2].a_optional.auser), .majority_o (voted_a_o.a_optional.auser), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[6]) ); + end else begin : gen_no_auser + assign faults[6] = 1'b0; end if (ObiCfg.OptionalCfg.WUserWidth) begin : gen_wuser - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.RUserWidth) ) i_r_id ( .a_i (three_a_i[0].a_optional.wuser), .b_i (three_a_i[1].a_optional.wuser), .c_i (three_a_i[2].a_optional.wuser), .majority_o (voted_a_o.a_optional.wuser), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[7]) ); + end else begin : gen_no_wuser + assign faults[7] = 1'b0; end if (ObiCfg.OptionalCfg.UseAtop) begin : gen_atop bitwise_TMR_voter #( @@ -98,65 +103,73 @@ module relobi_tmr_a #( .b_i (three_a_i[1].a_optional.atop), .c_i (three_a_i[2].a_optional.atop), .majority_o (voted_a_o.a_optional.atop), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[8]) ); + end else begin : gen_no_atop + assign faults[8] = 1'b0; end if (ObiCfg.OptionalCfg.UseMemtype) begin : gen_memtype - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(2) ) i_r_err ( .a_i (three_a_i[0].a_optional.memtype), .b_i (three_a_i[1].a_optional.memtype), .c_i (three_a_i[2].a_optional.memtype), .majority_o (voted_a_o.a_optional.memtype), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[9]) ); + end else begin : gen_no_memtype + assign faults[9] = 1'b0; end if (ObiCfg.OptionalCfg.MidWidth) begin : gen_mid - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.MidWidth) ) i_r_err ( .a_i (three_a_i[0].a_optional.mid), .b_i (three_a_i[1].a_optional.mid), .c_i (three_a_i[2].a_optional.mid), .majority_o (voted_a_o.a_optional.mid), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[10]) ); + end else begin : gen_no_mid + assign faults[10] = 1'b0; end if (ObiCfg.OptionalCfg.UseProt) begin : gen_prot - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(3) ) i_r_err ( .a_i (three_a_i[0].a_optional.prot), .b_i (three_a_i[1].a_optional.prot), .c_i (three_a_i[2].a_optional.prot), .majority_o (voted_a_o.a_optional.prot), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[11]) ); + end else begin : gen_no_prot + assign faults[11] = 1'b0; end if (ObiCfg.OptionalCfg.UseDbg) begin : gen_dbg - TMR_voter i_r_err ( + TMR_voter_fail i_r_err ( .a_i (three_a_i[0].a_optional.dbg), .b_i (three_a_i[1].a_optional.dbg), .c_i (three_a_i[2].a_optional.dbg), - .majority_o (voted_a_o.a_optional.dbg) + .majority_o (voted_a_o.a_optional.dbg), + .fault_detected_o (faults[12]) ); + end else begin : gen_no_dbg + assign faults[12] = 1'b0; end if (ObiCfg.OptionalCfg.AChkWidth) begin : gen_achk - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.AChkWidth) ) i_r_id ( .a_i (three_a_i[0].a_optional.achk), .b_i (three_a_i[1].a_optional.achk), .c_i (three_a_i[2].a_optional.achk), .majority_o (voted_a_o.a_optional.achk), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[13]) ); + end else begin : gen_no_achk + assign faults[13] = 1'b0; end if (!ObiCfg.OptionalCfg.AUserWidth && !ObiCfg.OptionalCfg.WUserWidth && @@ -168,15 +181,14 @@ module relobi_tmr_a #( !ObiCfg.OptionalCfg.AChkWidth ) begin : gen_optional_tie assign voted_a_o.a_optional = '0; end - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(hsiao_ecc_pkg::min_ecc(1+ObiCfg.DataWidth/8+ObiCfg.IdWidth+$bits(a_optional_t))) ) i_r_id ( .a_i (three_a_i[0].other_ecc), .b_i (three_a_i[1].other_ecc), .c_i (three_a_i[2].other_ecc), .majority_o (voted_a_o.other_ecc), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[14]) ); endmodule diff --git a/src/relobi_tmr_r.sv b/src/relobi_tmr_r.sv index d5534fe..7c0c9b2 100644 --- a/src/relobi_tmr_r.sv +++ b/src/relobi_tmr_r.sv @@ -10,67 +10,76 @@ module relobi_tmr_r #( parameter type r_optional_t = logic ) ( input obi_r_chan_t [2:0] three_r_i, - output obi_r_chan_t voted_r_o + output obi_r_chan_t voted_r_o, + + output logic fault_o ); - bitwise_TMR_voter #( + logic [6:0] faults; + assign fault_o = |faults; + + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)) ) i_r_data ( .a_i (three_r_i[0].rdata), .b_i (three_r_i[1].rdata), .c_i (three_r_i[2].rdata), .majority_o (voted_r_o.rdata), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[0]) ); - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.IdWidth) ) i_r_id ( .a_i (three_r_i[0].rid), .b_i (three_r_i[1].rid), .c_i (three_r_i[2].rid), .majority_o (voted_r_o.rid), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[1]) ); - TMR_voter i_r_err ( + TMR_voter_fail i_r_err ( .a_i (three_r_i[0].err), .b_i (three_r_i[1].err), .c_i (three_r_i[2].err), - .majority_o (voted_r_o.err) + .majority_o (voted_r_o.err), + .fault_detected_o (faults[2]) ); if (ObiCfg.OptionalCfg.RUserWidth) begin : gen_ruser - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.RUserWidth) ) i_r_user ( .a_i (three_r_i[0].r_optional.ruser), .b_i (three_r_i[1].r_optional.ruser), .c_i (three_r_i[2].r_optional.ruser), .majority_o (voted_r_o.r_optional.ruser), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[3]) ); + end else begin : gen_no_ruser + assign faults[3] = '0; end if (ObiCfg.OptionalCfg.RChkWidth) begin : gen_rchk - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(ObiCfg.OptionalCfg.RChkWidth) ) i_r_rchk ( .a_i (three_r_i[0].r_optional.rchk), .b_i (three_r_i[1].r_optional.rchk), .c_i (three_r_i[2].r_optional.rchk), .majority_o (voted_r_o.r_optional.rchk), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[4]) ); + end else begin : gen_no_rchk + assign faults[4] = '0; end if (ObiCfg.OptionalCfg.UseAtop) begin : gen_exokay - TMR_voter i_r_err ( + TMR_voter_fail i_r_err ( .a_i (three_r_i[0].r_optional.exokay), .b_i (three_r_i[1].r_optional.exokay), .c_i (three_r_i[2].r_optional.exokay), - .majority_o (voted_r_o.r_optional.exokay) + .majority_o (voted_r_o.r_optional.exokay), + .fault_detected_o (faults[5]) ); + end else begin : gen_no_exokay + assign faults[5] = '0; end if (!ObiCfg.OptionalCfg.RUserWidth && !ObiCfg.OptionalCfg.RChkWidth && @@ -78,15 +87,14 @@ module relobi_tmr_r #( assign voted_r_o.r_optional = '0; end - bitwise_TMR_voter #( + bitwise_TMR_voter_fail #( .DataWidth(hsiao_ecc_pkg::min_ecc(ObiCfg.IdWidth+1+$bits(r_optional_t))) ) i_r_other_ecc ( .a_i (three_r_i[0].other_ecc), .b_i (three_r_i[1].other_ecc), .c_i (three_r_i[2].other_ecc), .majority_o (voted_r_o.other_ecc), - .error_o (), - .error_cba_o() + .fault_detected_o (faults[6]) ); diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index 66dd758..e076c0a 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -58,9 +58,21 @@ module relobi_xbar #( input addr_map_rule_t [MapWidth-1:0][NumAddrRules-1:0] addr_map_i, input logic [MapWidth-1:0][NumSbrPorts-1:0] en_default_idx_i, - input logic [MapWidth-1:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] default_idx_i + input logic [MapWidth-1:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] default_idx_i, + + output logic [1:0] fault_o ); + logic [4*NumSbrPorts+NumMgrPorts-1:0][1:0] faults; + logic [1:0][4*NumSbrPorts+NumMgrPorts-1:0] faults_transpose; + for (genvar i = 0; i < 4*NumSbrPorts+NumMgrPorts; i++) begin : gen_faults_transpose + for (genvar j = 0; j < 2; j++) begin + assign faults_transpose[j][i] = faults[i][j]; + end + end + assign fault_o[0] = |faults_transpose[0]; + assign fault_o[1] = |faults_transpose[1]; + logic [NumSbrPorts-1:0][2:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; // Signals from the demuxes @@ -82,7 +94,7 @@ module relobi_xbar #( .in ( sbr_ports_req_i[i].a.addr ), .out ( addr ), .syndrome_o(), - .err_o () + .err_o (faults[4*i+j]) ); addr_decode #( @@ -117,7 +129,8 @@ module relobi_xbar #( .sbr_port_req_i ( sbr_ports_req_i[i] ), .sbr_port_rsp_o ( sbr_ports_rsp_o[i] ), .mgr_ports_req_o ( sbr_reqs[i] ), - .mgr_ports_rsp_i ( sbr_rsps[i] ) + .mgr_ports_rsp_i ( sbr_rsps[i] ), + .fault_o ( faults[4*i+3] ) ); end @@ -178,7 +191,8 @@ module relobi_xbar #( .sbr_ports_req_i ( mgr_reqs[i] ), .sbr_ports_rsp_o ( mgr_rsps[i] ), .mgr_port_req_o ( mgr_ports_req_o[i] ), - .mgr_port_rsp_i ( mgr_ports_rsp_i[i] ) + .mgr_port_rsp_i ( mgr_ports_rsp_i[i] ), + .fault_o ( faults[4*NumSbrPorts+i] ) ); end diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 67db23e..7f9f278 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -241,7 +241,7 @@ module tb_relobi_xbar; .rel_req_o (rel_mgr_bus_req[i]), .rel_rsp_i (rel_mgr_bus_rsp[i]), - .relerr_o () + .fault_o () ); end @@ -277,7 +277,9 @@ module tb_relobi_xbar; .addr_map_i ( {3{AddrMap}} ), .en_default_idx_i ( '0 ), - .default_idx_i ( '0 ) + .default_idx_i ( '0 ), + + .fault_o ( ) ); for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode @@ -296,7 +298,7 @@ module tb_relobi_xbar; .rel_req_i (rel_sbr_bus_req[i]), .rel_rsp_o (rel_sbr_bus_rsp[i]), - .relerr_o () + .fault_o () ); `OBI_ASSIGN_FROM_REQ(sbr_bus[i], sbr_bus_req[i], SbrConfig) From 6c4a4c363d54cc8a868784492d0cc71a10501917 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 20 May 2025 18:27:08 +0200 Subject: [PATCH 12/48] Enable VCS flow Co-authored-by: Diyou Shen --- .gitignore | 1 + Bender.lock | 2 +- Bender.yml | 6 ++--- Makefile | 32 +++++++++++++++++++++++-- src/relobi_decoder.sv | 2 +- src/relobi_encoder.sv | 2 +- src/relobi_pkg.sv | 49 ++++++++++++++++++++------------------ src/test/tb_relobi_xbar.sv | 2 +- 8 files changed, 64 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 87a730a..1eac3dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .bender working_dir +build diff --git a/Bender.lock b/Bender.lock index f176334..2122e46 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 6b179fa05f40a9a3e1ca3d027e54f724d50e26e0 + revision: 08d98b51cbc63bdcebf329b3791995c01b9b646a version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index 21b1abf..cf2f657 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 6b179fa05f40a9a3e1ca3d027e54f724d50e26e0 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 08d98b51cbc63bdcebf329b3791995c01b9b646a } export_include_dirs: - include @@ -31,7 +31,7 @@ sources: - src/obi_sram_shim.sv # Level 4 - src/obi_xbar.sv - - target: test + - target: any(test, obi_test) files: - src/test/obi_asserter.sv - src/test/obi_test.sv @@ -59,6 +59,6 @@ sources: - src/relobi_mux.sv # Level 5 - src/relobi_xbar.sv - - target: test + - target: any(test, obi_test) files: - src/test/tb_relobi_xbar.sv diff --git a/Makefile b/Makefile index 4df8c59..0877730 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,16 @@ BENDER ?= bender VSIM ?= vsim +VCS ?= vcs +VLOGAN ?= vlogan -BENDER_TARGETS := -t test +BENDER_TARGETS := -t obi_test BENDER_TARGETS += -t relOBI AVAILABLE_TESTBENCHES = tb_obi_xbar tb_obi_atop_resolver tb_relobi_xbar -scripts/compile.tcl: +# QuestaSim Flow +scripts/compile.tcl: Bender.yml Bender.lock mkdir -p scripts $(BENDER) script vsim $(BENDER_TARGETS) --vlog-arg="-svinputport=compat" > $@ @@ -29,6 +32,29 @@ endif .PHONY: all all: $(AVAILABLE_TESTBENCHES) +# VCS Flow +VCS_COMPILE_ARGS += -debug_access+all -override_timescale=10ns/10ps +VCS_RUNTIME_ARGS = + +scripts/compile_vcs.sh: Bender.yml Bender.lock + mkdir -p scripts + $(BENDER) script vcs --vlogan-bin="$(VLOGAN)" $(BENDER_TARGETS) --vlog-arg="-assert svaext +v2k -override_timescale=10ns10ps -kdb" > $@ + +.PHONY: build_vcs +build_vcs: scripts/compile_vcs.sh + mkdir -p build + chmod +x scripts/compile_vcs.sh + cd build && ../scripts/compile_vcs.sh + +build/%.sim: build_vcs + @if ! echo "$(AVAILABLE_TESTBENCHES)" | grep -wq "$*"; then \ + echo "Error: $(basename $@) is not an available testbench"; \ + echo "Available testbenches: $(AVAILABLE_TESTBENCHES)"; \ + exit 1; \ + fi + cd build && \ + $(VCS) $(VCS_COMPILE_ARGS) -o $*.sim $* + .PHONY: clean clean: rm -f scripts/compile.tcl @@ -36,3 +62,5 @@ clean: rm -f modelsim.ini rm -f transcript rm -f vsim.wlf + rm -f scripts/compile_vcs.sh + rm -rf build diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index e3f0708..5fdf88b 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -31,7 +31,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs for (genvar j = 0; j < 3; j++) begin - assign hsiao_errs_transpose[i][j] = hsiao_errs_transpose[j][i]; + assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; end end diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index be6db99..56660cd 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -21,7 +21,7 @@ module relobi_encoder #( output relobi_req_t rel_req_o, input relobi_rsp_t rel_rsp_i, - logic [1:0] fault_o + output logic [1:0] fault_o ); logic [1:0][2:0] voter_errs; diff --git a/src/relobi_pkg.sv b/src/relobi_pkg.sv index e073a5b..77657bb 100644 --- a/src/relobi_pkg.sv +++ b/src/relobi_pkg.sv @@ -6,41 +6,44 @@ package relobi_pkg; - let max(a,b) = (a > b) ? a : b; - - function automatic int unsigned relobi_a_other_width(obi_pkg::obi_cfg_t Cfg); - - relobi_a_other_width = 1 /* we */ + - Cfg.DataWidth/8 /* be */ + - Cfg.IdWidth /* aid */ + -/* a_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 6 : 0) + - (Cfg.OptionalCfg.UseMemtype ? 2 : 0) + - (Cfg.OptionalCfg.UseProt ? 3 : 0) + - (Cfg.OptionalCfg.UseDbg ? 1 : 0) + - Cfg.OptionalCfg.AUserWidth + - Cfg.OptionalCfg.WUserWidth + - Cfg.OptionalCfg.MidWidth + - Cfg.OptionalCfg.AChkWidth )); + // `let` is not supported by VCS, change it to a function + function automatic integer unsigned sigwidth (input integer unsigned width); + return (width != 32'd0) ? unsigned'(width) : 32'd1; + endfunction + + function automatic int unsigned relobi_a_other_width(input obi_pkg::obi_cfg_t Cfg); + + relobi_a_other_width = 1 /* we */ + + Cfg.DataWidth/8 /* be */ + + Cfg.IdWidth /* aid */ + +/* a_optional_t */ sigwidth((Cfg.OptionalCfg.UseAtop ? 6 : 0) + + (Cfg.OptionalCfg.UseMemtype ? 2 : 0) + + (Cfg.OptionalCfg.UseProt ? 3 : 0) + + (Cfg.OptionalCfg.UseDbg ? 1 : 0) + + Cfg.OptionalCfg.AUserWidth + + Cfg.OptionalCfg.WUserWidth + + Cfg.OptionalCfg.MidWidth + + Cfg.OptionalCfg.AChkWidth ); endfunction - function automatic int unsigned relobi_a_other_ecc_width(obi_pkg::obi_cfg_t Cfg); + function automatic int unsigned relobi_a_other_ecc_width(input obi_pkg::obi_cfg_t Cfg); relobi_a_other_ecc_width = hsiao_ecc_pkg::min_ecc(relobi_a_other_width(Cfg)); endfunction - function automatic int unsigned relobi_r_other_width(obi_pkg::obi_cfg_t Cfg); + function automatic int unsigned relobi_r_other_width(input obi_pkg::obi_cfg_t Cfg); - relobi_r_other_width = 1 /* err */ + - Cfg.IdWidth /* rid */ + -/* r_optional_t */ max(1, ((Cfg.OptionalCfg.UseAtop ? 1 : 0) + - Cfg.OptionalCfg.RUserWidth + - Cfg.OptionalCfg.RChkWidth )); + relobi_r_other_width = 1 /* err */ + + Cfg.IdWidth /* rid */ + +/* r_optional_t */ sigwidth((Cfg.OptionalCfg.UseAtop ? 1 : 0) + + Cfg.OptionalCfg.RUserWidth + + Cfg.OptionalCfg.RChkWidth ); endfunction - function automatic int unsigned relobi_r_other_ecc_width(obi_pkg::obi_cfg_t Cfg); + function automatic int unsigned relobi_r_other_ecc_width(input obi_pkg::obi_cfg_t Cfg); relobi_r_other_ecc_width = hsiao_ecc_pkg::min_ecc(relobi_r_other_width(Cfg)); diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 7f9f278..f6d105f 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -310,7 +310,7 @@ module tb_relobi_xbar; wait(&end_of_sim); repeat (1000) @(posedge clk); $display("Simulation stopped as all Masters transferred their data, Success.",); - $stop(); + $finish(); end endmodule From 4658ff03555518667f8da81414fe3b0a5aa44f5f Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 26 May 2025 15:41:13 +0200 Subject: [PATCH 13/48] Add VCS flow to CI --- .gitlab-ci.yml | 15 +++++++-------- Makefile | 34 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 55f8cf4..d0ad388 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,20 +3,19 @@ # SPDX-License-Identifier: SHL-0.51 stages: - - build - sim variables: VSIM: "questa-2022.3 vsim" + VCS: "vcs-2024.09-zr vcs" + VLOGAN: "vcs-2024.09-zr vlogan" -build: - stage: build +sim: + stage: sim script: - - make build + - make all_vsim -sim: +sim-vcs: stage: sim - dependencies: - - build script: - - make all + - make all_vcs diff --git a/Makefile b/Makefile index 0877730..4222374 100644 --- a/Makefile +++ b/Makefile @@ -12,25 +12,28 @@ BENDER_TARGETS += -t relOBI AVAILABLE_TESTBENCHES = tb_obi_xbar tb_obi_atop_resolver tb_relobi_xbar +TBS_VSIM = $(addsuffix _vsim, $(AVAILABLE_TESTBENCHES)) +TBS_VCS = $(addsuffix _vcs, $(AVAILABLE_TESTBENCHES)) + # QuestaSim Flow -scripts/compile.tcl: Bender.yml Bender.lock +scripts/compile_vsim.tcl: Bender.yml Bender.lock mkdir -p scripts $(BENDER) script vsim $(BENDER_TARGETS) --vlog-arg="-svinputport=compat" > $@ -.PHONY: build -build: scripts/compile.tcl - $(VSIM) -c -do 'exit -code [source scripts/compile.tcl]' +.PHONY: build_vsim +build_vsim: scripts/compile_vsim.tcl + $(VSIM) -c -do 'exit -code [source scripts/compile_vsim.tcl]' -.PHONY: $(AVAILABLE_TESTBENCHES) -$(AVAILABLE_TESTBENCHES): build +.PHONY: $(TBS_VSIM) +$(TBS_VSIM): build_vsim ifdef gui - $(VSIM) $@ -voptargs="+acc" + $(VSIM) $(patsubst %_vsim, %, $@) -voptargs="+acc" else - $(VSIM) -c $@ -do "run -all; quit -f" + $(VSIM) -c $(patsubst %_vsim, %, $@) -do "run -all; quit -f" endif -.PHONY: all -all: $(AVAILABLE_TESTBENCHES) +.PHONY: all_vsim +all_vsim: $(TBS_VSIM) # VCS Flow VCS_COMPILE_ARGS += -debug_access+all -override_timescale=10ns/10ps @@ -55,9 +58,18 @@ build/%.sim: build_vcs cd build && \ $(VCS) $(VCS_COMPILE_ARGS) -o $*.sim $* +.PHONY: $(TBS_VCS) +$(TBS_VCS): + @echo "Running VCS simulation for $@ as $(patsubst %_vcs,%,$@)" + $(MAKE) build/$(patsubst %_vcs,%,$@).sim + build/$(patsubst %_vcs,%,$@).sim $(VCS_RUNTIME_ARGS) + +.PHONY: all_vcs +all_vcs: $(TBS_VCS) + .PHONY: clean clean: - rm -f scripts/compile.tcl + rm -f scripts/compile_vsim.tcl rm -rf work rm -f modelsim.ini rm -f transcript From 47939f5885a249eaddc1acc6a2ea8845d041531c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 26 May 2025 16:15:49 +0200 Subject: [PATCH 14/48] Cleanup obi xbar interface variant --- src/obi_xbar.sv | 8 ++++++-- src/test/tb_obi_xbar.sv | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/obi_xbar.sv b/src/obi_xbar.sv index 2f1b3ce..b8949b9 100644 --- a/src/obi_xbar.sv +++ b/src/obi_xbar.sv @@ -161,8 +161,12 @@ endmodule module obi_xbar_intf #( /// The OBI configuration for the subordinate ports (input ports). parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + parameter type sbr_port_obi_a_optional_t = logic, + parameter type sbr_port_obi_r_optional_t = logic, /// The OBI configuration for the manager ports (ouput ports). parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + parameter type mgr_port_obi_a_optional_t = logic, + parameter type mgr_port_obi_r_optional_t = logic, /// The number of subordinate ports (input ports). parameter int unsigned NumSbrPorts = 32'd0, /// The number of manager ports (output ports). @@ -191,8 +195,8 @@ module obi_xbar_intf #( input logic [NumSbrPorts-1:0][cf_math_pkg::idx_width(NumMgrPorts)-1:0] default_idx_i ); - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_obi_a_optional_t, sbr_port_obi_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_obi_a_optional_t, mgr_port_obi_r_optional_t) sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; diff --git a/src/test/tb_obi_xbar.sv b/src/test/tb_obi_xbar.sv index c89d634..e395534 100644 --- a/src/test/tb_obi_xbar.sv +++ b/src/test/tb_obi_xbar.sv @@ -201,7 +201,11 @@ module tb_obi_xbar; // DUT obi_xbar_intf #( .SbrPortObiCfg ( MgrConfig ), + .sbr_port_obi_a_optional_t (sbr_a_optional_t), + .sbr_port_obi_r_optional_t (sbr_r_optional_t), .MgrPortObiCfg ( SbrConfig ), + .mgr_port_obi_a_optional_t (mgr_a_optional_t), + .mgr_port_obi_r_optional_t (mgr_r_optional_t), .NumSbrPorts ( NumManagers ), .NumMgrPorts ( NumSubordinates ), .NumMaxTrans ( NumMaxTrans ), @@ -223,7 +227,7 @@ module tb_obi_xbar; wait(&end_of_sim); repeat (1000) @(posedge clk); $display("Simulation stopped as all Masters transferred their data, Success.",); - $stop(); + $finish(); end endmodule From 522019dfa602c99f5a7fa0f76fb821e938fdbf3b Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 26 May 2025 17:19:47 +0200 Subject: [PATCH 15/48] Fix optional types for vsim --- src/obi_atop_resolver.sv | 18 ++++++++++++++++-- src/obi_mux.sv | 13 +++++++++++-- src/obi_xbar.sv | 17 +++++++++++------ src/test/obi_sim_mem.sv | 6 ++++++ src/test/tb_obi_atop_resolver.sv | 10 ++++++++++ src/test/tb_obi_xbar.sv | 8 ++++---- 6 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/obi_atop_resolver.sv b/src/obi_atop_resolver.sv index d5c1581..dc9479a 100644 --- a/src/obi_atop_resolver.sv +++ b/src/obi_atop_resolver.sv @@ -502,8 +502,12 @@ module obi_atop_resolver_intf #( /// The configuration of the subordinate ports (input ports). parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + parameter type sbr_port_a_optional_t = logic, + parameter type sbr_port_r_optional_t = logic, /// The configuration of the manager port (output port). parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + parameter type mgr_port_a_optional_t = logic, + parameter type mgr_port_r_optional_t = logic, /// Enable LR & SC AMOS parameter bit LrScEnable = 1, /// Cut path between request and response at the cost of increased AMO latency @@ -518,8 +522,13 @@ module obi_atop_resolver_intf OBI_BUS.Manager mgr_port ); - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `ifdef TARGET_VSIM + `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) + `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `else + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) + `endif sbr_port_obi_req_t sbr_port_req; sbr_port_obi_rsp_t sbr_port_rsp; @@ -540,8 +549,13 @@ module obi_atop_resolver_intf .sbr_port_obi_rsp_t (sbr_port_obi_rsp_t), .mgr_port_obi_req_t (mgr_port_obi_req_t), .mgr_port_obi_rsp_t (mgr_port_obi_rsp_t), +`ifdef TARGET_VSIM .mgr_port_obi_a_optional_t(mgr_port_obi_a_optional_t), .mgr_port_obi_r_optional_t(mgr_port_obi_r_optional_t), +`else + .mgr_port_obi_a_optional_t(mgr_port_a_optional_t), + .mgr_port_obi_r_optional_t(mgr_port_r_optional_t), +`endif .LrScEnable (LrScEnable), .RegisterAmo (RegisterAmo) ) i_obi_atop_resolver ( diff --git a/src/obi_mux.sv b/src/obi_mux.sv index 6c44cd8..7207e42 100644 --- a/src/obi_mux.sv +++ b/src/obi_mux.sv @@ -168,8 +168,12 @@ endmodule module obi_mux_intf #( /// The configuration of the subordinate ports (input ports). parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + parameter type sbr_port_a_optional_t = logic, + parameter type sbr_port_r_optional_t = logic, /// The configuration of the manager port (output port). parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + parameter type mgr_port_a_optional_t = logic, + parameter type mgr_port_r_optional_t = logic, /// The number of subordinate ports (input ports). parameter int unsigned NumSbrPorts = 32'd0, /// The maximum number of outstanding transactions. @@ -186,8 +190,13 @@ module obi_mux_intf #( OBI_BUS.Manager mgr_port ); - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `ifdef TARGET_VSIM + `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) + `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `else + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) + `endif sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; diff --git a/src/obi_xbar.sv b/src/obi_xbar.sv index b8949b9..a1aff70 100644 --- a/src/obi_xbar.sv +++ b/src/obi_xbar.sv @@ -161,12 +161,12 @@ endmodule module obi_xbar_intf #( /// The OBI configuration for the subordinate ports (input ports). parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, - parameter type sbr_port_obi_a_optional_t = logic, - parameter type sbr_port_obi_r_optional_t = logic, + parameter type sbr_port_a_optional_t = logic, + parameter type sbr_port_r_optional_t = logic, /// The OBI configuration for the manager ports (ouput ports). parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, - parameter type mgr_port_obi_a_optional_t = logic, - parameter type mgr_port_obi_r_optional_t = logic, + parameter type mgr_port_a_optional_t = logic, + parameter type mgr_port_r_optional_t = logic, /// The number of subordinate ports (input ports). parameter int unsigned NumSbrPorts = 32'd0, /// The number of manager ports (output ports). @@ -195,8 +195,13 @@ module obi_xbar_intf #( input logic [NumSbrPorts-1:0][cf_math_pkg::idx_width(NumMgrPorts)-1:0] default_idx_i ); - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_obi_a_optional_t, sbr_port_obi_r_optional_t) - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_obi_a_optional_t, mgr_port_obi_r_optional_t) + `ifdef TARGET_VSIM + `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) + `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) + `else + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) + `endif sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; diff --git a/src/test/obi_sim_mem.sv b/src/test/obi_sim_mem.sv index aec1528..e031347 100644 --- a/src/test/obi_sim_mem.sv +++ b/src/test/obi_sim_mem.sv @@ -150,6 +150,8 @@ endmodule module obi_sim_mem_intf import obi_pkg::*; #( parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic, parameter bit WarnUninitialized = 1'b0, parameter bit ClearErrOnAccess = 1'b0, parameter time ApplDelay = 0ps, @@ -167,7 +169,11 @@ module obi_sim_mem_intf import obi_pkg::*; #( output logic [ ObiCfg.IdWidth-1:0] mon_id_o ); + `ifdef TARGET_VSIM `OBI_TYPEDEF_ALL(obi, ObiCfg) + `else + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(obi, ObiCfg, a_optional_t, r_optional_t) + `endif obi_req_t obi_req; obi_rsp_t obi_rsp; diff --git a/src/test/tb_obi_atop_resolver.sv b/src/test/tb_obi_atop_resolver.sv index 0e4b33d..5a10e5f 100644 --- a/src/test/tb_obi_atop_resolver.sv +++ b/src/test/tb_obi_atop_resolver.sv @@ -169,7 +169,11 @@ module tb_obi_atop_resolver; obi_mux_intf #( .SbrPortObiCfg ( MgrConfig ), + .sbr_port_a_optional_t ( mgr_a_optional_t ), + .sbr_port_r_optional_t ( mgr_r_optional_t ), .MgrPortObiCfg ( MgrMuxedConfig ), + .mgr_port_a_optional_t ( mgr_a_optional_t ), + .mgr_port_r_optional_t ( mgr_r_optional_t ), .NumSbrPorts ( NumManagers ), .NumMaxTrans ( 2 ), .UseIdForRouting ( 1'b0 ) @@ -183,7 +187,11 @@ module tb_obi_atop_resolver; obi_atop_resolver_intf #( .SbrPortObiCfg ( MgrMuxedConfig ), + .sbr_port_a_optional_t ( mgr_a_optional_t ), + .sbr_port_r_optional_t ( mgr_r_optional_t ), .MgrPortObiCfg ( SbrConfig ), + .mgr_port_a_optional_t ( sbr_a_optional_t ), + .mgr_port_r_optional_t ( sbr_r_optional_t ), .LrScEnable ( 1 ), .RegisterAmo ( 1'b0 ) ) i_atop_resolver ( @@ -196,6 +204,8 @@ module tb_obi_atop_resolver; obi_sim_mem_intf #( .ObiCfg ( SbrConfig ), + .a_optional_t ( sbr_a_optional_t ), + .r_optional_t ( sbr_r_optional_t ), .ClearErrOnAccess ( 1'b0 ), .WarnUninitialized ( 1'b0 ), .ApplDelay ( ApplTime ), diff --git a/src/test/tb_obi_xbar.sv b/src/test/tb_obi_xbar.sv index e395534..bf5f9ad 100644 --- a/src/test/tb_obi_xbar.sv +++ b/src/test/tb_obi_xbar.sv @@ -201,11 +201,11 @@ module tb_obi_xbar; // DUT obi_xbar_intf #( .SbrPortObiCfg ( MgrConfig ), - .sbr_port_obi_a_optional_t (sbr_a_optional_t), - .sbr_port_obi_r_optional_t (sbr_r_optional_t), + .sbr_port_a_optional_t (mgr_a_optional_t), + .sbr_port_r_optional_t (mgr_r_optional_t), .MgrPortObiCfg ( SbrConfig ), - .mgr_port_obi_a_optional_t (mgr_a_optional_t), - .mgr_port_obi_r_optional_t (mgr_r_optional_t), + .mgr_port_a_optional_t (sbr_a_optional_t), + .mgr_port_r_optional_t (sbr_r_optional_t), .NumSbrPorts ( NumManagers ), .NumMgrPorts ( NumSubordinates ), .NumMaxTrans ( NumMaxTrans ), From 9c30d2b2703d402fda8b79e32f87f2777896acfe Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 10 Jun 2025 18:20:35 +0200 Subject: [PATCH 16/48] Bump questa version to avoid workaround --- .gitlab-ci.yml | 2 +- src/obi_xbar.sv | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d0ad388..9ea6457 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,7 @@ stages: - sim variables: - VSIM: "questa-2022.3 vsim" + VSIM: "questa-2025.1-dz vsim" VCS: "vcs-2024.09-zr vcs" VLOGAN: "vcs-2024.09-zr vlogan" diff --git a/src/obi_xbar.sv b/src/obi_xbar.sv index a1aff70..451c2ec 100644 --- a/src/obi_xbar.sv +++ b/src/obi_xbar.sv @@ -195,13 +195,8 @@ module obi_xbar_intf #( input logic [NumSbrPorts-1:0][cf_math_pkg::idx_width(NumMgrPorts)-1:0] default_idx_i ); - `ifdef TARGET_VSIM - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) - `else - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) - `endif + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; From 3e514d150023e7778518e16188150efb1def9e7d Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 10 Jun 2025 18:21:53 +0200 Subject: [PATCH 17/48] Fix vcs/lint issues --- Bender.lock | 4 ++-- Makefile | 3 ++- src/relobi_demux.sv | 2 +- src/relobi_err_sbr.sv | 4 ++-- src/relobi_xbar.sv | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Bender.lock b/Bender.lock index 2122e46..d303388 100644 --- a/Bender.lock +++ b/Bender.lock @@ -7,8 +7,8 @@ packages: dependencies: - common_cells axi: - revision: 39f5f2d51c5e524f6fc5cf8b6e901f7dcc5622d7 - version: 0.39.6 + revision: f07498d53ecd5518b277c7d213ec3b71ca4df93c + version: 0.39.7 source: Git: https://github.com/pulp-platform/axi.git dependencies: diff --git a/Makefile b/Makefile index 4222374..eb9ae62 100644 --- a/Makefile +++ b/Makefile @@ -36,12 +36,13 @@ endif all_vsim: $(TBS_VSIM) # VCS Flow +VCS_SCRIPT_ARGS += -assert svaext +v2k -override_timescale=10ns/10ps -kdb VCS_COMPILE_ARGS += -debug_access+all -override_timescale=10ns/10ps VCS_RUNTIME_ARGS = scripts/compile_vcs.sh: Bender.yml Bender.lock mkdir -p scripts - $(BENDER) script vcs --vlogan-bin="$(VLOGAN)" $(BENDER_TARGETS) --vlog-arg="-assert svaext +v2k -override_timescale=10ns10ps -kdb" > $@ + $(BENDER) script vcs --vlogan-bin="$(VLOGAN)" $(BENDER_TARGETS) --vlog-arg="$(VCS_SCRIPT_ARGS)" > $@ .PHONY: build_vcs build_vcs: scripts/compile_vcs.sh diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index 1015b58..aef8464 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -42,7 +42,7 @@ module relobi_demux #( $fatal(1, "unimplemented"); end - logic [7:0] faults; + logic [6:0] faults; assign fault_o[0] = |faults; assign fault_o[1] = 1'b0; // reserved for future use diff --git a/src/relobi_err_sbr.sv b/src/relobi_err_sbr.sv index 62f7781..cce4c6c 100644 --- a/src/relobi_err_sbr.sv +++ b/src/relobi_err_sbr.sv @@ -4,7 +4,7 @@ // Michael Rogenmoser -module obi_err_sbr #( +module relobi_err_sbr #( /// The OBI configuration for all ports. parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, /// The request struct. @@ -66,7 +66,7 @@ endmodule `include "obi/typedef.svh" `include "obi/assign.svh" -module obi_err_sbr_intf #( +module relobi_err_sbr_intf #( /// The OBI configuration for all ports. parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, /// Numper of transactions accepted before stalling if UseRReady diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index e076c0a..2425663 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -66,7 +66,7 @@ module relobi_xbar #( logic [4*NumSbrPorts+NumMgrPorts-1:0][1:0] faults; logic [1:0][4*NumSbrPorts+NumMgrPorts-1:0] faults_transpose; for (genvar i = 0; i < 4*NumSbrPorts+NumMgrPorts; i++) begin : gen_faults_transpose - for (genvar j = 0; j < 2; j++) begin + for (genvar j = 0; j < 2; j++) begin : gen_faults_transpose_inner assign faults_transpose[j][i] = faults[i][j]; end end From 1ded75ae96d4393497ae307a3089f2c00fe55c14 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 10 Jun 2025 18:22:30 +0200 Subject: [PATCH 18/48] Gate hsiao faults --- src/relobi_decoder.sv | 10 +++++++--- src/relobi_encoder.sv | 19 ++++++++++++++----- src/relobi_mux.sv | 21 +++++++++++++-------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/relobi_decoder.sv b/src/relobi_decoder.sv index 5fdf88b..66c6de6 100644 --- a/src/relobi_decoder.sv +++ b/src/relobi_decoder.sv @@ -27,11 +27,12 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( logic [1:0] voter_errs; logic [2:0][1:0] hsiao_errs; + logic [2:0][1:0] hsiao_errs_gated; logic [1:0][2:0] hsiao_errs_transpose; - for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs - for (genvar j = 0; j < 3; j++) begin - assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose + for (genvar j = 0; j < 3; j++) begin : gen_hsiao_errs_transpose_inner + assign hsiao_errs_transpose[i][j] = hsiao_errs_gated[j][i]; end end @@ -70,6 +71,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .syndrome_o(), .err_o (hsiao_errs[0]) ); + assign hsiao_errs_gated[0] = rel_req_i.req[0] ? hsiao_errs[0] : '0; hsiao_ecc_dec #( .DataWidth ( Cfg.DataWidth ) @@ -79,6 +81,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .syndrome_o(), .err_o (hsiao_errs[1]) ); + assign hsiao_errs_gated[1] = rel_req_i.req[0] ? hsiao_errs[1] : '0; relobi_a_other_decoder #( .Cfg (Cfg), @@ -95,6 +98,7 @@ module relobi_decoder import hsiao_ecc_pkg::*; #( .a_optional_o(req_o.a.a_optional), .fault_o (hsiao_errs[2]) ); + assign hsiao_errs_gated[2] = rel_req_i.req[0] ? hsiao_errs[2] : '0; hsiao_ecc_enc #( .DataWidth ( Cfg.DataWidth ) diff --git a/src/relobi_encoder.sv b/src/relobi_encoder.sv index 56660cd..b3ba32f 100644 --- a/src/relobi_encoder.sv +++ b/src/relobi_encoder.sv @@ -25,17 +25,24 @@ module relobi_encoder #( ); logic [1:0][2:0] voter_errs; + logic [1:0] voter_errs_red; + logic voter_errs_red_red; logic [1:0][1:0] hsiao_errs; + logic [2:0][1:0] hsiao_errs_gated; logic [1:0][1:0] hsiao_errs_transpose; + logic [1:0] hsiao_errs_transpose_red; - for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs - for (genvar j = 0; j < 2; j++) begin - assign hsiao_errs_transpose[i][j] = hsiao_errs_transpose[j][i]; + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose + assign voter_errs_red[i] = |voter_errs[i]; + assign hsiao_errs_transpose_red[i] = |hsiao_errs_transpose[i]; + for (genvar j = 0; j < 2; j++) begin : gen_hsiao_errs_transpose_inner + assign hsiao_errs_transpose[i][j] = hsiao_errs_gated[j][i]; end end - assign fault_o[0] = |voter_errs | |(hsiao_errs_transpose[0]); - assign fault_o[1] = |(hsiao_errs_transpose[1]); + assign voter_errs_red_red = |voter_errs_red; + assign fault_o[0] = voter_errs_red_red | hsiao_errs_transpose_red[0]; + assign fault_o[1] = hsiao_errs_transpose_red[1]; assign rel_req_o.req = {3{req_i.req}}; @@ -96,6 +103,7 @@ module relobi_encoder #( .syndrome_o(), .err_o (hsiao_errs[0]) ); + assign hsiao_errs_gated[0] = rel_rsp_i.rvalid[0] ? hsiao_errs[0] : '0; relobi_r_other_decoder #( .Cfg (Cfg), @@ -110,5 +118,6 @@ module relobi_encoder #( .r_optional_o(rsp_o.r.r_optional), .fault_o (hsiao_errs[1]) ); + assign hsiao_errs_gated[1] = rel_rsp_i.rvalid[0] ? hsiao_errs[1] : '0; endmodule diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index b9cf323..6719b45 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -68,12 +68,13 @@ module relobi_mux #( localparam int unsigned RequiredExtraIdWidth = $clog2(NumSbrPorts); - logic [5:0][1:0] hsiao_faults; - logic [1:0][5:0] hsiao_faults_transpose; - logic [3:0] voter_faults; - for (genvar i = 0; i < 6; i++) begin : gen_hsiao_faults - for (genvar j = 0; j < 2; j++) begin - assign hsiao_faults_transpose[j][i] = hsiao_faults[i][j]; + logic [6:0][1:0] hsiao_faults; + logic [6:0][1:0] hsiao_faults_gated; + logic [1:0][6:0] hsiao_faults_transpose; + logic [4:0] voter_faults; + for (genvar i = 0; i < 7; i++) begin : gen_hsiao_faults_transpose + for (genvar j = 0; j < 2; j++) begin : gen_hsiao_faults_transpose_inner + assign hsiao_faults_transpose[j][i] = hsiao_faults_gated[i][j]; end end assign fault_o[0] = |voter_faults | |hsiao_faults_transpose[0]; @@ -134,6 +135,7 @@ module relobi_mux #( mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr.other_ecc; end assign hsiao_faults[i] = '0; + assign hsiao_faults_gated[i] = '0; end else begin : gen_aid_extend logic we; logic [MgrPortObiCfg.DataWidth/8-1:0] be; @@ -157,13 +159,14 @@ module relobi_mux #( .fault_o (hsiao_faults[i]) ); + assign hsiao_faults_gated[i] = mgr_port_req[i] ? hsiao_faults[i] : '0; if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + - RequiredExtraIdWidth ) begin + RequiredExtraIdWidth ) begin : gen_aid_extend always_comb begin mgr_aid = '0; mgr_aid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0] = {selected_id[i], sbr_aid}; end - end else begin + end else begin : gen_aid_noextend always_comb begin mgr_aid = '0; mgr_aid[SbrPortObiCfg.IdWidth-1:0] = sbr_aid; @@ -216,6 +219,7 @@ module relobi_mux #( .r_optional_o(), .fault_o (hsiao_faults[3+i]) ); + assign hsiao_faults_gated[3+i] = mgr_port_rsp_i.rvalid[i] ? hsiao_faults[3+i] : '0; assign {response_id[i], rsp_rid[i]} = mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0]; @@ -244,6 +248,7 @@ module relobi_mux #( .syndrome_o(), .err_o (hsiao_faults[3+i]) ); + assign hsiao_faults_gated[3+i] = fifo_pop[i] ? hsiao_faults[3+i] : '0; end `VOTE31F(selected_id_tmr_three, selected_id_tmr, voter_faults[2]) From 6c8cfbe554e20545854288eae30ecc187b5f4502 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 10 Jun 2025 18:44:23 +0200 Subject: [PATCH 19/48] Properly handle rid resizing in mux --- src/relobi_mux.sv | 83 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 6719b45..6ba20b5 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -68,11 +68,11 @@ module relobi_mux #( localparam int unsigned RequiredExtraIdWidth = $clog2(NumSbrPorts); - logic [6:0][1:0] hsiao_faults; - logic [6:0][1:0] hsiao_faults_gated; - logic [1:0][6:0] hsiao_faults_transpose; + logic [8:0][1:0] hsiao_faults; + logic [8:0][1:0] hsiao_faults_gated; + logic [1:0][8:0] hsiao_faults_transpose; logic [4:0] voter_faults; - for (genvar i = 0; i < 7; i++) begin : gen_hsiao_faults_transpose + for (genvar i = 0; i < 9; i++) begin : gen_hsiao_faults_transpose for (genvar j = 0; j < 2; j++) begin : gen_hsiao_faults_transpose_inner assign hsiao_faults_transpose[j][i] = hsiao_faults_gated[i][j]; end @@ -286,15 +286,74 @@ module relobi_mux #( end logic [NumSbrPorts-1:0][2:0] sbr_rsp_rvalid; sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; - always_comb begin : proc_sbr_rsp - for (int i = 0; i < NumSbrPorts; i++) begin - // Always assign r struct to avoid triplication overhead - `OBI_SET_R_STRUCT(sbr_rsp_r[i], mgr_port_rsp_i.r); - sbr_rsp_r[i].other_ecc = mgr_port_rsp_i.r.other_ecc; - sbr_rsp_rvalid[i] = '0; + if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_rid_identical + always_comb begin : proc_sbr_rsp + for (int i = 0; i < NumSbrPorts; i++) begin + // Always assign r struct to avoid triplication overhead + `OBI_SET_R_STRUCT(sbr_rsp_r[i], mgr_port_rsp_i.r); + sbr_rsp_r[i].other_ecc = mgr_port_rsp_i.r.other_ecc; + sbr_rsp_rvalid[i] = '0; + end + for (int i = 0; i < 3; i++) begin + sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; + end end - for (int i = 0; i < 3; i++) begin - sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; + assign hsiao_faults[8:6] = '0; + assign hsiao_faults_gated[8:6] = '0; + assign voter_faults[4] = '0; + end else begin : gen_rid_decrease + logic [2:0][MgrPortObiCfg.IdWidth-1:0] mgr_rid_tmr; + sbr_port_r_chan_t [2:0] sbr_r_tmr; + sbr_port_r_chan_t sbr_r; + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_rid + relobi_r_other_decoder #( + .Cfg (MgrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_decode ( + .rid_i (mgr_port_rsp_i.r.rid), + .err_i (mgr_port_rsp_i.r.err), + .r_optional_i(mgr_port_rsp_i.r.r_optional), + .other_ecc_i (mgr_port_rsp_i.r.other_ecc), + .rid_o (mgr_rid_tmr[i]), + .err_o (sbr_r_tmr[i].err), + .r_optional_o(sbr_r_tmr[i].r_optional), + .fault_o (hsiao_faults[6+i]) + ); + assign sbr_r_tmr[i].rid = mgr_rid_tmr[i][SbrPortObiCfg.IdWidth-1:0]; + relobi_r_other_encoder #( + .Cfg (SbrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_encode ( + .rid_i (sbr_r_tmr[i].rid), + .err_i (sbr_r_tmr[i].err), + .r_optional_i(sbr_r_tmr[i].r_optional), + .other_ecc_o (sbr_r_tmr[i].other_ecc) + ); + assign sbr_r_tmr[i].rdata = mgr_port_rsp_i.r.rdata; + end + assign hsiao_faults_gated[8:6] = fifo_pop[0] ? hsiao_faults[8:6] : '0; + always_comb begin + sbr_rsp_rvalid = '0; + for (int i = 0; i < 3; i++) begin + sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; + end + end + relobi_tmr_r #( + .ObiCfg (SbrPortObiCfg), + .obi_r_chan_t (sbr_port_r_chan_t), + .r_optional_t (r_optional_t) + ) tmr_r_vote ( + .three_r_i(sbr_r_tmr), + .voted_r_o(sbr_r), + .fault_o (voter_faults[4]) + ); + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_r_assign + assign sbr_rsp_r[i].rdata = sbr_r.rdata; + assign sbr_rsp_r[i].rid = sbr_r.rid; + assign sbr_rsp_r[i].err = sbr_r.err; + assign sbr_rsp_r[i].r_optional = sbr_r.r_optional; + assign sbr_rsp_r[i].other_ecc = sbr_r.other_ecc; end end From dc5cc51d4fb1e3b82ae524c43b8e98473a808eba Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 10 Jun 2025 18:46:42 +0200 Subject: [PATCH 20/48] Add fault tracking to TB --- src/test/tb_relobi_xbar.sv | 40 +++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index f6d105f..99722a8 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -212,6 +212,10 @@ module tb_relobi_xbar; `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_mgr_bus, MgrConfig, mgr_a_optional_t, mgr_r_optional_t) `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) + localparam int unsigned MgrBusReqBits = $bits(mgr_bus_req_t); + localparam int unsigned MgrBusRspBits = $bits(mgr_bus_rsp_t); + localparam int unsigned SbrBusReqBits = $bits(sbr_bus_req_t); + localparam int unsigned SbrBusRspBits = $bits(sbr_bus_rsp_t); mgr_bus_req_t [NumManagers-1:0] mgr_bus_req; mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp; sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req; @@ -220,6 +224,9 @@ module tb_relobi_xbar; rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp; rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req; rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp; + logic [1:0] xbar_fault; + logic [NumManagers-1:0][1:0] encoder_faults; + logic [NumSubordinates-1:0][1:0] decoder_faults; for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_encode @@ -241,7 +248,7 @@ module tb_relobi_xbar; .rel_req_o (rel_mgr_bus_req[i]), .rel_rsp_i (rel_mgr_bus_rsp[i]), - .fault_o () + .fault_o (encoder_faults[i] ) ); end @@ -279,7 +286,7 @@ module tb_relobi_xbar; .en_default_idx_i ( '0 ), .default_idx_i ( '0 ), - .fault_o ( ) + .fault_o ( xbar_fault ) ); for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode @@ -298,7 +305,7 @@ module tb_relobi_xbar; .rel_req_i (rel_sbr_bus_req[i]), .rel_rsp_o (rel_sbr_bus_rsp[i]), - .fault_o () + .fault_o ( decoder_faults[i] ) ); `OBI_ASSIGN_FROM_REQ(sbr_bus[i], sbr_bus_req[i], SbrConfig) @@ -306,6 +313,33 @@ module tb_relobi_xbar; end + // Fault indication + logic corrected_fault; + logic uncorrectable_fault; + always_comb begin + corrected_fault = xbar_fault[0]; + uncorrectable_fault = xbar_fault[1]; + + for (int unsigned i = 0; i < NumManagers; i++) begin + corrected_fault = corrected_fault || encoder_faults[i][0]; + uncorrectable_fault = uncorrectable_fault || encoder_faults[i][1]; + end + for (int unsigned i = 0; i < NumSubordinates; i++) begin + corrected_fault = corrected_fault || decoder_faults[i][0]; + uncorrectable_fault = uncorrectable_fault || decoder_faults[i][1]; + end + end + + always @(posedge clk) begin + if (rst_n == 1'b1) begin + if (uncorrectable_fault) begin + $display("Uncorrectable fault detected in the crossbar at %t.", $time); + end else if (corrected_fault) begin + $display("Corrected fault detected in the crossbar at %t.", $time); + end + end + end + initial begin wait(&end_of_sim); repeat (1000) @(posedge clk); From ca71161c356e6429d181330a2713a6ac2e74a61e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 13 Jun 2025 20:40:01 +0200 Subject: [PATCH 21/48] Update fault tracking --- src/test/tb_relobi_xbar.sv | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 99722a8..4aced77 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -321,16 +321,17 @@ module tb_relobi_xbar; uncorrectable_fault = xbar_fault[1]; for (int unsigned i = 0; i < NumManagers; i++) begin - corrected_fault = corrected_fault || encoder_faults[i][0]; - uncorrectable_fault = uncorrectable_fault || encoder_faults[i][1]; + corrected_fault |= encoder_faults[i][0]; + uncorrectable_fault |= encoder_faults[i][1]; end for (int unsigned i = 0; i < NumSubordinates; i++) begin - corrected_fault = corrected_fault || decoder_faults[i][0]; - uncorrectable_fault = uncorrectable_fault || decoder_faults[i][1]; + corrected_fault |= decoder_faults[i][0]; + uncorrectable_fault |= decoder_faults[i][1]; end end always @(posedge clk) begin + #(TestTime); if (rst_n == 1'b1) begin if (uncorrectable_fault) begin $display("Uncorrectable fault detected in the crossbar at %t.", $time); From 9796464716ea0ae579728c961d2a5d64f18dcd9e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 16 Jun 2025 20:03:22 +0200 Subject: [PATCH 22/48] Update tb_relobi_xbar for concurrent FI --- .gitignore | 1 + Bender.yml | 9 +- src/test/tb_relobi_xbar.sv | 330 ++++++++++++++++++++++++------------- 3 files changed, 227 insertions(+), 113 deletions(-) diff --git a/.gitignore b/.gitignore index 1eac3dc..da4445e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .bender working_dir build +fault_sim diff --git a/Bender.yml b/Bender.yml index cf2f657..9d98633 100644 --- a/Bender.yml +++ b/Bender.yml @@ -61,4 +61,11 @@ sources: - src/relobi_xbar.sv - target: any(test, obi_test) files: - - src/test/tb_relobi_xbar.sv + - target: ZOIX + files: + - src/test/tb_relobi_xbar.sv + include_dirs: + - fault_sim + - target: not(ZOIX) + files: + - src/test/tb_relobi_xbar.sv diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 4aced77..bdad927 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -7,6 +7,186 @@ `include "obi/typedef.svh" `include "obi/assign.svh" +module relobi_xbar_dut_wrapper #( + parameter int unsigned NumManagers = 32'd6, + parameter int unsigned NumSubordinates = 32'd8, + parameter obi_pkg::obi_cfg_t MgrConfig = obi_pkg::ObiDefaultConfig, + parameter obi_pkg::obi_cfg_t SbrConfig = obi_pkg::ObiDefaultConfig, + parameter type rel_mgr_bus_req_t = logic, + parameter type rel_mgr_bus_rsp_t = logic, + parameter type rel_mgr_bus_a_chan_t = logic, + parameter type rel_mgr_bus_r_chan_t = logic, + parameter type rel_sbr_bus_req_t = logic, + parameter type rel_sbr_bus_rsp_t = logic, + parameter type rel_sbr_bus_a_chan_t = logic, + parameter type rel_sbr_bus_r_chan_t = logic, + parameter type mgr_bus_req_t = logic, + parameter type mgr_bus_rsp_t = logic, + parameter type sbr_bus_req_t = logic, + parameter type sbr_bus_rsp_t = logic, + parameter type mgr_a_optional_t = logic, + parameter type mgr_r_optional_t = logic, + parameter type sbr_a_optional_t = logic, + parameter type sbr_r_optional_t = logic, + parameter int unsigned NumMaxTrans = 32'd8, + parameter int unsigned NumRules = 8, + parameter type rule_t = struct packed { + int unsigned idx; + logic [31:0] start_addr; + logic [31:0] end_addr; + }, + parameter rule_t [NumRules-1:0] AddrMap = '0, + parameter bit UseIdForRouting = 1'b0, + parameter time TestTime = 8ns +) ( + input logic clk, + input logic rst_n, + + // Manager ports + input mgr_bus_req_t [NumManagers-1:0] mgr_bus_req, + output mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp, + + // Subordinate ports + output sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req, + input sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp +); + + localparam int unsigned MgrBusReqBits = $bits(mgr_bus_req_t); + localparam int unsigned MgrBusRspBits = $bits(mgr_bus_rsp_t); + localparam int unsigned SbrBusReqBits = $bits(sbr_bus_req_t); + localparam int unsigned SbrBusRspBits = $bits(sbr_bus_rsp_t); + + rel_mgr_bus_req_t [NumManagers-1:0] rel_mgr_bus_req; + rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp; + rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req; + rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp; + + logic [1:0] xbar_fault; + logic [NumManagers-1:0][1:0] encoder_faults; + logic [NumSubordinates-1:0][1:0] decoder_faults; + + logic [NumManagers-1:0][MgrBusRspBits-1:0] mgr_bus_rsp_flat; + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_bus_rsp + assign mgr_bus_rsp_flat[i] = mgr_bus_rsp[i]; + end + + logic [NumSubordinates-1:0][SbrBusReqBits-1:0] sbr_bus_req_flat; + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_bus_req + assign sbr_bus_req_flat[i] = sbr_bus_req[i]; + end + + + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_encode + relobi_encoder #( + .Cfg ( MgrConfig ), + .relobi_req_t ( rel_mgr_bus_req_t ), + .relobi_rsp_t ( rel_mgr_bus_rsp_t ), + .obi_req_t ( mgr_bus_req_t ), + .obi_rsp_t ( mgr_bus_rsp_t ), + .a_optional_t ( mgr_a_optional_t ), + .r_optional_t ( mgr_r_optional_t ) + ) i_enc_mgr ( + .req_i (mgr_bus_req[i]), + .rsp_o (mgr_bus_rsp[i]), + + .rel_req_o (rel_mgr_bus_req[i]), + .rel_rsp_i (rel_mgr_bus_rsp[i]), + + .fault_o (encoder_faults[i] ) + ); + end + + relobi_xbar #( + .SbrPortObiCfg ( MgrConfig ), + .MgrPortObiCfg ( SbrConfig ), + .sbr_port_obi_req_t ( rel_mgr_bus_req_t ), + .sbr_port_a_chan_t ( rel_mgr_bus_a_chan_t ), + .sbr_port_obi_rsp_t ( rel_mgr_bus_rsp_t ), + .sbr_port_r_chan_t ( rel_mgr_bus_r_chan_t ), + .mgr_port_obi_req_t ( rel_sbr_bus_req_t ), + .mgr_port_obi_rsp_t ( rel_sbr_bus_rsp_t ), + .mgr_port_a_chan_t ( rel_sbr_bus_a_chan_t ), + .a_optional_t ( mgr_a_optional_t ), + .r_optional_t ( mgr_r_optional_t ), + .NumSbrPorts ( NumManagers ), + .NumMgrPorts ( NumSubordinates ), + .NumMaxTrans ( NumMaxTrans ), + .NumAddrRules ( NumRules ), + .addr_map_rule_t ( rule_t ), + .UseIdForRouting ( UseIdForRouting ), + .TmrMap (1'b1) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .testmode_i ( 1'b0 ), + + .sbr_ports_req_i ( rel_mgr_bus_req ), + .sbr_ports_rsp_o ( rel_mgr_bus_rsp ), + + .mgr_ports_req_o ( rel_sbr_bus_req ), + .mgr_ports_rsp_i ( rel_sbr_bus_rsp ), + + .addr_map_i ( {3{AddrMap}} ), + .en_default_idx_i ( '0 ), + .default_idx_i ( '0 ), + + .fault_o ( xbar_fault ) + ); + + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode + relobi_decoder #( + .Cfg ( SbrConfig ), + .relobi_req_t ( rel_sbr_bus_req_t ), + .relobi_rsp_t ( rel_sbr_bus_rsp_t ), + .obi_req_t ( sbr_bus_req_t ), + .obi_rsp_t ( sbr_bus_rsp_t ), + .a_optional_t ( sbr_a_optional_t ), + .r_optional_t ( sbr_r_optional_t ) + ) i_dec_sbr ( + .req_o (sbr_bus_req[i]), + .rsp_i (sbr_bus_rsp[i]), + + .rel_req_i (rel_sbr_bus_req[i]), + .rel_rsp_o (rel_sbr_bus_rsp[i]), + + .fault_o ( decoder_faults[i] ) + ); + end + + // Fault indication + logic corrected_fault; + logic uncorrectable_fault; + always_comb begin + corrected_fault = xbar_fault[0]; + uncorrectable_fault = xbar_fault[1]; + + for (int unsigned i = 0; i < NumManagers; i++) begin + corrected_fault |= encoder_faults[i][0]; + uncorrectable_fault |= encoder_faults[i][1]; + end + for (int unsigned i = 0; i < NumSubordinates; i++) begin + corrected_fault |= decoder_faults[i][0]; + uncorrectable_fault |= decoder_faults[i][1]; + end + end + + always @(posedge clk) begin + #(TestTime); + if (rst_n == 1'b1) begin + if (uncorrectable_fault) begin + $display("Uncorrectable fault detected in the crossbar at %t.", $time); + end else if (corrected_fault) begin + $display("Corrected fault detected in the crossbar at %t.", $time); + end + end + end + + `ifdef TARGET_ZOIX + `include "strobe.sv" + `endif + +endmodule + module tb_relobi_xbar; import obi_pkg::*; @@ -212,133 +392,59 @@ module tb_relobi_xbar; `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_mgr_bus, MgrConfig, mgr_a_optional_t, mgr_r_optional_t) `RELOBI_TYPEDEF_ALL_WITH_OPTIONAL(rel_sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) - localparam int unsigned MgrBusReqBits = $bits(mgr_bus_req_t); - localparam int unsigned MgrBusRspBits = $bits(mgr_bus_rsp_t); - localparam int unsigned SbrBusReqBits = $bits(sbr_bus_req_t); - localparam int unsigned SbrBusRspBits = $bits(sbr_bus_rsp_t); mgr_bus_req_t [NumManagers-1:0] mgr_bus_req; mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp; sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req; sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp; - rel_mgr_bus_req_t [NumManagers-1:0] rel_mgr_bus_req; - rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp; - rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req; - rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp; - logic [1:0] xbar_fault; - logic [NumManagers-1:0][1:0] encoder_faults; - logic [NumSubordinates-1:0][1:0] decoder_faults; for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_encode - `OBI_ASSIGN_TO_REQ(mgr_bus_req[i], mgr_bus[i], MgrConfig) `OBI_ASSIGN_FROM_RSP(mgr_bus[i], mgr_bus_rsp[i], MgrConfig) - - relobi_encoder #( - .Cfg ( MgrConfig ), - .relobi_req_t ( rel_mgr_bus_req_t ), - .relobi_rsp_t ( rel_mgr_bus_rsp_t ), - .obi_req_t ( mgr_bus_req_t ), - .obi_rsp_t ( mgr_bus_rsp_t ), - .a_optional_t ( mgr_a_optional_t ), - .r_optional_t ( mgr_r_optional_t ) - ) i_enc_mgr ( - .req_i (mgr_bus_req[i]), - .rsp_o (mgr_bus_rsp[i]), - - .rel_req_o (rel_mgr_bus_req[i]), - .rel_rsp_i (rel_mgr_bus_rsp[i]), - - .fault_o (encoder_faults[i] ) - ); end - relobi_xbar #( - .SbrPortObiCfg ( MgrConfig ), - .MgrPortObiCfg ( SbrConfig ), - .sbr_port_obi_req_t ( rel_mgr_bus_req_t ), - .sbr_port_a_chan_t ( rel_mgr_bus_a_chan_t ), - .sbr_port_obi_rsp_t ( rel_mgr_bus_rsp_t ), - .sbr_port_r_chan_t ( rel_mgr_bus_r_chan_t ), - .mgr_port_obi_req_t ( rel_sbr_bus_req_t ), - .mgr_port_obi_rsp_t ( rel_sbr_bus_rsp_t ), - .mgr_port_a_chan_t ( rel_sbr_bus_a_chan_t ), - .a_optional_t ( mgr_a_optional_t ), - .r_optional_t ( mgr_r_optional_t ), - .NumSbrPorts ( NumManagers ), - .NumMgrPorts ( NumSubordinates ), - .NumMaxTrans ( NumMaxTrans ), - .NumAddrRules ( NumRules ), - .addr_map_rule_t ( rule_t ), - .UseIdForRouting ( UseIdForRouting ), - .TmrMap (1'b1) - ) i_dut ( - .clk_i ( clk ), - .rst_ni ( rst_n ), - .testmode_i ( 1'b0 ), - - .sbr_ports_req_i ( rel_mgr_bus_req ), - .sbr_ports_rsp_o ( rel_mgr_bus_rsp ), - - .mgr_ports_req_o ( rel_sbr_bus_req ), - .mgr_ports_rsp_i ( rel_sbr_bus_rsp ), - - .addr_map_i ( {3{AddrMap}} ), - .en_default_idx_i ( '0 ), - .default_idx_i ( '0 ), - - .fault_o ( xbar_fault ) + relobi_xbar_dut_wrapper #( + .NumManagers(NumManagers), + .NumSubordinates(NumSubordinates), + .MgrConfig(MgrConfig), + .SbrConfig(SbrConfig), + .rel_mgr_bus_req_t(rel_mgr_bus_req_t), + .rel_mgr_bus_rsp_t(rel_mgr_bus_rsp_t), + .rel_mgr_bus_a_chan_t(rel_mgr_bus_a_chan_t), + .rel_mgr_bus_r_chan_t(rel_mgr_bus_r_chan_t), + .rel_sbr_bus_req_t(rel_sbr_bus_req_t), + .rel_sbr_bus_rsp_t(rel_sbr_bus_rsp_t), + .rel_sbr_bus_a_chan_t(rel_sbr_bus_a_chan_t), + .rel_sbr_bus_r_chan_t(rel_sbr_bus_r_chan_t), + .mgr_bus_req_t(mgr_bus_req_t), + .mgr_bus_rsp_t(mgr_bus_rsp_t), + .sbr_bus_req_t(sbr_bus_req_t), + .sbr_bus_rsp_t(sbr_bus_rsp_t), + .mgr_a_optional_t(mgr_a_optional_t), + .mgr_r_optional_t(mgr_r_optional_t), + .sbr_a_optional_t(sbr_a_optional_t), + .sbr_r_optional_t(sbr_r_optional_t), + .NumMaxTrans(NumMaxTrans), + .NumRules(NumRules), + .rule_t(rule_t), + .AddrMap(AddrMap), + .UseIdForRouting(UseIdForRouting), + .TestTime(TestTime) + ) i_dut_wrapper ( + .clk, + .rst_n, + + // Manager ports + .mgr_bus_req, + .mgr_bus_rsp, + + // Subordinate ports + .sbr_bus_req, + .sbr_bus_rsp ); for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode - relobi_decoder #( - .Cfg ( SbrConfig ), - .relobi_req_t ( rel_sbr_bus_req_t ), - .relobi_rsp_t ( rel_sbr_bus_rsp_t ), - .obi_req_t ( sbr_bus_req_t ), - .obi_rsp_t ( sbr_bus_rsp_t ), - .a_optional_t ( sbr_a_optional_t ), - .r_optional_t ( sbr_r_optional_t ) - ) i_dec_sbr ( - .req_o (sbr_bus_req[i]), - .rsp_i (sbr_bus_rsp[i]), - - .rel_req_i (rel_sbr_bus_req[i]), - .rel_rsp_o (rel_sbr_bus_rsp[i]), - - .fault_o ( decoder_faults[i] ) - ); - `OBI_ASSIGN_FROM_REQ(sbr_bus[i], sbr_bus_req[i], SbrConfig) `OBI_ASSIGN_TO_RSP(sbr_bus_rsp[i], sbr_bus[i], SbrConfig) - - end - - // Fault indication - logic corrected_fault; - logic uncorrectable_fault; - always_comb begin - corrected_fault = xbar_fault[0]; - uncorrectable_fault = xbar_fault[1]; - - for (int unsigned i = 0; i < NumManagers; i++) begin - corrected_fault |= encoder_faults[i][0]; - uncorrectable_fault |= encoder_faults[i][1]; - end - for (int unsigned i = 0; i < NumSubordinates; i++) begin - corrected_fault |= decoder_faults[i][0]; - uncorrectable_fault |= decoder_faults[i][1]; - end - end - - always @(posedge clk) begin - #(TestTime); - if (rst_n == 1'b1) begin - if (uncorrectable_fault) begin - $display("Uncorrectable fault detected in the crossbar at %t.", $time); - end else if (corrected_fault) begin - $display("Corrected fault detected in the crossbar at %t.", $time); - end - end end initial begin From 5f2ff6f5e3ec4e828c3b4a9f3d2219c756540b5e Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 17 Jun 2025 16:25:00 +0200 Subject: [PATCH 23/48] Fix relobi_demux cnt signals for correct error behavior --- src/relobi_demux.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index aef8464..9d12169 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -130,9 +130,9 @@ module relobi_demux #( always_comb begin counter_d[i] = counter_q[i]; - if (cnt_up & ~cnt_down) begin + if (cnt_up[i] & ~cnt_down[i]) begin counter_d[i] = counter_q[i] + {{CounterWidth-1{1'b0}}, 1'b1}; - end else if (cnt_down & ~cnt_up) begin + end else if (cnt_down[i] & ~cnt_up[i]) begin counter_d[i] = counter_q[i] - {{CounterWidth-1{1'b0}}, 1'b1}; end end From 5680d7223fa381ae6c78aafcea0944f080c50893 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 18 Jun 2025 16:12:25 +0200 Subject: [PATCH 24/48] Fix lint --- src/obi_atop_resolver.sv | 11 ++++------- src/obi_mux.sv | 11 ++++------- src/obi_xbar.sv | 6 ++++-- src/relobi_demux.sv | 4 +++- src/relobi_mux.sv | 6 ++++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/obi_atop_resolver.sv b/src/obi_atop_resolver.sv index dc9479a..f32a368 100644 --- a/src/obi_atop_resolver.sv +++ b/src/obi_atop_resolver.sv @@ -522,13 +522,10 @@ module obi_atop_resolver_intf OBI_BUS.Manager mgr_port ); - `ifdef TARGET_VSIM - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) - `else - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) - `endif + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, + sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, + mgr_port_a_optional_t, mgr_port_r_optional_t) sbr_port_obi_req_t sbr_port_req; sbr_port_obi_rsp_t sbr_port_rsp; diff --git a/src/obi_mux.sv b/src/obi_mux.sv index 7207e42..f6b7c34 100644 --- a/src/obi_mux.sv +++ b/src/obi_mux.sv @@ -190,13 +190,10 @@ module obi_mux_intf #( OBI_BUS.Manager mgr_port ); - `ifdef TARGET_VSIM - `OBI_TYPEDEF_ALL(sbr_port_obi, SbrPortObiCfg) - `OBI_TYPEDEF_ALL(mgr_port_obi, MgrPortObiCfg) - `else - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) - `endif + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, + sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, + mgr_port_a_optional_t, mgr_port_r_optional_t) sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; diff --git a/src/obi_xbar.sv b/src/obi_xbar.sv index 451c2ec..2b89152 100644 --- a/src/obi_xbar.sv +++ b/src/obi_xbar.sv @@ -195,8 +195,10 @@ module obi_xbar_intf #( input logic [NumSbrPorts-1:0][cf_math_pkg::idx_width(NumMgrPorts)-1:0] default_idx_i ); - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, sbr_port_a_optional_t, sbr_port_r_optional_t) - `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, mgr_port_a_optional_t, mgr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(sbr_port_obi, SbrPortObiCfg, + sbr_port_a_optional_t, sbr_port_r_optional_t) + `OBI_TYPEDEF_ALL_WITH_OPTIONAL(mgr_port_obi, MgrPortObiCfg, + mgr_port_a_optional_t, mgr_port_r_optional_t) sbr_port_obi_req_t [NumSbrPorts-1:0] sbr_ports_req; sbr_port_obi_rsp_t [NumSbrPorts-1:0] sbr_ports_rsp; diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index 9d12169..8b7b42e 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -72,7 +72,9 @@ module relobi_demux #( sbr_port_gnt[i] = 1'b0; if (!overflow[i]) begin - if (select_i_tmr[i] == select_q[i] || in_flight[i] == '0 || (in_flight[i] == 1 && cnt_down[i])) begin + if (select_i_tmr[i] == select_q[i] || + in_flight[i] == '0 || + (in_flight[i] == 1 && cnt_down[i])) begin mgr_ports_req[select_i_tmr[i]][i] = sbr_port_req_i.req[i]; sbr_port_gnt[i] = mgr_ports_rsp_i[select_i_tmr[i]].gnt[i]; end diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 6ba20b5..6786eba 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -229,8 +229,10 @@ module relobi_mux #( assign voter_faults[3:2] = '0; end else begin : gen_no_id_assign - logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three; - logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr, response_id_encoded; + logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] + selected_id_tmr_three; + logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] + selected_id_tmr, response_id_encoded; for (genvar i = 0; i < 3; i++) begin : gen_extra_id_tmr hsiao_ecc_enc #( From 38d79ee7076ffd9bf886558e67c2bd6c084d8dc2 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 18 Jun 2025 16:13:40 +0200 Subject: [PATCH 25/48] Bump redundancy_cells to commit on main --- Bender.lock | 2 +- Bender.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bender.lock b/Bender.lock index d303388..a047309 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 08d98b51cbc63bdcebf329b3791995c01b9b646a + revision: 14899dfd0ea0aa0be3be74e00c1979802d5832b1 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index 9d98633..1701b1a 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 08d98b51cbc63bdcebf329b3791995c01b9b646a } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 14899dfd0ea0aa0be3be74e00c1979802d5832b1 } export_include_dirs: - include From 6714ef4c517f2079599db8d3a7b0ec060cd82b30 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 18 Jun 2025 16:31:52 +0200 Subject: [PATCH 26/48] Fix lint --- src/obi_atop_resolver.sv | 5 ----- src/test/tb_relobi_xbar.sv | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/obi_atop_resolver.sv b/src/obi_atop_resolver.sv index f32a368..ce71c58 100644 --- a/src/obi_atop_resolver.sv +++ b/src/obi_atop_resolver.sv @@ -546,13 +546,8 @@ module obi_atop_resolver_intf .sbr_port_obi_rsp_t (sbr_port_obi_rsp_t), .mgr_port_obi_req_t (mgr_port_obi_req_t), .mgr_port_obi_rsp_t (mgr_port_obi_rsp_t), -`ifdef TARGET_VSIM - .mgr_port_obi_a_optional_t(mgr_port_obi_a_optional_t), - .mgr_port_obi_r_optional_t(mgr_port_obi_r_optional_t), -`else .mgr_port_obi_a_optional_t(mgr_port_a_optional_t), .mgr_port_obi_r_optional_t(mgr_port_r_optional_t), -`endif .LrScEnable (LrScEnable), .RegisterAmo (RegisterAmo) ) i_obi_atop_resolver ( diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index bdad927..067f3f5 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -30,11 +30,7 @@ module relobi_xbar_dut_wrapper #( parameter type sbr_r_optional_t = logic, parameter int unsigned NumMaxTrans = 32'd8, parameter int unsigned NumRules = 8, - parameter type rule_t = struct packed { - int unsigned idx; - logic [31:0] start_addr; - logic [31:0] end_addr; - }, + parameter type rule_t = logic, parameter rule_t [NumRules-1:0] AddrMap = '0, parameter bit UseIdForRouting = 1'b0, parameter time TestTime = 8ns From 4ba7763d0c92cde93791e880da4cc39c850b4f62 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:54:52 +0200 Subject: [PATCH 27/48] relobi: add cuts to xbar tb --- src/test/tb_relobi_xbar.sv | 66 ++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 067f3f5..4984662 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -52,14 +52,16 @@ module relobi_xbar_dut_wrapper #( localparam int unsigned SbrBusReqBits = $bits(sbr_bus_req_t); localparam int unsigned SbrBusRspBits = $bits(sbr_bus_rsp_t); - rel_mgr_bus_req_t [NumManagers-1:0] rel_mgr_bus_req; - rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp; - rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req; - rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp; + rel_mgr_bus_req_t [NumManagers-1:0] rel_mgr_bus_req, rel_mgr_bus_req_cut; + rel_mgr_bus_rsp_t [NumManagers-1:0] rel_mgr_bus_rsp, rel_mgr_bus_rsp_cut; + rel_sbr_bus_req_t [NumSubordinates-1:0] rel_sbr_bus_req, rel_sbr_bus_req_cut; + rel_sbr_bus_rsp_t [NumSubordinates-1:0] rel_sbr_bus_rsp, rel_sbr_bus_rsp_cut; logic [1:0] xbar_fault; logic [NumManagers-1:0][1:0] encoder_faults; + logic [NumManagers-1:0] enc_cut_faults; logic [NumSubordinates-1:0][1:0] decoder_faults; + logic [NumSubordinates-1:0] dec_cut_faults; logic [NumManagers-1:0][MgrBusRspBits-1:0] mgr_bus_rsp_flat; for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_bus_rsp @@ -92,6 +94,28 @@ module relobi_xbar_dut_wrapper #( ); end + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_cut + relobi_cut #( + .ObiCfg ( MgrConfig ), + .obi_req_t ( rel_mgr_bus_req_t ), + .obi_rsp_t ( rel_mgr_bus_rsp_t ), + .obi_a_chan_t ( rel_mgr_bus_a_chan_t ), + .obi_r_chan_t ( rel_mgr_bus_r_chan_t ), + .Bypass ( 1'b0 ) + ) i_cut_mgr ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .sbr_port_req_i ( rel_mgr_bus_req[i] ), + .sbr_port_rsp_o ( rel_mgr_bus_rsp[i] ), + + .mgr_port_req_o ( rel_mgr_bus_req_cut[i] ), + .mgr_port_rsp_i ( rel_mgr_bus_rsp_cut[i] ), + + .fault_o ( enc_cut_faults[i] ) + ); + end + relobi_xbar #( .SbrPortObiCfg ( MgrConfig ), .MgrPortObiCfg ( SbrConfig ), @@ -116,11 +140,11 @@ module relobi_xbar_dut_wrapper #( .rst_ni ( rst_n ), .testmode_i ( 1'b0 ), - .sbr_ports_req_i ( rel_mgr_bus_req ), - .sbr_ports_rsp_o ( rel_mgr_bus_rsp ), + .sbr_ports_req_i ( rel_mgr_bus_req_cut ), + .sbr_ports_rsp_o ( rel_mgr_bus_rsp_cut ), - .mgr_ports_req_o ( rel_sbr_bus_req ), - .mgr_ports_rsp_i ( rel_sbr_bus_rsp ), + .mgr_ports_req_o ( rel_sbr_bus_req_cut ), + .mgr_ports_rsp_i ( rel_sbr_bus_rsp_cut ), .addr_map_i ( {3{AddrMap}} ), .en_default_idx_i ( '0 ), @@ -129,6 +153,28 @@ module relobi_xbar_dut_wrapper #( .fault_o ( xbar_fault ) ); + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_cut + relobi_cut #( + .ObiCfg ( SbrConfig ), + .obi_req_t ( rel_sbr_bus_req_t ), + .obi_rsp_t ( rel_sbr_bus_rsp_t ), + .obi_a_chan_t ( rel_sbr_bus_a_chan_t ), + .obi_r_chan_t ( rel_sbr_bus_r_chan_t ), + .Bypass ( 1'b0 ) + ) i_cut_sbr ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .sbr_port_req_i ( rel_sbr_bus_req_cut[i] ), + .sbr_port_rsp_o ( rel_sbr_bus_rsp_cut[i] ), + + .mgr_port_req_o ( rel_sbr_bus_req[i] ), + .mgr_port_rsp_i ( rel_sbr_bus_rsp[i] ), + + .fault_o ( dec_cut_faults[i] ) + ); + end + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode relobi_decoder #( .Cfg ( SbrConfig ), @@ -157,11 +203,11 @@ module relobi_xbar_dut_wrapper #( uncorrectable_fault = xbar_fault[1]; for (int unsigned i = 0; i < NumManagers; i++) begin - corrected_fault |= encoder_faults[i][0]; + corrected_fault |= encoder_faults[i][0] | enc_cut_faults[i]; uncorrectable_fault |= encoder_faults[i][1]; end for (int unsigned i = 0; i < NumSubordinates; i++) begin - corrected_fault |= decoder_faults[i][0]; + corrected_fault |= decoder_faults[i][0] | dec_cut_faults[i]; uncorrectable_fault |= decoder_faults[i][1]; end end From 1f80d6aa2b0882ec10b9fac19f298153ffdb56c4 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:56:46 +0200 Subject: [PATCH 28/48] Add relobi cut --- Bender.yml | 1 + src/relobi_cut.sv | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/relobi_cut.sv diff --git a/Bender.yml b/Bender.yml index 1701b1a..a030bb1 100644 --- a/Bender.yml +++ b/Bender.yml @@ -54,6 +54,7 @@ sources: - src/relobi_decoder.sv - src/relobi_encoder.sv # Level 4 + - src/relobi_cut.sv - src/relobi_demux.sv - src/relobi_err_sbr.sv - src/relobi_mux.sv diff --git a/src/relobi_cut.sv b/src/relobi_cut.sv new file mode 100644 index 0000000..11ce480 --- /dev/null +++ b/src/relobi_cut.sv @@ -0,0 +1,82 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_cut #( + /// The OBI configuration. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The obi A channel struct. + parameter type obi_a_chan_t = logic, + /// The obi R channel struct. + parameter type obi_r_chan_t = logic, + /// The request struct. + parameter type obi_req_t = logic, + /// The response struct. + parameter type obi_rsp_t = logic, + /// Bypass enable, can be individually overridden! + parameter bit Bypass = 1'b0, + /// Bypass enable for Request side. + parameter bit BypassReq = Bypass, + /// Bypass enable for Response side. + parameter bit BypassRsp = Bypass +) ( + input logic clk_i, + input logic rst_ni, + + input obi_req_t sbr_port_req_i, + output obi_rsp_t sbr_port_rsp_o, + + output obi_req_t mgr_port_req_o, + input obi_rsp_t mgr_port_rsp_i, + output logic fault_o +); + + logic [1:0] faults; + assign fault_o = |faults; + + rel_spill_register #( + .T ( obi_a_chan_t ), + .Bypass ( BypassReq ) + ) i_reg_a ( + .clk_i, + .rst_ni, + .valid_i ( sbr_port_req_i.req ), + .ready_o ( sbr_port_rsp_o.gnt ), + .data_i ( sbr_port_req_i.a ), + .valid_o ( mgr_port_req_o.req ), + .ready_i ( mgr_port_rsp_i.gnt ), + .data_o ( mgr_port_req_o.a ), + .fault_o ( faults[0] ) + ); + + if (ObiCfg.UseRReady) begin : gen_use_rready + rel_spill_register #( + .T ( obi_r_chan_t ), + .Bypass ( BypassRsp ) + ) i_reg_r ( + .clk_i, + .rst_ni, + .valid_i ( mgr_port_rsp_i.rvalid ), + .ready_o ( mgr_port_req_o.rready ), + .data_i ( mgr_port_rsp_i.r ), + .valid_o ( sbr_port_rsp_o.rvalid ), + .ready_i ( sbr_port_req_i.rready ), + .data_o ( sbr_port_rsp_o.r ), + .fault_o ( faults[1] ) + ); + end else begin : gen_no_use_rready + assign faults[1] = 1'b0; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + sbr_port_rsp_o.rvalid <= 1'b0; + sbr_port_rsp_o.r <= '0; + end else begin + sbr_port_rsp_o.rvalid <= mgr_port_rsp_i.rvalid; + sbr_port_rsp_o.r <= mgr_port_rsp_i.r; + end + end + end + +endmodule From 7acd1c67b004a1130a9e670ab2f8d533f1a65b02 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:57:39 +0200 Subject: [PATCH 29/48] Add vcs flags for lint --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index eb9ae62..1118fa5 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ all_vsim: $(TBS_VSIM) # VCS Flow VCS_SCRIPT_ARGS += -assert svaext +v2k -override_timescale=10ns/10ps -kdb VCS_COMPILE_ARGS += -debug_access+all -override_timescale=10ns/10ps +VCS_COMPILE_ARGS += +lint=TFIPC-L +lint=PCWM +warn=noCWUC +warn=noUII-L VCS_RUNTIME_ARGS = scripts/compile_vcs.sh: Bender.yml Bender.lock From 073d4581ea0523177cfe69f3304d93f1dfc532c2 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:57:47 +0200 Subject: [PATCH 30/48] Simplify obi cut --- src/obi_cut.sv | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/obi_cut.sv b/src/obi_cut.sv index b5f42d5..6582353 100644 --- a/src/obi_cut.sv +++ b/src/obi_cut.sv @@ -46,28 +46,30 @@ module obi_cut #( .data_o ( mgr_port_req_o.a ) ); - logic ready_o; - logic ready_i; - if (ObiCfg.UseRReady) begin : gen_use_rready - assign mgr_port_req_o.rready = ready_o; - assign ready_i = sbr_port_req_i.rready; + spill_register #( + .T ( obi_r_chan_t ), + .Bypass ( BypassRsp ) + ) i_req_r ( + .clk_i, + .rst_ni, + .valid_i ( mgr_port_rsp_i.rvalid ), + .ready_o ( mgr_port_req_o.rready ), + .data_i ( mgr_port_rsp_i.r ), + .valid_o ( sbr_port_rsp_o.rvalid ), + .ready_i ( sbr_port_req_i.rready ), + .data_o ( sbr_port_rsp_o.r ) + ); end else begin : gen_no_use_rready - assign ready_i = 1'b1; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + sbr_port_rsp_o.rvalid <= 1'b0; + sbr_port_rsp_o.r <= '0; + end else begin + sbr_port_rsp_o.rvalid <= mgr_port_rsp_i.rvalid; + sbr_port_rsp_o.r <= mgr_port_rsp_i.r; + end + end end - spill_register #( - .T ( obi_r_chan_t ), - .Bypass ( BypassRsp ) - ) i_req_r ( - .clk_i, - .rst_ni, - .valid_i ( mgr_port_rsp_i.rvalid ), - .ready_o ( ready_o ), - .data_i ( mgr_port_rsp_i.r ), - .valid_o ( sbr_port_rsp_o.rvalid ), - .ready_i ( ready_i ), - .data_o ( sbr_port_rsp_o.r ) - ); - endmodule From e0b68e208d72e757cdefed8cb73d7619c0a82e9f Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:58:30 +0200 Subject: [PATCH 31/48] alter obi test parameters for more appropriate xbar behavior --- src/test/obi_test.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/obi_test.sv b/src/test/obi_test.sv index fc3a1c0..ebe2585 100644 --- a/src/test/obi_test.sv +++ b/src/test/obi_test.sv @@ -176,9 +176,9 @@ package obi_test; parameter int unsigned MaxAddr = 32'hffff_ffff, // Wait Parameters parameter int unsigned AMinWaitCycles = 0, - parameter int unsigned AMaxWaitCycles = 100, + parameter int unsigned AMaxWaitCycles = 20, parameter int unsigned RMinWaitCycles = 0, - parameter int unsigned RMaxWaitCycles = 100 + parameter int unsigned RMaxWaitCycles = 20 ); typedef obi_test::obi_driver #( .ObiCfg ( ObiCfg ), From cc63c8378fd6af52d895689009e45e48e8eaf9d6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 4 Jul 2025 19:58:45 +0200 Subject: [PATCH 32/48] Partition out relobi tmr parts --- src/relobi_demux.sv | 254 +++++++++++++++------ src/relobi_mux.sv | 445 ++++++++++++++++++++++++------------- src/relobi_xbar.sv | 107 ++++++--- src/test/tb_relobi_xbar.sv | 1 + 4 files changed, 543 insertions(+), 264 deletions(-) diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index 8b7b42e..d3bd9bb 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -51,66 +51,76 @@ module relobi_demux #( // Internals TMR'd - logic [2:0] cnt_up, cnt_down, overflow; - logic [2:0][CounterWidth-1:0] in_flight; - logic [2:0] sbr_port_gnt; - logic [2:0] sbr_port_rready; - - select_t [2:0] select_d, select_d_voted, select_q, select_i_tmr; - - logic [NumMgrPorts-1:0][2:0] mgr_ports_req; + logic [2:0][NumMgrPorts-1:0] mgr_ports_req; - always_comb begin : proc_req - for (int i = 0; i < 3; i++) begin : gen_tmr - select_i_tmr[i] = TmrSelect ? sbr_port_select_i[i] : sbr_port_select_i[0]; + obi_r_chan_t [NumMgrPorts-1:0] mgr_ports_rsp_r; + logic [2:0][NumMgrPorts-1:0] mgr_ports_rsp_rvalid; + logic [2:0][NumMgrPorts-1:0] mgr_ports_gnt; + obi_r_chan_t [2:0] sbr_port_rsp_r; + logic [2:0] sbr_port_rready; - select_d[i] = select_q[i]; - cnt_up[i] = 1'b0; - for (int j = 0; j < NumMgrPorts; j++) begin - mgr_ports_req[j][i] = 1'b0; - end - sbr_port_gnt[i] = 1'b0; - - if (!overflow[i]) begin - if (select_i_tmr[i] == select_q[i] || - in_flight[i] == '0 || - (in_flight[i] == 1 && cnt_down[i])) begin - mgr_ports_req[select_i_tmr[i]][i] = sbr_port_req_i.req[i]; - sbr_port_gnt[i] = mgr_ports_rsp_i[select_i_tmr[i]].gnt[i]; - end - end + for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_mgr_rsp + assign mgr_ports_rsp_r[i] = mgr_ports_rsp_i[i].r; + for (genvar j = 0; j < 3; j++) begin : gen_mgr_rsp_valid + assign mgr_ports_rsp_rvalid[j][i] = mgr_ports_rsp_i[i].rvalid[j]; + assign mgr_ports_gnt[j][i] = mgr_ports_rsp_i[i].gnt[j]; + end + end - if (mgr_ports_req[select_i_tmr[i]][i] && mgr_ports_rsp_i[select_i_tmr[i]].gnt[i]) begin - select_d[i] = select_i_tmr[i]; - cnt_up[i] = 1'b1; - end + select_t [2:0] select_d_sync; + select_t [2:0][1:0] alt_select_d_sync; + logic [2:0][CounterWidth:0] counter_d_sync; + logic [2:0][1:0][CounterWidth:0] alt_counter_d_sync; + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + for (genvar j = 0; j < 2; j++) begin : gen_alt_sync + assign alt_select_d_sync[i][j] = select_d_sync[(i+j+1) % 3]; + assign alt_counter_d_sync[i][j] = counter_d_sync[(i+j+1) % 3]; end + (* dont_touch *) + relobi_demux_tmr_part #( + .NumMgrPorts (NumMgrPorts), + .CounterWidth (CounterWidth), + .select_t (select_t), + .obi_r_chan_t (obi_r_chan_t), + .TmrBeforeReg (1'b1) + ) i_tmr_part ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .select_i (TmrSelect ? sbr_port_select_i[i] : sbr_port_select_i[0]), + .sbr_port_req (sbr_port_req_i.req[i]), + .sbr_port_gnt (sbr_port_rsp_o.gnt[i]), + .mgr_ports_req (mgr_ports_req[i]), + .mgr_ports_gnt (mgr_ports_gnt[i]), + .mgr_ports_rsp_r (mgr_ports_rsp_r), + .mgr_ports_rsp_rvalid (mgr_ports_rsp_rvalid[i]), + .sbr_port_rsp_r (sbr_port_rsp_r[i]), + .sbr_port_rsp_rvalid (sbr_port_rsp_o.rvalid[i]), + .sbr_port_rready (sbr_port_rready[i]), + .select_d_sync (select_d_sync[i]), + .counter_d_sync (counter_d_sync[i]), + .alt_select_d_sync (alt_select_d_sync[i]), + .alt_counter_d_sync (alt_counter_d_sync[i]), + .fault_o (faults[2*i+1:2*i]) + ); end for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_mgr_req - assign mgr_ports_req_o[i].req = mgr_ports_req[i]; + assign mgr_ports_req_o[i].req[0] = mgr_ports_req[0][i]; + assign mgr_ports_req_o[i].req[1] = mgr_ports_req[1][i]; + assign mgr_ports_req_o[i].req[2] = mgr_ports_req[2][i]; assign mgr_ports_req_o[i].a = sbr_port_req_i.a; end - assign sbr_port_rsp_o.gnt = sbr_port_gnt; - relobi_tmr_r #( .ObiCfg (ObiCfg), .obi_r_chan_t(obi_r_chan_t), .r_optional_t (obi_r_optional_t) ) i_r_vote ( - .three_r_i({mgr_ports_rsp_i[select_q[2]].r, - mgr_ports_rsp_i[select_q[1]].r, - mgr_ports_rsp_i[select_q[0]].r}), + .three_r_i(sbr_port_rsp_r), .voted_r_o(sbr_port_rsp_o.r), - .fault_o (faults[0]) + .fault_o (faults[6]) ); - for (genvar i = 0; i < 3; i++) begin : gen_rvalid - // Could be voted, but with only one error source (either select_q or rvalid) should suffice - assign sbr_port_rsp_o.rvalid[i] = mgr_ports_rsp_i[select_q[i]].rvalid[i]; - end - if (ObiCfg.UseRReady) begin : gen_rready assign sbr_port_rready = sbr_port_req_i.rready; for (genvar i = 0; i < NumMgrPorts; i++) begin : gen_rready @@ -120,55 +130,151 @@ module relobi_demux #( assign sbr_port_rready = 3'b111; end - logic [2:0][CounterWidth:0] counter_q, counter_d_voted, counter_d; +endmodule + +(* no_ungroup *) +(* no_boundary_optimization *) +module relobi_demux_tmr_part #( + parameter int unsigned NumMgrPorts = 32'd0, + parameter int unsigned CounterWidth = 7, + parameter type select_t = logic [$clog2(NumMgrPorts)-1:0], + parameter type obi_r_chan_t = logic, + parameter bit TmrBeforeReg = 1'b1 +) ( + input logic clk_i, + input logic rst_ni, + input select_t select_i, + input logic sbr_port_req, + output logic sbr_port_gnt, + output logic [NumMgrPorts-1:0] mgr_ports_req, + input logic [NumMgrPorts-1:0] mgr_ports_gnt, + input obi_r_chan_t [NumMgrPorts-1:0] mgr_ports_rsp_r, + input logic [NumMgrPorts-1:0] mgr_ports_rsp_rvalid, + output obi_r_chan_t sbr_port_rsp_r, + output logic sbr_port_rsp_rvalid, + input logic sbr_port_rready, + output select_t select_d_sync, + output logic [CounterWidth:0] counter_d_sync, + input select_t [1:0] alt_select_d_sync, + input logic [1:0][CounterWidth:0] alt_counter_d_sync, + output logic [1:0] fault_o +); - for (genvar i = 0; i < 3; i++) begin : gen_counter - // Could be voted, but with only one error source (either select_q or rvalid) should suffice - assign cnt_down[i] = mgr_ports_rsp_i[select_q[i]].rvalid[i] && sbr_port_rready[i]; - assign overflow[i] = counter_q[i][CounterWidth]; - assign in_flight[i] = counter_q[i][CounterWidth-1:0]; + logic cnt_up, cnt_down, overflow; + logic [CounterWidth-1:0] in_flight; - always_comb begin - counter_d[i] = counter_q[i]; + select_t select_d, select_q; + logic [CounterWidth:0] counter_d, counter_q; - if (cnt_up[i] & ~cnt_down[i]) begin - counter_d[i] = counter_q[i] + {{CounterWidth-1{1'b0}}, 1'b1}; - end else if (cnt_down[i] & ~cnt_up[i]) begin - counter_d[i] = counter_q[i] - {{CounterWidth-1{1'b0}}, 1'b1}; + always_comb begin : proc_req + select_d = select_q; + cnt_up = 1'b0; + for (int j = 0; j < NumMgrPorts; j++) begin + mgr_ports_req[j] = 1'b0; + end + sbr_port_gnt = 1'b0; + if (!overflow) begin + if (select_i == select_q || + in_flight == '0 || + (in_flight == 1 && cnt_down)) begin + mgr_ports_req[select_i] = sbr_port_req; + sbr_port_gnt = mgr_ports_gnt[select_i]; end end + + if (mgr_ports_req[select_i] && mgr_ports_gnt[select_i]) begin + select_d = select_i; + cnt_up = 1'b1; + end end - for (genvar i = 0; i < 3; i++) begin : gen_tmr_state + assign sbr_port_rsp_r = mgr_ports_rsp_r[select_q]; + assign sbr_port_rsp_rvalid = mgr_ports_rsp_rvalid[select_q]; + + // Could be voted, but with only one error source (either select_q or rvalid) should suffice + assign cnt_down = mgr_ports_rsp_rvalid[select_q] && sbr_port_rready; + + assign overflow = counter_q[CounterWidth]; + assign in_flight = counter_q[CounterWidth-1:0]; + + always_comb begin + counter_d = counter_q; + + if (cnt_up & ~cnt_down) begin + counter_d = counter_q + {{CounterWidth-1{1'b0}}, 1'b1}; + end else if (cnt_down & ~cnt_up) begin + counter_d = counter_q - {{CounterWidth-1{1'b0}}, 1'b1}; + end + end + + if (TmrBeforeReg) begin : gen_tmr_before_reg + select_t select_d_voted; + logic [CounterWidth:0] counter_d_voted; + assign select_d_sync = select_d; + assign counter_d_sync = counter_d; bitwise_TMR_voter_fail #( .DataWidth( $clog2(NumMgrPorts) ) ) i_select_vote ( - .a_i (select_d[0]), - .b_i (select_d[1]), - .c_i (select_d[2]), - .majority_o (select_d_voted[i]), - .fault_detected_o (faults[1+2*i]) + .a_i (select_d), + .b_i (alt_select_d_sync[0]), + .c_i (alt_select_d_sync[1]), + .majority_o (select_d_voted), + .fault_detected_o (fault_o[0]) ); bitwise_TMR_voter_fail #( .DataWidth( CounterWidth+1 ) ) i_counter_vote ( - .a_i (counter_d[0]), - .b_i (counter_d[1]), - .c_i (counter_d[2]), - .majority_o (counter_d_voted[i]), - .fault_detected_o (faults[2+2*i]) + .a_i (counter_d), + .b_i (alt_counter_d_sync[0]), + .c_i (alt_counter_d_sync[1]), + .majority_o (counter_d_voted), + .fault_detected_o (fault_o[1]) ); - end - - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_select - if(!rst_ni) begin - counter_q <= '0; - select_q <= '0; - end else begin - counter_q <= counter_d_voted; - select_q <= select_d_voted; + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_select + if(!rst_ni) begin + counter_q <= '0; + select_q <= '0; + end else begin + counter_q <= counter_d_voted; + select_q <= select_d_voted; + end + end + end else begin : gen_tmr_after_reg + select_t select_d_next; + logic [CounterWidth:0] counter_d_next; + assign select_d_sync = select_d_next; + assign counter_d_sync = counter_d_next; + bitwise_TMR_voter_fail #( + .DataWidth( $clog2(NumMgrPorts) ) + ) i_select_vote ( + .a_i (select_d_next), + .b_i (alt_select_d_sync[0]), + .c_i (alt_select_d_sync[1]), + .majority_o (select_q), + .fault_detected_o (fault_o[0]) + ); + bitwise_TMR_voter_fail #( + .DataWidth( CounterWidth+1 ) + ) i_counter_vote ( + .a_i (counter_d_next), + .b_i (alt_counter_d_sync[0]), + .c_i (alt_counter_d_sync[1]), + .majority_o (counter_q), + .fault_detected_o (fault_o[1]) + ); + always_ff @(posedge clk_i or negedge rst_ni) begin : proc_select + if(!rst_ni) begin + counter_d_next <= '0; + select_d_next <= '0; + end else begin + counter_d_next <= counter_d; + select_d_next <= select_d; + end end + end + + endmodule diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 6786eba..4d4569a 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -27,6 +27,8 @@ module relobi_mux #( parameter type mgr_port_obi_rsp_t = sbr_port_obi_rsp_t, /// The A channel struct for the manager port (output port). parameter type mgr_port_a_chan_t = logic, + /// The R channel struct for the manager port (output port). + parameter type mgr_port_r_chan_t = logic, /// The A channel optionals struct for all ports. parameter type a_optional_t = logic, /// The R channel optionals struct for all ports. @@ -85,11 +87,23 @@ module relobi_mux #( sbr_port_a_chan_t mgr_port_a_in_sbr; mgr_port_a_chan_t [2:0] mgr_port_a_tmr; - logic [2:0][RequiredExtraIdWidth-1:0] selected_id, response_id; + logic [2:0][RequiredExtraIdWidth-1:0] selected_id; logic [2:0] mgr_port_req, fifo_full, fifo_pop; logic [2:0] rr_arb_mgr_port_gnt; + logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] + selected_id_tmr_three; + logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] + selected_id_tmr, response_id_encoded; + + logic [2:0][NumSbrPorts-1:0] sbr_rsp_rvalid; + logic [2:0][NumSbrPorts-1:0] sbr_req_rready; + logic [2:0] mgr_req_rready; + + sbr_port_r_chan_t [2:0] sbr_r_tmr; + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_assign assign sbr_ports_req[i] = sbr_ports_req_i[i].req; assign sbr_ports_a[i] = sbr_ports_req_i[i].a; @@ -97,9 +111,47 @@ module relobi_mux #( end assign mgr_port_req_o.req = mgr_port_req & ~fifo_full; + assign rr_arb_mgr_port_gnt = mgr_port_rsp_i.gnt & ~fifo_full; + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + (* dont_touch *) + relobi_mux_tmr_part #( + .SbrPortObiCfg ( SbrPortObiCfg ), + .MgrPortObiCfg ( MgrPortObiCfg ), + .NumSbrPorts ( NumSbrPorts ), + .mgr_port_a_chan_t ( mgr_port_a_chan_t ), + .mgr_port_r_chan_t ( mgr_port_r_chan_t ), + .sbr_port_a_chan_t ( sbr_port_a_chan_t ), + .sbr_port_r_chan_t ( sbr_port_r_chan_t ), + .a_optional_t ( a_optional_t ), + .r_optional_t ( r_optional_t ), + .RequiredExtraIdWidth( RequiredExtraIdWidth ), + .UseIdForRouting ( UseIdForRouting ) + ) i_tmr_part ( + .clk_i, + .rst_ni, - for (genvar i = 0; i < 3; i++) begin : gen_mgr_port_gnt - assign rr_arb_mgr_port_gnt[i] = mgr_port_rsp_i.gnt[i] && ~fifo_full[i]; + .mgr_port_a_in_sbr ( mgr_port_a_in_sbr ), + .mgr_port_req ( mgr_port_req[i] ), + .selected_id ( selected_id[i] ), + .mgr_port_a_tmr ( mgr_port_a_tmr[i] ), + + .mgr_port_rsp_r ( UseIdForRouting || MgrPortObiCfg.IdWidth != SbrPortObiCfg.IdWidth ? mgr_port_rsp_i.r : '0 ), + .mgr_port_rsp_rvalid( UseIdForRouting ? mgr_port_rsp_i.rvalid[i] : '0 ), + .selected_id_tmr_three ( selected_id_tmr_three[i] ), + .response_id_encoded( UseIdForRouting ? '0 : response_id_encoded ), + .fifo_pop ( UseIdForRouting ? '0 : fifo_pop[i] ), + + .mgr_rsp_rvalid ( mgr_port_rsp_i.rvalid[i] ), + .sbr_rsp_rvalid ( sbr_rsp_rvalid[i] ), + .sbr_req_rready ( MgrPortObiCfg.UseRReady ? sbr_req_rready[i] : '1 ), + .mgr_req_rready ( mgr_req_rready[i] ), + + .sbr_r_tmr ( sbr_r_tmr[i] ), + + .hsiao_faults ( hsiao_faults[3*i+2:3*i] ), + .hsiao_faults_gated( hsiao_faults_gated[2*i+1:2*i] ) + ); end rel_rr_arb_tree #( @@ -128,73 +180,16 @@ module relobi_mux #( .fault_o ( voter_faults[0] ) ); - for (genvar i = 0; i < 3; i++) begin : gen_tmr_aid - if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical - always_comb begin - `OBI_SET_A_STRUCT(mgr_port_a_tmr[i], mgr_port_a_in_sbr) - mgr_port_a_tmr[i].other_ecc = mgr_port_a_in_sbr.other_ecc; - end - assign hsiao_faults[i] = '0; - assign hsiao_faults_gated[i] = '0; - end else begin : gen_aid_extend - logic we; - logic [MgrPortObiCfg.DataWidth/8-1:0] be; - logic [SbrPortObiCfg.IdWidth-1:0] sbr_aid; - logic [MgrPortObiCfg.IdWidth-1:0] mgr_aid; - a_optional_t a_optional; - logic [relobi_pkg::relobi_a_other_ecc_width(MgrPortObiCfg)-1:0] other_ecc; - relobi_a_other_decoder #( - .Cfg (SbrPortObiCfg), - .a_optional_t (a_optional_t) - ) i_other_decode ( - .we_i (mgr_port_a_in_sbr.we), - .be_i (mgr_port_a_in_sbr.be), - .aid_i (mgr_port_a_in_sbr.aid), - .a_optional_i(mgr_port_a_in_sbr.a_optional), - .other_ecc_i (mgr_port_a_in_sbr.other_ecc), - .we_o (we), - .be_o (be), - .aid_o (sbr_aid), - .a_optional_o(a_optional), - - .fault_o (hsiao_faults[i]) - ); - assign hsiao_faults_gated[i] = mgr_port_req[i] ? hsiao_faults[i] : '0; - if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + - RequiredExtraIdWidth ) begin : gen_aid_extend - always_comb begin - mgr_aid = '0; - mgr_aid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0] = {selected_id[i], sbr_aid}; - end - end else begin : gen_aid_noextend - always_comb begin - mgr_aid = '0; - mgr_aid[SbrPortObiCfg.IdWidth-1:0] = sbr_aid; - end - end - relobi_a_other_encoder #( - .Cfg (MgrPortObiCfg), - .a_optional_t (a_optional_t) - ) i_other_encode ( - .we_i (we), - .be_i (be), - .aid_i (mgr_aid), - .a_optional_i(a_optional), - .other_ecc_o (other_ecc) - ); - - assign mgr_port_a_tmr[i].addr = mgr_port_a_in_sbr.addr; - assign mgr_port_a_tmr[i].wdata = mgr_port_a_in_sbr.wdata; - assign mgr_port_a_tmr[i].we = we; - assign mgr_port_a_tmr[i].be = be; - assign mgr_port_a_tmr[i].aid = mgr_aid; - assign mgr_port_a_tmr[i].a_optional = a_optional; - assign mgr_port_a_tmr[i].other_ecc = other_ecc; - - end - end - - `VOTE31F(mgr_port_a_tmr, mgr_port_req_o.a, voter_faults[1]) + bitwise_TMR_voter_fail #( + .DataWidth ( $bits(mgr_port_a_chan_t) ), + .VoterType ( 1 ) + ) i_a_tmr ( + .a_i ( mgr_port_a_tmr[0] ), + .b_i ( mgr_port_a_tmr[1] ), + .c_i ( mgr_port_a_tmr[2] ), + .majority_o ( mgr_port_req_o.a ), + .fault_detected_o ( voter_faults[1] ) + ); logic [2:0][SbrPortObiCfg.IdWidth-1:0] rsp_rid; @@ -205,55 +200,23 @@ module relobi_mux #( $fatal(1, "UseIdForRouting requires MgrPort IdWidth to increase with log2(NumSbrPorts)"); end - for (genvar i = 0; i < 3; i++) begin : gen_tmr_rid - relobi_r_other_decoder #( - .Cfg (SbrPortObiCfg), - .r_optional_t (r_optional_t) - ) i_r_other_decode ( - .rid_i (mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth-1:0]), - .err_i (mgr_port_rsp_i.r.err), - .r_optional_i(mgr_port_rsp_i.r.r_optional), - .other_ecc_i (mgr_port_rsp_i.r.other_ecc), - .rid_o (rsp_rid[i]), - .err_o (), - .r_optional_o(), - .fault_o (hsiao_faults[3+i]) - ); - assign hsiao_faults_gated[3+i] = mgr_port_rsp_i.rvalid[i] ? hsiao_faults[3+i] : '0; - - assign {response_id[i], rsp_rid[i]} = - mgr_port_rsp_i.r.rid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0]; - assign fifo_full[i] = 1'b0; - end + assign fifo_full = 3'b0; assign voter_faults[3:2] = '0; + assign selected_id_tmr = '0; end else begin : gen_no_id_assign - logic [2:0][RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] - selected_id_tmr_three; - logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] - selected_id_tmr, response_id_encoded; - - for (genvar i = 0; i < 3; i++) begin : gen_extra_id_tmr - hsiao_ecc_enc #( - .DataWidth (RequiredExtraIdWidth) - ) i_ecc ( - .in (selected_id[i]), - .out (selected_id_tmr_three[i]) - ); - - hsiao_ecc_dec #( - .DataWidth (RequiredExtraIdWidth) - ) i_ecc_dec ( - .in (response_id_encoded), - .out (response_id[i]), - .syndrome_o(), - .err_o (hsiao_faults[3+i]) - ); - assign hsiao_faults_gated[3+i] = fifo_pop[i] ? hsiao_faults[3+i] : '0; - end - `VOTE31F(selected_id_tmr_three, selected_id_tmr, voter_faults[2]) + bitwise_TMR_voter_fail #( + .DataWidth ( RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth) ), + .VoterType ( 1 ) + ) i_selected_id_tmr ( + .a_i ( selected_id_tmr_three[0] ), + .b_i ( selected_id_tmr_three[1] ), + .c_i ( selected_id_tmr_three[2] ), + .majority_o ( selected_id_tmr ), + .fault_detected_o ( voter_faults[2] ) + ); rel_fifo #( .FallThrough( 1'b0 ), @@ -282,11 +245,15 @@ module relobi_mux #( end if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect - for (genvar i = 0; i < 3; i++) begin : gen_rready_connect_tmr - assign mgr_port_req_o.rready[i] = sbr_ports_req_i[response_id[i]].rready[i]; - end + assign mgr_port_req_o.rready = mgr_req_rready; + for (genvar i = 0; i < NumSbrPorts; i++) begin + for (genvar j = 0; j < 3; j++) begin : gen_sbr_req_rready + assign sbr_req_rready[j][i] = sbr_ports_req_i[i].rready[j]; + end + end + end else begin + assign sbr_req_rready = '1; end - logic [NumSbrPorts-1:0][2:0] sbr_rsp_rvalid; sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_rid_identical always_comb begin : proc_sbr_rsp @@ -294,53 +261,16 @@ module relobi_mux #( // Always assign r struct to avoid triplication overhead `OBI_SET_R_STRUCT(sbr_rsp_r[i], mgr_port_rsp_i.r); sbr_rsp_r[i].other_ecc = mgr_port_rsp_i.r.other_ecc; - sbr_rsp_rvalid[i] = '0; - end - for (int i = 0; i < 3; i++) begin - sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; end end - assign hsiao_faults[8:6] = '0; assign hsiao_faults_gated[8:6] = '0; assign voter_faults[4] = '0; end else begin : gen_rid_decrease - logic [2:0][MgrPortObiCfg.IdWidth-1:0] mgr_rid_tmr; - sbr_port_r_chan_t [2:0] sbr_r_tmr; sbr_port_r_chan_t sbr_r; - for (genvar i = 0; i < 3; i++) begin : gen_tmr_rid - relobi_r_other_decoder #( - .Cfg (MgrPortObiCfg), - .r_optional_t (r_optional_t) - ) i_r_other_decode ( - .rid_i (mgr_port_rsp_i.r.rid), - .err_i (mgr_port_rsp_i.r.err), - .r_optional_i(mgr_port_rsp_i.r.r_optional), - .other_ecc_i (mgr_port_rsp_i.r.other_ecc), - .rid_o (mgr_rid_tmr[i]), - .err_o (sbr_r_tmr[i].err), - .r_optional_o(sbr_r_tmr[i].r_optional), - .fault_o (hsiao_faults[6+i]) - ); - assign sbr_r_tmr[i].rid = mgr_rid_tmr[i][SbrPortObiCfg.IdWidth-1:0]; - relobi_r_other_encoder #( - .Cfg (SbrPortObiCfg), - .r_optional_t (r_optional_t) - ) i_r_other_encode ( - .rid_i (sbr_r_tmr[i].rid), - .err_i (sbr_r_tmr[i].err), - .r_optional_i(sbr_r_tmr[i].r_optional), - .other_ecc_o (sbr_r_tmr[i].other_ecc) - ); - assign sbr_r_tmr[i].rdata = mgr_port_rsp_i.r.rdata; - end - assign hsiao_faults_gated[8:6] = fifo_pop[0] ? hsiao_faults[8:6] : '0; - always_comb begin - sbr_rsp_rvalid = '0; - for (int i = 0; i < 3; i++) begin - sbr_rsp_rvalid[response_id[i]][i] = mgr_port_rsp_i.rvalid[i]; - end - end + assign hsiao_faults_gated[6] = fifo_pop[0] ? hsiao_faults[2] : '0; + assign hsiao_faults_gated[7] = fifo_pop[1] ? hsiao_faults[5] : '0; + assign hsiao_faults_gated[8] = fifo_pop[2] ? hsiao_faults[8] : '0; relobi_tmr_r #( .ObiCfg (SbrPortObiCfg), .obi_r_chan_t (sbr_port_r_chan_t), @@ -361,7 +291,9 @@ module relobi_mux #( for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_rsp_assign assign sbr_ports_rsp_o[i].r = sbr_rsp_r[i]; - assign sbr_ports_rsp_o[i].rvalid = sbr_rsp_rvalid[i]; + assign sbr_ports_rsp_o[i].rvalid = {sbr_rsp_rvalid[2][i], + sbr_rsp_rvalid[1][i], + sbr_rsp_rvalid[0][i]}; end if (MgrPortObiCfg.UseRReady) begin : gen_fifo_pop @@ -371,3 +303,198 @@ module relobi_mux #( end endmodule + +(* no_ungroup *) +(* no_boundary_optimization *) +module relobi_mux_tmr_part #( + parameter obi_pkg::obi_cfg_t SbrPortObiCfg = obi_pkg::ObiDefaultConfig, + parameter obi_pkg::obi_cfg_t MgrPortObiCfg = SbrPortObiCfg, + parameter int unsigned NumSbrPorts = 32'd0, + parameter type mgr_port_a_chan_t = logic, + parameter type mgr_port_r_chan_t = logic, + parameter type sbr_port_a_chan_t = logic, + parameter type sbr_port_r_chan_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic, + parameter int unsigned RequiredExtraIdWidth = 0, + parameter bit UseIdForRouting = 1'b0 + +) ( + input logic clk_i, + input logic rst_ni, + input sbr_port_a_chan_t mgr_port_a_in_sbr, + input logic mgr_port_req, + input logic [RequiredExtraIdWidth-1:0] selected_id, + output mgr_port_a_chan_t mgr_port_a_tmr, + + // Only if UseIdForRouting is true or Id width increases + input mgr_port_r_chan_t mgr_port_rsp_r, + // Only if UseIdForRouting is true + input logic mgr_port_rsp_rvalid, + // Only if UseIdForRouting is false + output logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three, + input logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] response_id_encoded, + input logic fifo_pop, + + output sbr_port_r_chan_t sbr_r_tmr, + + input logic mgr_rsp_rvalid, + output logic [NumSbrPorts-1:0] sbr_rsp_rvalid, + input logic [NumSbrPorts-1:0] sbr_req_rready, + output logic mgr_req_rready, + + output logic [2:0][1:0] hsiao_faults, + output logic [1:0][1:0] hsiao_faults_gated +); + + logic [RequiredExtraIdWidth-1:0] response_id; + + if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical + always_comb begin + `OBI_SET_A_STRUCT(mgr_port_a_tmr, mgr_port_a_in_sbr) + mgr_port_a_tmr.other_ecc = mgr_port_a_in_sbr.other_ecc; + end + assign hsiao_faults[0] = '0; + assign hsiao_faults_gated[0] = '0; + end else begin : gen_aid_extend + logic we; + logic [MgrPortObiCfg.DataWidth/8-1:0] be; + logic [SbrPortObiCfg.IdWidth-1:0] sbr_aid; + logic [MgrPortObiCfg.IdWidth-1:0] mgr_aid; + a_optional_t a_optional; + logic [relobi_pkg::relobi_a_other_ecc_width(MgrPortObiCfg)-1:0] other_ecc; + relobi_a_other_decoder #( + .Cfg (SbrPortObiCfg), + .a_optional_t (a_optional_t) + ) i_other_decode ( + .we_i (mgr_port_a_in_sbr.we), + .be_i (mgr_port_a_in_sbr.be), + .aid_i (mgr_port_a_in_sbr.aid), + .a_optional_i(mgr_port_a_in_sbr.a_optional), + .other_ecc_i (mgr_port_a_in_sbr.other_ecc), + .we_o (we), + .be_o (be), + .aid_o (sbr_aid), + .a_optional_o(a_optional), + + .fault_o (hsiao_faults[0]) + ); + assign hsiao_faults_gated[0] = mgr_port_req ? hsiao_faults[0] : '0; + if (MgrPortObiCfg.IdWidth >= SbrPortObiCfg.IdWidth + + RequiredExtraIdWidth ) begin : gen_aid_extend + always_comb begin + mgr_aid = '0; + mgr_aid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0] = {selected_id, sbr_aid}; + end + end else begin : gen_aid_noextend + always_comb begin + mgr_aid = '0; + mgr_aid[SbrPortObiCfg.IdWidth-1:0] = sbr_aid; + end + end + relobi_a_other_encoder #( + .Cfg (MgrPortObiCfg), + .a_optional_t (a_optional_t) + ) i_other_encode ( + .we_i (we), + .be_i (be), + .aid_i (mgr_aid), + .a_optional_i(a_optional), + .other_ecc_o (other_ecc) + ); + + assign mgr_port_a_tmr.addr = mgr_port_a_in_sbr.addr; + assign mgr_port_a_tmr.wdata = mgr_port_a_in_sbr.wdata; + assign mgr_port_a_tmr.we = we; + assign mgr_port_a_tmr.be = be; + assign mgr_port_a_tmr.aid = mgr_aid; + assign mgr_port_a_tmr.a_optional = a_optional; + assign mgr_port_a_tmr.other_ecc = other_ecc; + + end + + if (UseIdForRouting) begin : gen_id_assign + logic [MgrPortObiCfg.IdWidth-1:0] corr_rsp_rid; + logic [SbrPortObiCfg.IdWidth-1:0] rsp_rid; + relobi_r_other_decoder #( + .Cfg (MgrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_decode ( + .rid_i (mgr_port_rsp_r.rid), + .err_i (mgr_port_rsp_r.err), + .r_optional_i(mgr_port_rsp_r.r_optional), + .other_ecc_i (mgr_port_rsp_r.other_ecc), + .rid_o (corr_rsp_rid), + .err_o (), + .r_optional_o(), + .fault_o (hsiao_faults[1]) + ); + assign hsiao_faults_gated[1] = mgr_port_rsp_rvalid ? hsiao_faults[1] : '0; + + assign {response_id, rsp_rid} = + corr_rsp_rid[SbrPortObiCfg.IdWidth + RequiredExtraIdWidth-1:0]; + + // TODO encode rsp_rid packet for sbrs? + end else begin : gen_no_id_assign + hsiao_ecc_enc #( + .DataWidth (RequiredExtraIdWidth) + ) i_ecc ( + .in (selected_id), + .out (selected_id_tmr_three) + ); + + hsiao_ecc_dec #( + .DataWidth (RequiredExtraIdWidth) + ) i_ecc_dec ( + .in (response_id_encoded), + .out (response_id), + .syndrome_o(), + .err_o (hsiao_faults[1]) + ); + assign hsiao_faults_gated[1] = fifo_pop ? hsiao_faults[1] : '0; + end + + always_comb begin + sbr_rsp_rvalid = '0; + sbr_rsp_rvalid[response_id] = mgr_rsp_rvalid; + end + if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect + assign mgr_req_rready = sbr_req_rready[response_id]; + end else begin + assign mgr_req_rready = '1; + end + + + if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_rid_identical + assign hsiao_faults[2] = '0; + assign sbr_r_tmr = '0; + end else begin : gen_rid_decrease + logic [MgrPortObiCfg.IdWidth-1:0] mgr_rid_tmr; + relobi_r_other_decoder #( + .Cfg (MgrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_decode ( + .rid_i (mgr_port_rsp_r.rid), + .err_i (mgr_port_rsp_r.err), + .r_optional_i(mgr_port_rsp_r.r_optional), + .other_ecc_i (mgr_port_rsp_r.other_ecc), + .rid_o (mgr_rid_tmr), + .err_o (sbr_r_tmr.err), + .r_optional_o(sbr_r_tmr.r_optional), + .fault_o (hsiao_faults[2]) + ); + assign sbr_r_tmr.rid = mgr_rid_tmr[SbrPortObiCfg.IdWidth-1:0]; + relobi_r_other_encoder #( + .Cfg (SbrPortObiCfg), + .r_optional_t (r_optional_t) + ) i_r_other_encode ( + .rid_i (sbr_r_tmr.rid), + .err_i (sbr_r_tmr.err), + .r_optional_i(sbr_r_tmr.r_optional), + .other_ecc_o (sbr_r_tmr.other_ecc) + ); + assign sbr_r_tmr.rdata = mgr_port_rsp_r.rdata; + + end + +endmodule diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index 2425663..bb01560 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -24,6 +24,8 @@ module relobi_xbar #( parameter type mgr_port_obi_rsp_t = sbr_port_obi_rsp_t, /// The A channel struct for the manager port (output port). parameter type mgr_port_a_chan_t = logic, + /// The R channel struct for the manager port (output port). + parameter type mgr_port_r_chan_t = logic, /// The A channel optionals struct for all ports. parameter type a_optional_t = logic, /// The R channel optionals struct for all ports. @@ -73,7 +75,8 @@ module relobi_xbar #( assign fault_o[0] = |faults_transpose[0]; assign fault_o[1] = |faults_transpose[1]; - logic [NumSbrPorts-1:0][2:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; + logic [2:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; + logic [NumSbrPorts-1:0][ MgrPortObiCfg.AddrWidth + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth) - 1:0] addr_input; // Signals from the demuxes sbr_port_obi_req_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_reqs; @@ -83,35 +86,28 @@ module relobi_xbar #( sbr_port_obi_req_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_reqs; sbr_port_obi_rsp_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_rsps; + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + (* dont_touch *) + relobi_xbar_tmr_part #( + .NumSbrPorts ( NumSbrPorts ), + .NumMgrPorts ( NumMgrPorts ), + .AddrWidth ( MgrPortObiCfg.AddrWidth ), + .EccAddrWidth( MgrPortObiCfg.AddrWidth + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth) ), + .NumAddrRules( NumAddrRules ), + .addr_map_rule_t( addr_map_rule_t ) + ) i_tmr_part ( + .addr_i ( addr_input ), + .addr_map_i ( TmrMap ? addr_map_i[i] : addr_map_i[0] ), + .en_default_idx_i ( TmrMap ? en_default_idx_i[i] : en_default_idx_i[0] ), + .default_idx_i ( TmrMap ? default_idx_i[i] : default_idx_i[0] ), + .sbr_port_select ( sbr_port_select[i] ), + .faults ( faults[i*NumSbrPorts +: NumSbrPorts] ) + ); + end + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_demux - for (genvar j = 0; j < 3; j++) begin : gen_tmr - - logic [MgrPortObiCfg.AddrWidth-1:0] addr; - - hsiao_ecc_dec #( - .DataWidth ( MgrPortObiCfg.AddrWidth ) - ) i_addr_dec ( - .in ( sbr_ports_req_i[i].a.addr ), - .out ( addr ), - .syndrome_o(), - .err_o (faults[4*i+j]) - ); - - addr_decode #( - .NoIndices ( NumMgrPorts ), - .NoRules ( NumAddrRules ), - .addr_t ( logic [MgrPortObiCfg.AddrWidth-1:0] ), - .rule_t ( addr_map_rule_t ) - ) i_addr_decode ( - .addr_i ( addr ), - .addr_map_i ( TmrMap ? addr_map_i[j] : addr_map_i[0] ), - .idx_o ( sbr_port_select[i][j] ), - .dec_valid_o (), - .dec_error_o (), - .en_default_idx_i( TmrMap ? en_default_idx_i[j][i] : en_default_idx_i[0][i] ), - .default_idx_i ( TmrMap ? default_idx_i[j][i] : default_idx_i[0][i] ) - ); - end + + assign addr_input[i] = sbr_ports_req_i[i].a.addr; relobi_demux #( .ObiCfg ( SbrPortObiCfg ), @@ -125,12 +121,12 @@ module relobi_xbar #( ) i_demux ( .clk_i, .rst_ni, - .sbr_port_select_i ( sbr_port_select[i] ), + .sbr_port_select_i ( {sbr_port_select[2][i], sbr_port_select[1][i], sbr_port_select[0][i] } ), .sbr_port_req_i ( sbr_ports_req_i[i] ), .sbr_port_rsp_o ( sbr_ports_rsp_o[i] ), .mgr_ports_req_o ( sbr_reqs[i] ), .mgr_ports_rsp_i ( sbr_rsps[i] ), - .fault_o ( faults[4*i+3] ) + .fault_o ( faults[3*NumSbrPorts+i] ) ); end @@ -179,6 +175,7 @@ module relobi_xbar #( .mgr_port_obi_req_t ( mgr_port_obi_req_t ), .mgr_port_obi_rsp_t ( mgr_port_obi_rsp_t ), .mgr_port_a_chan_t ( mgr_port_a_chan_t ), + .mgr_port_r_chan_t ( mgr_port_r_chan_t ), .a_optional_t ( a_optional_t ), .r_optional_t ( r_optional_t ), .NumSbrPorts ( NumSbrPorts ), @@ -197,3 +194,51 @@ module relobi_xbar #( end endmodule + +(* no_ungroup *) +(* no_boundary_optimization *) +module relobi_xbar_tmr_part #( + parameter int unsigned NumSbrPorts = 32'd0, + parameter int unsigned NumMgrPorts = 32'd0, + parameter int unsigned AddrWidth = 32'd0, + parameter int unsigned EccAddrWidth = AddrWidth + hsiao_ecc_pkg::min_ecc(AddrWidth), + parameter int unsigned NumAddrRules = 32'd0, + parameter type addr_map_rule_t = logic +) ( + input logic [NumSbrPorts-1:0][EccAddrWidth-1:0] addr_i, + input addr_map_rule_t [NumAddrRules-1:0] addr_map_i, + input logic [NumSbrPorts-1:0] en_default_idx_i, + input logic [NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] default_idx_i, + output logic [NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] sbr_port_select, + output logic [NumSbrPorts-1:0][1:0] faults +); + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sel + logic [AddrWidth-1:0] addr; + + hsiao_ecc_dec #( + .DataWidth ( AddrWidth ) + ) i_addr_dec ( + .in ( addr_i[i] ), + .out ( addr ), + .syndrome_o(), + .err_o (faults[i]) + ); + + addr_decode #( + .NoIndices ( NumMgrPorts ), + .NoRules ( NumAddrRules ), + .addr_t ( logic [AddrWidth-1:0] ), + .rule_t ( addr_map_rule_t ) + ) i_addr_decode ( + .addr_i ( addr ), + .addr_map_i ( addr_map_i ), + .idx_o ( sbr_port_select[i] ), + .dec_valid_o (), + .dec_error_o (), + .en_default_idx_i( en_default_idx_i[i] ), + .default_idx_i ( default_idx_i[i] ) + ); + end + +endmodule diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 4984662..9cf6207 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -126,6 +126,7 @@ module relobi_xbar_dut_wrapper #( .mgr_port_obi_req_t ( rel_sbr_bus_req_t ), .mgr_port_obi_rsp_t ( rel_sbr_bus_rsp_t ), .mgr_port_a_chan_t ( rel_sbr_bus_a_chan_t ), + .mgr_port_r_chan_t ( rel_sbr_bus_r_chan_t ), .a_optional_t ( mgr_a_optional_t ), .r_optional_t ( mgr_r_optional_t ), .NumSbrPorts ( NumManagers ), From 8c79496df30a58f729ae3cfbbadf932af57ce6a6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 14 Jul 2025 16:10:04 +0200 Subject: [PATCH 33/48] Add corrector IPs --- Bender.yml | 3 + src/relobi_a_other_corrector.sv | 46 +++++++++++ src/relobi_corrector.sv | 136 ++++++++++++++++++++++++++++++++ src/relobi_r_other_corrector.sv | 43 ++++++++++ 4 files changed, 228 insertions(+) create mode 100644 src/relobi_a_other_corrector.sv create mode 100644 src/relobi_corrector.sv create mode 100644 src/relobi_r_other_corrector.sv diff --git a/Bender.yml b/Bender.yml index a030bb1..14e08d0 100644 --- a/Bender.yml +++ b/Bender.yml @@ -48,11 +48,14 @@ sources: # Level 2 - src/relobi_a_other_decoder.sv - src/relobi_a_other_encoder.sv + - src/relobi_a_other_corrector.sv - src/relobi_r_other_decoder.sv - src/relobi_r_other_encoder.sv + - src/relobi_r_other_corrector.sv # Level 3 - src/relobi_decoder.sv - src/relobi_encoder.sv + - src/relobi_corrector.sv # Level 4 - src/relobi_cut.sv - src/relobi_demux.sv diff --git a/src/relobi_a_other_corrector.sv b/src/relobi_a_other_corrector.sv new file mode 100644 index 0000000..16f839e --- /dev/null +++ b/src/relobi_a_other_corrector.sv @@ -0,0 +1,46 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_a_other_corrector #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type a_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_a_other_ecc_width(Cfg) +) ( + input logic we_i, + input logic [Cfg.DataWidth/8-1:0] be_i, + input logic [Cfg.IdWidth -1:0] aid_i, + input a_optional_t a_optional_i, + input logic [ OtherEccWidth-1:0] other_ecc_i, + + output logic we_o, + output logic [Cfg.DataWidth/8-1:0] be_o, + output logic [Cfg.IdWidth -1:0] aid_o, + output a_optional_t a_optional_o, + output logic [ OtherEccWidth-1:0] other_ecc_o, + + output logic [1:0] fault_o +); + + hsiao_ecc_cor #( + .DataWidth (relobi_pkg::relobi_a_other_width(Cfg)) + ) i_a_remaining_cor ( + .in ( {other_ecc_i, + we_i, + be_i, + aid_i, + a_optional_i} ), + .out ( {other_ecc_o, + we_o, + be_o, + aid_o, + a_optional_o} ), + .syndrome_o(), + .err_o (fault_o) + ); + +endmodule diff --git a/src/relobi_corrector.sv b/src/relobi_corrector.sv new file mode 100644 index 0000000..798dc63 --- /dev/null +++ b/src/relobi_corrector.sv @@ -0,0 +1,136 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_corrector #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type relobi_req_t = logic, + parameter type relobi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic +) ( + input relobi_req_t req_i, + output relobi_rsp_t rsp_o, + + output relobi_req_t req_o, + input relobi_rsp_t rsp_i, + + output logic [1:0] fault_o +); + + logic [11:0] voter_errs; + logic voter_errs_red; + logic [4:0][1:0] hsiao_errs; + logic [1:0][4:0] hsiao_errs_transpose; + logic [1:0] hsiao_errs_transpose_red; + + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose + assign hsiao_errs_transpose_red[i] = |hsiao_errs_transpose[i]; + for (genvar j = 0; j < 5; j++) begin : gen_hsiao_errs_transpose_inner + assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; + end + end + + assign voter_errs_red = |voter_errs; + assign fault_o[0] = voter_errs_red | hsiao_errs_transpose_red[0]; + assign fault_o[1] = hsiao_errs_transpose_red[1]; + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + TMR_voter_fail i_req_req_vote ( + .a_i (req_i.req[0]), + .b_i (req_i.req[1]), + .c_i (req_i.req[2]), + .majority_o (req_o.req[i]), + .fault_detected_o(voter_errs[i]) + ); + TMR_voter_fail i_rsp_gnt_vote ( + .a_i (rsp_i.gnt[0]), + .b_i (rsp_i.gnt[1]), + .c_i (rsp_i.gnt[2]), + .majority_o (rsp_o.gnt[i]), + .fault_detected_o(voter_errs[3+i]) + ); + TMR_voter_fail i_rsp_rvalid_vote ( + .a_i (rsp_i.rvalid[0]), + .b_i (rsp_i.rvalid[1]), + .c_i (rsp_i.rvalid[2]), + .majority_o (rsp_o.rvalid[i]), + .fault_detected_o(voter_errs[6+i]) + ); + if (Cfg.UseRReady) begin : gen_rready_vote + TMR_voter_fail i_req_rready_vote ( + .a_i (req_i.rready[0]), + .b_i (req_i.rready[1]), + .c_i (req_i.rready[2]), + .majority_o (req_o.rready[i]), + .fault_detected_o(voter_errs[9+i]) + ); + end else begin : gen_no_rready_vote + assign voter_errs[9+i] = 1'b0; + end + end + + hsiao_ecc_cor #( + .DataWidth ( Cfg.AddrWidth ) + ) i_addr_enc ( + .in ( req_i.a.addr ), + .out( req_o.a.addr ), + .syndrome_o(), + .err_o (hsiao_errs[0]) + ); + + hsiao_ecc_cor #( + .DataWidth ( Cfg.DataWidth ) + ) i_wdata_enc ( + .in ( req_i.a.wdata ), + .out( req_o.a.wdata ), + .syndrome_o(), + .err_o (hsiao_errs[1]) + ); + + relobi_a_other_corrector #( + .Cfg (Cfg), + .a_optional_t (a_optional_t) + ) i_a_remaining_enc ( + .we_i (req_i.a.we), + .be_i (req_i.a.be), + .aid_i (req_i.a.aid), + .a_optional_i(req_i.a.a_optional), + .other_ecc_i (req_i.a.other_ecc), + .we_o (req_o.a.we), + .be_o (req_o.a.be), + .aid_o (req_o.a.aid), + .a_optional_o(req_o.a.a_optional), + .other_ecc_o (req_o.a.other_ecc), + .fault_o (hsiao_errs[2]) + ); + + hsiao_ecc_cor #( + .DataWidth ( Cfg.DataWidth ) + ) i_rdata_dec ( + .in ( rsp_i.r.rdata ), + .out ( rsp_o.r.rdata ), + .syndrome_o(), + .err_o (hsiao_errs[3]) + ); + + relobi_r_other_corrector #( + .Cfg (Cfg), + .r_optional_t (r_optional_t) + ) i_r_remaining_dec ( + .rid_i (rsp_i.r.rid), + .err_i (rsp_i.r.err), + .r_optional_i(rsp_i.r.r_optional), + .other_ecc_i (rsp_i.r.other_ecc), + .rid_o (rsp_o.r.rid), + .err_o (rsp_o.r.err), + .r_optional_o(rsp_o.r.r_optional), + .other_ecc_o (rsp_o.r.other_ecc), + .fault_o (hsiao_errs[4]) + ); + +endmodule diff --git a/src/relobi_r_other_corrector.sv b/src/relobi_r_other_corrector.sv new file mode 100644 index 0000000..b801a01 --- /dev/null +++ b/src/relobi_r_other_corrector.sv @@ -0,0 +1,43 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module relobi_r_other_corrector #( + /// Configuration of the bus + parameter obi_pkg::obi_cfg_t Cfg = obi_pkg::ObiDefaultConfig, + + parameter type r_optional_t = logic, + parameter int unsigned OtherEccWidth = relobi_pkg::relobi_r_other_ecc_width(Cfg) +) ( + input logic [Cfg.IdWidth -1:0] rid_i, + input logic err_i, + input r_optional_t r_optional_i, + input logic [OtherEccWidth-1:0] other_ecc_i, + + output logic [Cfg.IdWidth -1:0] rid_o, + output logic err_o, + output r_optional_t r_optional_o, + output logic [ OtherEccWidth-1:0] other_ecc_o, + + output logic [1:0] fault_o +); + + + hsiao_ecc_cor #( + .DataWidth ( relobi_pkg::relobi_r_other_width(Cfg) ) + ) i_r_remaining_cor ( + .in ( {other_ecc_i, + rid_i, + err_i, + r_optional_i} ), + .out( {other_ecc_o, + rid_o, + err_o, + r_optional_o} ), + .syndrome_o(), + .err_o (fault_o) + ); + +endmodule From e66a71a67a18d61dfa1b9c9c8c25ba88649f4d26 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 14 Jul 2025 16:13:13 +0200 Subject: [PATCH 34/48] Update relobi IPs --- src/relobi_cut.sv | 57 ++++++++++++++++++++++++++++------- src/relobi_demux.sv | 8 ++--- src/relobi_mux.sv | 26 +++++++++------- src/relobi_xbar.sv | 61 ++++++++++++++++++++++++++++---------- src/test/tb_relobi_xbar.sv | 21 ++++++++----- 5 files changed, 122 insertions(+), 51 deletions(-) diff --git a/src/relobi_cut.sv b/src/relobi_cut.sv index 11ce480..3d0d7a5 100644 --- a/src/relobi_cut.sv +++ b/src/relobi_cut.sv @@ -7,14 +7,18 @@ module relobi_cut #( /// The OBI configuration. parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, - /// The obi A channel struct. - parameter type obi_a_chan_t = logic, - /// The obi R channel struct. - parameter type obi_r_chan_t = logic, /// The request struct. parameter type obi_req_t = logic, /// The response struct. parameter type obi_rsp_t = logic, + /// The obi A channel struct. + parameter type obi_a_chan_t = logic, + /// The obi R channel struct. + parameter type obi_r_chan_t = logic, + /// Optional type for the A channel. + parameter type a_optional_t = logic, + /// Optional type for the R channel. + parameter type r_optional_t = logic, /// Bypass enable, can be individually overridden! parameter bit Bypass = 1'b0, /// Bypass enable for Request side. @@ -30,15 +34,41 @@ module relobi_cut #( output obi_req_t mgr_port_req_o, input obi_rsp_t mgr_port_rsp_i, - output logic fault_o + output logic [1:0] fault_o ); logic [1:0] faults; - assign fault_o = |faults; + logic [1:0] corrector_faults; + assign fault_o[0] = |faults | corrector_faults[0]; + assign fault_o[1] = corrector_faults[1]; + + obi_req_t corrector_req, corrected_req; + obi_rsp_t corrector_rsp, corrected_rsp; + assign corrector_req.req = '0; + if (ObiCfg.UseRReady) begin : gen_corrector_req_rready + assign corrector_req.rready = '0; + end + assign corrector_rsp.rvalid = '0; + assign corrector_rsp.gnt = '0; + + relobi_corrector #( + .Cfg ( ObiCfg ), + .relobi_req_t ( obi_req_t ), + .relobi_rsp_t ( obi_rsp_t ), + .a_optional_t ( a_optional_t ), + .r_optional_t ( r_optional_t ) + ) i_relobi_corrector ( + .req_i (corrector_req), + .rsp_i (corrector_rsp), + .req_o (corrected_req), + .rsp_o (corrected_rsp), + .fault_o (corrector_faults) + ); rel_spill_register #( .T ( obi_a_chan_t ), - .Bypass ( BypassReq ) + .Bypass ( BypassReq ), + .TmrHandshake ( 1'b1 ) ) i_reg_a ( .clk_i, .rst_ni, @@ -48,13 +78,16 @@ module relobi_cut #( .valid_o ( mgr_port_req_o.req ), .ready_i ( mgr_port_rsp_i.gnt ), .data_o ( mgr_port_req_o.a ), - .fault_o ( faults[0] ) + .fault_o ( faults[0] ), + .data_corrector_o ( corrector_req.a ), + .data_corrected_i ( corrected_req.a ) ); if (ObiCfg.UseRReady) begin : gen_use_rready rel_spill_register #( .T ( obi_r_chan_t ), - .Bypass ( BypassRsp ) + .Bypass ( BypassRsp ), + .TmrHandshake ( 1'b1 ) ) i_reg_r ( .clk_i, .rst_ni, @@ -64,14 +97,16 @@ module relobi_cut #( .valid_o ( sbr_port_rsp_o.rvalid ), .ready_i ( sbr_port_req_i.rready ), .data_o ( sbr_port_rsp_o.r ), - .fault_o ( faults[1] ) + .fault_o ( faults[1] ), + .data_corrector_o ( corrector_rsp.r ), + .data_corrected_i ( corrected_rsp.r ) ); end else begin : gen_no_use_rready assign faults[1] = 1'b0; + assign corrector_rsp.r = '0; always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin sbr_port_rsp_o.rvalid <= 1'b0; - sbr_port_rsp_o.r <= '0; end else begin sbr_port_rsp_o.rvalid <= mgr_port_rsp_i.rvalid; sbr_port_rsp_o.r <= mgr_port_rsp_i.r; diff --git a/src/relobi_demux.sv b/src/relobi_demux.sv index d3bd9bb..2af2299 100644 --- a/src/relobi_demux.sv +++ b/src/relobi_demux.sv @@ -76,13 +76,12 @@ module relobi_demux #( assign alt_select_d_sync[i][j] = select_d_sync[(i+j+1) % 3]; assign alt_counter_d_sync[i][j] = counter_d_sync[(i+j+1) % 3]; end - (* dont_touch *) relobi_demux_tmr_part #( .NumMgrPorts (NumMgrPorts), .CounterWidth (CounterWidth), .select_t (select_t), .obi_r_chan_t (obi_r_chan_t), - .TmrBeforeReg (1'b1) + .TmrBeforeReg (1'b0) ) i_tmr_part ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -139,7 +138,7 @@ module relobi_demux_tmr_part #( parameter int unsigned CounterWidth = 7, parameter type select_t = logic [$clog2(NumMgrPorts)-1:0], parameter type obi_r_chan_t = logic, - parameter bit TmrBeforeReg = 1'b1 + parameter bit TmrBeforeReg = 1'b0 ) ( input logic clk_i, input logic rst_ni, @@ -176,8 +175,7 @@ module relobi_demux_tmr_part #( sbr_port_gnt = 1'b0; if (!overflow) begin if (select_i == select_q || - in_flight == '0 || - (in_flight == 1 && cnt_down)) begin + in_flight == '0) begin mgr_ports_req[select_i] = sbr_port_req; sbr_port_gnt = mgr_ports_gnt[select_i]; end diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 4d4569a..6748910 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -114,7 +114,6 @@ module relobi_mux #( assign rr_arb_mgr_port_gnt = mgr_port_rsp_i.gnt & ~fifo_full; for (genvar i = 0; i < 3; i++) begin : gen_tmr_part - (* dont_touch *) relobi_mux_tmr_part #( .SbrPortObiCfg ( SbrPortObiCfg ), .MgrPortObiCfg ( MgrPortObiCfg ), @@ -180,16 +179,21 @@ module relobi_mux #( .fault_o ( voter_faults[0] ) ); - bitwise_TMR_voter_fail #( - .DataWidth ( $bits(mgr_port_a_chan_t) ), - .VoterType ( 1 ) - ) i_a_tmr ( - .a_i ( mgr_port_a_tmr[0] ), - .b_i ( mgr_port_a_tmr[1] ), - .c_i ( mgr_port_a_tmr[2] ), - .majority_o ( mgr_port_req_o.a ), - .fault_detected_o ( voter_faults[1] ) - ); + if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical + assign mgr_port_req_o.a = mgr_port_a_in_sbr; + assign voter_faults[1] = '0; + end else begin + bitwise_TMR_voter_fail #( + .DataWidth ( $bits(mgr_port_a_chan_t) ), + .VoterType ( 1 ) + ) i_a_tmr ( + .a_i ( mgr_port_a_tmr[0] ), + .b_i ( mgr_port_a_tmr[1] ), + .c_i ( mgr_port_a_tmr[2] ), + .majority_o ( mgr_port_req_o.a ), + .fault_detected_o ( voter_faults[1] ) + ); + end logic [2:0][SbrPortObiCfg.IdWidth-1:0] rsp_rid; diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index bb01560..68186cc 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -46,7 +46,8 @@ module relobi_xbar #( parameter bit [NumSbrPorts-1:0][NumMgrPorts-1:0] Connectivity = '1, /// Use TMR for addr map signal parameter bit TmrMap = 1'b1, - parameter int unsigned MapWidth = TmrMap ? 3 : 1 + parameter int unsigned MapWidth = TmrMap ? 3 : 1, + parameter bit DecodeAbort = 1'b0 ) ( input logic clk_i, input logic rst_ni, @@ -77,31 +78,34 @@ module relobi_xbar #( logic [2:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; logic [NumSbrPorts-1:0][ MgrPortObiCfg.AddrWidth + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth) - 1:0] addr_input; + logic [2:0][NumSbrPorts-1:0] decode_abort; + // Signals from the demuxes - sbr_port_obi_req_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_reqs; - sbr_port_obi_rsp_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_rsps; + sbr_port_obi_req_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_reqs, sbr_reqs_aborted; + sbr_port_obi_rsp_t [NumSbrPorts-1:0][NumMgrPorts-1:0] sbr_rsps, sbr_rsps_aborted; // Signals to the muxes sbr_port_obi_req_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_reqs; sbr_port_obi_rsp_t [NumMgrPorts-1:0][NumSbrPorts-1:0] mgr_rsps; for (genvar i = 0; i < 3; i++) begin : gen_tmr_part - (* dont_touch *) relobi_xbar_tmr_part #( .NumSbrPorts ( NumSbrPorts ), .NumMgrPorts ( NumMgrPorts ), .AddrWidth ( MgrPortObiCfg.AddrWidth ), .EccAddrWidth( MgrPortObiCfg.AddrWidth + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth) ), .NumAddrRules( NumAddrRules ), - .addr_map_rule_t( addr_map_rule_t ) + .addr_map_rule_t( addr_map_rule_t ), + .DecodeAbort( DecodeAbort ) ) i_tmr_part ( .addr_i ( addr_input ), .addr_map_i ( TmrMap ? addr_map_i[i] : addr_map_i[0] ), .en_default_idx_i ( TmrMap ? en_default_idx_i[i] : en_default_idx_i[0] ), .default_idx_i ( TmrMap ? default_idx_i[i] : default_idx_i[0] ), .sbr_port_select ( sbr_port_select[i] ), - .faults ( faults[i*NumSbrPorts +: NumSbrPorts] ) + .faults ( faults[i*NumSbrPorts +: NumSbrPorts] ), + .decode_abort_o ( decode_abort[i] ) ); end @@ -128,12 +132,24 @@ module relobi_xbar #( .mgr_ports_rsp_i ( sbr_rsps[i] ), .fault_o ( faults[3*NumSbrPorts+i] ) ); + always_comb begin : sbr_reqs_abort + sbr_reqs_aborted[i] = sbr_reqs[i]; + sbr_rsps_aborted[i] = sbr_rsps[i]; + for (int j = 0; j < NumMgrPorts; j++) begin : sbr_reqs_abort_inner + sbr_reqs_aborted[i][j].req[0] = sbr_reqs[i][j].req[0] & ~decode_abort[0][i]; + sbr_reqs_aborted[i][j].req[1] = sbr_reqs[i][j].req[1] & ~decode_abort[1][i]; + sbr_reqs_aborted[i][j].req[2] = sbr_reqs[i][j].req[2] & ~decode_abort[2][i]; + sbr_rsps_aborted[i][j].gnt[0] = sbr_rsps[i][j].gnt[0] & ~decode_abort[0][i]; + sbr_rsps_aborted[i][j].gnt[1] = sbr_rsps[i][j].gnt[1] & ~decode_abort[1][i]; + sbr_rsps_aborted[i][j].gnt[2] = sbr_rsps[i][j].gnt[2] & ~decode_abort[2][i]; + end + end end for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_interco_sbr for (genvar j = 0; j < NumMgrPorts; j++) begin : gen_interco_mgr if (Connectivity[i][j]) begin : gen_connected - assign mgr_reqs[j][i] = sbr_reqs[i][j]; + assign mgr_reqs[j][i] = sbr_reqs_aborted[i][j]; assign sbr_rsps[i][j] = mgr_rsps[j][i]; end else begin : gen_err_sbr assign mgr_reqs[j][i].req = '0; @@ -157,7 +173,7 @@ module relobi_xbar #( .clk_i, .rst_ni, .testmode_i, - .obi_req_i (sbr_reqs[i][j]), + .obi_req_i (sbr_reqs_aborted[i][j]), .obi_rsp_o (sbr_rsps[i][j]) ); end @@ -184,7 +200,7 @@ module relobi_xbar #( ) i_mux ( .clk_i, .rst_ni, - .testmode_i, + .testmode_i ( testmode_i ), .sbr_ports_req_i ( mgr_reqs[i] ), .sbr_ports_rsp_o ( mgr_rsps[i] ), .mgr_port_req_o ( mgr_ports_req_o[i] ), @@ -203,35 +219,48 @@ module relobi_xbar_tmr_part #( parameter int unsigned AddrWidth = 32'd0, parameter int unsigned EccAddrWidth = AddrWidth + hsiao_ecc_pkg::min_ecc(AddrWidth), parameter int unsigned NumAddrRules = 32'd0, - parameter type addr_map_rule_t = logic + parameter type addr_map_rule_t = logic, + parameter bit DecodeAbort = 1'b1 ) ( input logic [NumSbrPorts-1:0][EccAddrWidth-1:0] addr_i, input addr_map_rule_t [NumAddrRules-1:0] addr_map_i, input logic [NumSbrPorts-1:0] en_default_idx_i, input logic [NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] default_idx_i, output logic [NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] sbr_port_select, - output logic [NumSbrPorts-1:0][1:0] faults + output logic [NumSbrPorts-1:0][1:0] faults, + output logic [NumSbrPorts-1:0] decode_abort_o ); + logic [NumSbrPorts-1:0][AddrWidth-1:0] addr, addr_dec; - for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sel - logic [AddrWidth-1:0] addr; - + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_ecc_dec hsiao_ecc_dec #( .DataWidth ( AddrWidth ) ) i_addr_dec ( .in ( addr_i[i] ), - .out ( addr ), + .out ( addr_dec [i] ), .syndrome_o(), .err_o (faults[i]) ); + end + if (DecodeAbort) begin : gen_decode_abort + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_addr + assign addr[i] = addr_i[i][AddrWidth-1:0]; + assign decode_abort_o[i] = faults[i][0] | faults[i][1]; + end + end else begin : gen_no_decode_abort + assign addr = addr_dec; + assign decode_abort_o = '0; + end + + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sel addr_decode #( .NoIndices ( NumMgrPorts ), .NoRules ( NumAddrRules ), .addr_t ( logic [AddrWidth-1:0] ), .rule_t ( addr_map_rule_t ) ) i_addr_decode ( - .addr_i ( addr ), + .addr_i ( addr [i] ), .addr_map_i ( addr_map_i ), .idx_o ( sbr_port_select[i] ), .dec_valid_o (), diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 9cf6207..5df1fda 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -59,9 +59,9 @@ module relobi_xbar_dut_wrapper #( logic [1:0] xbar_fault; logic [NumManagers-1:0][1:0] encoder_faults; - logic [NumManagers-1:0] enc_cut_faults; + logic [NumManagers-1:0][1:0] enc_cut_faults; logic [NumSubordinates-1:0][1:0] decoder_faults; - logic [NumSubordinates-1:0] dec_cut_faults; + logic [NumSubordinates-1:0][1:0] dec_cut_faults; logic [NumManagers-1:0][MgrBusRspBits-1:0] mgr_bus_rsp_flat; for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_bus_rsp @@ -101,6 +101,8 @@ module relobi_xbar_dut_wrapper #( .obi_rsp_t ( rel_mgr_bus_rsp_t ), .obi_a_chan_t ( rel_mgr_bus_a_chan_t ), .obi_r_chan_t ( rel_mgr_bus_r_chan_t ), + .a_optional_t ( mgr_a_optional_t ), + .r_optional_t ( mgr_r_optional_t ), .Bypass ( 1'b0 ) ) i_cut_mgr ( .clk_i ( clk ), @@ -135,7 +137,8 @@ module relobi_xbar_dut_wrapper #( .NumAddrRules ( NumRules ), .addr_map_rule_t ( rule_t ), .UseIdForRouting ( UseIdForRouting ), - .TmrMap (1'b1) + .TmrMap (1'b1), + .DecodeAbort (1'b1) ) i_dut ( .clk_i ( clk ), .rst_ni ( rst_n ), @@ -161,6 +164,8 @@ module relobi_xbar_dut_wrapper #( .obi_rsp_t ( rel_sbr_bus_rsp_t ), .obi_a_chan_t ( rel_sbr_bus_a_chan_t ), .obi_r_chan_t ( rel_sbr_bus_r_chan_t ), + .a_optional_t ( sbr_a_optional_t ), + .r_optional_t ( sbr_r_optional_t ), .Bypass ( 1'b0 ) ) i_cut_sbr ( .clk_i ( clk ), @@ -204,12 +209,12 @@ module relobi_xbar_dut_wrapper #( uncorrectable_fault = xbar_fault[1]; for (int unsigned i = 0; i < NumManagers; i++) begin - corrected_fault |= encoder_faults[i][0] | enc_cut_faults[i]; - uncorrectable_fault |= encoder_faults[i][1]; + corrected_fault |= encoder_faults[i][0] | enc_cut_faults[i][0]; + uncorrectable_fault |= encoder_faults[i][1] | enc_cut_faults[i][1]; end for (int unsigned i = 0; i < NumSubordinates; i++) begin - corrected_fault |= decoder_faults[i][0] | dec_cut_faults[i]; - uncorrectable_fault |= decoder_faults[i][1]; + corrected_fault |= decoder_faults[i][0] | dec_cut_faults[i][0]; + uncorrectable_fault |= decoder_faults[i][1] | dec_cut_faults[i][1]; end end @@ -241,7 +246,7 @@ module tb_relobi_xbar; localparam int unsigned AddrWidth = 32; localparam int unsigned DataWidth = 32; localparam int unsigned MgrIdWidth = 5; - localparam int unsigned SbrIdWidth = MgrIdWidth+$clog2(NumManagers); + localparam int unsigned SbrIdWidth = MgrIdWidth; localparam int unsigned AUserWidth = 4; localparam int unsigned WUserWidth = 2; localparam int unsigned RUserWidth = 3; From 4cace52720bf344991c53f7cc0531d0b33583e39 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 29 Jul 2025 17:57:06 +0200 Subject: [PATCH 35/48] Fixes/updates from testing --- Bender.lock | 2 +- Bender.yml | 2 +- src/relobi_cut.sv | 1 + src/relobi_mux.sv | 5 +- src/relobi_xbar.sv | 26 ++++---- src/test/tb_relobi_xbar.sv | 119 +++++++++++++++++++++++++++++++++++-- 6 files changed, 133 insertions(+), 22 deletions(-) diff --git a/Bender.lock b/Bender.lock index a047309..b473961 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 14899dfd0ea0aa0be3be74e00c1979802d5832b1 + revision: 9d1a43b89ee599a4b8bee2f802950a2d3f4ee0b8 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index 14e08d0..6cb3590 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 14899dfd0ea0aa0be3be74e00c1979802d5832b1 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 9d1a43b89ee599a4b8bee2f802950a2d3f4ee0b8 } export_include_dirs: - include diff --git a/src/relobi_cut.sv b/src/relobi_cut.sv index 3d0d7a5..93879a4 100644 --- a/src/relobi_cut.sv +++ b/src/relobi_cut.sv @@ -107,6 +107,7 @@ module relobi_cut #( always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin sbr_port_rsp_o.rvalid <= 1'b0; + sbr_port_rsp_o.r <= '0; end else begin sbr_port_rsp_o.rvalid <= mgr_port_rsp_i.rvalid; sbr_port_rsp_o.r <= mgr_port_rsp_i.r; diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index 6748910..ac2e2e8 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -354,10 +354,7 @@ module relobi_mux_tmr_part #( logic [RequiredExtraIdWidth-1:0] response_id; if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical - always_comb begin - `OBI_SET_A_STRUCT(mgr_port_a_tmr, mgr_port_a_in_sbr) - mgr_port_a_tmr.other_ecc = mgr_port_a_in_sbr.other_ecc; - end + assign mgr_port_a_tmr = mgr_port_a_in_sbr; assign hsiao_faults[0] = '0; assign hsiao_faults_gated[0] = '0; end else begin : gen_aid_extend diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index 68186cc..aa6f20f 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -132,18 +132,22 @@ module relobi_xbar #( .mgr_ports_rsp_i ( sbr_rsps[i] ), .fault_o ( faults[3*NumSbrPorts+i] ) ); - always_comb begin : sbr_reqs_abort - sbr_reqs_aborted[i] = sbr_reqs[i]; - sbr_rsps_aborted[i] = sbr_rsps[i]; - for (int j = 0; j < NumMgrPorts; j++) begin : sbr_reqs_abort_inner - sbr_reqs_aborted[i][j].req[0] = sbr_reqs[i][j].req[0] & ~decode_abort[0][i]; - sbr_reqs_aborted[i][j].req[1] = sbr_reqs[i][j].req[1] & ~decode_abort[1][i]; - sbr_reqs_aborted[i][j].req[2] = sbr_reqs[i][j].req[2] & ~decode_abort[2][i]; - sbr_rsps_aborted[i][j].gnt[0] = sbr_rsps[i][j].gnt[0] & ~decode_abort[0][i]; - sbr_rsps_aborted[i][j].gnt[1] = sbr_rsps[i][j].gnt[1] & ~decode_abort[1][i]; - sbr_rsps_aborted[i][j].gnt[2] = sbr_rsps[i][j].gnt[2] & ~decode_abort[2][i]; + + for (genvar j = 0; j < NumMgrPorts; j++) begin : sbr_reqs_abort_inner + assign sbr_reqs_aborted[i][j].a = sbr_reqs[i][j].a; + assign sbr_rsps_aborted[i][j].r = sbr_rsps[i][j].r; + assign sbr_rsps_aborted[i][j].rvalid = sbr_rsps[i][j].rvalid; + if (SbrPortObiCfg.UseRReady) begin : gen_rready + assign sbr_reqs_aborted[i][j].rready = sbr_reqs[i][j].rready; end - end + assign sbr_reqs_aborted[i][j].req[0] = sbr_reqs[i][j].req[0] & ~decode_abort[0][i]; + assign sbr_reqs_aborted[i][j].req[1] = sbr_reqs[i][j].req[1] & ~decode_abort[1][i]; + assign sbr_reqs_aborted[i][j].req[2] = sbr_reqs[i][j].req[2] & ~decode_abort[2][i]; + assign sbr_rsps_aborted[i][j].gnt[0] = sbr_rsps[i][j].gnt[0] & ~decode_abort[0][i]; + assign sbr_rsps_aborted[i][j].gnt[1] = sbr_rsps[i][j].gnt[1] & ~decode_abort[1][i]; + assign sbr_rsps_aborted[i][j].gnt[2] = sbr_rsps[i][j].gnt[2] & ~decode_abort[2][i]; + end + end for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_interco_sbr diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 5df1fda..77519ba 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -24,6 +24,10 @@ module relobi_xbar_dut_wrapper #( parameter type mgr_bus_rsp_t = logic, parameter type sbr_bus_req_t = logic, parameter type sbr_bus_rsp_t = logic, + parameter type mgr_bus_a_chan_t = logic, + parameter type mgr_bus_r_chan_t = logic, + parameter type sbr_bus_a_chan_t = logic, + parameter type sbr_bus_r_chan_t = logic, parameter type mgr_a_optional_t = logic, parameter type mgr_r_optional_t = logic, parameter type sbr_a_optional_t = logic, @@ -33,7 +37,8 @@ module relobi_xbar_dut_wrapper #( parameter type rule_t = logic, parameter rule_t [NumRules-1:0] AddrMap = '0, parameter bit UseIdForRouting = 1'b0, - parameter time TestTime = 8ns + parameter time TestTime = 8ns, + parameter int unsigned NumRequests = 1 ) ( input logic clk, input logic rst_n, @@ -44,7 +49,9 @@ module relobi_xbar_dut_wrapper #( // Subordinate ports output sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req, - input sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp + input sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp, + + input logic [NumManagers-1:0] end_of_sim ); localparam int unsigned MgrBusReqBits = $bits(mgr_bus_req_t); @@ -201,6 +208,101 @@ module relobi_xbar_dut_wrapper #( ); end + logic interface_error; + logic [NumSubordinates-1:0] sbr_error; + logic [NumManagers-1:0] mgr_error; + assign interface_error = |sbr_error | |mgr_error; + + // Collect sent requests and responses + localparam int unsigned NumMABits = $bits(mgr_bus_a_chan_t); + localparam int unsigned NumMRBits = $bits(mgr_bus_r_chan_t); + localparam int unsigned NumSABits = $bits(sbr_bus_a_chan_t); + localparam int unsigned NumSRBits = $bits(sbr_bus_r_chan_t); + logic [NumMABits-1:0] mgr_bus_a_chan_flat [NumManagers][NumSubordinates][$]; + logic mgr_bus_a_chan_flat_empty [NumManagers][NumSubordinates]; + logic [NumMABits-1:0] mgr_bus_a_chan_flat_front [NumManagers][NumSubordinates]; + logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx [NumManagers][$]; + logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx_front [NumManagers]; + logic [NumSRBits-1:0] sbr_bus_r_chan_flat [NumSubordinates][$]; + logic [NumSRBits-1:0] sbr_bus_r_chan_flat_front [NumSubordinates]; + logic [NumSubordinates-1:0][NumManagers-1:0] sbr_mgr_match; + logic [NumManagers-1:0][NumSubordinates-1:0] mgr_sbr_match; + + logic [NumSubordinates-1:0] sbr_data_valid; + logic [NumManagers-1:0] mgr_data_valid; + for (genvar i = 0; i < NumSubordinates; i++) begin + assign sbr_data_valid[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt; + assign sbr_error[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt & ~(|sbr_mgr_match[i]); + end + for (genvar i = 0; i < NumManagers; i++) begin + assign mgr_data_valid[i] = mgr_bus_rsp[i].rvalid; + assign mgr_error[i] = mgr_bus_rsp[i].rvalid & ~(|mgr_sbr_match[i]); + end + + always_comb begin + for (int unsigned i = 0; i < NumSubordinates; i++) begin + for (int unsigned j = 0; j < NumManagers; j++) begin + if (sbr_bus_req[i].req && sbr_bus_rsp[i].gnt) begin + if (mgr_bus_a_chan_flat_empty[j][i]) begin + sbr_mgr_match[i][j] = 1'b0; + end else begin + sbr_mgr_match[i][j] = mgr_bus_a_chan_flat_front[j][i] == sbr_bus_req[i].a; + end + end else begin + sbr_mgr_match[i][j] = 1'b0; + end + end + end + for (int unsigned i = 0; i < NumManagers; i++) begin + if (mgr_bus_rsp[i].rvalid) begin + mgr_sbr_match[i] = sbr_bus_r_chan_flat_front[mgr_bus_rsp_idx_front[i]] == mgr_bus_rsp[i].r; + end else begin + mgr_sbr_match[i] = '0; + end + end + end + + always @(posedge clk) begin + for (int unsigned i = 0; i < NumManagers; i++) begin + for (int unsigned j = 0; j < NumSubordinates; j++) begin + if (mgr_bus_req[i].req && mgr_bus_rsp[i].gnt && + mgr_bus_req[i].a.addr >= AddrMap[j].start_addr && + mgr_bus_req[i].a.addr < AddrMap[j].end_addr) begin + mgr_bus_a_chan_flat[i][j].push_back(mgr_bus_req[i].a); + mgr_bus_rsp_idx[i].push_back(j); + end + end + if (mgr_bus_rsp[i].rvalid) begin + sbr_bus_r_chan_flat[mgr_bus_rsp_idx[i][0]].pop_front(); + mgr_bus_rsp_idx[i].pop_front(); + end + end + for (int unsigned i = 0; i < NumSubordinates; i++) begin + if (sbr_bus_req[i].req && sbr_bus_rsp[i].gnt) begin + for (int unsigned j = 0; j < NumManagers; j++) begin + if (mgr_bus_a_chan_flat[j][i][0] == sbr_bus_req[i].a) begin + mgr_bus_a_chan_flat[j][i].pop_front(); + break; + end + end + end + if (sbr_bus_rsp[i].rvalid) begin + sbr_bus_r_chan_flat[i].push_back(sbr_bus_rsp[i].r); + end + end + + for (int unsigned i = 0; i < NumManagers; i++) begin + mgr_bus_rsp_idx_front[i] = mgr_bus_rsp_idx[i][0]; + for (int unsigned j = 0; j < NumSubordinates; j++) begin + mgr_bus_a_chan_flat_empty[i][j] = (mgr_bus_a_chan_flat[i][j].size() == 0); + mgr_bus_a_chan_flat_front[i][j] = mgr_bus_a_chan_flat[i][j][0]; + end + end + for (int unsigned i = 0; i < NumSubordinates; i++) begin + sbr_bus_r_chan_flat_front[i] = sbr_bus_r_chan_flat[i][0]; + end + end + // Fault indication logic corrected_fault; logic uncorrectable_fault; @@ -300,7 +402,7 @@ module tb_relobi_xbar; .TA ( ApplTime ), .TT ( TestTime ), .MinAddr (32'h0000_0000), - .MaxAddr (32'h0001_3000) + .MaxAddr (32'h0001_1000) ) rand_manager_t; localparam obi_pkg::obi_cfg_t SbrConfig = '{ @@ -467,6 +569,10 @@ module tb_relobi_xbar; .mgr_bus_rsp_t(mgr_bus_rsp_t), .sbr_bus_req_t(sbr_bus_req_t), .sbr_bus_rsp_t(sbr_bus_rsp_t), + .mgr_bus_a_chan_t(mgr_bus_a_chan_t), + .mgr_bus_r_chan_t(mgr_bus_r_chan_t), + .sbr_bus_a_chan_t(sbr_bus_a_chan_t), + .sbr_bus_r_chan_t(sbr_bus_r_chan_t), .mgr_a_optional_t(mgr_a_optional_t), .mgr_r_optional_t(mgr_r_optional_t), .sbr_a_optional_t(sbr_a_optional_t), @@ -476,7 +582,8 @@ module tb_relobi_xbar; .rule_t(rule_t), .AddrMap(AddrMap), .UseIdForRouting(UseIdForRouting), - .TestTime(TestTime) + .TestTime(TestTime), + .NumRequests(NumRequests) ) i_dut_wrapper ( .clk, .rst_n, @@ -487,7 +594,9 @@ module tb_relobi_xbar; // Subordinate ports .sbr_bus_req, - .sbr_bus_rsp + .sbr_bus_rsp, + + .end_of_sim(end_of_sim) ); for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode From dfcfedfcc3452ea96408dac9a005d0884682d0c3 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 30 Jul 2025 20:04:22 +0200 Subject: [PATCH 36/48] Bump redundancy cells for ecc width fix --- Bender.lock | 2 +- Bender.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bender.lock b/Bender.lock index b473961..85d2289 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 9d1a43b89ee599a4b8bee2f802950a2d3f4ee0b8 + revision: 69468c8f8503d603bbcd6971607c7896104b8519 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index 6cb3590..aa474a2 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 9d1a43b89ee599a4b8bee2f802950a2d3f4ee0b8 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 69468c8f8503d603bbcd6971607c7896104b8519 } export_include_dirs: - include From 4601fa18f0de63e9faeedac12eef34a9be25a4d7 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 30 Jul 2025 21:57:51 +0200 Subject: [PATCH 37/48] Correct relobi_err_sbr --- src/relobi_err_sbr.sv | 175 ++++++++++++++++++++++++++++++++++++------ src/relobi_xbar.sv | 5 +- 2 files changed, 155 insertions(+), 25 deletions(-) diff --git a/src/relobi_err_sbr.sv b/src/relobi_err_sbr.sv index cce4c6c..c3143f8 100644 --- a/src/relobi_err_sbr.sv +++ b/src/relobi_err_sbr.sv @@ -11,6 +11,8 @@ module relobi_err_sbr #( parameter type obi_req_t = logic, /// The response struct. parameter type obi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic, /// Numper of transactions accepted before stalling if UseRReady parameter int unsigned NumMaxTrans = 1, /// Data to respond with from error subordinate @@ -21,44 +23,169 @@ module relobi_err_sbr #( input logic testmode_i, input obi_req_t obi_req_i, - output obi_rsp_t obi_rsp_o + output obi_rsp_t obi_rsp_o, + + output logic [1:0] fault_o ); - logic [ObiCfg.IdWidth-1:0] rid; - logic fifo_full, fifo_empty, fifo_pop; + logic [3:0][1:0] hsiao_errs; + logic [1:0][3:0] hsiao_errs_transpose; + logic [1:0] voter_errs; + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose + for (genvar j = 0; j < 4; j++) begin : gen_hsiao_errs_transpose_inner + assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; + end + end + assign fault_o[0] = |voter_errs | |hsiao_errs_transpose[0]; + assign fault_o[1] = |hsiao_errs_transpose[1]; + + logic [ObiCfg.IdWidth-1:0] rid_d, rid_q; + logic [2:0][ObiCfg.IdWidth-1:0] rid_tmr; + logic [2:0] fifo_full, fifo_empty, fifo_pop; + + logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_d, other_ecc_q; + logic [2:0][relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_tmr; + logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] rdata_encoded; + + hsiao_ecc_enc #( + .DataWidth (ObiCfg.DataWidth) + ) i_rdata_encoder ( + .in ( RspData ), + .out ( rdata_encoded ) + ); + + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + relobi_err_sbr_tmr_part #( + .ObiCfg(ObiCfg), + .a_optional_t(a_optional_t), + .r_optional_t(r_optional_t) + ) i_tmr_part ( + .we_i(obi_req_i.a.we), + .be_i(obi_req_i.a.be), + .aid_i(obi_req_i.a.aid), + .a_optional_i(obi_req_i.a.a_optional), + .other_ecc_i(obi_req_i.a.other_ecc), + + .rid_o(rid_tmr[i]), + .other_ecc_o(other_ecc_tmr[i]), + + .fault_o(hsiao_errs[i]) + ); + end + + bitwise_TMR_voter_fail #( + .DataWidth( ObiCfg.IdWidth ) + ) i_rid_vote ( + .a_i (rid_tmr[0]), + .b_i (rid_tmr[1]), + .c_i (rid_tmr[2]), + .majority_o (rid_d), + .fault_detected_o(voter_errs[0]) + ); + bitwise_TMR_voter_fail #( + .DataWidth( relobi_pkg::relobi_r_other_ecc_width(ObiCfg) ) + ) i_other_ecc_vote ( + .a_i (other_ecc_tmr[0]), + .b_i (other_ecc_tmr[1]), + .c_i (other_ecc_tmr[2]), + .majority_o (other_ecc_d), + .fault_detected_o(voter_errs[1]) + ); always_comb begin obi_rsp_o.r.rdata = '0; - obi_rsp_o.r.rdata = RspData; - obi_rsp_o.r.rid = rid; + obi_rsp_o.r.rdata = rdata_encoded; + obi_rsp_o.r.rid = rid_q; obi_rsp_o.r.err = 1'b1; obi_rsp_o.r.r_optional = '0; + obi_rsp_o.r.other_ecc = other_ecc_q; obi_rsp_o.gnt = ~fifo_full; obi_rsp_o.rvalid = ~fifo_empty; end - if (ObiCfg.UseRReady) begin : gen_pop_rready + if (ObiCfg.UseRReady) begin : gen_rready_fifo assign fifo_pop = obi_rsp_o.rvalid && obi_req_i.rready; - end else begin : gen_pop_default - assign fifo_pop = obi_rsp_o.rvalid; + rel_fifo #( + .Depth ( ObiCfg.UseRReady ? NumMaxTrans : 1 ), + .FallThrough ( 1'b0 ), + .DataWidth ( ObiCfg.IdWidth + relobi_pkg::relobi_r_other_ecc_width(ObiCfg) ), + .TmrStatus ( 1'b1 ), + .DataHasEcc ( 1'b1 ) + ) i_id_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( '0 ), + .full_o ( fifo_full ), + .empty_o ( fifo_empty ), + .usage_o (), + .data_i ( {other_ecc_d, rid_d} ), + .push_i ( obi_req_i.req & obi_rsp_o.gnt ), + .data_o ( {other_ecc_q, rid_q} ), + .pop_i ( fifo_pop ), + .fault_o (hsiao_errs[3]) + ); + end else begin : gen_no_rready_fifo + assign fifo_full = 1'b0; + assign fifo_pop = 1'b0; + assign hsiao_errs[3] = '0; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + rid_q <= '0; + other_ecc_q <= '0; + fifo_empty <= 1'b1; + end else begin + rid_q <= rid_d; + other_ecc_q <= other_ecc_d; + fifo_empty <= ~(obi_req_i.req & obi_rsp_o.gnt); + end + end end - fifo_v3 #( - .DEPTH ( ObiCfg.UseRReady ? NumMaxTrans : 1 ), - .FALL_THROUGH ( 1'b0 ), - .DATA_WIDTH ( ObiCfg.IdWidth ) - ) i_id_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( '0 ), - .full_o ( fifo_full ), - .empty_o ( fifo_empty ), - .usage_o (), - .data_i ( obi_req_i.a.aid ), - .push_i ( obi_req_i.req && obi_rsp_o.gnt ), - .data_o ( rid ), - .pop_i ( fifo_pop ) +endmodule + +module relobi_err_sbr_tmr_part #( + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic + +) ( + input logic we_i, + input logic [ObiCfg.DataWidth/8-1:0] be_i, + input logic [ObiCfg.IdWidth -1:0] aid_i, + input a_optional_t a_optional_i, + input logic [relobi_pkg::relobi_a_other_ecc_width(ObiCfg)-1:0] other_ecc_i, + + output logic [ObiCfg.IdWidth -1:0] rid_o, + output logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_o, + + output logic [1:0] fault_o +); + + relobi_a_other_decoder #( + .Cfg(ObiCfg), + .a_optional_t(a_optional_t) + ) i_a_other_decoder ( + .we_i(we_i), + .be_i(be_i), + .aid_i(aid_i), + .a_optional_i(a_optional_i), + .other_ecc_i(other_ecc_i), + .we_o(), + .be_o(), + .aid_o(rid_o), + .a_optional_o(), + .fault_o(fault_o) + ); + + relobi_r_other_encoder #( + .Cfg(ObiCfg), + .r_optional_t(r_optional_t) + ) i_other_ecc_encoder ( + .rid_i(rid_o), + .err_i(1'b1), // Always error + .r_optional_i('0), // No optional fields in error response + .other_ecc_o(other_ecc_o) ); endmodule diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index aa6f20f..a0b37c5 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -171,6 +171,8 @@ module relobi_xbar #( .ObiCfg ( SbrPortObiCfg ), .obi_req_t ( sbr_port_obi_req_t ), .obi_rsp_t ( sbr_port_obi_rsp_t ), + .a_optional_t ( a_optional_t ), + .r_optional_t ( r_optional_t ), .NumMaxTrans ( NumMaxTrans ), .RspData ( 32'hBADCAB1E ) ) i_err_sbr ( @@ -178,7 +180,8 @@ module relobi_xbar #( .rst_ni, .testmode_i, .obi_req_i (sbr_reqs_aborted[i][j]), - .obi_rsp_o (sbr_rsps[i][j]) + .obi_rsp_o (sbr_rsps[i][j]), + .fault_o () // TODO ); end end From 949657a9c63230f141c23afc7797bd533396001d Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 30 Jul 2025 22:07:40 +0200 Subject: [PATCH 38/48] Add relobi sram shim with rmw --- Bender.yml | 1 + src/relobi_sram_shim.sv | 322 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100644 src/relobi_sram_shim.sv diff --git a/Bender.yml b/Bender.yml index aa474a2..989f7da 100644 --- a/Bender.yml +++ b/Bender.yml @@ -61,6 +61,7 @@ sources: - src/relobi_demux.sv - src/relobi_err_sbr.sv - src/relobi_mux.sv + - src/relobi_sram_shim.sv # Level 5 - src/relobi_xbar.sv - target: any(test, obi_test) diff --git a/src/relobi_sram_shim.sv b/src/relobi_sram_shim.sv new file mode 100644 index 0000000..5e8ceb4 --- /dev/null +++ b/src/relobi_sram_shim.sv @@ -0,0 +1,322 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +// For single-cycle SRAMs, supports RMW for byte enable +module relobi_sram_shim #( + /// The OBI configuration for all ports. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The request struct for all ports. + parameter type relobi_req_t = logic, + /// The response struct for all ports. + parameter type relobi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic, + parameter bit EnableScrubber = 1'b0 // Unimplemented, WIP +) ( + input logic clk_i, + input logic rst_ni, + + input relobi_req_t obi_req_i, + output relobi_rsp_t obi_rsp_o, + + output logic req_o, + output logic we_o, + output logic [ObiCfg.AddrWidth-1:0] addr_o, + output logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_o, + + input logic gnt_i, // Should generally be 1'b1 + input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] rdata_i, + + output logic [1:0] fault_o +); + + if (ObiCfg.OptionalCfg.UseAtop) $error("Please use an ATOP resolver before sram shim."); + if (ObiCfg.UseRReady) $error("Please use an RReady Fifo before sram shim."); + if (ObiCfg.Integrity) $error("Integrity not yet supported, WIP"); + if (ObiCfg.OptionalCfg.UseProt) $warning("Prot not checked!"); + if (ObiCfg.OptionalCfg.UseMemtype) $warning("Memtype not checked!"); + + logic [5:0] voter_errs; + logic [9:0][1:0] hsiao_errs; + logic [1:0][9:0] hsiao_errs_transpose; + + for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose + for (genvar j = 0; j < 10; j++) begin : gen_hsiao_errs_transpose_inner + assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; + end + end + + assign fault_o[0] = |voter_errs | |hsiao_errs_transpose[0]; + assign fault_o[1] = |hsiao_errs_transpose[1]; + + + logic [2:0] rvalid_d, rvalid_q; + logic [ObiCfg.IdWidth-1:0] id_d, id_q; + logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_d, other_ecc_q; + + logic use_buffered; + logic [2:0] use_buffered_tmr; + logic [2:0] req_o_tmr; + logic [2:0] we; + logic [2:0][ObiCfg.DataWidth/8-1:0] be; + logic [2:0][ObiCfg.IdWidth-1:0] aid; + logic [2:0][relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc; + logic [2:0][ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] rmw_wdata_tmr; + logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_buffer, rmw_wdata; + logic [ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)-1:0] addr_buffer; + logic [2:0] r_gnt; + + TMR_voter_fail i_req_valid_vote ( + .a_i (req_o_tmr[0]), + .b_i (req_o_tmr[1]), + .c_i (req_o_tmr[2]), + .majority_o (req_o), + .fault_detected_o(voter_errs[0]) + ); + + TMR_voter_fail i_use_buffered_vote ( + .a_i (use_buffered_tmr[0]), + .b_i (use_buffered_tmr[1]), + .c_i (use_buffered_tmr[2]), + .majority_o (use_buffered), + .fault_detected_o(voter_errs[1]) + ); + + assign wdata_o = use_buffered ? rmw_wdata : obi_req_i.a.wdata; + + always_comb begin + obi_rsp_o = '0; + obi_rsp_o.gnt = r_gnt; + obi_rsp_o.rvalid = rvalid_q; + obi_rsp_o.r.rdata = rdata_i; + obi_rsp_o.r.rid = id_q; + obi_rsp_o.r.err = 1'b0; + obi_rsp_o.r.other_ecc = other_ecc_q; + end + + assign rvalid_d = obi_req_i.req & obi_rsp_o.gnt; + + hsiao_ecc_dec #( + .DataWidth ( ObiCfg.AddrWidth ) + ) i_addr_dec ( + .in ( use_buffered ? addr_buffer : obi_req_i.a.addr ), + .out ( addr_o ), + .syndrome_o(), + .err_o (hsiao_errs[0]) + ); + + for (genvar i = 0; i < 3; i++) begin : tmr_part + relobi_sram_shim_tmr_part #( + .ObiCfg(ObiCfg), + .relobi_req_t(relobi_req_t), + .relobi_rsp_t(relobi_rsp_t), + .a_optional_t(a_optional_t), + .r_optional_t(r_optional_t) + ) i_tmr_part ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .req_i(obi_req_i.req[i]), + .gnt_i(gnt_i), + .gnt_o(r_gnt[i]), + .a_we_i(obi_req_i.a.we), + .a_be_i(obi_req_i.a.be), + .a_aid_i(obi_req_i.a.aid), + .a_optional_i(obi_req_i.a.a_optional), + .a_other_ecc_i(obi_req_i.a.other_ecc), + .wdata_rmw(wdata_buffer), + .ldata_rmw(rdata_i), + .wdata_modified(rmw_wdata_tmr[i]), + .use_buffered(use_buffered_tmr[i]), + .req_o(req_o_tmr[i]), + .a_we_o(we[i]), + .a_aid_o(aid[i]), + .other_ecc_d(other_ecc[i]), + .hsiao_errs(hsiao_errs[1+3*i+:3]) + ); + end + + TMR_voter_fail i_we_vote ( + .a_i (we[0]), + .b_i (we[1]), + .c_i (we[2]), + .majority_o (we_o), + .fault_detected_o(voter_errs[2]) + ); + bitwise_TMR_voter_fail #( + .DataWidth( ObiCfg.IdWidth ) + ) i_aid_vote ( + .a_i (aid[0]), + .b_i (aid[1]), + .c_i (aid[2]), + .majority_o (id_d), + .fault_detected_o(voter_errs[3]) + ); + bitwise_TMR_voter_fail #( + .DataWidth( relobi_pkg::relobi_r_other_ecc_width(ObiCfg) ) + ) i_other_ecc_vote ( + .a_i (other_ecc[0]), + .b_i (other_ecc[1]), + .c_i (other_ecc[2]), + .majority_o (other_ecc_d), + .fault_detected_o(voter_errs[4]) + ); + bitwise_TMR_voter_fail #( + .DataWidth( ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth) ) + ) i_wdata_vote ( + .a_i (rmw_wdata_tmr[0]), + .b_i (rmw_wdata_tmr[1]), + .c_i (rmw_wdata_tmr[2]), + .majority_o (rmw_wdata), + .fault_detected_o(voter_errs[5]) + ); + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(!rst_ni) begin + rvalid_q <= 1'b0; + id_q <= '0; + other_ecc_q <= '0; + end else begin + rvalid_q <= rvalid_d; + id_q <= id_d; + other_ecc_q <= other_ecc_d; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(!rst_ni) begin + wdata_buffer <= '0; + addr_buffer <= '0; + end else if (req_o && gnt_i) begin + wdata_buffer <= obi_req_i.a.wdata; + addr_buffer <= obi_req_i.a.addr; + end + end + + +endmodule + +module relobi_sram_shim_tmr_part #( + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + parameter type relobi_req_t = logic, + parameter type relobi_rsp_t = logic, + parameter type a_optional_t = logic, + parameter type r_optional_t = logic +) ( + input logic clk_i, + input logic rst_ni, + input logic req_i, + input logic gnt_i, + output logic gnt_o, + input logic a_we_i, + input logic [ObiCfg.DataWidth/8-1:0] a_be_i, + input logic [ObiCfg.IdWidth-1:0] a_aid_i, + input a_optional_t a_optional_i, + input logic [relobi_pkg::relobi_a_other_ecc_width(ObiCfg)-1:0] a_other_ecc_i, + input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_rmw, + input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] ldata_rmw, + output logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_modified, + output logic use_buffered, + output logic req_o, + output logic a_we_o, + output logic [ObiCfg.IdWidth-1:0] a_aid_o, + output logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_d, + output logic [2:0][1:0] hsiao_errs +); + + typedef enum logic { NORMAL, READ_MODIFY_WRITE } store_state_e; + store_state_e store_state_d, store_state_q; + + logic [ObiCfg.DataWidth/8-1:0] a_be_int, be_buffer; + + logic [ObiCfg.DataWidth-1:0] wdata_rmw_dec, ldata_rmw_dec; + logic [ObiCfg.DataWidth-1:0] be_selector; + logic a_we_int; + + relobi_a_other_decoder #( + .Cfg (ObiCfg), + .a_optional_t (a_optional_t) + ) i_a_other_decoder ( + .we_i (a_we_i), + .be_i (a_be_i), + .aid_i (a_aid_i), + .a_optional_i (a_optional_i), + .other_ecc_i (a_other_ecc_i), + .we_o (a_we_int), + .be_o (a_be_int), + .aid_o (a_aid_o), + .a_optional_o (), + .fault_o (hsiao_errs[0]) + ); + + relobi_r_other_encoder #( + .Cfg(ObiCfg), + .r_optional_t(r_optional_t) + ) i_r_other_enc ( + .rid_i(a_aid_o), + .err_i(1'b0), + .r_optional_i('0), + .other_ecc_o (other_ecc_d) + ); + + for (genvar i = 0; i < ObiCfg.DataWidth/8; i++) begin : gen_be_selector + assign be_selector[i*8 +: 8] = {8{be_buffer[i]}}; + end + + hsiao_ecc_dec #( + .DataWidth ( ObiCfg.DataWidth ) + ) i_wdata_dec ( + .in ( wdata_rmw ), + .out ( wdata_rmw_dec ), + .syndrome_o(), + .err_o (hsiao_errs[1]) + ); + hsiao_ecc_dec #( + .DataWidth ( ObiCfg.DataWidth ) + ) i_rdata_dec ( + .in ( ldata_rmw ), + .out ( ldata_rmw_dec ), + .syndrome_o(), + .err_o (hsiao_errs[2]) + ); + hsiao_ecc_enc #( + .DataWidth ( ObiCfg.DataWidth ) + ) i_wdata_enc ( + .in ( be_selector & wdata_rmw_dec | + (~be_selector & ldata_rmw_dec) ), + .out ( wdata_modified ) + ); + + always_comb begin + req_o = req_i; + gnt_o = gnt_i; + store_state_d = NORMAL; + use_buffered = 1'b0; + a_we_o = a_we_int; + if (store_state_q == NORMAL) begin + if (req_i & (a_be_int != {ObiCfg.DataWidth/8{1'b1}}) & a_we_int) begin + store_state_d = READ_MODIFY_WRITE; + a_we_o = 1'b0; + end + end else begin + req_o = 1'b1; + gnt_o = 1'b0; + a_we_o = 1'b1; + use_buffered = 1'b1; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if(!rst_ni) begin + store_state_q <= NORMAL; + be_buffer <= '0; + end else if (req_o && gnt_i) begin + store_state_q <= store_state_d; // Quick to reload and dependents always voted + be_buffer <= a_be_i; // Quick to reload and always voted with wdata + end + end + + +endmodule From 797324655523e328568ddbf6be1ed73a5d16e2ef Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 4 Aug 2025 20:32:30 +0200 Subject: [PATCH 39/48] Add obi_to_apb module --- Bender.yml | 1 + src/obi_to_apb.sv | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 src/obi_to_apb.sv diff --git a/Bender.yml b/Bender.yml index 989f7da..8adc371 100644 --- a/Bender.yml +++ b/Bender.yml @@ -22,6 +22,7 @@ sources: - src/obi_intf.sv - src/obi_rready_converter.sv - src/apb_to_obi.sv + - src/obi_to_apb.sv # Level 3 - src/obi_atop_resolver.sv - src/obi_cut.sv diff --git a/src/obi_to_apb.sv b/src/obi_to_apb.sv new file mode 100644 index 0000000..651dad1 --- /dev/null +++ b/src/obi_to_apb.sv @@ -0,0 +1,167 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +`include "common_cells/assertions.svh" + +/// An OBI to APB adapter. +module obi_to_apb #( + /// The configuration of the subordinate port (input port). + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The OBI request struct for the subordinate port (input port). + parameter type obi_req_t = logic, + /// The OBI response struct for the subordinate port (input port). + parameter type obi_rsp_t = logic, // OBI response struct + /// The APB request struct for the manager port (output port). + parameter type apb_req_t = logic, // APB request struct + /// The APB response struct for the manager port (output port). + parameter type apb_rsp_t = logic, // APB response struct + /// Disable gnt/rvalid in same cycle. + parameter bit DisableSameCycleRsp = 1'b1 +) ( + input logic clk_i, + input logic rst_ni, + // Subordinate OBI port. + input obi_req_t obi_req_i, + output obi_rsp_t obi_rsp_o, + // Manager APB port. + output apb_req_t apb_req_o, + input apb_rsp_t apb_rsp_i +); + + logic [ObiCfg.AddrWidth-1:0] addr; + logic [ObiCfg.DataWidth-1:0] wdata; + logic we; + logic [ObiCfg.DataWidth/8-1:0] be; + logic [2:0] prot; + + assign apb_req_o.paddr = addr; + assign apb_req_o.pwrite = we; + // OBI expects '1 on writes, APB sets pstrb to '0 on reads. + assign apb_req_o.pstrb = we ? be : '0; + assign apb_req_o.pwdata = wdata; + if (ObiCfg.OptionalCfg.UseProt) begin : gen_pprot + // Bit 2: inverted bit 0 of OBI prot + assign apb_req_o.pprot[2] = ~prot[2]; + // Bit 1: secure access only for machine mode + assign apb_req_o.pprot[1] = ~(prot[1] & prot[0]); + // Bit 0: privileged for machine mode and supervisor mode + assign apb_req_o.pprot[0] = prot[1]; + end else begin : gen_no_pprot + // OBI does not enable prot, so we set it to priviledged, secure, instruction. + assign apb_req_o.pprot = 3'b101; + end + + assign obi_rsp_o.r.rdata = apb_rsp_i.prdata; + assign obi_rsp_o.r.err = apb_rsp_i.pslverr; + assign obi_rsp_o.r.r_optional = '0; // No optional R feature supported at the moment. + + if (DisableSameCycleRsp) begin : gen_hs_buffers + logic tsxn_in_progress; + logic [ObiCfg.IdWidth-1:0] aid_q; + logic [ObiCfg.AddrWidth-1:0] addr_q; + logic [ObiCfg.DataWidth-1:0] wdata_q; + logic we_q; + logic [ObiCfg.DataWidth/8-1:0] be_q; + logic [2:0] prot_q; + + assign apb_req_o.psel = obi_req_i.req | tsxn_in_progress; + assign apb_req_o.penable = tsxn_in_progress; + assign obi_rsp_o.gnt = ~tsxn_in_progress; + assign obi_rsp_o.rvalid = apb_rsp_i.pready & tsxn_in_progress; + // Mirror AID to RID + assign obi_rsp_o.r.rid = aid_q; + + assign addr = tsxn_in_progress ? addr_q : obi_req_i.a.addr; + assign wdata = tsxn_in_progress ? wdata_q : obi_req_i.a.wdata; + assign we = tsxn_in_progress ? we_q : obi_req_i.a.we; + assign be = tsxn_in_progress ? be_q : obi_req_i.a.be; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + tsxn_in_progress <= 1'b0; + aid_q <= '0; + addr_q <= '0; + wdata_q <= '0; + we_q <= 1'b0; + be_q <= '0; + end else begin + tsxn_in_progress <= apb_req_o.psel & ~apb_rsp_i.pready; + if (obi_req_i.req & obi_rsp_o.gnt) begin + aid_q <= obi_req_i.a.aid; + addr_q <= obi_req_i.a.addr; + wdata_q <= obi_req_i.a.wdata; + we_q <= obi_req_i.a.we; + be_q <= obi_req_i.a.be; + end + end + end + if (ObiCfg.OptionalCfg.UseProt) begin : gen_prot + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + prot <= 3'b101; // Privileged, secure, instruction. + end else if (obi_req_i.req & obi_rsp_o.gnt) begin + prot <= obi_req_i.a.a_optional.prot; + end + end + end else begin : gen_no_prot + assign prot = 3'b101; // Privileged, secure, instruction. + end + + end else begin : gen_no_hs_buffers + logic psel_q; + assign apb_req_o.psel = obi_req_i.req; + assign apb_req_o.penable = psel_q; + assign obi_rsp_o.gnt = apb_rsp_i.pready; + assign obi_rsp_o.rvalid = apb_rsp_i.pready; + // Mirror AID to RID + assign obi_rsp_o.r.rid = obi_req_i.a.aid; + assign addr = obi_req_i.a.addr; + assign wdata = obi_req_i.a.wdata; + assign we = obi_req_i.a.we; + assign be = obi_req_i.a.be; + if (ObiCfg.OptionalCfg.UseProt) begin : gen_prot + assign prot = obi_req_i.a.a_optional.prot; + end else begin : gen_no_prot + assign prot = 3'b101; // Privileged, secure, instruction. + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + psel_q <= 1'b0; + end else begin + psel_q <= obi_req_i.req & ~apb_rsp_i.pready; + end + end + end + + + // ---------- + // Assertions + // ---------- + + `ASSERT_INIT(no_rready, ObiCfg.UseRReady == 0, + "RReady not supported in OBI to APB conversion") + `ASSERT_INIT(no_atop, ObiCfg.OptionalCfg.UseAtop == 0, + "ATOP not supported in OBI to APB conversion") + `ASSERT_INIT(no_memtype, ObiCfg.OptionalCfg.UseMemtype == 0, + "Memtype not supported in OBI to APB conversion") + `ASSERT_INIT(no_debug, ObiCfg.OptionalCfg.UseDbg == 0, + "Debug not supported in OBI to APB conversion") + `ASSERT_INIT(no_integrity, !ObiCfg.Integrity, + "Integrity not supported!") + `ASSERT_INIT(no_achk, ObiCfg.OptionalCfg.AChkWidth == 0, + "ACHK field not supported!") + `ASSERT_INIT(equal_wdata_width, $bits(apb_req_o.pwdata) == $bits(obi_req_i.a.wdata), + "WDATA width mismatch between APB and OBI ports!") + `ASSERT_INIT(equal_be_width, $bits(apb_req_o.pstrb) == $bits(obi_req_i.a.be), + "Strobe width mismatch between APB and OBI ports!") + `ASSERT_INIT(equal_rdata_width, $bits(apb_rsp_i.prdata) == $bits(obi_rsp_o.r.rdata), + "RDATA width mismatch between APB and OBI ports!") + `ASSERT_INIT(equal_addr_width, $bits(apb_req_o.paddr) == $bits(obi_req_i.a.addr), + "Address width mismatch between APB and OBI ports!") + + +endmodule From b0664ff6f767bcc43c0e7255105f435de899d3df Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 5 Aug 2025 21:21:54 +0200 Subject: [PATCH 40/48] Fix relobi_err_sbr --- src/relobi_err_sbr.sv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/relobi_err_sbr.sv b/src/relobi_err_sbr.sv index c3143f8..5065c80 100644 --- a/src/relobi_err_sbr.sv +++ b/src/relobi_err_sbr.sv @@ -126,14 +126,14 @@ module relobi_err_sbr #( .fault_o (hsiao_errs[3]) ); end else begin : gen_no_rready_fifo - assign fifo_full = 1'b0; - assign fifo_pop = 1'b0; + assign fifo_full = '0; + assign fifo_pop = '0; assign hsiao_errs[3] = '0; always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin rid_q <= '0; other_ecc_q <= '0; - fifo_empty <= 1'b1; + fifo_empty <= '1; end else begin rid_q <= rid_d; other_ecc_q <= other_ecc_d; From 558594f7e92ff03f071f84836c08c75d166978f0 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 11 Aug 2025 18:26:48 +0200 Subject: [PATCH 41/48] Bump redundancy_cells --- Bender.lock | 2 +- Bender.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bender.lock b/Bender.lock index 85d2289..e6e15a5 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 69468c8f8503d603bbcd6971607c7896104b8519 + revision: 3c7c57e80fe2f65812db092182ce68ee810943df version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index 8adc371..f5b742a 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 69468c8f8503d603bbcd6971607c7896104b8519 } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 3c7c57e80fe2f65812db092182ce68ee810943df } export_include_dirs: - include From ea32b1604e9b98f86d9cb0403538d8d040736521 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 11 Aug 2025 21:50:26 +0200 Subject: [PATCH 42/48] Fix CI --- Makefile | 2 +- src/relobi_err_sbr.sv | 4 ++-- src/relobi_mux.sv | 19 +++++++++++-------- src/relobi_sram_shim.sv | 2 +- src/relobi_xbar.sv | 7 ++++--- src/test/tb_relobi_xbar.sv | 4 ++-- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 1118fa5..3799eb1 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ $(TBS_VSIM): build_vsim ifdef gui $(VSIM) $(patsubst %_vsim, %, $@) -voptargs="+acc" else - $(VSIM) -c $(patsubst %_vsim, %, $@) -do "run -all; quit -f" + $(VSIM) -c $(patsubst %_vsim, %, $@) -voptargs="+acc" -do "run -all; quit -f" endif .PHONY: all_vsim diff --git a/src/relobi_err_sbr.sv b/src/relobi_err_sbr.sv index 5065c80..13d175c 100644 --- a/src/relobi_err_sbr.sv +++ b/src/relobi_err_sbr.sv @@ -68,7 +68,7 @@ module relobi_err_sbr #( .rid_o(rid_tmr[i]), .other_ecc_o(other_ecc_tmr[i]), - + .fault_o(hsiao_errs[i]) ); end @@ -158,7 +158,7 @@ module relobi_err_sbr_tmr_part #( output logic [ObiCfg.IdWidth -1:0] rid_o, output logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_o, - + output logic [1:0] fault_o ); diff --git a/src/relobi_mux.sv b/src/relobi_mux.sv index ac2e2e8..02d3180 100644 --- a/src/relobi_mux.sv +++ b/src/relobi_mux.sv @@ -135,7 +135,8 @@ module relobi_mux #( .selected_id ( selected_id[i] ), .mgr_port_a_tmr ( mgr_port_a_tmr[i] ), - .mgr_port_rsp_r ( UseIdForRouting || MgrPortObiCfg.IdWidth != SbrPortObiCfg.IdWidth ? mgr_port_rsp_i.r : '0 ), + .mgr_port_rsp_r ( UseIdForRouting || MgrPortObiCfg.IdWidth != SbrPortObiCfg.IdWidth ? + mgr_port_rsp_i.r : '0 ), .mgr_port_rsp_rvalid( UseIdForRouting ? mgr_port_rsp_i.rvalid[i] : '0 ), .selected_id_tmr_three ( selected_id_tmr_three[i] ), .response_id_encoded( UseIdForRouting ? '0 : response_id_encoded ), @@ -182,7 +183,7 @@ module relobi_mux #( if (MgrPortObiCfg.IdWidth == SbrPortObiCfg.IdWidth) begin : gen_aid_identical assign mgr_port_req_o.a = mgr_port_a_in_sbr; assign voter_faults[1] = '0; - end else begin + end else begin : gen_aid_vote bitwise_TMR_voter_fail #( .DataWidth ( $bits(mgr_port_a_chan_t) ), .VoterType ( 1 ) @@ -250,12 +251,12 @@ module relobi_mux #( if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect assign mgr_port_req_o.rready = mgr_req_rready; - for (genvar i = 0; i < NumSbrPorts; i++) begin + for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_sbr_ports_rready for (genvar j = 0; j < 3; j++) begin : gen_sbr_req_rready assign sbr_req_rready[j][i] = sbr_ports_req_i[i].rready[j]; end - end - end else begin + end + end else begin : gen_rready_tie assign sbr_req_rready = '1; end sbr_port_r_chan_t [NumSbrPorts-1:0] sbr_rsp_r; @@ -336,8 +337,10 @@ module relobi_mux_tmr_part #( // Only if UseIdForRouting is true input logic mgr_port_rsp_rvalid, // Only if UseIdForRouting is false - output logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three, - input logic [RequiredExtraIdWidth + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] response_id_encoded, + output logic [RequiredExtraIdWidth+ + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] selected_id_tmr_three, + input logic [RequiredExtraIdWidth+ + hsiao_ecc_pkg::min_ecc(RequiredExtraIdWidth)-1:0] response_id_encoded, input logic fifo_pop, output sbr_port_r_chan_t sbr_r_tmr, @@ -461,7 +464,7 @@ module relobi_mux_tmr_part #( end if (MgrPortObiCfg.UseRReady) begin : gen_rready_connect assign mgr_req_rready = sbr_req_rready[response_id]; - end else begin + end else begin : gen_rready_tie assign mgr_req_rready = '1; end diff --git a/src/relobi_sram_shim.sv b/src/relobi_sram_shim.sv index 5e8ceb4..71346c4 100644 --- a/src/relobi_sram_shim.sv +++ b/src/relobi_sram_shim.sv @@ -108,7 +108,7 @@ module relobi_sram_shim #( .err_o (hsiao_errs[0]) ); - for (genvar i = 0; i < 3; i++) begin : tmr_part + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part relobi_sram_shim_tmr_part #( .ObiCfg(ObiCfg), .relobi_req_t(relobi_req_t), diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index a0b37c5..fe5353a 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -77,7 +77,8 @@ module relobi_xbar #( assign fault_o[1] = |faults_transpose[1]; logic [2:0][NumSbrPorts-1:0][$clog2(NumMgrPorts)-1:0] sbr_port_select; - logic [NumSbrPorts-1:0][ MgrPortObiCfg.AddrWidth + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth) - 1:0] addr_input; + logic [NumSbrPorts-1:0][MgrPortObiCfg.AddrWidth+ + hsiao_ecc_pkg::min_ecc(MgrPortObiCfg.AddrWidth)-1:0] addr_input; logic [2:0][NumSbrPorts-1:0] decode_abort; @@ -110,7 +111,7 @@ module relobi_xbar #( end for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_demux - + assign addr_input[i] = sbr_ports_req_i[i].a.addr; relobi_demux #( @@ -133,7 +134,7 @@ module relobi_xbar #( .fault_o ( faults[3*NumSbrPorts+i] ) ); - for (genvar j = 0; j < NumMgrPorts; j++) begin : sbr_reqs_abort_inner + for (genvar j = 0; j < NumMgrPorts; j++) begin : gen_sbr_reqs_abort_inner assign sbr_reqs_aborted[i][j].a = sbr_reqs[i][j].a; assign sbr_rsps_aborted[i][j].r = sbr_rsps[i][j].r; assign sbr_rsps_aborted[i][j].rvalid = sbr_rsps[i][j].rvalid; diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index 77519ba..b399c06 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -230,11 +230,11 @@ module relobi_xbar_dut_wrapper #( logic [NumSubordinates-1:0] sbr_data_valid; logic [NumManagers-1:0] mgr_data_valid; - for (genvar i = 0; i < NumSubordinates; i++) begin + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_data_valid assign sbr_data_valid[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt; assign sbr_error[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt & ~(|sbr_mgr_match[i]); end - for (genvar i = 0; i < NumManagers; i++) begin + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_data_valid assign mgr_data_valid[i] = mgr_bus_rsp[i].rvalid; assign mgr_error[i] = mgr_bus_rsp[i].rvalid & ~(|mgr_sbr_match[i]); end From f2dc6d64b6bde983da40ae700fae9c52aaa404ca Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 9 Sep 2025 15:19:24 +0200 Subject: [PATCH 43/48] update for relOBI testing --- src/relobi_cut.sv | 6 +- src/relobi_xbar.sv | 2 +- src/test/tb_obi_xbar.sv | 391 ++++++++++++++++++++++++++++++++++--- src/test/tb_relobi_xbar.sv | 121 +++++++++--- 4 files changed, 467 insertions(+), 53 deletions(-) diff --git a/src/relobi_cut.sv b/src/relobi_cut.sv index 93879a4..33acd16 100644 --- a/src/relobi_cut.sv +++ b/src/relobi_cut.sv @@ -68,7 +68,8 @@ module relobi_cut #( rel_spill_register #( .T ( obi_a_chan_t ), .Bypass ( BypassReq ), - .TmrHandshake ( 1'b1 ) + .TmrHandshake ( 1'b1 ), + .DataCorrector ( 1'b1 ) ) i_reg_a ( .clk_i, .rst_ni, @@ -87,7 +88,8 @@ module relobi_cut #( rel_spill_register #( .T ( obi_r_chan_t ), .Bypass ( BypassRsp ), - .TmrHandshake ( 1'b1 ) + .TmrHandshake ( 1'b1 ), + .DataCorrector ( 1'b1 ) ) i_reg_r ( .clk_i, .rst_ni, diff --git a/src/relobi_xbar.sv b/src/relobi_xbar.sv index fe5353a..3bcf38f 100644 --- a/src/relobi_xbar.sv +++ b/src/relobi_xbar.sv @@ -253,7 +253,7 @@ module relobi_xbar_tmr_part #( if (DecodeAbort) begin : gen_decode_abort for (genvar i = 0; i < NumSbrPorts; i++) begin : gen_addr assign addr[i] = addr_i[i][AddrWidth-1:0]; - assign decode_abort_o[i] = faults[i][0] | faults[i][1]; + assign decode_abort_o[i] = faults[i][0];// | faults[i][1]; end end else begin : gen_no_decode_abort assign addr = addr_dec; diff --git a/src/test/tb_obi_xbar.sv b/src/test/tb_obi_xbar.sv index bf5f9ad..95e4df0 100644 --- a/src/test/tb_obi_xbar.sv +++ b/src/test/tb_obi_xbar.sv @@ -7,6 +7,315 @@ `include "obi/typedef.svh" `include "obi/assign.svh" +module obi_xbar_dut_wrapper #( + parameter int unsigned NumManagers = 32'd6, + parameter int unsigned NumSubordinates = 32'd8, + parameter obi_pkg::obi_cfg_t MgrConfig = obi_pkg::ObiDefaultConfig, + parameter obi_pkg::obi_cfg_t SbrConfig = obi_pkg::ObiDefaultConfig, + parameter type mgr_bus_req_t = logic, + parameter type mgr_bus_rsp_t = logic, + parameter type sbr_bus_req_t = logic, + parameter type sbr_bus_rsp_t = logic, + parameter type mgr_bus_a_chan_t = logic, + parameter type mgr_bus_r_chan_t = logic, + parameter type sbr_bus_a_chan_t = logic, + parameter type sbr_bus_r_chan_t = logic, + parameter type mgr_a_optional_t = logic, + parameter type mgr_r_optional_t = logic, + parameter type sbr_a_optional_t = logic, + parameter type sbr_r_optional_t = logic, + parameter int unsigned NumMaxTrans = 32'd8, + parameter int unsigned NumRules = 8, + parameter type rule_t = logic, + parameter rule_t [NumRules-1:0] AddrMap = '0, + parameter bit UseIdForRouting = 1'b0, + parameter time TestTime = 8ns, + parameter int unsigned NumRequests = 1 + +) ( + input logic clk, + input logic rst_n, + + // Manager ports + input mgr_bus_req_t [NumManagers-1:0] mgr_bus_req, + output mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp, + + // Subordinate ports + output sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req, + input sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp, + + input logic [NumManagers-1:0] end_of_sim +); + + localparam int unsigned MgrBusReqBits = $bits(mgr_bus_req_t); + localparam int unsigned MgrBusRspBits = $bits(mgr_bus_rsp_t); + localparam int unsigned SbrBusReqBits = $bits(sbr_bus_req_t); + localparam int unsigned SbrBusRspBits = $bits(sbr_bus_rsp_t); + + mgr_bus_req_t [NumManagers-1:0] mgr_bus_req_cut; + mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp_cut; + sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req_cut; + sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp_cut; + + logic [NumManagers-1:0][MgrBusRspBits-1:0] mgr_bus_rsp_flat; + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_bus_rsp + assign mgr_bus_rsp_flat[i] = mgr_bus_rsp[i]; + end + + logic [NumSubordinates-1:0][SbrBusReqBits-1:0] sbr_bus_req_flat; + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_bus_req + assign sbr_bus_req_flat[i] = sbr_bus_req[i]; + end + + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_cut + obi_cut #( + .ObiCfg ( MgrConfig ), + .obi_req_t ( mgr_bus_req_t ), + .obi_rsp_t ( mgr_bus_rsp_t ), + .obi_a_chan_t ( mgr_bus_a_chan_t ), + .obi_r_chan_t ( mgr_bus_r_chan_t ), + .Bypass ( 1'b0 ) + ) i_cut_mgr ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .sbr_port_req_i ( mgr_bus_req[i] ), + .sbr_port_rsp_o ( mgr_bus_rsp[i] ), + + .mgr_port_req_o ( mgr_bus_req_cut[i] ), + .mgr_port_rsp_i ( mgr_bus_rsp_cut[i] ) + ); + end + + // DUT + obi_xbar #( + .SbrPortObiCfg ( MgrConfig ), + .sbr_port_obi_req_t ( mgr_bus_req_t ), + .sbr_port_obi_rsp_t ( mgr_bus_rsp_t ), + .sbr_port_a_chan_t ( mgr_bus_a_chan_t ), + .sbr_port_r_chan_t ( mgr_bus_r_chan_t ), + .MgrPortObiCfg ( SbrConfig ), + .mgr_port_obi_req_t ( sbr_bus_req_t ), + .mgr_port_obi_rsp_t ( sbr_bus_rsp_t ), + .NumSbrPorts ( NumManagers ), + .NumMgrPorts ( NumSubordinates ), + .NumMaxTrans ( NumMaxTrans ), + .NumAddrRules ( NumRules ), + .addr_map_rule_t ( rule_t ), + .UseIdForRouting ( UseIdForRouting ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .testmode_i ( 1'b0 ), + .sbr_ports_req_i ( mgr_bus_req_cut ), + .sbr_ports_rsp_o ( mgr_bus_rsp_cut ), + .mgr_ports_req_o ( sbr_bus_req_cut ), + .mgr_ports_rsp_i ( sbr_bus_rsp_cut ), + .addr_map_i ( AddrMap ), + .en_default_idx_i ( '0 ), + .default_idx_i ( '0 ) + ); + + + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_cut + obi_cut #( + .ObiCfg ( SbrConfig ), + .obi_req_t ( sbr_bus_req_t ), + .obi_rsp_t ( sbr_bus_rsp_t ), + .obi_a_chan_t ( sbr_bus_a_chan_t ), + .obi_r_chan_t ( sbr_bus_r_chan_t ), + .Bypass ( 1'b0 ) + ) i_cut_sbr ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + + .sbr_port_req_i ( sbr_bus_req_cut[i] ), + .sbr_port_rsp_o ( sbr_bus_rsp_cut[i] ), + + .mgr_port_req_o ( sbr_bus_req[i] ), + .mgr_port_rsp_i ( sbr_bus_rsp[i] ) + ); + end + + + logic interface_error; + logic [NumSubordinates-1:0] sbr_error; + logic [NumManagers-1:0] mgr_error; + assign interface_error = |sbr_error | |mgr_error; + + // Collect sent requests and responses + localparam int unsigned NumMABits = $bits(mgr_bus_a_chan_t); + localparam int unsigned NumMRBits = $bits(mgr_bus_r_chan_t); + localparam int unsigned NumSABits = $bits(sbr_bus_a_chan_t); + localparam int unsigned NumSRBits = $bits(sbr_bus_r_chan_t); + // logic [NumMABits-1:0] mgr_bus_a_chan_flat [NumManagers][NumSubordinates][$]; + logic mgr_bus_a_chan_flat_empty [NumManagers][NumSubordinates]; + logic [NumManagers-1:0][NumSubordinates-1:0] mgr_bus_a_chan_flat_pop; + logic [NumMABits-1:0] mgr_bus_a_chan_flat_front [NumManagers][NumSubordinates]; + // logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx [NumManagers][$]; + logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx_front [NumManagers]; + logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx_next [NumManagers]; + logic [NumManagers-1:0] mgr_bus_rsp_idx_push; + // logic [NumSRBits-1:0] sbr_bus_r_chan_flat [NumSubordinates][$]; + logic [NumSRBits-1:0] sbr_bus_r_chan_flat_front [NumSubordinates]; + logic [NumSubordinates-1:0] sbr_bus_r_chan_flat_pop; + logic [NumSubordinates-1:0][NumManagers-1:0] sbr_mgr_match; + logic [NumManagers-1:0][NumSubordinates-1:0] mgr_sbr_match; + + logic [NumSubordinates-1:0] sbr_data_valid; + logic [NumManagers-1:0] mgr_data_valid; + for (genvar i = 0; i < NumSubordinates; i++) begin + assign sbr_data_valid[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt; + assign sbr_error[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt & ~(|sbr_mgr_match[i]); + end + for (genvar i = 0; i < NumManagers; i++) begin + assign mgr_data_valid[i] = mgr_bus_rsp[i].rvalid; + assign mgr_error[i] = mgr_bus_rsp[i].rvalid & ~(|mgr_sbr_match[i]); + end + + for (genvar i = 0; i < NumManagers; i++) begin + for (genvar j = 0; j < NumSubordinates; j++) begin + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH (NumMABits), + .DEPTH (NumMaxTrans) + ) i_fifo_mgr_a_chan ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (mgr_bus_a_chan_flat_empty[i][j]), + .usage_o (), + .data_i (mgr_bus_req[i].a), + .push_i (mgr_bus_req[i].req && mgr_bus_rsp[i].gnt && + mgr_bus_req[i].a.addr >= AddrMap[j].start_addr && + mgr_bus_req[i].a.addr < AddrMap[j].end_addr), + .data_o (mgr_bus_a_chan_flat_front[i][j]), + .pop_i (mgr_bus_a_chan_flat_pop[i][j]) + ); + end + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH ($clog2(NumSubordinates)), + .DEPTH (NumMaxTrans) + ) i_fifo_mgr_idx ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (), + .usage_o (), + .data_i (mgr_bus_rsp_idx_next[i]), + .push_i (mgr_bus_rsp_idx_push[i]), + .data_o (mgr_bus_rsp_idx_front[i]), + .pop_i (mgr_bus_rsp[i].rvalid) + ); + end + for (genvar i = 0; i < NumSubordinates; i++) begin + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH (NumSRBits), + .DEPTH (NumMaxTrans*NumManagers) + ) i_fifo_sbr_r_chan ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (), + .usage_o (), + .data_i (sbr_bus_rsp[i].r), + .push_i (sbr_bus_rsp[i].rvalid), + .data_o (sbr_bus_r_chan_flat_front[i]), + .pop_i (sbr_bus_r_chan_flat_pop[i]) + ); + end + + always_comb begin + for (int unsigned i = 0; i < NumSubordinates; i++) begin + for (int unsigned j = 0; j < NumManagers; j++) begin + if (sbr_bus_req[i].req && sbr_bus_rsp[i].gnt) begin + if (mgr_bus_a_chan_flat_empty[j][i]) begin + sbr_mgr_match[i][j] = 1'b0; + end else begin + sbr_mgr_match[i][j] = mgr_bus_a_chan_flat_front[j][i] == sbr_bus_req[i].a; + end + end else begin + sbr_mgr_match[i][j] = 1'b0; + end + end + end + for (int unsigned i = 0; i < NumManagers; i++) begin + if (mgr_bus_rsp[i].rvalid) begin + mgr_sbr_match[i] = sbr_bus_r_chan_flat_front[mgr_bus_rsp_idx_front[i]] == mgr_bus_rsp[i].r; + end else begin + mgr_sbr_match[i] = '0; + end + end + end + + always_comb begin + mgr_bus_a_chan_flat_pop = '0; + mgr_bus_rsp_idx_push = '0; + sbr_bus_r_chan_flat_pop = '0; + for (int unsigned i = 0; i < NumManagers; i++) begin + for (int unsigned j = 0; j < NumSubordinates; j++) begin + if (mgr_bus_req[i].req && mgr_bus_rsp[i].gnt && + mgr_bus_req[i].a.addr >= AddrMap[j].start_addr && + mgr_bus_req[i].a.addr < AddrMap[j].end_addr) begin + // mgr_bus_a_chan_flat[i][j].push_back(mgr_bus_req[i].a); + mgr_bus_rsp_idx_next[i] = j; + mgr_bus_rsp_idx_push[i] = 1'b1; + // mgr_bus_rsp_idx[i].push_back(j); + end + end + if (mgr_bus_rsp[i].rvalid) begin + sbr_bus_r_chan_flat_pop[mgr_bus_rsp_idx_front[i]] = 1'b1; + // sbr_bus_r_chan_flat[mgr_bus_rsp_idx[i][0]].pop_front(); + // mgr_bus_rsp_idx[i].pop_front(); + end + end + for (int unsigned i = 0; i < NumSubordinates; i++) begin + if (sbr_bus_req[i].req && sbr_bus_rsp[i].gnt) begin + for (int unsigned j = 0; j < NumManagers; j++) begin + if (mgr_bus_a_chan_flat_front[j][i] == sbr_bus_req[i].a) begin + // mgr_bus_a_chan_flat[j][i].pop_front(); + mgr_bus_a_chan_flat_pop[j][i] = 1'b1; + break; + end + end + end + // if (sbr_bus_rsp[i].rvalid) begin + // sbr_bus_r_chan_flat[i].push_back(sbr_bus_rsp[i].r); + // end + end + + // for (int unsigned i = 0; i < NumManagers; i++) begin + // mgr_bus_rsp_idx_front[i] = mgr_bus_rsp_idx[i][0]; + // for (int unsigned j = 0; j < NumSubordinates; j++) begin + // mgr_bus_a_chan_flat_empty[i][j] = (mgr_bus_a_chan_flat[i][j].size() == 0); + // mgr_bus_a_chan_flat_front[i][j] = mgr_bus_a_chan_flat[i][j][0]; + // end + // end + // for (int unsigned i = 0; i < NumSubordinates; i++) begin + // sbr_bus_r_chan_flat_front[i] = sbr_bus_r_chan_flat[i][0]; + // end + end + + // Fault indication + logic corrected_fault; + logic uncorrectable_fault; + assign corrected_fault = '0; + assign uncorrectable_fault = 1'b1; + + `ifdef TARGET_ZOIX + `include "strobe.sv" + `endif + +endmodule + module tb_obi_xbar; localparam int unsigned NumManagers = 32'd6; @@ -17,14 +326,14 @@ module tb_obi_xbar; localparam int unsigned AddrWidth = 32; localparam int unsigned DataWidth = 32; localparam int unsigned MgrIdWidth = 5; - localparam int unsigned SbrIdWidth = MgrIdWidth+cf_math_pkg::idx_width(NumManagers); + localparam int unsigned SbrIdWidth = MgrIdWidth; localparam int unsigned AUserWidth = 4; localparam int unsigned WUserWidth = 2; localparam int unsigned RUserWidth = 3; // TODO CHK! - localparam int unsigned NumRequests = 32'd10000; + localparam int unsigned NumRequests = 32'd1000; localparam time CyclTime = 10ns; localparam time ApplTime = 2ns; @@ -60,7 +369,7 @@ module tb_obi_xbar; .TA ( ApplTime ), .TT ( TestTime ), .MinAddr (32'h0000_0000), - .MaxAddr (32'h0001_3000) + .MaxAddr (32'h0001_1000) ) rand_manager_t; localparam obi_pkg::obi_cfg_t SbrConfig = '{ @@ -199,30 +508,62 @@ module tb_obi_xbar; ); // DUT - obi_xbar_intf #( - .SbrPortObiCfg ( MgrConfig ), - .sbr_port_a_optional_t (mgr_a_optional_t), - .sbr_port_r_optional_t (mgr_r_optional_t), - .MgrPortObiCfg ( SbrConfig ), - .mgr_port_a_optional_t (sbr_a_optional_t), - .mgr_port_r_optional_t (sbr_r_optional_t), - .NumSbrPorts ( NumManagers ), - .NumMgrPorts ( NumSubordinates ), - .NumMaxTrans ( NumMaxTrans ), - .NumAddrRules ( NumRules ), - .addr_map_rule_t ( rule_t ), - .UseIdForRouting ( UseIdForRouting ) - ) i_dut ( - .clk_i ( clk ), - .rst_ni ( rst_n ), - .testmode_i ( 1'b0 ), - .sbr_ports ( mgr_bus ), - .mgr_ports ( sbr_bus ), - .addr_map_i ( AddrMap ), - .en_default_idx_i ( '0 ), - .default_idx_i ( '0 ) + `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(mgr_bus, MgrConfig, mgr_a_optional_t, mgr_r_optional_t) + `OBI_TYPEDEF_ALL_DEFAULT_WITH_OPTIONAL(sbr_bus, SbrConfig, sbr_a_optional_t, sbr_r_optional_t) + mgr_bus_req_t [NumManagers-1:0] mgr_bus_req; + mgr_bus_rsp_t [NumManagers-1:0] mgr_bus_rsp; + sbr_bus_req_t [NumSubordinates-1:0] sbr_bus_req; + sbr_bus_rsp_t [NumSubordinates-1:0] sbr_bus_rsp; + + for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_encode + `OBI_ASSIGN_TO_REQ(mgr_bus_req[i], mgr_bus[i], MgrConfig) + `OBI_ASSIGN_FROM_RSP(mgr_bus[i], mgr_bus_rsp[i], MgrConfig) + end + + obi_xbar_dut_wrapper #( + .NumManagers(NumManagers), + .NumSubordinates(NumSubordinates), + .MgrConfig(MgrConfig), + .SbrConfig(SbrConfig), + .mgr_bus_req_t(mgr_bus_req_t), + .mgr_bus_rsp_t(mgr_bus_rsp_t), + .sbr_bus_req_t(sbr_bus_req_t), + .sbr_bus_rsp_t(sbr_bus_rsp_t), + .mgr_bus_a_chan_t(mgr_bus_a_chan_t), + .mgr_bus_r_chan_t(mgr_bus_r_chan_t), + .sbr_bus_a_chan_t(sbr_bus_a_chan_t), + .sbr_bus_r_chan_t(sbr_bus_r_chan_t), + .mgr_a_optional_t(mgr_a_optional_t), + .mgr_r_optional_t(mgr_r_optional_t), + .sbr_a_optional_t(sbr_a_optional_t), + .sbr_r_optional_t(sbr_r_optional_t), + .NumMaxTrans(NumMaxTrans), + .NumRules(NumRules), + .rule_t(rule_t), + .AddrMap(AddrMap), + .UseIdForRouting(UseIdForRouting), + .TestTime(TestTime), + .NumRequests(NumRequests) + ) i_dut_wrapper ( + .clk, + .rst_n, + + // Manager ports + .mgr_bus_req, + .mgr_bus_rsp, + + // Subordinate ports + .sbr_bus_req, + .sbr_bus_rsp, + + .end_of_sim(end_of_sim) ); + for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_decode + `OBI_ASSIGN_FROM_REQ(sbr_bus[i], sbr_bus_req[i], SbrConfig) + `OBI_ASSIGN_TO_RSP(sbr_bus_rsp[i], sbr_bus[i], SbrConfig) + end + initial begin wait(&end_of_sim); repeat (1000) @(posedge clk); diff --git a/src/test/tb_relobi_xbar.sv b/src/test/tb_relobi_xbar.sv index b399c06..9e2e723 100644 --- a/src/test/tb_relobi_xbar.sv +++ b/src/test/tb_relobi_xbar.sv @@ -218,27 +218,91 @@ module relobi_xbar_dut_wrapper #( localparam int unsigned NumMRBits = $bits(mgr_bus_r_chan_t); localparam int unsigned NumSABits = $bits(sbr_bus_a_chan_t); localparam int unsigned NumSRBits = $bits(sbr_bus_r_chan_t); - logic [NumMABits-1:0] mgr_bus_a_chan_flat [NumManagers][NumSubordinates][$]; + // logic [NumMABits-1:0] mgr_bus_a_chan_flat [NumManagers][NumSubordinates][$]; logic mgr_bus_a_chan_flat_empty [NumManagers][NumSubordinates]; + logic [NumManagers-1:0][NumSubordinates-1:0] mgr_bus_a_chan_flat_pop; logic [NumMABits-1:0] mgr_bus_a_chan_flat_front [NumManagers][NumSubordinates]; - logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx [NumManagers][$]; + // logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx [NumManagers][$]; logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx_front [NumManagers]; - logic [NumSRBits-1:0] sbr_bus_r_chan_flat [NumSubordinates][$]; + logic [$clog2(NumSubordinates)-1:0] mgr_bus_rsp_idx_next [NumManagers]; + logic [NumManagers-1:0] mgr_bus_rsp_idx_push; + // logic [NumSRBits-1:0] sbr_bus_r_chan_flat [NumSubordinates][$]; logic [NumSRBits-1:0] sbr_bus_r_chan_flat_front [NumSubordinates]; + logic [NumSubordinates-1:0] sbr_bus_r_chan_flat_pop; logic [NumSubordinates-1:0][NumManagers-1:0] sbr_mgr_match; logic [NumManagers-1:0][NumSubordinates-1:0] mgr_sbr_match; logic [NumSubordinates-1:0] sbr_data_valid; logic [NumManagers-1:0] mgr_data_valid; - for (genvar i = 0; i < NumSubordinates; i++) begin : gen_sbr_data_valid + for (genvar i = 0; i < NumSubordinates; i++) begin assign sbr_data_valid[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt; assign sbr_error[i] = sbr_bus_req[i].req & sbr_bus_rsp[i].gnt & ~(|sbr_mgr_match[i]); end - for (genvar i = 0; i < NumManagers; i++) begin : gen_mgr_data_valid + for (genvar i = 0; i < NumManagers; i++) begin assign mgr_data_valid[i] = mgr_bus_rsp[i].rvalid; assign mgr_error[i] = mgr_bus_rsp[i].rvalid & ~(|mgr_sbr_match[i]); end + for (genvar i = 0; i < NumManagers; i++) begin + for (genvar j = 0; j < NumSubordinates; j++) begin + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH (NumMABits), + .DEPTH (NumMaxTrans) + ) i_fifo_mgr_a_chan ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (mgr_bus_a_chan_flat_empty[i][j]), + .usage_o (), + .data_i (mgr_bus_req[i].a), + .push_i (mgr_bus_req[i].req && mgr_bus_rsp[i].gnt && + mgr_bus_req[i].a.addr >= AddrMap[j].start_addr && + mgr_bus_req[i].a.addr < AddrMap[j].end_addr), + .data_o (mgr_bus_a_chan_flat_front[i][j]), + .pop_i (mgr_bus_a_chan_flat_pop[i][j]) + ); + end + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH ($clog2(NumSubordinates)), + .DEPTH (NumMaxTrans) + ) i_fifo_mgr_idx ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (), + .usage_o (), + .data_i (mgr_bus_rsp_idx_next[i]), + .push_i (mgr_bus_rsp_idx_push[i]), + .data_o (mgr_bus_rsp_idx_front[i]), + .pop_i (mgr_bus_rsp[i].rvalid) + ); + end + for (genvar i = 0; i < NumSubordinates; i++) begin + fifo_v3 #( + .FALL_THROUGH (1'b0), + .DATA_WIDTH (NumSRBits), + .DEPTH (NumMaxTrans*NumManagers) + ) i_fifo_sbr_r_chan ( + .clk_i (clk), + .rst_ni (rst_n), + .flush_i (1'b0), + .testmode_i (1'b0), + .full_o (), + .empty_o (), + .usage_o (), + .data_i (sbr_bus_rsp[i].r), + .push_i (sbr_bus_rsp[i].rvalid), + .data_o (sbr_bus_r_chan_flat_front[i]), + .pop_i (sbr_bus_r_chan_flat_pop[i]) + ); + end + always_comb begin for (int unsigned i = 0; i < NumSubordinates; i++) begin for (int unsigned j = 0; j < NumManagers; j++) begin @@ -262,45 +326,52 @@ module relobi_xbar_dut_wrapper #( end end - always @(posedge clk) begin + always_comb begin + mgr_bus_a_chan_flat_pop = '0; + mgr_bus_rsp_idx_push = '0; + sbr_bus_r_chan_flat_pop = '0; for (int unsigned i = 0; i < NumManagers; i++) begin for (int unsigned j = 0; j < NumSubordinates; j++) begin if (mgr_bus_req[i].req && mgr_bus_rsp[i].gnt && mgr_bus_req[i].a.addr >= AddrMap[j].start_addr && mgr_bus_req[i].a.addr < AddrMap[j].end_addr) begin - mgr_bus_a_chan_flat[i][j].push_back(mgr_bus_req[i].a); - mgr_bus_rsp_idx[i].push_back(j); + // mgr_bus_a_chan_flat[i][j].push_back(mgr_bus_req[i].a); + mgr_bus_rsp_idx_next[i] = j; + mgr_bus_rsp_idx_push[i] = 1'b1; + // mgr_bus_rsp_idx[i].push_back(j); end end if (mgr_bus_rsp[i].rvalid) begin - sbr_bus_r_chan_flat[mgr_bus_rsp_idx[i][0]].pop_front(); - mgr_bus_rsp_idx[i].pop_front(); + sbr_bus_r_chan_flat_pop[mgr_bus_rsp_idx_front[i]] = 1'b1; + // sbr_bus_r_chan_flat[mgr_bus_rsp_idx[i][0]].pop_front(); + // mgr_bus_rsp_idx[i].pop_front(); end end for (int unsigned i = 0; i < NumSubordinates; i++) begin if (sbr_bus_req[i].req && sbr_bus_rsp[i].gnt) begin for (int unsigned j = 0; j < NumManagers; j++) begin - if (mgr_bus_a_chan_flat[j][i][0] == sbr_bus_req[i].a) begin - mgr_bus_a_chan_flat[j][i].pop_front(); + if (mgr_bus_a_chan_flat_front[j][i] == sbr_bus_req[i].a) begin + // mgr_bus_a_chan_flat[j][i].pop_front(); + mgr_bus_a_chan_flat_pop[j][i] = 1'b1; break; end end end - if (sbr_bus_rsp[i].rvalid) begin - sbr_bus_r_chan_flat[i].push_back(sbr_bus_rsp[i].r); - end + // if (sbr_bus_rsp[i].rvalid) begin + // sbr_bus_r_chan_flat[i].push_back(sbr_bus_rsp[i].r); + // end end - for (int unsigned i = 0; i < NumManagers; i++) begin - mgr_bus_rsp_idx_front[i] = mgr_bus_rsp_idx[i][0]; - for (int unsigned j = 0; j < NumSubordinates; j++) begin - mgr_bus_a_chan_flat_empty[i][j] = (mgr_bus_a_chan_flat[i][j].size() == 0); - mgr_bus_a_chan_flat_front[i][j] = mgr_bus_a_chan_flat[i][j][0]; - end - end - for (int unsigned i = 0; i < NumSubordinates; i++) begin - sbr_bus_r_chan_flat_front[i] = sbr_bus_r_chan_flat[i][0]; - end + // for (int unsigned i = 0; i < NumManagers; i++) begin + // mgr_bus_rsp_idx_front[i] = mgr_bus_rsp_idx[i][0]; + // for (int unsigned j = 0; j < NumSubordinates; j++) begin + // mgr_bus_a_chan_flat_empty[i][j] = (mgr_bus_a_chan_flat[i][j].size() == 0); + // mgr_bus_a_chan_flat_front[i][j] = mgr_bus_a_chan_flat[i][j][0]; + // end + // end + // for (int unsigned i = 0; i < NumSubordinates; i++) begin + // sbr_bus_r_chan_flat_front[i] = sbr_bus_r_chan_flat[i][0]; + // end end // Fault indication From efb34a7d6a22388116cefcf242e352f0f70437fa Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 17 Oct 2025 18:53:29 +0200 Subject: [PATCH 44/48] Add scrubber to relobi sram shim --- Bender.lock | 2 +- Bender.yml | 2 +- src/relobi_sram_shim.sv | 157 ++++++++++++++++++++++++++++++---------- 3 files changed, 121 insertions(+), 40 deletions(-) diff --git a/Bender.lock b/Bender.lock index e6e15a5..fc5b373 100644 --- a/Bender.lock +++ b/Bender.lock @@ -30,7 +30,7 @@ packages: Git: https://github.com/pulp-platform/common_verification.git dependencies: [] redundancy_cells: - revision: 3c7c57e80fe2f65812db092182ce68ee810943df + revision: 766e376b7ddb70e744740e703a371f7fe7cc3e74 version: null source: Git: https://github.com/pulp-platform/redundancy_cells.git diff --git a/Bender.yml b/Bender.yml index f5b742a..0871202 100644 --- a/Bender.yml +++ b/Bender.yml @@ -10,7 +10,7 @@ package: dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.38.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } - redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 3c7c57e80fe2f65812db092182ce68ee810943df } + redundancy_cells: { git: "https://github.com/pulp-platform/redundancy_cells.git", rev: 766e376b7ddb70e744740e703a371f7fe7cc3e74 } export_include_dirs: - include diff --git a/src/relobi_sram_shim.sv b/src/relobi_sram_shim.sv index 71346c4..8d90d8f 100644 --- a/src/relobi_sram_shim.sv +++ b/src/relobi_sram_shim.sv @@ -14,7 +14,10 @@ module relobi_sram_shim #( parameter type relobi_rsp_t = logic, parameter type a_optional_t = logic, parameter type r_optional_t = logic, - parameter bit EnableScrubber = 1'b0 // Unimplemented, WIP + parameter bit EnableScrubber = 1'b0, + parameter int unsigned ScrubberMemWords = 256, + parameter bit ScrubberCorrectRead = 1'b1, + parameter int unsigned AddrWidth = EnableScrubber ? $clog2(ScrubberMemWords) : ObiCfg.AddrWidth ) ( input logic clk_i, input logic rst_ni, @@ -24,12 +27,15 @@ module relobi_sram_shim #( output logic req_o, output logic we_o, - output logic [ObiCfg.AddrWidth-1:0] addr_o, + output logic [AddrWidth-1:0] addr_o, output logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_o, input logic gnt_i, // Should generally be 1'b1 input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] rdata_i, + input logic scrub_trigger_i, // Set to 1'b0 to disable + output logic scrub_bit_corrected_o, + output logic scrub_uncorrectable_o, output logic [1:0] fault_o ); @@ -39,12 +45,12 @@ module relobi_sram_shim #( if (ObiCfg.OptionalCfg.UseProt) $warning("Prot not checked!"); if (ObiCfg.OptionalCfg.UseMemtype) $warning("Memtype not checked!"); - logic [5:0] voter_errs; - logic [9:0][1:0] hsiao_errs; - logic [1:0][9:0] hsiao_errs_transpose; + logic [7:0] voter_errs; + logic [12:0][1:0] hsiao_errs; + logic [1:0][12:0] hsiao_errs_transpose; for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose - for (genvar j = 0; j < 10; j++) begin : gen_hsiao_errs_transpose_inner + for (genvar j = 0; j < 13; j++) begin : gen_hsiao_errs_transpose_inner assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; end end @@ -57,27 +63,33 @@ module relobi_sram_shim #( logic [ObiCfg.IdWidth-1:0] id_d, id_q; logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_d, other_ecc_q; - logic use_buffered; - logic [2:0] use_buffered_tmr; - logic [2:0] req_o_tmr; - logic [2:0] we; + logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] use_buffered; + logic [2:0][ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] use_buffered_tmr; + logic [2:0] req_o_tmr, req_o_scrubbed_tmr; + logic [2:0] we, we_scrubbed; logic [2:0][ObiCfg.DataWidth/8-1:0] be; logic [2:0][ObiCfg.IdWidth-1:0] aid; logic [2:0][relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc; logic [2:0][ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] rmw_wdata_tmr; - logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_buffer, rmw_wdata; + logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_buffer, rmw_wdata, scrub_wdata, scrub_rdata; logic [ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)-1:0] addr_buffer; logic [2:0] r_gnt; + logic [2:0] scrub_gnt; + logic [2:0][ObiCfg.AddrWidth-1:0] addr_decoded; + logic [2:0][AddrWidth-1:0] addr_decoded_trimmed; + logic [2:0][AddrWidth-1:0] addr_scrubbed; TMR_voter_fail i_req_valid_vote ( - .a_i (req_o_tmr[0]), - .b_i (req_o_tmr[1]), - .c_i (req_o_tmr[2]), + .a_i (req_o_scrubbed_tmr[0]), + .b_i (req_o_scrubbed_tmr[1]), + .c_i (req_o_scrubbed_tmr[2]), .majority_o (req_o), .fault_detected_o(voter_errs[0]) ); - TMR_voter_fail i_use_buffered_vote ( + bitwise_TMR_voter_fail #( + .DataWidth( ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth) ) + ) i_use_buffered_vote ( .a_i (use_buffered_tmr[0]), .b_i (use_buffered_tmr[1]), .c_i (use_buffered_tmr[2]), @@ -85,13 +97,15 @@ module relobi_sram_shim #( .fault_detected_o(voter_errs[1]) ); - assign wdata_o = use_buffered ? rmw_wdata : obi_req_i.a.wdata; + for (genvar i = 0; i < ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth); i++) begin : gen_scrub_wdata + assign scrub_wdata[i] = use_buffered[i] ? rmw_wdata[i] : obi_req_i.a.wdata[i]; + end always_comb begin obi_rsp_o = '0; obi_rsp_o.gnt = r_gnt; obi_rsp_o.rvalid = rvalid_q; - obi_rsp_o.r.rdata = rdata_i; + obi_rsp_o.r.rdata = scrub_rdata; obi_rsp_o.r.rid = id_q; obi_rsp_o.r.err = 1'b0; obi_rsp_o.r.other_ecc = other_ecc_q; @@ -99,14 +113,55 @@ module relobi_sram_shim #( assign rvalid_d = obi_req_i.req & obi_rsp_o.gnt; - hsiao_ecc_dec #( - .DataWidth ( ObiCfg.AddrWidth ) - ) i_addr_dec ( - .in ( use_buffered ? addr_buffer : obi_req_i.a.addr ), - .out ( addr_o ), - .syndrome_o(), - .err_o (hsiao_errs[0]) - ); + if (EnableScrubber) begin : gen_scrubber + ecc_scrubber #( + .BankSize (ScrubberMemWords), + .UseExternalECC (1'b0), + .DataWidth (ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)), + .ProtWidth (hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)), + .CorrectRead (ScrubberCorrectRead), + .TmrHs (1'b1) + ) i_scrubber ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .scrub_trigger_i (scrub_trigger_i), + .bit_corrected_o (scrub_bit_corrected_o), + .uncorrectable_o (scrub_uncorrectable_o), + + // Input signals from others accessing memory bank + .intc_req_i (req_o_tmr), + .intc_gnt_o (scrub_gnt), + .intc_we_i (we), + .intc_add_i (addr_decoded_trimmed), + .intc_wdata_i (scrub_wdata), + .intc_rdata_o (scrub_rdata), + + // Output directly to bank + .bank_req_o (req_o_scrubbed_tmr), + .bank_gnt_i ({3{gnt_i}}), + .bank_we_o (we_scrubbed), + .bank_add_o (addr_scrubbed), + .bank_wdata_o (wdata_o), + .bank_rdata_i (rdata_i), + + // If using external ECC + .ecc_out_o (), + .ecc_in_i ('0), + .ecc_err_i ('0), + + .fault_o (voter_errs[7]) + ); + end else begin : gen_no_scrubber + assign req_o_scrubbed_tmr = req_o_tmr; + assign scrub_gnt = {3{gnt_i}}; + assign we_scrubbed = we; + assign addr_scrubbed = addr_decoded; + assign wdata_o = scrub_wdata; + assign scrub_bit_corrected_o = 1'b0; + assign scrub_uncorrectable_o = 1'b0; + assign voter_errs[7] = 1'b0; + end for (genvar i = 0; i < 3; i++) begin : gen_tmr_part relobi_sram_shim_tmr_part #( @@ -119,7 +174,7 @@ module relobi_sram_shim #( .clk_i(clk_i), .rst_ni(rst_ni), .req_i(obi_req_i.req[i]), - .gnt_i(gnt_i), + .gnt_i(scrub_gnt[i]), .gnt_o(r_gnt[i]), .a_we_i(obi_req_i.a.we), .a_be_i(obi_req_i.a.be), @@ -127,24 +182,37 @@ module relobi_sram_shim #( .a_optional_i(obi_req_i.a.a_optional), .a_other_ecc_i(obi_req_i.a.other_ecc), .wdata_rmw(wdata_buffer), - .ldata_rmw(rdata_i), + .ldata_rmw(scrub_rdata), .wdata_modified(rmw_wdata_tmr[i]), .use_buffered(use_buffered_tmr[i]), .req_o(req_o_tmr[i]), .a_we_o(we[i]), .a_aid_o(aid[i]), .other_ecc_d(other_ecc[i]), - .hsiao_errs(hsiao_errs[1+3*i+:3]) + .a_addr_i(obi_req_i.a.addr), + .addr_buffer(addr_buffer), + .addr_o(addr_decoded[i]), + .hsiao_errs(hsiao_errs[1+4*i+:4]) ); + assign addr_decoded_trimmed[i] = addr_decoded[i][AddrWidth-1+$clog2(ObiCfg.AddrWidth/8):$clog2(ObiCfg.AddrWidth/8)]; end TMR_voter_fail i_we_vote ( - .a_i (we[0]), - .b_i (we[1]), - .c_i (we[2]), + .a_i (we_scrubbed[0]), + .b_i (we_scrubbed[1]), + .c_i (we_scrubbed[2]), .majority_o (we_o), .fault_detected_o(voter_errs[2]) ); + bitwise_TMR_voter_fail #( + .DataWidth(AddrWidth) + ) i_addr_vote ( + .a_i (addr_scrubbed[0]), + .b_i (addr_scrubbed[1]), + .c_i (addr_scrubbed[2]), + .majority_o (addr_o), + .fault_detected_o(voter_errs[3]) + ); bitwise_TMR_voter_fail #( .DataWidth( ObiCfg.IdWidth ) ) i_aid_vote ( @@ -152,7 +220,7 @@ module relobi_sram_shim #( .b_i (aid[1]), .c_i (aid[2]), .majority_o (id_d), - .fault_detected_o(voter_errs[3]) + .fault_detected_o(voter_errs[4]) ); bitwise_TMR_voter_fail #( .DataWidth( relobi_pkg::relobi_r_other_ecc_width(ObiCfg) ) @@ -161,7 +229,7 @@ module relobi_sram_shim #( .b_i (other_ecc[1]), .c_i (other_ecc[2]), .majority_o (other_ecc_d), - .fault_detected_o(voter_errs[4]) + .fault_detected_o(voter_errs[5]) ); bitwise_TMR_voter_fail #( .DataWidth( ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth) ) @@ -170,7 +238,7 @@ module relobi_sram_shim #( .b_i (rmw_wdata_tmr[1]), .c_i (rmw_wdata_tmr[2]), .majority_o (rmw_wdata), - .fault_detected_o(voter_errs[5]) + .fault_detected_o(voter_errs[6]) ); always_ff @(posedge clk_i or negedge rst_ni) begin @@ -218,12 +286,15 @@ module relobi_sram_shim_tmr_part #( input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_rmw, input logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] ldata_rmw, output logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] wdata_modified, - output logic use_buffered, + output logic [ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth)-1:0] use_buffered, output logic req_o, output logic a_we_o, output logic [ObiCfg.IdWidth-1:0] a_aid_o, output logic [relobi_pkg::relobi_r_other_ecc_width(ObiCfg)-1:0] other_ecc_d, - output logic [2:0][1:0] hsiao_errs + input logic [ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)-1:0] a_addr_i, + input logic [ObiCfg.AddrWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.AddrWidth)-1:0] addr_buffer, + output logic [ObiCfg.AddrWidth-1:0] addr_o, + output logic [3:0][1:0] hsiao_errs ); typedef enum logic { NORMAL, READ_MODIFY_WRITE } store_state_e; @@ -289,11 +360,21 @@ module relobi_sram_shim_tmr_part #( .out ( wdata_modified ) ); + hsiao_ecc_dec #( + .DataWidth ( ObiCfg.AddrWidth ) + ) i_addr_dec ( + .in ( use_buffered[0] ? addr_buffer : a_addr_i ), + .out ( addr_o ), + .syndrome_o(), + .err_o (hsiao_errs[3]) + ); + + always_comb begin req_o = req_i; gnt_o = gnt_i; store_state_d = NORMAL; - use_buffered = 1'b0; + use_buffered = {ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth){1'b0}}; a_we_o = a_we_int; if (store_state_q == NORMAL) begin if (req_i & (a_be_int != {ObiCfg.DataWidth/8{1'b1}}) & a_we_int) begin @@ -304,7 +385,7 @@ module relobi_sram_shim_tmr_part #( req_o = 1'b1; gnt_o = 1'b0; a_we_o = 1'b1; - use_buffered = 1'b1; + use_buffered = {ObiCfg.DataWidth+hsiao_ecc_pkg::min_ecc(ObiCfg.DataWidth){1'b1}}; end end From 588b4dabd329e90e4c4ea0c91b58870703eab836 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 7 Nov 2025 16:47:54 +0100 Subject: [PATCH 45/48] Add obi isolate --- Bender.yml | 1 + src/obi_isolate.sv | 179 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 src/obi_isolate.sv diff --git a/Bender.yml b/Bender.yml index 0871202..1558f3e 100644 --- a/Bender.yml +++ b/Bender.yml @@ -31,6 +31,7 @@ sources: - src/obi_mux.sv - src/obi_sram_shim.sv # Level 4 + - src/obi_isolate.sv - src/obi_xbar.sv - target: any(test, obi_test) files: diff --git a/src/obi_isolate.sv b/src/obi_isolate.sv new file mode 100644 index 0000000..7dd170d --- /dev/null +++ b/src/obi_isolate.sv @@ -0,0 +1,179 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module obi_isolate #( + /// The OBI configuration. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The request struct. + parameter type obi_req_t = logic, + /// The response struct. + parameter type obi_rsp_t = logic, + /// Maximum number of pending requests per channel + parameter int unsigned MaxPending = 4, + /// Gracefully terminate all incoming transactions in case of isolation by returning proper error + /// responses. + parameter bit TerminateTransaction = 1'b0 +) ( + input logic clk_i, + input logic rst_ni, + + input obi_req_t sbr_port_req_i, + output obi_rsp_t sbr_port_rsp_o, + + output obi_req_t mgr_port_req_o, + input obi_rsp_t mgr_port_rsp_i, + + input logic isolate_i, + output logic isolated_o +); + // plus 1 in clog for accouning no open transaction + localparam int unsigned CounterWidth = $clog2(NumPending + 32'd1); + typedef logic [CounterWidth-1:0] cnt_t; + + + obi_req_t in_req, out_req; + obi_rsp_t in_rsp, out_rsp; + + if (TerminateTransaction) begin : gen_err_rsp + obi_req_t err_req; + obi_rsp_t err_rsp; + // demux to error subordinate + obi_demux #( + .ObiCfg ( ObiCfg ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .NumMgrPorts ( 2 ), + .NumMaxTrans ( MaxPending ) + ) i_demux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .sbr_port_select_i ( isolated_o ), + .sbr_port_req_i ( sbr_port_req_i ), + .sbr_port_rsp_o ( sbr_port_rsp_o ), + + .mgr_ports_req_o ( { in_req, err_req } ), + .mgr_ports_rsp_i ( { in_rsp, err_rsp } ) + ); + + obi_err_sbr #( + .ObiCfg ( ObiCfg ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .NumMaxTrans ( MaxPending ) + ) i_err_sbr ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( 1'b0 ), + + .obi_req_i ( err_req ), + .obi_rsp_o ( err_rsp ) + ); + end else begin : gen_no_err_rsp + assign in_req = sbr_port_req_i; + assign sbr_port_rsp_o = in_rsp; + end + + typedef enum logic [1:0] { + Normal, + Hold, + Drain, + Isolate + } isolate_state_e; + + isolate_state_e isolate_state_d, isolate_state_q; + cnt_t in_flight_d, in_flight_q; + logic rready, mgr_rready; + + if (ObiCfg.UseRReady) begin : gen_rready + assign rready = in_rsp.rready; + always_comb begin + mgr_port_req_o = out_req; + mgr_port_req_o.rready = mgr_rready; + end + end else begin : gen_no_rready + assign rready = 1'b1; + assign mgr_port_req_o = out_req; + end + + // Update counters + always_comb begin + in_flight_d = in_flight_q; + if (out_req.req && (isolate_state_q == Normal)) begin + in_flight_d++; + end + if (out_rsp.rvalid && rready) begin + in_flight_d--; + end + end + + // Perform isolation + always_comb begin + isolate_state_d = isolate_state_q; + // Connect channel by default + out_req = in_req; + in_rsp = out_rsp; + mgr_rready = rready; + unique case (isolate_state_q) + Normal: begin + // Block if in flight transactions overflows + if (in_flight_q >= cnt_t'(MaxPending)) begin + out_req.req = 1'b0; + in_rsp.gnt = 1'b0; + if (isolate_i) begin + isolate_state_d = Hold; + end + end else begin + if (in_req.req && !out_rsp.gnt) begin + isolate_state_d = Hold; + end else begin + if (isolate_i) begin + isolate_state_d = Drain; + end + end + end + end + Hold: begin + out_req.req = 1'b1; + if (out_rsp.gnt) begin + isolate_state_d = isolate_i ? Drain : Normal; + end + end + Drain: begin + out_req.req = 1'b0; + in_rsp.gnt = 1'b0; + if (in_flight_q == '0) begin + isolate_state_d = Isolate; + end + end + Isolate: begin + out_req.req = 1'b0; + out_req.a = '{default: '0}; + in_rsp.gnt = 1'b0; + in_rsp.rvalid = 1'b0; + in_rsp.r = '{default: '0}; + mgr_rready = 1'b0; + if (!isolate_i) begin + isolate_state_d = Normal; + end + end + default: ; + endcase + end + + assign isolated_o = (isolate_state_q == Isolate); + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + isolate_state_q <= Isolate; + in_flight_q <= '0; + end else begin + isolate_state_q <= isolate_state_d; + in_flight_q <= in_flight_d; + end + end + +endmodule From 2b279c8b1546a10f8f45ad67a8b82f1b1390bb31 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 7 Nov 2025 16:48:05 +0100 Subject: [PATCH 46/48] Add relobi isolate --- Bender.yml | 1 + src/relobi_isolate.sv | 336 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 src/relobi_isolate.sv diff --git a/Bender.yml b/Bender.yml index 1558f3e..b59fa29 100644 --- a/Bender.yml +++ b/Bender.yml @@ -65,6 +65,7 @@ sources: - src/relobi_mux.sv - src/relobi_sram_shim.sv # Level 5 + - src/relobi_isolate.sv - src/relobi_xbar.sv - target: any(test, obi_test) files: diff --git a/src/relobi_isolate.sv b/src/relobi_isolate.sv new file mode 100644 index 0000000..186dbb3 --- /dev/null +++ b/src/relobi_isolate.sv @@ -0,0 +1,336 @@ +// Copyright 2025 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module obi_isolate #( + /// The OBI configuration. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, + /// The request struct. + parameter type obi_req_t = logic, + /// The response struct. + parameter type obi_rsp_t = logic, + /// The a_chan struct for all ports. + parameter type obi_a_chan_t = logic, + /// The r_chan struct for all ports. + parameter type obi_r_chan_t = logic, + /// The optional a_chan struct for all ports. + parameter type obi_a_optional_t = logic, + /// The optional r_chan struct for all ports. + parameter type obi_r_optional_t = logic, + /// Maximum number of pending requests per channel + parameter int unsigned MaxPending = 4, + /// Gracefully terminate all incoming transactions in case of isolation by returning proper error + /// responses. + parameter bit TerminateTransaction = 1'b0, + /// Use TMR for isolate signals + parameter bit TmrSelect = 1'b0, + parameter int unsigned SelWidth = TmrSelect ? 3 : 1 +) ( + input logic clk_i, + input logic rst_ni, + + input obi_req_t sbr_port_req_i, + output obi_rsp_t sbr_port_rsp_o, + + output obi_req_t mgr_port_req_o, + input obi_rsp_t mgr_port_rsp_i, + + input logic [SelWidth-1:0] isolate_i, + output logic [SelWidth-1:0] isolated_o, + + output logic fault_o +); + + // plus 1 in clog for accouning no open transaction + localparam int unsigned CounterWidth = $clog2(MaxPending + 32'd1); + typedef logic [CounterWidth-1:0] cnt_t; + + logic faults[3:0]; + assign fault_o = |faults; + + obi_req_t in_req, out_req; + obi_rsp_t in_rsp, out_rsp; + + if (TerminateTransaction) begin : gen_err_rsp + obi_req_t err_req; + obi_rsp_t err_rsp; + // demux to error subordinate + relobi_demux #( + .ObiCfg ( ObiCfg ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .obi_r_chan_t( obi_r_chan_t), + .obi_r_optional_t( obi_r_optional_t), + .NumMgrPorts ( 2 ), + .NumMaxTrans ( MaxPending ), + .TmrSelect ( TmrSelect ) + ) i_demux ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .sbr_port_select_i ( isolated_o ), + .sbr_port_req_i ( sbr_port_req_i ), + .sbr_port_rsp_o ( sbr_port_rsp_o ), + + .mgr_ports_req_o ( { in_req, err_req } ), + .mgr_ports_rsp_i ( { in_rsp, err_rsp } ) + ); + + relobi_err_sbr #( + .ObiCfg ( ObiCfg ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .a_optional_t( obi_a_optional_t), + .r_optional_t( obi_r_optional_t), + .NumMaxTrans ( MaxPending ) + ) i_err_sbr ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( 1'b0 ), + + .obi_req_i ( err_req ), + .obi_rsp_o ( err_rsp ) + ); + end else begin : gen_no_err_rsp + assign in_req = sbr_port_req_i; + assign sbr_port_rsp_o = in_rsp; + end + + logic [2:0] rready, mgr_rready; + logic [2:0] isolate_in, isolated_out; + + if (TmrSelect) begin : gen_tmr_isolate + assign isolate_in = isolate_i; + assign isolated_o = isolated_out; + assign faults[0] = 1'b0; + end else begin : gen_no_tmr_isolate + assign isolate_in[0] = isolate_i; + assign isolate_in[1] = isolate_i; + assign isolate_in[2] = isolate_i; + TMR_voter_fail i_isolate_vote ( + .a_i (isolated_out[0]), + .b_i (isolated_out[1]), + .c_i (isolated_out[2]), + .majority_o (isolated_o), + .fault_detected_o(faults[0]) + ); + end + + if (ObiCfg.UseRReady) begin : gen_rready + assign rready = in_rsp.rready; + always_comb begin + mgr_port_req_o = out_req; + mgr_port_req_o.rready = mgr_rready; + end + end else begin : gen_no_rready + assign rready = 1'b1; + assign mgr_port_req_o = out_req; + end + + logic [2:0][1:0] isolate_state_sync; + logic [2:0][1:0][1:0] alt_isolate_state_sync; + logic [2:0][CounterWidth-1:0] in_flight_sync; + logic [2:0][1:0][CounterWidth-1:0] alt_in_flight_sync; + for (genvar i = 0; i < 3; i++) begin : gen_tmr_part + for (genvar j = 0; j < 2; j++) begin : gen_alt_sync + assign alt_isolate_state_sync[i][j] = isolate_state_sync[(i+j+1) % 3]; + assign alt_in_flight_sync[i][j] = in_flight_sync[(i+j+1) % 3]; + end + relobi_isolate_tmr_part #( + .CounterWidth ( CounterWidth ), + .cnt_t ( cnt_t ) + ) i_tmr_part ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .in_req_req_i ( in_req.req[i] ), + .in_rsp_gnt_o ( in_rsp.gnt[i] ), + .in_rsp_rvalid_o ( in_rsp.rvalid[i] ), + .out_req_req_o ( out_req.req[i] ), + .out_rsp_gnt_i ( mgr_port_rsp_i.gnt[i] ), + .out_rsp_rvalid_i ( mgr_port_rsp_i.rvalid[i] ), + .mgr_rready_o ( mgr_rready[i] ), + .rready_i ( rready[i] ), + + .isolate_i ( isolate_in[i] ), + .isolated_o ( isolated_out[i] ), + + .in_flight_sync_o ( in_flight_sync[i] ), + .alt_in_flight_sync_i ( alt_in_flight_sync[i] ), + .isolate_state_sync_o ( isolate_state_sync[i] ), + .alt_isolate_state_sync_i( alt_isolate_state_sync[i] ), + + .fault_o ( faults[i+1] ) + ); + end + + logic [$bits(obi_a_chan_t)-1:0] in_req_a, out_req_a; + logic [$bits(obi_r_chan_t)-1:0] in_rsp_r, out_rsp_r; + assign in_req_a = in_req.a; + assign out_req.a = obi_a_chan_t'(out_req_a); + assign in_rsp.r = obi_r_chan_t'(in_rsp_r); + assign out_rsp_r = out_rsp.r; + + for (genvar i = 0; i < $bits(obi_a_chan_t); i++) begin : gen_chan_connections + logic isolated_out_voted; + TMR_voter_fail i_isolate_vote_tmr_part ( + .a_i (isolated_out[0]), + .b_i (isolated_out[1]), + .c_i (isolated_out[2]), + .majority_o (isolated_out_voted), + .fault_detected_o(faults[4+i]) + ); + if (isolated_out_voted) begin + assign out_req_a[i] = '0; + if (i < $bits(obi_r_chan_t)) begin + assign in_rsp_r[i] = '0; + end + end else begin + assign out_req_a[i] = in_req_a[i]; + if (i < $bits(obi_r_chan_t)) begin + assign in_rsp_r[i] = out_rsp_r[i]; + end + end + end + +endmodule + +module relobi_isolate_tmr_part #( + parameter int unsigned MaxPending = 4, + parameter int unsigned CounterWidth = $clog2(MaxPending + 32'd1), + parameter type cnt_t = logic[CounterWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + input logic in_req_req_i, + output logic in_rsp_gnt_o, + output logic in_rsp_rvalid_o, + output logic out_req_req_o, + input logic out_rsp_gnt_i, + input logic out_rsp_rvalid_i, + output logic mgr_rready_o, + input logic rready_i, + + input logic isolate_i, + output logic isolated_o, + + output cnt_t in_flight_sync_o, + input cnt_t [1:0] alt_in_flight_sync_i, + output logic [1:0] isolate_state_sync_o, + input logic [1:0][1:0] alt_isolate_state_sync_i, + output logic fault_o +); + + typedef enum logic [1:0] { + Normal, + Hold, + Drain, + Isolate + } isolate_state_e; + + isolate_state_e isolate_state_d, isolate_state_q, isolate_state_q_voted; + cnt_t in_flight_d, in_flight_q, in_flight_q_voted; + logic [1:0] faults; + assign fault_o = |faults; + + // Update counters + always_comb begin + in_flight_d = in_flight_q_voted; + if (out_req_req_o && (isolate_state_q_voted == Normal)) begin + in_flight_d++; + end + if (out_rsp_rvalid_i && rready_i) begin + in_flight_d--; + end + end + + // Perform isolation + always_comb begin + isolate_state_d = isolate_state_q_voted; + // Connect channel by default + out_req_req_o = in_req_req_i; + in_rsp_gnt_o = out_rsp_gnt_i; + in_rsp_rvalid_o = out_rsp_rvalid_i; + mgr_rready_o = rready_i; + unique case (isolate_state_q_voted) + Normal: begin + // Block if in flight transactions overflows + if (in_flight_q_voted >= cnt_t'(MaxPending)) begin + out_req_req_o = 1'b0; + in_rsp_gnt_o = 1'b0; + if (isolate_i) begin + isolate_state_d = Hold; + end + end else begin + if (in_req_req_i && !out_rsp_gnt_i) begin + isolate_state_d = Hold; + end else begin + if (isolate_i) begin + isolate_state_d = Drain; + end + end + end + end + Hold: begin + out_req_req_o = 1'b1; + if (out_rsp_gnt_i) begin + isolate_state_d = isolate_i ? Drain : Normal; + end + end + Drain: begin + out_req_req_o = 1'b0; + in_rsp_gnt_o = 1'b0; + if (in_flight_q_voted == '0) begin + isolate_state_d = Isolate; + end + end + Isolate: begin + out_req_req_o = 1'b0; + in_rsp_gnt_o = 1'b0; + in_rsp_rvalid_o = 1'b0; + mgr_rready_o = 1'b0; + if (!isolate_i) begin + isolate_state_d = Normal; + end + end + default: ; + endcase + end + + assign isolated_o = (isolate_state_q_voted == Isolate); + + bitwise_TMR_voter_fail #( + .DataWidth( $bits(isolate_state_e) ) + ) i_isolate_state_vote ( + .a_i (isolate_state_q), + .b_i (alt_isolate_state_sync_i[0]), + .c_i (alt_isolate_state_sync_i[1]), + .majority_o (isolate_state_q_voted), + .fault_detected_o(faults[0]) + ); + assign isolate_state_sync_o = isolate_state_q; + bitwise_TMR_voter_fail #( + .DataWidth( CounterWidth ) + ) i_in_flight_vote ( + .a_i (in_flight_q), + .b_i (alt_in_flight_sync_i[0]), + .c_i (alt_in_flight_sync_i[1]), + .majority_o (in_flight_q_voted), + .fault_detected_o(faults[1]) + ); + assign in_flight_sync_o = in_flight_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + isolate_state_q <= Isolate; + in_flight_q <= '0; + end else begin + isolate_state_q <= isolate_state_d; + in_flight_q <= in_flight_d; + end + end + +endmodule From bf55dc0b66e6b86edc525ff8b293c9194fd45058 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 10 Nov 2025 13:54:33 +0100 Subject: [PATCH 47/48] Fix obi isolate parameter name --- src/obi_isolate.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obi_isolate.sv b/src/obi_isolate.sv index 7dd170d..fbdc1f8 100644 --- a/src/obi_isolate.sv +++ b/src/obi_isolate.sv @@ -30,7 +30,7 @@ module obi_isolate #( output logic isolated_o ); // plus 1 in clog for accouning no open transaction - localparam int unsigned CounterWidth = $clog2(NumPending + 32'd1); + localparam int unsigned CounterWidth = $clog2(MaxPending + 32'd1); typedef logic [CounterWidth-1:0] cnt_t; From b9b94d1c92117c5a3f44d8ab74d34a3f3f56fbdd Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 12 Nov 2025 18:50:02 +0100 Subject: [PATCH 48/48] Fixes --- src/obi_demux.sv | 2 +- src/relobi_isolate.sv | 17 +++++------------ src/relobi_sram_shim.sv | 8 ++++---- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/obi_demux.sv b/src/obi_demux.sv index 3eb016e..5570327 100644 --- a/src/obi_demux.sv +++ b/src/obi_demux.sv @@ -53,7 +53,7 @@ module obi_demux #( sbr_port_gnt = 1'b0; if (!overflow) begin - if (sbr_port_select_i == select_q || in_flight == '0 || (in_flight == 1 && cnt_down)) begin + if (sbr_port_select_i == select_q || in_flight == '0) begin mgr_ports_req_o[sbr_port_select_i].req = sbr_port_req_i.req; mgr_ports_req_o[sbr_port_select_i].a = sbr_port_req_i.a; sbr_port_gnt = mgr_ports_rsp_i[sbr_port_select_i].gnt; diff --git a/src/relobi_isolate.sv b/src/relobi_isolate.sv index 186dbb3..fc82ecc 100644 --- a/src/relobi_isolate.sv +++ b/src/relobi_isolate.sv @@ -4,7 +4,7 @@ // Michael Rogenmoser -module obi_isolate #( +module relobi_isolate #( /// The OBI configuration. parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, /// The request struct. @@ -47,7 +47,7 @@ module obi_isolate #( localparam int unsigned CounterWidth = $clog2(MaxPending + 32'd1); typedef logic [CounterWidth-1:0] cnt_t; - logic faults[3:0]; + logic [3:0] faults; assign fault_o = |faults; obi_req_t in_req, out_req; @@ -182,16 +182,9 @@ module obi_isolate #( .majority_o (isolated_out_voted), .fault_detected_o(faults[4+i]) ); - if (isolated_out_voted) begin - assign out_req_a[i] = '0; - if (i < $bits(obi_r_chan_t)) begin - assign in_rsp_r[i] = '0; - end - end else begin - assign out_req_a[i] = in_req_a[i]; - if (i < $bits(obi_r_chan_t)) begin - assign in_rsp_r[i] = out_rsp_r[i]; - end + assign out_req_a[i] = isolated_out_voted ? '0 : in_req_a[i]; + if (i < $bits(obi_r_chan_t)) begin + assign in_rsp_r[i] = isolated_out_voted ? '0 : in_rsp_r[i]; end end diff --git a/src/relobi_sram_shim.sv b/src/relobi_sram_shim.sv index 8d90d8f..551dff3 100644 --- a/src/relobi_sram_shim.sv +++ b/src/relobi_sram_shim.sv @@ -46,11 +46,11 @@ module relobi_sram_shim #( if (ObiCfg.OptionalCfg.UseMemtype) $warning("Memtype not checked!"); logic [7:0] voter_errs; - logic [12:0][1:0] hsiao_errs; - logic [1:0][12:0] hsiao_errs_transpose; + logic [11:0][1:0] hsiao_errs; + logic [1:0][11:0] hsiao_errs_transpose; for (genvar i = 0; i < 2; i++) begin : gen_hsiao_errs_transpose - for (genvar j = 0; j < 13; j++) begin : gen_hsiao_errs_transpose_inner + for (genvar j = 0; j < 12; j++) begin : gen_hsiao_errs_transpose_inner assign hsiao_errs_transpose[i][j] = hsiao_errs[j][i]; end end @@ -192,7 +192,7 @@ module relobi_sram_shim #( .a_addr_i(obi_req_i.a.addr), .addr_buffer(addr_buffer), .addr_o(addr_decoded[i]), - .hsiao_errs(hsiao_errs[1+4*i+:4]) + .hsiao_errs(hsiao_errs[4*i+:4]) ); assign addr_decoded_trimmed[i] = addr_decoded[i][AddrWidth-1+$clog2(ObiCfg.AddrWidth/8):$clog2(ObiCfg.AddrWidth/8)]; end