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 12, 2025
1 parent 614b8a9 commit c85ca39
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 32 deletions.
1 change: 1 addition & 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,7 @@ filesets:
- lowrisc:ip:tlul
- lowrisc:prim:mubi
- lowrisc:prim:all
- lowrisc:prim:arbiter
- lowrisc:systems:top_racl_pkg
files:
- rtl/${module_instance_name}_reg_pkg.sv
Expand Down
53 changes: 37 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 combined_racl_error[NumAllIps];
// 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,39 @@ 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 are multiple errors in the same cycle, arbitrate and get the first error.
// Lower index in combined_racl_error_valid has higher priority
logic [$bits(racl_error_log_t)-1:0] racl_error_logic;
logic [NumAllIps-1:0] gnt;
racl_error_log_t racl_error_arb;
assign racl_error_arb = |combined_racl_error;
prim_arbiter_fixed #(
.N ( NumAllIps ),
.DW ( $bits(racl_error_log_t) )
) u_prim_err_arb (
.clk_i,
.rst_ni,
.req_i ( combined_racl_error_valid ),
.data_i ( combined_racl_error ),
.gnt_o ( gnt ),
.idx_o ( ),
.valid_o ( ),
.data_o ( racl_error_logic ),
.ready_i ( 1'b1 )
);
assign racl_error_arb = racl_error_log_t'(racl_error_logic);
// If there are multiple errors at the same time, we need to directly assert the
// overflow bit in the log. Se if another request is there besides out the masked granted one.
logic multiple_errors;
assign multiple_errors = racl_error_arb.valid & |(combined_racl_error_valid & ~gnt);
// 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 +197,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
1 change: 1 addition & 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,7 @@ filesets:
- lowrisc:ip:tlul
- lowrisc:prim:mubi
- lowrisc:prim:all
- lowrisc:prim:arbiter
- lowrisc:systems:top_racl_pkg
files:
- rtl/racl_ctrl_reg_pkg.sv
Expand Down
53 changes: 37 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 combined_racl_error[NumAllIps];

// 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,39 @@ 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 are multiple errors in the same cycle, arbitrate and get the first error.
// Lower index in combined_racl_error_valid has higher priority
logic [$bits(racl_error_log_t)-1:0] racl_error_logic;
logic [NumAllIps-1:0] gnt;
racl_error_log_t racl_error_arb;
assign racl_error_arb = |combined_racl_error;
prim_arbiter_fixed #(
.N ( NumAllIps ),
.DW ( $bits(racl_error_log_t) )
) u_prim_err_arb (
.clk_i,
.rst_ni,
.req_i ( combined_racl_error_valid ),
.data_i ( combined_racl_error ),
.gnt_o ( gnt ),
.idx_o ( ),
.valid_o ( ),
.data_o ( racl_error_logic ),
.ready_i ( 1'b1 )
);
assign racl_error_arb = racl_error_log_t'(racl_error_logic);

// If there are multiple errors at the same time, we need to directly assert the
// overflow bit in the log. Se if another request is there besides out the masked granted one.
logic multiple_errors;
assign multiple_errors = racl_error_arb.valid & |(combined_racl_error_valid & ~gnt);

// 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 +180,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 c85ca39

Please sign in to comment.