diff --git a/.github/workflows/floogen.yml b/.github/workflows/floogen.yml index a534bf76..fb3fa688 100644 --- a/.github/workflows/floogen.yml +++ b/.github/workflows/floogen.yml @@ -13,6 +13,10 @@ on: - main - develop +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: unit-test-pip: diff --git a/.github/workflows/gitlab-ci.yml b/.github/workflows/gitlab-ci.yml index ed28e5e2..19249780 100644 --- a/.github/workflows/gitlab-ci.yml +++ b/.github/workflows/gitlab-ci.yml @@ -13,12 +13,16 @@ on: - main - develop +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: check: runs-on: ubuntu-latest steps: - name: Mirror and check - uses: pulp-platform/pulp-actions/gitlab-ci@v2.4.5 + uses: pulp-platform/pulp-actions/gitlab-ci@v2.5.0 # Skip on forks or pull requests from forks due to missing secrets. if: > github.repository == 'pulp-platform/FlooNoC' && diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ee160d0f..b80d590c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,6 +13,10 @@ on: - main - develop +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: ################ @@ -21,7 +25,7 @@ jobs: verible-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: chipsalliance/verible-linter-action@main with: config_file: '' @@ -47,5 +51,5 @@ jobs: reuse: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: fsfe/reuse-action@v5 diff --git a/.github/workflows/slang.yml b/.github/workflows/slang.yml new file mode 100644 index 00000000..01eb548c --- /dev/null +++ b/.github/workflows/slang.yml @@ -0,0 +1,56 @@ +# Copyright 2026 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 + +name: slang + +on: + pull_request: + push: + branches: + - main + - develop + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + ######### + # Slang # + ######### + slang: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + DUT: [axi_mesh, nw_mesh] + ROUTE_ALGO: [xy, src, id] + steps: + - uses: actions/checkout@v6 + + - name: Install bender + uses: pulp-platform/pulp-actions/bender-install@v2.5.0 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Generate RTL + run: uv run floogen rtl -c floogen/examples/${{ matrix.DUT }}_${{ matrix.ROUTE_ALGO }}.yml -o generated --no-format + + - name: Generate bender file list + # TODO: Remove -e fpnew once fpnew_top.sv is fixed upstream. + run: bender script flist-plus -t floo_synth -t ${{ matrix.DUT }} -e fpnew > sources.f + + - name: Slang lint + uses: pulp-platform/pulp-actions/slang@v2.5.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + slang-flags: >- + -f sources.f --top floo_${{ matrix.DUT }}_noc + --ignore-unknown-modules + -Wno-finish-num + --suppress-warnings .bender diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6bccb716..9a10da07 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,6 +12,9 @@ variables: UV: /home/fischeti/.local/bin/uv UV_LINK_MODE: hardlink +default: + interruptible: true + stages: - init - build diff --git a/Bender.yml b/Bender.yml index 4c5bb860..d81e1cc7 100644 --- a/Bender.yml +++ b/Bender.yml @@ -42,8 +42,6 @@ sources: - hw/floo_route_xymask.sv - hw/floo_alu.sv # Level 2 - - hw/floo_route_select.sv - - hw/floo_route_comp.sv - hw/floo_meta_buffer.sv - hw/floo_reduction_arbiter.sv - hw/floo_reduction_unit.sv diff --git a/floogen/templates/floo_nw_router.sv.mako b/floogen/templates/floo_nw_router.sv.mako index 569e7373..e22dc8a2 100644 --- a/floogen/templates/floo_nw_router.sv.mako +++ b/floogen/templates/floo_nw_router.sv.mako @@ -120,5 +120,9 @@ floo_nw_router #( .floo_req_o (${router.name}_req_out), .floo_rsp_i (${router.name}_rsp_in), .floo_wide_i (${router.name}_wide_in), - .floo_wide_o (${router.name}_wide_out) + .floo_wide_o (${router.name}_wide_out), + .offload_narrow_req_o (), + .offload_narrow_rsp_i ('0), + .offload_wide_req_o (), + .offload_wide_rsp_i ('0) ); diff --git a/hw/floo_axi_chimney.sv b/hw/floo_axi_chimney.sv index 64138b90..efd37f8d 100644 --- a/hw/floo_axi_chimney.sv +++ b/hw/floo_axi_chimney.sv @@ -684,17 +684,17 @@ module floo_axi_chimney ); spill_register #( - .T ( floo_req_generic_flit_t ), - .Bypass( !ChimneyCfg.CutOup ) + .T ( floo_req_chan_t ), + .Bypass( !ChimneyCfg.CutOup ) ) i_req_out_cut ( .clk_i, .rst_ni, .valid_i ( floo_req_arb_valid ), .ready_o ( floo_req_arb_ready ), - .data_i ( floo_req_arb_data ), - .valid_o ( floo_req_o.valid ), - .ready_i ( floo_req_i.ready ), - .data_o ( floo_req_o.req ) + .data_i ( floo_req_chan_t'(floo_req_arb_data) ), + .valid_o ( floo_req_o.valid ), + .ready_i ( floo_req_i.ready ), + .data_o ( floo_req_o.req ) ); floo_rsp_generic_flit_t floo_rsp_arb_data; @@ -715,17 +715,17 @@ module floo_axi_chimney ); spill_register #( - .T ( floo_rsp_generic_flit_t ), - .Bypass( !ChimneyCfg.CutOup ) + .T ( floo_rsp_chan_t ), + .Bypass( !ChimneyCfg.CutOup ) ) i_rsp_out_cut ( .clk_i, .rst_ni, .valid_i ( floo_rsp_arb_valid ), .ready_o ( floo_rsp_arb_ready ), - .data_i ( floo_rsp_arb_data ), - .valid_o ( floo_rsp_o.valid ), - .ready_i ( floo_rsp_i.ready ), - .data_o ( floo_rsp_o.rsp ) + .data_i ( floo_rsp_chan_t'(floo_rsp_arb_data) ), + .valid_o ( floo_rsp_o.valid ), + .ready_i ( floo_rsp_i.ready ), + .data_o ( floo_rsp_o.rsp ) ); //////////////////// diff --git a/hw/floo_meta_buffer.sv b/hw/floo_meta_buffer.sv index 1293f462..54283e24 100644 --- a/hw/floo_meta_buffer.sv +++ b/hw/floo_meta_buffer.sv @@ -196,10 +196,8 @@ module floo_meta_buffer #( assign ar_no_atop_buf_full = !ar_no_atop_buf_not_full; assign aw_no_atop_buf_full = !aw_no_atop_buf_not_full; - `ASSERT(NoBResponseIdQueue, axi_rsp_i.b_valid -> (b_oup_data_valid && b_oup_gnt), - "Meta data for B response must exist in Id Queue!") - `ASSERT(NoRResponseIdQueue, axi_rsp_i.r_valid -> (r_oup_data_valid && r_oup_gnt), - "Meta data for R response must exist in Id Queue!") + `ASSERT(NoBResponseIdQueue, axi_rsp_i.b_valid -> (b_oup_data_valid && b_oup_gnt)) + `ASSERT(NoRResponseIdQueue, axi_rsp_i.r_valid -> (r_oup_data_valid && r_oup_gnt)) end // Non-atomic AR's @@ -213,8 +211,7 @@ module floo_meta_buffer #( assign is_atop_r_rsp = AtopSupport && axi_rsp_i.r_valid && (axi_rsp_i.r.id < MaxAtomicTxns); assign is_atop_b_rsp = AtopSupport && axi_rsp_i.b_valid && (axi_rsp_i.b.id < MaxAtomicTxns); - `ASSERT(NoAtopSupportAw, !(!AtopSupport && is_atop_aw), - "Atomics not supported, but atomic request received!") + `ASSERT(NoAtopSupportAw, !(!AtopSupport && is_atop_aw)) assign r_buf_o = (is_atop_r_rsp && AtopSupport)? atop_r_buf[axi_rsp_i.r.id] : no_atop_r_buf; assign b_buf_o = (is_atop_b_rsp && AtopSupport)? atop_b_buf[axi_rsp_i.b.id] : no_atop_b_buf; diff --git a/hw/floo_nw_chimney.sv b/hw/floo_nw_chimney.sv index 166b5cb1..ae2cb15c 100644 --- a/hw/floo_nw_chimney.sv +++ b/hw/floo_nw_chimney.sv @@ -1176,9 +1176,9 @@ module floo_nw_chimney // Reduction --> Multicast the B response to all members floo_narrow_b.hdr.collective_op = floo_pkg::collect_op_e'('0); if(en_narrow_collective(CollectOpCfg)) begin: gen_nar_b_coll - if(is_multicast_op(narrow_aw_buf_hdr_out.hdr.collective_op)) begin: gen_nar_red_rsp + if(is_multicast_op(collect_op_e'(narrow_aw_buf_hdr_out.hdr.collective_op))) begin: gen_nar_red_rsp floo_narrow_b.hdr.collective_op = CollectB; - end else if(is_reduction_op(narrow_aw_buf_hdr_out.hdr.collective_op)) begin: gen_nar_mcast + end else if(is_reduction_op(collect_op_e'(narrow_aw_buf_hdr_out.hdr.collective_op))) begin: gen_nar_mcast floo_narrow_b.hdr.collective_op = Multicast; end end @@ -1267,9 +1267,9 @@ module floo_nw_chimney // Reduction --> Multicast the B response to all members floo_wide_b.hdr.collective_op = Unicast; if(en_wide_collective(CollectOpCfg)) begin: gen_wide_b_coll - if(is_multicast_op(wide_aw_buf_hdr_out.hdr.collective_op)) begin: gen_wide_red_rsp + if(is_multicast_op(collect_op_e'(wide_aw_buf_hdr_out.hdr.collective_op))) begin: gen_wide_red_rsp floo_wide_b.hdr.collective_op = CollectB; - end else if(is_reduction_op(wide_aw_buf_hdr_out.hdr.collective_op)) begin: gen_wide_mcast + end else if(is_reduction_op(collect_op_e'(wide_aw_buf_hdr_out.hdr.collective_op))) begin: gen_wide_mcast floo_wide_b.hdr.collective_op = Multicast; end end @@ -1375,17 +1375,17 @@ module floo_nw_chimney ); spill_register #( - .T ( floo_req_generic_flit_t ), - .Bypass( !ChimneyCfgN.CutOup ) + .T ( floo_req_chan_t ), + .Bypass( !ChimneyCfgN.CutOup ) ) i_req_out_cut ( .clk_i, .rst_ni, - .valid_i ( floo_req_arb_valid ), - .ready_o ( floo_req_arb_ready ), - .data_i ( floo_req_arb_data ), - .valid_o ( floo_req_o.valid ), - .ready_i ( floo_req_i.ready ), - .data_o ( floo_req_o.req ) + .valid_i ( floo_req_arb_valid ), + .ready_o ( floo_req_arb_ready ), + .data_i ( floo_req_chan_t'(floo_req_arb_data) ), + .valid_o ( floo_req_o.valid ), + .ready_i ( floo_req_i.ready ), + .data_o ( floo_req_o.req ) ); floo_rsp_generic_flit_t floo_rsp_arb_data; @@ -1406,17 +1406,17 @@ module floo_nw_chimney ); spill_register #( - .T ( floo_rsp_generic_flit_t ), - .Bypass( !ChimneyCfgN.CutOup ) + .T ( floo_rsp_chan_t ), + .Bypass( !ChimneyCfgN.CutOup ) ) i_rsp_out_cut ( .clk_i, .rst_ni, - .valid_i ( floo_rsp_arb_valid ), - .ready_o ( floo_rsp_arb_ready ), - .data_i ( floo_rsp_arb_data ), - .valid_o ( floo_rsp_o.valid ), - .ready_i ( floo_rsp_i.ready ), - .data_o ( floo_rsp_o.rsp ) + .valid_i ( floo_rsp_arb_valid ), + .ready_o ( floo_rsp_arb_ready ), + .data_i ( floo_rsp_chan_t'(floo_rsp_arb_data) ), + .valid_o ( floo_rsp_o.valid ), + .ready_i ( floo_rsp_i.ready ), + .data_o ( floo_rsp_o.rsp ) ); // Credit is never used for narrow req/rsp if (VcImpl == floo_pkg::VcCredit) begin : gen_credit_tie @@ -1443,17 +1443,17 @@ module floo_nw_chimney ); spill_register #( - .T ( floo_wide_generic_flit_t ), - .Bypass( !ChimneyCfgW.CutOup ) + .T ( floo_wide_chan_t ), + .Bypass( !ChimneyCfgW.CutOup ) ) i_wide_out_cut ( .clk_i, .rst_ni, - .valid_i ( floo_wide_arb_valid ), - .ready_o ( floo_wide_arb_ready ), - .data_i ( floo_wide_arb_data ), - .valid_o ( floo_wide_req_arb_valid_out ), - .ready_i ( floo_wide_req_arb_gnt_in ), - .data_o ( floo_wide_o.wide ) + .valid_i ( floo_wide_arb_valid ), + .ready_o ( floo_wide_arb_ready ), + .data_i ( floo_wide_chan_t'(floo_wide_arb_data) ), + .valid_o ( floo_wide_req_arb_valid_out ), + .ready_i ( floo_wide_req_arb_gnt_in ), + .data_o ( floo_wide_o.wide ) ); // Mux the ready of the read and write channels to the ACK/NACK protocol diff --git a/hw/floo_output_arbiter.sv b/hw/floo_output_arbiter.sv index 7926162c..9603c4fe 100644 --- a/hw/floo_output_arbiter.sv +++ b/hw/floo_output_arbiter.sv @@ -56,7 +56,7 @@ module floo_output_arbiter import floo_pkg::*; reduce_mask = '0; if (EnParallelReduction) begin for (int i = 0; i < NumParallelRedRoutes; i++) begin - reduce_mask[i] = (is_parallel_reduction_op(data_i[i].hdr.collective_op)); + reduce_mask[i] = (is_parallel_reduction_op(collect_op_e'(data_i[i].hdr.collective_op))); end end end diff --git a/hw/floo_route_comp.sv b/hw/floo_route_comp.sv deleted file mode 100644 index 0341a27a..00000000 --- a/hw/floo_route_comp.sv +++ /dev/null @@ -1,131 +0,0 @@ -// 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 route config - parameter floo_pkg::route_cfg_t RouteCfg = '0, - parameter bit UseIdTable = RouteCfg.UseIdTable, - parameter type id_t = logic, - /// The type of the address - parameter type addr_t = logic, - parameter type mask_t = addr_t, - /// The type of the route - parameter type route_t = logic, - /// The type of the address rules - parameter type addr_rule_t = logic, - parameter type mask_rule_t = logic, - parameter type mask_sel_t = logic -) ( - input logic clk_i, - input logic rst_ni, - input id_t id_i, - input addr_t addr_i, - input mask_t mask_i, - input addr_rule_t [RouteCfg.NumSamRules-1:0] addr_map_i, - input mask_rule_t [RouteCfg.NumSamRules-1:0] mask_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 mask_o -); - - localparam bit EnCollective = floo_pkg::en_collective(RouteCfg.CollectiveCfg.OpCfg); - - // Use an address decoder to map the address to a destination ID. - // The `rule_t` struct has to have the fields `idx`, `start_addr` and `end_addr`. - // `SourceRouting` is a special case, where the the `idx` is the actual (pre-computed) route. - // 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. - localparam int unsigned AddrWidth = $bits(addr_t); - if (UseIdTable && - ((RouteCfg.RouteAlgo == IdTable) || - (RouteCfg.RouteAlgo == XYRouting) || - (RouteCfg.RouteAlgo == SourceRouting))) - begin : gen_table_routing - logic dec_error; - logic mask_dec_error; - mask_sel_t x_mask_sel, y_mask_sel; - addr_t x_addr_mask, y_addr_mask; - // idx_t idx; - - // 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 ) - ); - if (EnCollective && RouteCfg.UseIdTable && - (RouteCfg.RouteAlgo == floo_pkg::XYRouting)) - begin : gen_mcast_mask - floo_mask_decode #( - .NumMaskRules ( RouteCfg.NumSamRules ), - .mask_rule_t ( mask_rule_t ), - .id_t ( id_t ), - .mask_sel_t ( mask_sel_t ) - ) i_mask_decode ( - .id_i ( id_o ), - .mask_x_mask ( x_mask_sel ), - .mask_y_mask ( y_mask_sel ), - .mask_map_i ( mask_map_i ), - .dec_error_o ( mask_dec_error ) - ); - always_comb begin - x_addr_mask = (({AddrWidth{1'b1}} >> (AddrWidth - x_mask_sel.len)) << x_mask_sel.offset); - y_addr_mask = (({AddrWidth{1'b1}} >> (AddrWidth - y_mask_sel.len)) << y_mask_sel.offset); - end - assign mask_o.x = (mask_i & x_addr_mask) >> x_mask_sel.offset; - assign mask_o.y = (mask_i & y_addr_mask) >> y_mask_sel.offset; - assign mask_o.port_id = '0; - `ASSERT(MaskDecodeError, !mask_dec_error) - end - else begin : gen_no_mcast_mask - assign mask_o = '0; - end - - `ASSERT(DecodeError, !dec_error) - 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)]; - if(EnCollective) begin : gen_mcast_mask - assign mask_o.x = mask_i[RouteCfg.XYAddrOffsetX +: $bits(id_o.x)]; - assign mask_o.y = mask_i[RouteCfg.XYAddrOffsetY +: $bits(id_o.y)]; - assign mask_o.port_id = '0; - end else begin : gen_no_mcast_mask - assign mask_o = '0; - end - 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 - end else begin : gen_error - $fatal(1, "Routing algorithm not implemented"); - end - if (RouteCfg.RouteAlgo == SourceRouting) begin : gen_route - assign route_o = (UseIdTable)? route_table_i[id_o] : route_table_i[id_i]; - end else begin : gen_no_route - assign route_o = '0; - end - -endmodule