Skip to content

Commit

Permalink
Add AXI error slave to network interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yvan Tortorella committed Oct 8, 2024
1 parent b139479 commit c8cde8a
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 37 deletions.
48 changes: 36 additions & 12 deletions hw/floo_axi_chimney.sv
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ module floo_axi_chimney #(
// Duplicate AXI port signals to degenerate ports
// in case they are not used
axi_req_t axi_req_in;
axi_rsp_t axi_rsp_out;
axi_rsp_t axi_rsp_out, axi_in_rsp_err;

// AX queue
axi_aw_chan_t axi_aw_queue;
Expand Down Expand Up @@ -158,14 +158,30 @@ module floo_axi_chimney #(
meta_buf_t aw_out_hdr_in, aw_out_hdr_out;
meta_buf_t ar_out_hdr_in, ar_out_hdr_out;

// Error signals from AR/AW address decoders
logic [NumAxiChannels-1:0] decode_error_d, decode_error_q;
///////////////////////
// Spill registers //
///////////////////////

if (ChimneyCfg.EnMgrPort) begin : gen_sbr_port

assign axi_req_in = axi_in_req_i;
assign axi_in_rsp_o = axi_rsp_out;
assign axi_in_rsp_o = (decode_error_q[AxiAr] || decode_error_q[AxiAw]) ? axi_in_rsp_err :
axi_rsp_out;

axi_err_slv #(
.AxiIdWidth ( AxiCfg.InIdWidth ),
.ATOPs ( AtopSupport ),
.axi_req_t ( axi_in_req_t ),
.axi_resp_t ( axi_in_rsp_t )
) i_axi_err_slv (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_i ( test_enable_i ),
.slv_req_i ( axi_in_req_i ),
.slv_resp_o ( axi_in_rsp_err )
);

if (ChimneyCfg.CutAx) begin : gen_ax_cuts
spill_register #(
Expand Down Expand Up @@ -193,6 +209,9 @@ module floo_axi_chimney #(
.valid_o ( axi_ar_queue_valid_out ),
.ready_i ( axi_ar_queue_ready_in )
);

`FF(decode_error_q[AxiAr], decode_error_d[AxiAr], '0)
`FF(decode_error_q[AxiAw], decode_error_d[AxiAw], '0)
end else begin : gen_no_ax_cuts
assign axi_aw_queue = axi_in_req_i.aw;
assign axi_aw_queue_valid_out = axi_in_req_i.aw_valid;
Expand All @@ -201,6 +220,9 @@ module floo_axi_chimney #(
assign axi_ar_queue = axi_in_req_i.ar;
assign axi_ar_queue_valid_out = axi_in_req_i.ar_valid;
assign axi_rsp_out.ar_ready = axi_ar_queue_ready_in;

assign decode_error_q[AxiAr] = decode_error_d[AxiAr];
assign decode_error_q[AxiAw] = decode_error_d[AxiAw];
end
end else begin : gen_err_slv_port
axi_err_slv #(
Expand Down Expand Up @@ -398,11 +420,12 @@ module floo_axi_chimney #(
.clk_i,
.rst_ni,
.route_table_i,
.addr_map_i ( Sam ),
.id_i ( id_t'('0) ),
.addr_i ( axi_req_addr[ch] ),
.route_o ( route_out[ch] ),
.id_o ( id_out[ch] )
.addr_map_i ( Sam ),
.id_i ( id_t'('0) ),
.addr_i ( axi_req_addr[ch] ),
.route_o ( route_out[ch] ),
.id_o ( id_out[ch] ),
.decode_error_o ( decode_error_d[ch] )
);
end else if (RouteCfg.RouteAlgo == floo_pkg::SourceRouting &&
(Ch == AxiB || Ch == AxiR)) begin : gen_rsp_route_comp
Expand All @@ -420,11 +443,12 @@ module floo_axi_chimney #(
.clk_i,
.rst_ni,
.route_table_i,
.addr_i ( '0 ),
.addr_map_i ( '0 ),
.id_i ( axi_rsp_src_id[ch] ),
.route_o ( route_out[ch] ),
.id_o ( id_out[ch] )
.addr_i ( '0 ),
.addr_map_i ( Sam ),
.id_i ( axi_rsp_src_id[ch] ),
.route_o ( route_out[ch] ),
.id_o ( id_out[ch] ),
.decode_error_o ( decode_error_d[ch] )
);
end
end
Expand Down
49 changes: 24 additions & 25 deletions hw/floo_route_comp.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ module floo_route_comp
input addr_rule_t [RouteCfg.NumSamRules-1:0] addr_map_i,
input route_t [RouteCfg.NumRoutes-1:0] route_table_i,
output route_t route_o,
output id_t id_o
output id_t id_o,
output logic decode_error_o
);

// Use an address decoder to map the address to a destination ID.
Expand All @@ -36,42 +37,40 @@ module floo_route_comp
// Further, the `rule_t` requires an additional field `id`, which can be used for the return route.
// The reason for that is that a request destination is given by a physical address, while the
// response destination is given by the ID of the source.

id_t addr_decode_id;

addr_decode #(
.NoIndices ( RouteCfg.NumRoutes ),
.NoRules ( RouteCfg.NumSamRules ),
.addr_t ( addr_t ),
.rule_t ( addr_rule_t ),
.idx_t ( id_t )
) i_addr_dst_decode (
.addr_i ( addr_i ),
.addr_map_i ( addr_map_i ),
.idx_o ( addr_decode_id ),
.dec_valid_o ( ),
.dec_error_o ( decode_error_o ),
.en_default_idx_i ( 1'b0 ),
.default_idx_i ( '0 )
);

if (UseIdTable &&
((RouteCfg.RouteAlgo == IdTable) ||
(RouteCfg.RouteAlgo == XYRouting) ||
(RouteCfg.RouteAlgo == SourceRouting)))
begin : gen_table_routing
logic dec_error;

// This is simply to pass the assertions in addr_decode
// It is not used otherwise, since we specify `idx_t`
localparam int unsigned MaxPossibleId = 1 << $bits(id_o);

addr_decode #(
.NoIndices ( MaxPossibleId ),
.NoRules ( RouteCfg.NumSamRules ),
.addr_t ( addr_t ),
.rule_t ( addr_rule_t ),
.idx_t ( id_t )
) i_addr_dst_decode (
.addr_i ( addr_i ),
.addr_map_i ( addr_map_i ),
.idx_o ( id_o ),
.dec_valid_o ( ),
.dec_error_o ( dec_error ),
.en_default_idx_i ( 1'b0 ),
.default_idx_i ( '0 )
);

`ASSERT(DecodeError, !dec_error)
assign id_o = addr_decode_id;
end else if (RouteCfg.RouteAlgo == XYRouting) begin : gen_xy_bits_routing
assign id_o.port_id = '0;
assign id_o.x = addr_i[RouteCfg.XYAddrOffsetX +: $bits(id_o.x)];
assign id_o.y = addr_i[RouteCfg.XYAddrOffsetY +: $bits(id_o.y)];
end else if (RouteCfg.RouteAlgo == IdTable) begin : gen_id_bits_routing
assign id_o = addr_i[RouteCfg.IdAddrOffset +: $bits(id_o)];
end else if (RouteCfg.RouteAlgo == SourceRouting) begin : gen_source_routing
// Nothing to do here
// Default the ID output to 0
assign id_o = '0;
end else begin : gen_error
$fatal(1, "Routing algorithm not implemented");
end
Expand Down

0 comments on commit c8cde8a

Please sign in to comment.