Skip to content

Commit

Permalink
[hw,racl_ctrl,rtl] Arbitrate multiple incoming errors
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Feb 10, 2025
1 parent 999bb69 commit 4caebc0
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 32 deletions.
2 changes: 2 additions & 0 deletions hw/ip_templates/racl_ctrl/racl_ctrl.core.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ filesets:
- lowrisc:ip:tlul
- lowrisc:prim:mubi
- lowrisc:prim:all
- lowrisc:prim:arbiter
- lowrisc:prim:onehot_check
- lowrisc:systems:top_racl_pkg
files:
- rtl/${module_instance_name}_reg_pkg.sv
Expand Down
65 changes: 49 additions & 16 deletions hw/ip_templates/racl_ctrl/rtl/racl_ctrl.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,12 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
// Error handling
//////////////////////////////////////////////////////////////////////////////////////////////////
// The total number of RACL error sources
localparam int unsigned NumAllIps = NumSubscribingIps + NumExternalSubscribingIps + 1;
// Concatenate the two incoming RACL error vectors for common handling
logic [NumSubscribingIps+NumExternalSubscribingIps:0] combined_racl_error_valid;
racl_error_log_t [NumSubscribingIps+NumExternalSubscribingIps:0] combined_racl_error;
logic [NumAllIps-1:0] combined_racl_error_valid;
racl_error_log_t [NumAllIps-1:0] combined_racl_error;
// Combine the internal and external RACL log to a single valid vector (for assertion) and a
// combined error vector for common handling in the logging logic.
Expand All @@ -153,23 +156,51 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
end
// Last element is the internal RACL error of the own reg_top
combined_racl_error_valid[NumSubscribingIps+NumExternalSubscribingIps] =
racl_ctrl_racl_error.valid;
combined_racl_error [NumSubscribingIps+NumExternalSubscribingIps] = racl_ctrl_racl_error;
combined_racl_error_valid[NumAllIps-1] = racl_ctrl_racl_error.valid;
combined_racl_error [NumAllIps-1] = racl_ctrl_racl_error;
end
// A RACL error can only happen for one IP at a time in one RACL domain. Therefore, it is
// safe to OR all RACL error bits together and no arbitration is needed. This is true also
// for the corresponding RACL role or Write/Read information.
`ASSERT(OneHotRaclError_A, $onehot0(combined_racl_error_valid))
// Reduce all incoming error vectors to a single role and write/read bit.
// Only a single IP can have a RACL error at one time.
// If there a multiple errors in the same cycle, arbitrate and get the first error.
// Lower index in combined_racl_error_valid has higher priority
logic [$clog2(NumAllIps)-1:0] error_idx;
prim_arbiter_fixed #(
.N ( NumAllIps ),
.EnDataPort ( 0 )
) u_prim_err_arb (
.clk_i,
.rst_ni,
.req_i ( combined_racl_error_valid ),
.data_i ( '{default:'0} ),
.gnt_o ( ),
.idx_o ( error_idx ),
.valid_o ( ),
.data_o ( ),
.ready_i ( 1'b1 )
);
racl_error_log_t racl_error_arb;
assign racl_error_arb = |combined_racl_error;
assign racl_error_arb = combined_racl_error[error_idx];
// If there are multiple errors at the same time, we need to directly assert the
// overflow bit in the log. We use a one-hot checker to determine if there is more
// than one error. The checker asserts an error in these cases.
logic multiple_errors;
prim_onehot_check #(
.OneHotWidth ( NumAllIps ),
.AddrCheck ( 0 ),
.EnableCheck ( 1 ),
.StrictCheck ( 0 )
) u_multiple_err_det (
.clk_i,
.rst_ni,
.oh_i ( combined_racl_error_valid ),
.addr_i ( '0 ),
.en_i ( 1'b1 ),
.err_o ( multiple_errors )
);
// On the first error, we log the address and other information
logic first_error;
assign first_error = ~reg2hw.error_log.valid.q & racl_error;
assign first_error = ~reg2hw.error_log.valid.q & racl_error_arb.valid;
// Writing 1 to the error valid bit clears the log again
logic clear_log;
Expand All @@ -178,15 +209,17 @@ module ${module_instance_name} import ${module_instance_name}_reg_pkg::*; #(
assign hw2reg.error_log.valid.d = ~clear_log;
assign hw2reg.error_log.valid.de = racl_error_arb.valid | clear_log;
// Overflow is raised when error is valid and a new error is coming in
// Overflow is raised when error is valid and a new error is coming in or more than one
// error is coming in at the same time
assign hw2reg.error_log.overflow.d = ~clear_log;
assign hw2reg.error_log.overflow.de = (reg2hw.error_log.valid.q & racl_error_arb.valid) |
multiple_errors |
clear_log;
assign hw2reg.error_log.read_access.d = clear_log ? '0 : racl_error_arb.read_access;
assign hw2reg.error_log.read_access.de = first_error | clear_log;
assign hw2reg.error_log.role.d = clear_log ? '0 : racl_error_arb.role;
assign hw2reg.error_log.role.d = clear_log ? '0 : racl_error_arb.racl_role;
assign hw2reg.error_log.role.de = first_error | clear_log;
assign hw2reg.error_log.ctn_uid.d = clear_log ? '0 : racl_error_arb.ctn_uid;
Expand Down
2 changes: 2 additions & 0 deletions hw/top_darjeeling/ip_autogen/racl_ctrl/racl_ctrl.core
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ filesets:
- lowrisc:ip:tlul
- lowrisc:prim:mubi
- lowrisc:prim:all
- lowrisc:prim:arbiter
- lowrisc:prim:onehot_check
- lowrisc:systems:top_racl_pkg
files:
- rtl/racl_ctrl_reg_pkg.sv
Expand Down
65 changes: 49 additions & 16 deletions hw/top_darjeeling/ip_autogen/racl_ctrl/rtl/racl_ctrl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@ module racl_ctrl import racl_ctrl_reg_pkg::*; #(
// Error handling
//////////////////////////////////////////////////////////////////////////////////////////////////

// The total number of RACL error sources
localparam int unsigned NumAllIps = NumSubscribingIps + NumExternalSubscribingIps + 1;

// Concatenate the two incoming RACL error vectors for common handling
logic [NumSubscribingIps+NumExternalSubscribingIps:0] combined_racl_error_valid;
racl_error_log_t [NumSubscribingIps+NumExternalSubscribingIps:0] combined_racl_error;
logic [NumAllIps-1:0] combined_racl_error_valid;
racl_error_log_t [NumAllIps-1:0] combined_racl_error;

// Combine the internal and external RACL log to a single valid vector (for assertion) and a
// combined error vector for common handling in the logging logic.
Expand All @@ -136,23 +139,51 @@ module racl_ctrl import racl_ctrl_reg_pkg::*; #(
end

// Last element is the internal RACL error of the own reg_top
combined_racl_error_valid[NumSubscribingIps+NumExternalSubscribingIps] =
racl_ctrl_racl_error.valid;
combined_racl_error [NumSubscribingIps+NumExternalSubscribingIps] = racl_ctrl_racl_error;
combined_racl_error_valid[NumAllIps-1] = racl_ctrl_racl_error.valid;
combined_racl_error [NumAllIps-1] = racl_ctrl_racl_error;
end

// A RACL error can only happen for one IP at a time in one RACL domain. Therefore, it is
// safe to OR all RACL error bits together and no arbitration is needed. This is true also
// for the corresponding RACL role or Write/Read information.
`ASSERT(OneHotRaclError_A, $onehot0(combined_racl_error_valid))

