Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AXI error slave to network interface. #79

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading