From a6e981a3014e63de3ca20ce228ba591cf6f56364 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Fri, 24 Nov 2023 15:08:04 +0100 Subject: [PATCH] routing: Add possibility to compute XY coordinates with a routing table --- Bender.yml | 1 + src/floo_axi_chimney.sv | 80 +++++++++++-------- src/floo_narrow_wide_chimney.sv | 131 ++++++++++++++------------------ src/floo_route_comp.sv | 72 ++++++++++++++++++ 4 files changed, 181 insertions(+), 103 deletions(-) create mode 100644 src/floo_route_comp.sv diff --git a/Bender.yml b/Bender.yml index 4fb033f8..58324b59 100644 --- a/Bender.yml +++ b/Bender.yml @@ -27,6 +27,7 @@ sources: - src/floo_fifo.sv - src/floo_cdc.sv - src/floo_route_select.sv + - src/floo_route_comp.sv - src/floo_vc_arbiter.sv - src/floo_wormhole_arbiter.sv - src/floo_simple_rob.sv diff --git a/src/floo_axi_chimney.sv b/src/floo_axi_chimney.sv index 40fc47b8..c2de29cd 100644 --- a/src/floo_axi_chimney.sv +++ b/src/floo_axi_chimney.sv @@ -26,13 +26,20 @@ module floo_axi_chimney parameter int unsigned MaxAtomicTxns = 1, /// Routing Algorithm parameter route_algo_e RouteAlgo = IdTable, + /// Whether to look up the coordinates in a table or + /// directly read them from the request address + parameter bit UseIdTable = 1'b0, /// X Coordinate address offset for XY routing parameter int unsigned XYAddrOffsetX = 0, /// Y Coordinate address offset for XY routing parameter int unsigned XYAddrOffsetY = 0, /// ID address offset for ID routing - parameter int unsigned IdTableAddrOffset = 8, - /// Number of maximum oustanding requests + parameter int unsigned IdAddrOffset = 0, + /// Number of Endpoints in the system, only used for Table based routing + parameter int unsigned NumIDs = 0, + /// Number of rules in the routing table, only used for Table based routing + parameter int unsigned NumRules = 0, + /// ID address offset for ID routing parameter int unsigned MaxTxns = 32, /// Maximum number of outstanding requests per ID parameter int unsigned MaxTxnsPerId = MaxTxns, @@ -40,12 +47,14 @@ module floo_axi_chimney parameter rob_type_e RoBType = NoRoB, /// Capacity of the reorder buffer parameter int unsigned ReorderBufferSize = 32, - /// Type of Coordinates/Id - parameter type id_t = logic, /// Cut timing paths of outgoing requests parameter bit CutAx = 1'b0, /// Cut timing paths of incoming responses parameter bit CutRsp = 1'b1, + /// Type of Coordinates/Id + parameter type id_t = logic, + /// Only used for IDRouting + parameter type id_rule_t = logic, /// Type for implementation inputs and outputs parameter type sram_cfg_t = logic ) ( @@ -60,6 +69,8 @@ module floo_axi_chimney input axi_out_rsp_t axi_out_rsp_i, /// Coordinates/ID of the current tile input id_t id_i, + /// Routing table + input id_rule_t[NumRules-1:0] id_map_i, /// Output to NoC output floo_req_t floo_req_o, output floo_rsp_t floo_rsp_o, @@ -349,33 +360,42 @@ module floo_axi_chimney // ROUTING // ///////////////// + typedef enum logic [1:0] {AwReq, ArReq, NumAddrDecoders} axi_req_ch_e; + + id_t axi_aw_id_q; + + axi_in_addr_t [NumAddrDecoders-1:0] addr_to_decode; + id_t [NumAddrDecoders-1:0] decoded_id; + assign addr_to_decode[AwReq] = axi_aw_queue.addr; + assign addr_to_decode[ArReq] = axi_ar_queue.addr; + + floo_route_comp #( + .RouteAlgo ( RouteAlgo ), + .UseIdTable ( UseIdTable ), + .XYAddrOffsetX ( XYAddrOffsetX ), + .XYAddrOffsetY ( XYAddrOffsetY ), + .IdAddrOffset ( IdAddrOffset ), + .NumIDs ( NumIDs ), + .NumRules ( NumRules ), + .id_t ( id_t ), + .id_rule_t ( id_rule_t ), + .addr_t ( axi_in_addr_t ) + ) i_floo_narrow_route_comp [NumAddrDecoders-1:0] ( + .clk_i, + .rst_ni, + .id_map_i, + .addr_i ( addr_to_decode ), + .id_o ( decoded_id ) + ); + + assign dst_id[AxiAw] = decoded_id[AwReq]; + assign dst_id[AxiW] = axi_aw_id_q; + assign dst_id[AxiAr] = decoded_id[ArReq]; + assign dst_id[AxiB] = aw_out_data_out.src_id; + assign dst_id[AxiR] = ar_out_data_out.src_id; + `FFL(axi_aw_id_q, dst_id[AxiAw], axi_aw_queue_valid_out && + axi_aw_queue_ready_in, '0) - if (RouteAlgo == XYRouting) begin : gen_xy_routing - id_t aw_xy_id_q, aw_xy_id, ar_xy_id; - assign aw_xy_id.x = axi_aw_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign aw_xy_id.y = axi_aw_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign ar_xy_id.x = axi_ar_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign ar_xy_id.y = axi_ar_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign dst_id[AxiAw] = aw_xy_id; - assign dst_id[AxiAr] = ar_xy_id; - assign dst_id[AxiW] = aw_xy_id_q; - assign dst_id[AxiB] = aw_out_data_out.src_id; - assign dst_id[AxiR] = ar_out_data_out.src_id; - `FFL(aw_xy_id_q, aw_xy_id, axi_aw_queue_valid_out && axi_aw_queue_ready_in, '0) - end else if (RouteAlgo == IdTable) begin : gen_id_table_routing - id_t aw_id_q, aw_id, ar_id; - assign aw_id = axi_aw_queue.addr[IdTableAddrOffset+:$bits(id_i)]; - assign ar_id = axi_ar_queue.addr[IdTableAddrOffset+:$bits(id_i)]; - assign dst_id[AxiAw] = aw_id; - assign dst_id[AxiAr] = ar_id; - assign dst_id[AxiW] = aw_id_q; - assign dst_id[AxiB] = aw_out_data_out.src_id; - assign dst_id[AxiR] = ar_out_data_out.src_id; - `FFL(aw_id_q, aw_id, axi_aw_queue_valid_out && axi_aw_queue_ready_in, '0) - end else begin : gen_no_routing - // TODO: Implement other routing algorithms - $fatal(1, "Routing algorithm not implemented"); - end /////////////////// // FLIT PACKING // diff --git a/src/floo_narrow_wide_chimney.sv b/src/floo_narrow_wide_chimney.sv index bf27da62..b34dd3b8 100644 --- a/src/floo_narrow_wide_chimney.sv +++ b/src/floo_narrow_wide_chimney.sv @@ -31,10 +31,19 @@ module floo_narrow_wide_chimney parameter int unsigned MaxAtomicTxns = 1, /// Routing Algorithm parameter route_algo_e RouteAlgo = IdTable, + /// Whether to look up the coordinates in a table or + /// directly read them from the request address with an offset + parameter bit UseIdTable = 1'b0, /// X Coordinate address offset for XY routing parameter int unsigned XYAddrOffsetX = 0, /// Y Coordinate address offset for XY routing parameter int unsigned XYAddrOffsetY = 0, + /// ID address offset for ID routing + parameter int unsigned IdAddrOffset = 0, + /// Number of Endpoints in the system, only used for Table based routing + parameter int unsigned NumIDs = 0, + /// Number of rules in the routing table, only used for Table based routing + parameter int unsigned NumRules = 0, /// Number of maximum oustanding requests on the narrow network parameter int unsigned NarrowMaxTxns = 32, /// Number of maximum oustanding requests on the wide network @@ -59,8 +68,6 @@ module floo_narrow_wide_chimney parameter type id_t = logic, /// Only used for IDRouting parameter type id_rule_t = logic, - parameter int unsigned NumIDs = 1, - parameter int unsigned NumRules = NumIDs, /// Type for implementation inputs and outputs parameter type sram_cfg_t = logic ) ( @@ -603,78 +610,51 @@ module floo_narrow_wide_chimney // ROUTING // ///////////////// + typedef enum logic [2:0] {NarrowAwReq, NarrowArReq, WideAwReq, WideArReq, NumAddrDecoders} axi_req_ch_e; + typedef axi_narrow_in_addr_t addr_t; + + id_t narrow_aw_id_q, wide_aw_id_q; + + addr_t [NumAddrDecoders-1:0] addr_to_decode; + id_t [NumAddrDecoders-1:0] decoded_id; + assign addr_to_decode[NarrowAwReq] = axi_narrow_aw_queue.addr; + assign addr_to_decode[NarrowArReq] = axi_narrow_ar_queue.addr; + assign addr_to_decode[WideAwReq] = axi_wide_aw_queue.addr; + assign addr_to_decode[WideArReq] = axi_wide_ar_queue.addr; + + floo_route_comp #( + .RouteAlgo ( RouteAlgo ), + .UseIdTable ( UseIdTable ), + .XYAddrOffsetX ( XYAddrOffsetX ), + .XYAddrOffsetY ( XYAddrOffsetY ), + .IdAddrOffset ( IdAddrOffset ), + .NumIDs ( NumIDs ), + .NumRules ( NumRules ), + .id_t ( id_t ), + .id_rule_t ( id_rule_t ), + .addr_t ( addr_t ) + ) i_floo_narrow_route_comp [NumAddrDecoders-1:0] ( + .clk_i, + .rst_ni, + .id_map_i, + .addr_i ( addr_to_decode ), + .id_o ( decoded_id ) + ); - if (RouteAlgo == XYRouting) begin : gen_xy_routing - id_t narrow_aw_xy_id_q, narrow_aw_xy_id, narrow_ar_xy_id; - id_t wide_aw_xy_id_q, wide_aw_xy_id, wide_ar_xy_id; - assign narrow_aw_xy_id.x = axi_narrow_aw_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign narrow_aw_xy_id.y = axi_narrow_aw_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign narrow_ar_xy_id.x = axi_narrow_ar_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign narrow_ar_xy_id.y = axi_narrow_ar_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign wide_aw_xy_id.x = axi_wide_aw_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign wide_aw_xy_id.y = axi_wide_aw_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign wide_ar_xy_id.x = axi_wide_ar_queue.addr[XYAddrOffsetX+:$bits(id_i.x)]; - assign wide_ar_xy_id.y = axi_wide_ar_queue.addr[XYAddrOffsetY+:$bits(id_i.y)]; - assign dst_id[NarrowAw] = narrow_aw_xy_id; - assign dst_id[NarrowAr] = narrow_ar_xy_id; - assign dst_id[NarrowW] = narrow_aw_xy_id_q; - assign dst_id[NarrowB] = narrow_aw_out_data_out.src_id; - assign dst_id[NarrowR] = narrow_ar_out_data_out.src_id; - assign dst_id[WideAw] = wide_aw_xy_id; - assign dst_id[WideAr] = wide_ar_xy_id; - assign dst_id[WideW] = wide_aw_xy_id_q; - assign dst_id[WideB] = wide_aw_out_data_out.src_id; - assign dst_id[WideR] = wide_ar_out_data_out.src_id; - `FFL(narrow_aw_xy_id_q,narrow_aw_xy_id, axi_narrow_aw_queue_valid_out && - axi_narrow_aw_queue_ready_in,'0) - `FFL(wide_aw_xy_id_q, wide_aw_xy_id, axi_wide_aw_queue_valid_out && - axi_wide_aw_queue_ready_in, '0) - end else if (RouteAlgo == IdTable) begin : gen_id_table_routing - typedef enum logic [1:0] {NarrowAwReq, NarrowArReq, WideAwReq, WideArReq} axi_req_ch_e; - id_t narrow_aw_id_q, wide_aw_id_q; - axi_narrow_in_addr_t [WideArReq:NarrowAwReq] decode_addr_in; - id_t [WideArReq:NarrowAwReq] dst_addr_out; - - assign decode_addr_in[NarrowAwReq] = axi_narrow_aw_queue.addr; - assign decode_addr_in[NarrowArReq] = axi_narrow_ar_queue.addr; - assign decode_addr_in[WideAwReq] = axi_wide_aw_queue.addr; - assign decode_addr_in[WideArReq] = axi_wide_ar_queue.addr; - - addr_decode #( - .NoIndices ( NumIDs ), - .NoRules ( NumRules ), - .addr_t ( axi_narrow_in_addr_t ), - .rule_t ( id_rule_t ), - .idx_t ( id_t ) - ) i_addr_dst_decode [3:0] ( - .addr_i ( decode_addr_in ), - .addr_map_i ( id_map_i ), - .idx_o ( dst_addr_out ), - .dec_valid_o ( ), - .dec_error_o ( ), - .en_default_idx_i ( 1'b0 ), - .default_idx_i ( '0 ) - ); - - assign src_id = id_i; - assign dst_id[NarrowAw] = dst_addr_out[NarrowAwReq]; - assign dst_id[NarrowW] = narrow_aw_id_q; - assign dst_id[NarrowAr] = dst_addr_out[NarrowArReq]; - assign dst_id[NarrowB] = narrow_aw_out_data_out.src_id; - assign dst_id[NarrowR] = narrow_ar_out_data_out.src_id; - assign dst_id[WideAw] = dst_addr_out[WideAwReq]; - assign dst_id[WideW] = wide_aw_id_q; - assign dst_id[WideAr] = dst_addr_out[WideArReq]; - assign dst_id[WideB] = wide_aw_out_data_out.src_id; - assign dst_id[WideR] = wide_ar_out_data_out.src_id; - `FFL(narrow_aw_id_q, dst_id[NarrowAw], axi_narrow_aw_queue_valid_out && - axi_narrow_aw_queue_ready_in, '0) - `FFL(wide_aw_id_q, dst_id[WideAw], axi_wide_aw_queue_valid_out && - axi_wide_aw_queue_ready_in, '0) - end else begin : gen_no_routing - // TODO: Implement other routing algorithms - $fatal(1, "Routing algorithm not implemented"); - end + assign dst_id[NarrowAw] = decoded_id[NarrowAwReq]; + assign dst_id[NarrowW] = narrow_aw_id_q; + assign dst_id[NarrowAr] = decoded_id[NarrowArReq]; + assign dst_id[NarrowB] = narrow_aw_out_data_out.src_id; + assign dst_id[NarrowR] = narrow_ar_out_data_out.src_id; + assign dst_id[WideAw] = decoded_id[WideAwReq]; + assign dst_id[WideW] = wide_aw_id_q; + assign dst_id[WideAr] = decoded_id[WideArReq]; + assign dst_id[WideB] = wide_aw_out_data_out.src_id; + assign dst_id[WideR] = wide_ar_out_data_out.src_id; + `FFL(narrow_aw_id_q, dst_id[NarrowAw], axi_narrow_aw_queue_valid_out && + axi_narrow_aw_queue_ready_in, '0) + `FFL(wide_aw_id_q, dst_id[WideAw], axi_wide_aw_queue_valid_out && + axi_wide_aw_queue_ready_in, '0) /////////////////// // FLIT PACKING // @@ -1153,6 +1133,11 @@ module floo_narrow_wide_chimney `ASSERT_INIT(NoNarrowSbrPortRobType, EnNarrowSbrPort || (NarrowRoBType == NoRoB)) `ASSERT_INIT(NoWideSbrPortRobType, EnWideSbrPort || (WideRoBType == NoRoB)) + // Check that all addresses have the same width + `ASSERT_INIT(SameAddrWidth1, NarrowInAddrWidth == NarrowOutAddrWidth) + `ASSERT_INIT(SameAddrWidth2, WideInAddrWidth == NarrowOutAddrWidth) + `ASSERT_INIT(SameAddrWidth3, WideInAddrWidth == WideOutAddrWidth) + // Data and valid signals must be stable/asserted when ready is low `ASSERT(NarrowReqOutStableValid, floo_req_o.valid && !floo_req_i.ready |=> floo_req_o.valid) diff --git a/src/floo_route_comp.sv b/src/floo_route_comp.sv new file mode 100644 index 00000000..8da50dee --- /dev/null +++ b/src/floo_route_comp.sv @@ -0,0 +1,72 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Author: Tim Fischer + +`include "common_cells/assertions.svh" + +module floo_route_comp + import floo_pkg::*; +#( + /// The type of routing algorithms to use + parameter route_algo_e RouteAlgo = IdTable, + /// Whether to use a routing table with address decoder + /// In case of XY Routing or the coordinates should be + /// directly read from the request address + parameter bit UseIdTable = 1'b1, + /// The offset bit to read the X coordinate from + parameter int unsigned XYAddrOffsetX = 0, + /// The offset bit to read the Y coordinate from + parameter int unsigned XYAddrOffsetY = 0, + /// The offset bit to read the ID from + parameter int unsigned IdAddrOffset = 0, + /// The number of possible endpoints + parameter int unsigned NumIDs = 0, + /// The number of possible rules + parameter int unsigned NumRules = 0, + /// The type of the coordinates or IDs + parameter type id_t = logic, + /// The type of the rules + parameter type id_rule_t = logic, + /// The address type + parameter type addr_t = logic +) ( + input logic clk_i, + input logic rst_ni, + input addr_t addr_i, + input id_rule_t [NumRules-1:0] id_map_i, + output id_t id_o +); + + if (UseIdTable && ((RouteAlgo == IdTable) || (RouteAlgo == XYRouting))) + begin : gen_table_routing + logic dec_error; + + addr_decode #( + .NoIndices ( NumIDs ), + .NoRules ( NumRules ), + .addr_t ( addr_t ), + .rule_t ( id_rule_t ), + .idx_t ( id_t ) + ) i_addr_dst_decode ( + .addr_i ( addr_i ), + .addr_map_i ( id_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) + end else if (RouteAlgo == XYRouting) begin : gen_xy_bits_routing + assign id_o.x = addr_i[XYAddrOffsetX +: $bits(id_o.x)]; + assign id_o.y = addr_i[XYAddrOffsetY +: $bits(id_o.y)]; + end else if (RouteAlgo == IdTable) begin : gen_id_bits_routing + assign id_o = addr_i[IdAddrOffset +: $bits(id_o)]; + end else begin : gen_error + $fatal(1, "Routing algorithm not implemented"); + end + +endmodule