// Reduce all incoming error vectors to a single role and write/read bit.
// Only a single IP can have a RACL error at one time.
// If there a multiple errors in the same cycle, arbitrate and get the first error.
// Lower index in combined_racl_error_valid has higher priority
logic [$clog2(NumAllIps)-1:0] error_idx;
prim_arbiter_fixed #(
.N ( NumAllIps ),
.EnDataPort ( 0 )
) u_prim_err_arb (
.clk_i,
.rst_ni,
.req_i ( combined_racl_error_valid ),
.data_i ( '{default:'0} ),
.gnt_o ( ),
.idx_o ( error_idx ),
.valid_o ( ),
.data_o ( ),
.ready_i ( 1'b1 )
);
racl_error_log_t racl_error_arb;
assign racl_error_arb = |combined_racl_error;
assign racl_error_arb = combined_racl_error[error_idx];

// If there are multiple errors at the same time, we need to directly assert the
// overflow bit in the log. We use a one-hot checker to determine if there is more
// than one error. The checker asserts an error in these cases.
logic multiple_errors;
prim_onehot_check #(
.OneHotWidth ( NumAllIps ),
.AddrCheck ( 0 ),
.EnableCheck ( 1 ),
.StrictCheck ( 0 )
) u_multiple_err_det (
.clk_i,
.rst_ni,
.oh_i ( combined_racl_error_valid ),
.addr_i ( '0 ),
.en_i ( 1'b1 ),
.err_o ( multiple_errors )
);

// On the first error, we log the address and other information
logic first_error;
assign first_error = ~reg2hw.error_log.valid.q & racl_error;
assign first_error = ~reg2hw.error_log.valid.q & racl_error_arb.valid;

// Writing 1 to the error valid bit clears the log again
logic clear_log;
Expand All @@ -161,15 +192,17 @@ module racl_ctrl import racl_ctrl_reg_pkg::*; #(
assign hw2reg.error_log.valid.d = ~clear_log;
assign hw2reg.error_log.valid.de = racl_error_arb.valid | clear_log;

// Overflow is raised when error is valid and a new error is coming in
// Overflow is raised when error is valid and a new error is coming in or more than one
// error is coming in at the same time
assign hw2reg.error_log.overflow.d = ~clear_log;
assign hw2reg.error_log.overflow.de = (reg2hw.error_log.valid.q & racl_error_arb.valid) |
multiple_errors |
clear_log;

assign hw2reg.error_log.read_access.d = clear_log ? '0 : racl_error_arb.read_access;
assign hw2reg.error_log.read_access.de = first_error | clear_log;

assign hw2reg.error_log.role.d = clear_log ? '0 : racl_error_arb.role;
assign hw2reg.error_log.role.d = clear_log ? '0 : racl_error_arb.racl_role;
assign hw2reg.error_log.role.de = first_error | clear_log;

assign hw2reg.error_log.ctn_uid.d = clear_log ? '0 : racl_error_arb.ctn_uid;
Expand Down

0 comments on commit 4caebc0

Please sign in to comment.