From 06a7490d923d20a4b1c31b728f60356e27c1a288 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 10 Dec 2024 15:58:57 +0100 Subject: [PATCH 1/4] hw(chimney): Cut AW out paths --- hw/floo_axi_chimney.sv | 1 - hw/floo_nw_chimney.sv | 28 +++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/hw/floo_axi_chimney.sv b/hw/floo_axi_chimney.sv index 275dd758..fb830984 100644 --- a/hw/floo_axi_chimney.sv +++ b/hw/floo_axi_chimney.sv @@ -206,7 +206,6 @@ module floo_axi_chimney #( assign axi_ar_queue_valid_out = axi_in_req_i.ar_valid; assign axi_rsp_out.ar_ready = axi_ar_queue_ready_in; end - end else begin : gen_err_slv_port axi_err_slv #( .AxiIdWidth ( AxiCfg.InIdWidth ), diff --git a/hw/floo_nw_chimney.sv b/hw/floo_nw_chimney.sv index 6da15334..66168df7 100644 --- a/hw/floo_nw_chimney.sv +++ b/hw/floo_nw_chimney.sv @@ -271,6 +271,33 @@ module floo_nw_chimney #( assign axi_narrow_rsp_out.ar_ready = axi_narrow_ar_queue_ready_in; end + logic narrow_aw_out_queue_valid, narrow_aw_out_queue_ready; + axi_narrow_out_aw_chan_t axi_narrow_aw_queue_out; + + // Since AW and W are transferred over the same link, it can happen that + // a downstream module does not accept the AW until the W is valid. + // Therefore, we need to add a spill register for the AW channel. + spill_register #( + .T (axi_narrow_out_aw_chan_t) + ) i_aw_narrow_out_queue ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( axi_narrow_meta_buf_req_out.aw_valid ), + .ready_o ( narrow_aw_out_queue_ready ), + .data_i ( axi_narrow_meta_buf_req_out.aw ), + .valid_o ( narrow_aw_out_queue_valid ), + .ready_i ( axi_narrow_out_rsp_i.aw_ready ), + .data_o ( axi_narrow_aw_queue_out ) + ); + + always_comb begin + axi_narrow_out_req_o = axi_narrow_meta_buf_req_out; + axi_narrow_out_req_o.aw_valid = narrow_aw_out_queue_valid; + axi_narrow_out_req_o.aw = axi_narrow_aw_queue_out; + axi_narrow_meta_buf_rsp_in = axi_narrow_out_rsp_i; + axi_narrow_meta_buf_rsp_in.aw_ready = narrow_aw_out_queue_ready; + end + end else begin : gen_narrow_err_slv_port axi_err_slv #( .AxiIdWidth ( AxiCfgN.InIdWidth ), @@ -330,7 +357,6 @@ module floo_nw_chimney #( assign axi_wide_ar_queue_valid_out = axi_wide_in_req_i.ar_valid; assign axi_wide_rsp_out.ar_ready = axi_wide_ar_queue_ready_in; end - end else begin : gen_wide_err_slv_port axi_err_slv #( .AxiIdWidth ( AxiCfgW.InIdWidth ), From 0d8068f0ca673936ded4f215908dca61eaa8d508 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Tue, 10 Dec 2024 17:57:03 +0100 Subject: [PATCH 2/4] hw(chimney): Fix location of AW cuts --- hw/floo_nw_chimney.sv | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/hw/floo_nw_chimney.sv b/hw/floo_nw_chimney.sv index 66168df7..4ba45089 100644 --- a/hw/floo_nw_chimney.sv +++ b/hw/floo_nw_chimney.sv @@ -271,33 +271,6 @@ module floo_nw_chimney #( assign axi_narrow_rsp_out.ar_ready = axi_narrow_ar_queue_ready_in; end - logic narrow_aw_out_queue_valid, narrow_aw_out_queue_ready; - axi_narrow_out_aw_chan_t axi_narrow_aw_queue_out; - - // Since AW and W are transferred over the same link, it can happen that - // a downstream module does not accept the AW until the W is valid. - // Therefore, we need to add a spill register for the AW channel. - spill_register #( - .T (axi_narrow_out_aw_chan_t) - ) i_aw_narrow_out_queue ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( axi_narrow_meta_buf_req_out.aw_valid ), - .ready_o ( narrow_aw_out_queue_ready ), - .data_i ( axi_narrow_meta_buf_req_out.aw ), - .valid_o ( narrow_aw_out_queue_valid ), - .ready_i ( axi_narrow_out_rsp_i.aw_ready ), - .data_o ( axi_narrow_aw_queue_out ) - ); - - always_comb begin - axi_narrow_out_req_o = axi_narrow_meta_buf_req_out; - axi_narrow_out_req_o.aw_valid = narrow_aw_out_queue_valid; - axi_narrow_out_req_o.aw = axi_narrow_aw_queue_out; - axi_narrow_meta_buf_rsp_in = axi_narrow_out_rsp_i; - axi_narrow_meta_buf_rsp_in.aw_ready = narrow_aw_out_queue_ready; - end - end else begin : gen_narrow_err_slv_port axi_err_slv #( .AxiIdWidth ( AxiCfgN.InIdWidth ), From 66d471cb7b98c3c2f5416a5d5a91e2543703423e Mon Sep 17 00:00:00 2001 From: zexinfu Date: Wed, 19 Mar 2025 19:14:58 +0100 Subject: [PATCH 3/4] Merge Terapool-NoC adaptive routing supports (#112) * hw: Add support for YX-Routing * hw: Add support for O1-Routing (XY/YX according to VC id) * hw: Add support for Odd-Even-Routing * [lint] All generate block statements must have a label. --------- Co-authored-by: Yinrong Li --- hw/floo_pkg.sv | 7 ++- hw/floo_route_select.sv | 75 ++++++++++++++++++++++++++++++++ hw/floo_router.sv | 96 +++++++++++++++++++++++++++++++---------- 3 files changed, 154 insertions(+), 24 deletions(-) diff --git a/hw/floo_pkg.sv b/hw/floo_pkg.sv index 44b74e39..a94bedbd 100644 --- a/hw/floo_pkg.sv +++ b/hw/floo_pkg.sv @@ -10,7 +10,7 @@ package floo_pkg; /// Currently Supported Routing Algorithms - typedef enum logic[1:0] { + typedef enum logic[2:0] { /// `IdTable` routing uses a table of routing rules to determine to /// which output port a packet should be routed, based on the /// destination ID encoded in the header of the flit. Every router @@ -35,7 +35,10 @@ package floo_pkg; /// XY coordinates, which can be done with addressoffsets `XYAddrOffsetX` /// and `XYAddrOffsetY`, or by indexing the system address map `Sam`. This /// is controlled with the `UseIdTable` parameter. - XYRouting + XYRouting, + YXRouting, + OddEvenRouting, + O1Routing } route_algo_e; /// The directions in a 2D mesh network, mainly useful for indexing diff --git a/hw/floo_route_select.sv b/hw/floo_route_select.sv index ddfb932e..03e78ab6 100644 --- a/hw/floo_route_select.sv +++ b/hw/floo_route_select.sv @@ -121,6 +121,81 @@ if (RouteAlgo == IdTable) begin : gen_id_table assign channel_o = channel_i; + end else if (RouteAlgo == YXRouting) begin : gen_yx_routing + + id_t id_in; + assign id_in = id_t'(channel_i.hdr.dst_id); + + always_comb begin : proc_route_sel + route_sel = '0; + if (id_in == xy_id_i) begin + route_sel[Eject] = 1'b1; + end else if (id_in.y == xy_id_i.y) begin + if (id_in.x < xy_id_i.x) begin + route_sel[West] = 1'b1; + end else begin + route_sel[East] = 1'b1; + end + end else begin + if (id_in.y < xy_id_i.y) begin + route_sel[South] = 1'b1; + end else begin + route_sel[North] = 1'b1; + end + end + end + + assign channel_o = channel_i; + + end else if (RouteAlgo == OddEvenRouting) begin : gen_oddeven_routing + id_t id_src, id_dst; + assign id_src = id_t'(channel_i.hdr.src_id); + assign id_dst = id_t'(channel_i.hdr.dst_id); + + always_comb begin : proc_route_sel + route_sel = '0; + if (xy_id_i == id_dst) begin + route_sel[Eject] = 1'b1; + end else if (xy_id_i.x == id_dst.x) begin //currently in the same column as destination + if (xy_id_i.y < id_dst.y) begin + route_sel[North] = 1'b1; + end else begin + route_sel[South] = 1'b1; + end + end else if (xy_id_i.x < id_dst.x) begin //eastbound traffic + if (xy_id_i.y == id_dst.y) begin + route_sel[East] = 1'b1; + end else if (((xy_id_i.x % 2) == 1) || (xy_id_i.x == id_src.x)) begin + if ((((id_dst.x) % 2 == 1) || ((id_dst.x - xy_id_i.x) != 1)) && (^channel_i)) begin + route_sel[East] = 1'b1; + end else begin + if (xy_id_i.y < id_dst.y) begin + route_sel[North] = 1'b1; + end else begin + route_sel[South] = 1'b1; + end + end + end else begin + assert ((id_dst.x % 2 == 1) || (id_dst.x - xy_id_i.x != 1)); + route_sel[East] = 1'b1; + end + end else begin //westbound traffic + if (xy_id_i.y == id_dst.y) begin + route_sel[West] = 1'b1; + end else if (((xy_id_i.x % 2) == 0) && (^channel_i)) begin + if (xy_id_i.y < id_dst.y) begin + route_sel[North] = 1'b1; + end else begin + route_sel[South] = 1'b1; + end + end else begin + route_sel[West] = 1'b1; + end + end + end + + assign channel_o = channel_i; + end else begin : gen_err // Unknown or unimplemented routing otherwise initial begin diff --git a/hw/floo_router.sv b/hw/floo_router.sv index 323b7be8..b1e3695a 100644 --- a/hw/floo_router.sv +++ b/hw/floo_router.sv @@ -83,28 +83,80 @@ module floo_router .ready_i ( in_ready[in_route][v_chan] ) ); - floo_route_select #( - .NumRoutes ( NumOutput ), - .flit_t ( flit_t ), - .RouteAlgo ( RouteAlgo ), - .IdWidth ( IdWidth ), - .id_t ( id_t ), - .NumAddrRules ( NumAddrRules ), - .addr_rule_t ( addr_rule_t ) - ) i_route_select ( - .clk_i, - .rst_ni, - .test_enable_i, - - .xy_id_i ( xy_id_i ), - .id_route_map_i ( id_route_map_i ), - .channel_i ( in_data [in_route][v_chan] ), - .valid_i ( in_valid [in_route][v_chan] ), - .ready_i ( in_ready [in_route][v_chan] ), - .channel_o ( in_routed_data[in_route][v_chan] ), - .route_sel_o ( route_mask [in_route][v_chan] ), - .route_sel_id_o ( ) - ); + if (RouteAlgo == O1Routing) begin: gen_o1routing + + if (v_chan % 2 == 0) begin: gen_o1routing_xy + floo_route_select #( + .NumRoutes ( NumOutput ), + .flit_t ( flit_t ), + .RouteAlgo ( XYRouting ), + .IdWidth ( IdWidth ), + .id_t ( id_t ), + .NumAddrRules ( NumAddrRules ), + .addr_rule_t ( addr_rule_t ) + ) i_route_select ( + .clk_i, + .rst_ni, + .test_enable_i, + + .xy_id_i ( xy_id_i ), + .id_route_map_i ( id_route_map_i ), + .channel_i ( in_data [in_route][v_chan] ), + .valid_i ( in_valid [in_route][v_chan] ), + .ready_i ( in_ready [in_route][v_chan] ), + .channel_o ( in_routed_data[in_route][v_chan] ), + .route_sel_o ( route_mask [in_route][v_chan] ) + ); + end else begin: gen_o1routing_yx + floo_route_select #( + .NumRoutes ( NumOutput ), + .flit_t ( flit_t ), + .RouteAlgo ( YXRouting ), + .IdWidth ( IdWidth ), + .id_t ( id_t ), + .NumAddrRules ( NumAddrRules ), + .addr_rule_t ( addr_rule_t ) + ) i_route_select ( + .clk_i, + .rst_ni, + .test_enable_i, + + .xy_id_i ( xy_id_i ), + .id_route_map_i ( id_route_map_i ), + .channel_i ( in_data [in_route][v_chan] ), + .valid_i ( in_valid [in_route][v_chan] ), + .ready_i ( in_ready [in_route][v_chan] ), + .channel_o ( in_routed_data[in_route][v_chan] ), + .route_sel_o ( route_mask [in_route][v_chan] ) + ); + end + + end else begin: gen_xyrouting + + floo_route_select #( + .NumRoutes ( NumOutput ), + .flit_t ( flit_t ), + .RouteAlgo ( RouteAlgo ), + .IdWidth ( IdWidth ), + .id_t ( id_t ), + .NumAddrRules ( NumAddrRules ), + .addr_rule_t ( addr_rule_t ) + ) i_route_select ( + .clk_i, + .rst_ni, + .test_enable_i, + + .xy_id_i ( xy_id_i ), + .id_route_map_i ( id_route_map_i ), + .channel_i ( in_data [in_route][v_chan] ), + .valid_i ( in_valid [in_route][v_chan] ), + .ready_i ( in_ready [in_route][v_chan] ), + .channel_o ( in_routed_data[in_route][v_chan] ), + .route_sel_o ( route_mask [in_route][v_chan] ), + .route_sel_id_o ( ) + ); + + end end end From 3b2f7bfd1a648d6757b640610ba748cd33904fc7 Mon Sep 17 00:00:00 2001 From: No Matter No Date: Fri, 28 Mar 2025 14:39:19 +0100 Subject: [PATCH 4/4] Update yx-routing and oe-routing to fit new router_select design. (#115) --- hw/floo_route_select.sv | 46 ++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/hw/floo_route_select.sv b/hw/floo_route_select.sv index 03e78ab6..81d13362 100644 --- a/hw/floo_route_select.sv +++ b/hw/floo_route_select.sv @@ -127,22 +127,24 @@ if (RouteAlgo == IdTable) begin : gen_id_table assign id_in = id_t'(channel_i.hdr.dst_id); always_comb begin : proc_route_sel - route_sel = '0; - if (id_in == xy_id_i) begin - route_sel[Eject] = 1'b1; + route_sel_id = East; + if (id_in.x == xy_id_i.x && id_in.y == xy_id_i.y) begin + route_sel_id = Eject + channel_i.hdr.dst_id.port_id; end else if (id_in.y == xy_id_i.y) begin if (id_in.x < xy_id_i.x) begin - route_sel[West] = 1'b1; + route_sel_id = West; end else begin - route_sel[East] = 1'b1; + route_sel_id = East; end end else begin if (id_in.y < xy_id_i.y) begin - route_sel[South] = 1'b1; + route_sel_id = South; end else begin - route_sel[North] = 1'b1; + route_sel_id = North; end end + route_sel = '0; + route_sel[route_sel_id] = 1'b1; end assign channel_o = channel_i; @@ -153,45 +155,47 @@ if (RouteAlgo == IdTable) begin : gen_id_table assign id_dst = id_t'(channel_i.hdr.dst_id); always_comb begin : proc_route_sel - route_sel = '0; - if (xy_id_i == id_dst) begin - route_sel[Eject] = 1'b1; + route_sel_id = East; + if (id_dst.x == xy_id_i.x && id_dst.y == xy_id_i.y) begin + route_sel_id = Eject + channel_i.hdr.dst_id.port_id; end else if (xy_id_i.x == id_dst.x) begin //currently in the same column as destination if (xy_id_i.y < id_dst.y) begin - route_sel[North] = 1'b1; + route_sel_id = North; end else begin - route_sel[South] = 1'b1; + route_sel_id = South; end end else if (xy_id_i.x < id_dst.x) begin //eastbound traffic if (xy_id_i.y == id_dst.y) begin - route_sel[East] = 1'b1; + route_sel_id = East; end else if (((xy_id_i.x % 2) == 1) || (xy_id_i.x == id_src.x)) begin if ((((id_dst.x) % 2 == 1) || ((id_dst.x - xy_id_i.x) != 1)) && (^channel_i)) begin - route_sel[East] = 1'b1; + route_sel_id = East; end else begin if (xy_id_i.y < id_dst.y) begin - route_sel[North] = 1'b1; + route_sel_id = North; end else begin - route_sel[South] = 1'b1; + route_sel_id = South; end end end else begin assert ((id_dst.x % 2 == 1) || (id_dst.x - xy_id_i.x != 1)); - route_sel[East] = 1'b1; + route_sel_id = East; end end else begin //westbound traffic if (xy_id_i.y == id_dst.y) begin - route_sel[West] = 1'b1; + route_sel_id = West; end else if (((xy_id_i.x % 2) == 0) && (^channel_i)) begin if (xy_id_i.y < id_dst.y) begin - route_sel[North] = 1'b1; + route_sel_id = North; end else begin - route_sel[South] = 1'b1; + route_sel_id = South; end end else begin - route_sel[West] = 1'b1; + route_sel_id = West; end end + route_sel = '0; + route_sel[route_sel_id] = 1'b1; end assign channel_o = channel_i;