diff --git a/Bender.local b/Bender.local index 121e0ef29..d69b62af2 100644 --- a/Bender.local +++ b/Bender.local @@ -4,4 +4,4 @@ overrides: # Some of our dependencies have false conflicts with our new AXI version; force our version. - axi: {git: https://github.com/pulp-platform/axi.git, version: 0.39.0} + axi: {git: https://github.com/pulp-platform/axi.git, version: 0.39.2 } diff --git a/Bender.yml b/Bender.yml index 61539826f..dc4281912 100644 --- a/Bender.yml +++ b/Bender.yml @@ -19,7 +19,7 @@ package: - Matheus Cavalcante dependencies: - axi: { git: https://github.com/pulp-platform/axi, version: 0.39.0 } + axi: { git: https://github.com/pulp-platform/axi, version: 0.39.2 } axi_riscv_atomics: { git: https://github.com/pulp-platform/axi_riscv_atomics, version: 0.6.0 } common_cells: { git: https://github.com/pulp-platform/common_cells, version: 1.28.0 } FPnew: { git: "https://github.com/pulp-platform/cvfpu.git", rev: pulp-v0.1.3 } @@ -27,6 +27,7 @@ dependencies: tech_cells_generic: { git: https://github.com/pulp-platform/tech_cells_generic, version: 0.2.11 } riscv-dbg: { git: https://github.com/pulp-platform/riscv-dbg, version: 0.8.0 } cluster_icache: { git: https://github.com/pulp-platform/cluster_icache.git, version: 0.1.0 } + idma: { git: https://github.com/pulp-platform/iDMA, version: 0.6.0 } vendor_package: - name: musl @@ -86,28 +87,6 @@ export_include_dirs: - hw/snitch_ssr/include sources: - # future - - files: - # Level 0 - - hw/future/src/mem_to_axi_lite.sv - - hw/future/src/idma_reg64_frontend_reg_pkg.sv - - hw/future/src/idma_tf_id_gen.sv - - hw/future/src/dma/axi_dma_data_path.sv - - hw/future/src/axi_interleaved_xbar.sv - # Level 1 - - hw/future/src/axi_zero_mem.sv - - hw/future/src/idma_reg64_frontend_reg_top.sv - # Level 2 - - hw/future/src/idma_reg64_frontend.sv - - hw/future/src/dma/axi_dma_data_mover.sv - - hw/future/src/dma/axi_dma_burst_reshaper.sv - # Level 3 - - hw/future/src/dma/axi_dma_backend.sv - - target: test - files: - - hw/future/test/fixture_axi_dma_backend.sv - - hw/future/test/tb_axi_dma_backend.sv - # reqrsp_interface - files: # Level 0 @@ -187,17 +166,6 @@ sources: - files: - hw/snitch_vm/src/snitch_ptw.sv - # snitch_dma - - files: - # Level 0 - - hw/snitch_dma/src/axi_dma_pkg.sv - # Level 1 - - hw/snitch_dma/src/axi_dma_error_handler.sv - - hw/snitch_dma/src/axi_dma_perf_counters.sv - - hw/snitch_dma/src/axi_dma_twod_ext.sv - # Level 2: - - hw/snitch_dma/src/axi_dma_tc_snitch_fe.sv - # snitch_ipu - files: # Level 0 diff --git a/hw/future/README.md b/hw/future/README.md deleted file mode 100644 index 8ee1fdbd7..000000000 --- a/hw/future/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Future Folder - -The folder contains IPs which are in development somewhere and in early preview -here. Do not expect that this folder will be stable in any kind. - -This can be seen as a kind of staging area where IPs reside until they will be -upstreamed. diff --git a/hw/future/src/axi_interleaved_xbar.sv b/hw/future/src/axi_interleaved_xbar.sv deleted file mode 100644 index 77c112f45..000000000 --- a/hw/future/src/axi_interleaved_xbar.sv +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// Authors: -// - Wolfgang Roenninger -// - Andreas Kurth -// - Florian Zaruba -// - Thomas Benz - -// axi_interleaved_xbar -module axi_interleaved_xbar -import cf_math_pkg::idx_width; -#( - parameter axi_pkg::xbar_cfg_t Cfg = '0, - parameter bit ATOPs = 1'b1, - parameter bit [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts-1:0] Connectivity = '1, - parameter type slv_aw_chan_t = logic, - parameter type mst_aw_chan_t = logic, - parameter type w_chan_t = logic, - parameter type slv_b_chan_t = logic, - parameter type mst_b_chan_t = logic, - parameter type slv_ar_chan_t = logic, - parameter type mst_ar_chan_t = logic, - parameter type slv_r_chan_t = logic, - parameter type mst_r_chan_t = logic, - parameter type slv_req_t = logic, - parameter type slv_resp_t = logic, - parameter type mst_req_t = logic, - parameter type mst_resp_t = logic, - parameter type rule_t = axi_pkg::xbar_rule_64_t, - // don't overwrite - parameter int unsigned MstPortsIdxWidth = - (Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts)) -) ( - input logic clk_i, - input logic rst_ni, - input logic test_i, - input slv_req_t [Cfg.NoSlvPorts-1:0] slv_ports_req_i, - output slv_resp_t [Cfg.NoSlvPorts-1:0] slv_ports_resp_o, - output mst_req_t [Cfg.NoMstPorts-1:0] mst_ports_req_o, - input mst_resp_t [Cfg.NoMstPorts-1:0] mst_ports_resp_i, - input rule_t [Cfg.NoAddrRules-1:0] addr_map_i, - input logic interleaved_mode_ena_i, - input logic [Cfg.NoSlvPorts-1:0] en_default_mst_port_i, -`ifdef VCS - input logic [Cfg.NoSlvPorts-1:0][MstPortsIdxWidth-1:0] default_mst_port_i -`else - input logic [Cfg.NoSlvPorts-1:0][idx_width(Cfg.NoMstPorts)-1:0] default_mst_port_i -`endif -); - - typedef logic [Cfg.AxiAddrWidth-1:0] addr_t; - // to account for the decoding error slave -`ifdef VCS - localparam int unsigned MstPortsIdxWidthOne = - (Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts + 1)); - typedef logic [MstPortsIdxWidthOne-1:0] mst_port_idx_t; -`else - typedef logic [idx_width(Cfg.NoMstPorts + 1)-1:0] mst_port_idx_t; -`endif - - // signals from the axi_demuxes, one index more for decode error - slv_req_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_reqs; - slv_resp_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_resps; - - // workaround for issue #133 (problem with vsim 10.6c) - localparam int unsigned cfg_NoMstPorts = Cfg.NoMstPorts; - - // signals into the axi_muxes, are of type slave as the multiplexer extends the ID - slv_req_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_reqs; - slv_resp_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_resps; - - // interleaved address modify - slv_req_t [Cfg.NoSlvPorts-1:0] slv_reqs_mod; - - for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_slv_port_demux -`ifdef VCS - logic [MstPortsIdxWidth-1:0] dec_aw, dec_ar; - logic [MstPortsIdxWidth-1:0] dec_inter_aw, dec_inter_ar; -`else - logic [idx_width(Cfg.NoMstPorts)-1:0] dec_aw, dec_ar; - logic [idx_width(Cfg.NoMstPorts)-1:0] dec_inter_aw, dec_inter_ar; -`endif - mst_port_idx_t slv_aw_select, slv_ar_select; - logic dec_aw_valid, dec_aw_error; - logic dec_ar_valid, dec_ar_error; - - localparam int unsigned BankSelLow = 'd16; - localparam int unsigned BankSelHigh = BankSelLow + MstPortsIdxWidth; - - // interleaved select (4kiB blocks) - assign dec_inter_aw = slv_ports_req_i[i].aw.addr[BankSelLow +: MstPortsIdxWidth]; - assign dec_inter_ar = slv_ports_req_i[i].ar.addr[BankSelLow +: MstPortsIdxWidth]; - - // interleaved address modify - always_comb begin : proc_modify_addr_interleaved - slv_reqs_mod[i] = slv_ports_req_i[i]; - - // only modify if interleaved mode is active - if (interleaved_mode_ena_i == 1'b1) begin - // modify AW address by removing bank bits - slv_reqs_mod[i].aw.addr = { {(MstPortsIdxWidth){1'b0}}, - slv_ports_req_i[i].aw.addr[Cfg.AxiAddrWidth-1:BankSelHigh], - slv_ports_req_i[i].aw.addr[BankSelLow-1:0] }; - - // modify AR address by removing bank bits - slv_reqs_mod[i].ar.addr = { {(MstPortsIdxWidth){1'b0}}, - slv_ports_req_i[i].ar.addr[Cfg.AxiAddrWidth-1:BankSelHigh], - slv_ports_req_i[i].ar.addr[BankSelLow-1:0] }; - end - end - - addr_decode #( - .NoIndices ( Cfg.NoMstPorts ), - .NoRules ( Cfg.NoAddrRules ), - .addr_t ( addr_t ), - .rule_t ( rule_t ) - ) i_axi_aw_decode ( - .addr_i ( slv_ports_req_i[i].aw.addr ), - .addr_map_i ( addr_map_i ), - .idx_o ( dec_aw ), - .dec_valid_o ( dec_aw_valid ), - .dec_error_o ( dec_aw_error ), - .en_default_idx_i ( en_default_mst_port_i[i] ), - .default_idx_i ( default_mst_port_i[i] ) - ); - - addr_decode #( - .NoIndices ( Cfg.NoMstPorts ), - .addr_t ( addr_t ), - .NoRules ( Cfg.NoAddrRules ), - .rule_t ( rule_t ) - ) i_axi_ar_decode ( - .addr_i ( slv_ports_req_i[i].ar.addr ), - .addr_map_i ( addr_map_i ), - .idx_o ( dec_ar ), - .dec_valid_o ( dec_ar_valid ), - .dec_error_o ( dec_ar_error ), - .en_default_idx_i ( en_default_mst_port_i[i] ), - .default_idx_i ( default_mst_port_i[i] ) - ); - - always_comb begin : ax_select - if (interleaved_mode_ena_i == 1'b1) begin - slv_aw_select = dec_inter_aw; - slv_ar_select = dec_inter_ar; - end else begin - slv_aw_select = (dec_aw_error) ? - mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_aw); - slv_ar_select = (dec_ar_error) ? - mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_ar); - end - end - - // make sure that the default slave does not get changed, if there is an unserved Ax - // pragma translate_off - `ifndef VERILATOR - `ifndef XSIM - default disable iff (~rst_ni); - default_aw_mst_port_en: assert property( - @(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready) - |=> $stable(en_default_mst_port_i[i])) - else $fatal (1, $sformatf({"It is not allowed to change the default mst port enable,", - "when there is an unserved Aw beat. Slave Port: %0d"}, i)); - default_aw_mst_port: assert property( - @(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready) - |=> $stable(default_mst_port_i[i])) - else $fatal (1, $sformatf({"It is not allowed to change the default mst port", - "when there is an unserved Aw beat. Slave Port: %0d"}, i)); - default_ar_mst_port_en: assert property( - @(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready) - |=> $stable(en_default_mst_port_i[i])) - else $fatal (1, $sformatf({"It is not allowed to change the enable, when", - "there is an unserved Ar beat. Slave Port: %0d"}, i)); - default_ar_mst_port: assert property( - @(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready) - |=> $stable(default_mst_port_i[i])) - else $fatal (1, $sformatf({"It is not allowed to change the default mst port", - "when there is an unserved Ar beat. Slave Port: %0d"}, i)); - `endif - `endif - // pragma translate_on - axi_demux #( - .AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), // ID Width - .AtopSupport ( ATOPs ), - .aw_chan_t ( slv_aw_chan_t ), // AW Channel Type - .w_chan_t ( w_chan_t ), // W Channel Type - .b_chan_t ( slv_b_chan_t ), // B Channel Type - .ar_chan_t ( slv_ar_chan_t ), // AR Channel Type - .r_chan_t ( slv_r_chan_t ), // R Channel Type - .axi_req_t ( slv_req_t ), - .axi_resp_t ( slv_resp_t ), - .NoMstPorts ( Cfg.NoMstPorts + 1 ), - .MaxTrans ( Cfg.MaxMstTrans ), - .AxiLookBits ( Cfg.AxiIdUsedSlvPorts ), - .UniqueIds ( Cfg.UniqueIds ), - .SpillAw ( Cfg.LatencyMode[9] ), - .SpillW ( Cfg.LatencyMode[8] ), - .SpillB ( Cfg.LatencyMode[7] ), - .SpillAr ( Cfg.LatencyMode[6] ), - .SpillR ( Cfg.LatencyMode[5] ) - ) i_axi_demux ( - .clk_i, // Clock - .rst_ni, // Asynchronous reset active low - .test_i, // Testmode enable - .slv_req_i ( slv_reqs_mod[i] ), - .slv_aw_select_i ( slv_aw_select ), - .slv_ar_select_i ( slv_ar_select ), - .slv_resp_o ( slv_ports_resp_o[i] ), - .mst_reqs_o ( slv_reqs[i] ), - .mst_resps_i ( slv_resps[i] ) - ); - - axi_err_slv #( - .AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), - .axi_req_t ( slv_req_t ), - .axi_resp_t ( slv_resp_t ), - .Resp ( axi_pkg::RESP_DECERR ), - .ATOPs ( ATOPs ), - .MaxTrans ( 4 ) // Transactions terminate at this slave, so minimize - // resource consumption by accepting only a few - // transactions at a time. - ) i_axi_err_slv ( - .clk_i, // Clock - .rst_ni, // Asynchronous reset active low - .test_i, // Testmode enable - // slave port - .slv_req_i ( slv_reqs[i][Cfg.NoMstPorts] ), - .slv_resp_o ( slv_resps[i][cfg_NoMstPorts] ) - ); - end - - // cross all channels - for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_xbar_slv_cross - for (genvar j = 0; j < Cfg.NoMstPorts; j++) begin : gen_xbar_mst_cross - if (Connectivity[i][j]) begin : gen_connection - assign mst_reqs[j][i] = slv_reqs[i][j]; - assign slv_resps[i][j] = mst_resps[j][i]; - - end else begin : gen_no_connection - assign mst_reqs[j][i] = '0; - axi_err_slv #( - .AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), - .axi_req_t ( slv_req_t ), - .axi_resp_t ( slv_resp_t ), - .Resp ( axi_pkg::RESP_DECERR ), - .ATOPs ( ATOPs ), - .MaxTrans ( 1 ) - ) i_axi_err_slv ( - .clk_i, - .rst_ni, - .test_i, - .slv_req_i ( slv_reqs[i][j] ), - .slv_resp_o ( slv_resps[i][j] ) - ); - end - end - end - - for (genvar i = 0; i < Cfg.NoMstPorts; i++) begin : gen_mst_port_mux - axi_mux #( - .SlvAxiIDWidth ( Cfg.AxiIdWidthSlvPorts ), // ID width of the slave ports - .slv_aw_chan_t ( slv_aw_chan_t ), // AW Channel Type, slave ports - .mst_aw_chan_t ( mst_aw_chan_t ), // AW Channel Type, master port - .w_chan_t ( w_chan_t ), // W Channel Type, all ports - .slv_b_chan_t ( slv_b_chan_t ), // B Channel Type, slave ports - .mst_b_chan_t ( mst_b_chan_t ), // B Channel Type, master port - .slv_ar_chan_t ( slv_ar_chan_t ), // AR Channel Type, slave ports - .mst_ar_chan_t ( mst_ar_chan_t ), // AR Channel Type, master port - .slv_r_chan_t ( slv_r_chan_t ), // R Channel Type, slave ports - .mst_r_chan_t ( mst_r_chan_t ), // R Channel Type, master port - .slv_req_t ( slv_req_t ), - .slv_resp_t ( slv_resp_t ), - .mst_req_t ( mst_req_t ), - .mst_resp_t ( mst_resp_t ), - .NoSlvPorts ( Cfg.NoSlvPorts ), // Number of Masters for the module - .MaxWTrans ( Cfg.MaxSlvTrans ), - .FallThrough ( Cfg.FallThrough ), - .SpillAw ( Cfg.LatencyMode[4] ), - .SpillW ( Cfg.LatencyMode[3] ), - .SpillB ( Cfg.LatencyMode[2] ), - .SpillAr ( Cfg.LatencyMode[1] ), - .SpillR ( Cfg.LatencyMode[0] ) - ) i_axi_mux ( - .clk_i, // Clock - .rst_ni, // Asynchronous reset active low - .test_i, // Test Mode enable - .slv_reqs_i ( mst_reqs[i] ), - .slv_resps_o ( mst_resps[i] ), - .mst_req_o ( mst_ports_req_o[i] ), - .mst_resp_i ( mst_ports_resp_i[i] ) - ); - end - - // pragma translate_off - `ifndef VERILATOR - `ifndef XSIM - initial begin : check_params - id_slv_req_ports: assert ($bits(slv_ports_req_i[0].aw.id ) == Cfg.AxiIdWidthSlvPorts) else - $fatal(1, $sformatf("Slv_req and aw_chan id width not equal.")); - id_slv_resp_ports: assert ($bits(slv_ports_resp_o[0].r.id) == Cfg.AxiIdWidthSlvPorts) else - $fatal(1, $sformatf("Slv_req and aw_chan id width not equal.")); - end - `endif - `endif - // pragma translate_on -endmodule : axi_interleaved_xbar - -`include "axi/assign.svh" -`include "axi/typedef.svh" - -module axi_interleaved_xbar_intf -import cf_math_pkg::idx_width; -#( - parameter int unsigned AXI_USER_WIDTH = 0, - parameter bit ATOPS = 1'b1, - parameter bit [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts-1:0] CONNECTIVITY = '1, - parameter axi_pkg::xbar_cfg_t Cfg = '0, - parameter type rule_t = axi_pkg::xbar_rule_64_t -`ifdef VCS - , localparam int unsigned MstPortsIdxWidth = - (Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts)) -`endif -) ( - input logic clk_i, - input logic rst_ni, - input logic test_i, - AXI_BUS.Slave slv_ports [Cfg.NoSlvPorts-1:0], - AXI_BUS.Master mst_ports [Cfg.NoMstPorts-1:0], - input rule_t [Cfg.NoAddrRules-1:0] addr_map_i, - input logic [Cfg.NoSlvPorts-1:0] en_default_mst_port_i, - input logic interleaved_mode_ena_i, -`ifdef VCS - input logic [Cfg.NoSlvPorts-1:0][MstPortsIdxWidth-1:0] default_mst_port_i -`else - input logic [Cfg.NoSlvPorts-1:0][idx_width(Cfg.NoMstPorts)-1:0] default_mst_port_i -`endif -); - - localparam int unsigned AxiIdWidthMstPorts = Cfg.AxiIdWidthSlvPorts + $clog2(Cfg.NoSlvPorts); - - typedef logic [AxiIdWidthMstPorts -1:0] id_mst_t; - typedef logic [Cfg.AxiIdWidthSlvPorts -1:0] id_slv_t; - typedef logic [Cfg.AxiAddrWidth -1:0] addr_t; - typedef logic [Cfg.AxiDataWidth -1:0] data_t; - typedef logic [Cfg.AxiDataWidth/8 -1:0] strb_t; - typedef logic [AXI_USER_WIDTH -1:0] user_t; - - `AXI_TYPEDEF_AW_CHAN_T(mst_aw_chan_t, addr_t, id_mst_t, user_t) - `AXI_TYPEDEF_AW_CHAN_T(slv_aw_chan_t, addr_t, id_slv_t, user_t) - `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_B_CHAN_T(mst_b_chan_t, id_mst_t, user_t) - `AXI_TYPEDEF_B_CHAN_T(slv_b_chan_t, id_slv_t, user_t) - `AXI_TYPEDEF_AR_CHAN_T(mst_ar_chan_t, addr_t, id_mst_t, user_t) - `AXI_TYPEDEF_AR_CHAN_T(slv_ar_chan_t, addr_t, id_slv_t, user_t) - `AXI_TYPEDEF_R_CHAN_T(mst_r_chan_t, data_t, id_mst_t, user_t) - `AXI_TYPEDEF_R_CHAN_T(slv_r_chan_t, data_t, id_slv_t, user_t) - `AXI_TYPEDEF_REQ_T(mst_req_t, mst_aw_chan_t, w_chan_t, mst_ar_chan_t) - `AXI_TYPEDEF_REQ_T(slv_req_t, slv_aw_chan_t, w_chan_t, slv_ar_chan_t) - `AXI_TYPEDEF_RESP_T(mst_resp_t, mst_b_chan_t, mst_r_chan_t) - `AXI_TYPEDEF_RESP_T(slv_resp_t, slv_b_chan_t, slv_r_chan_t) - - mst_req_t [Cfg.NoMstPorts-1:0] mst_reqs; - mst_resp_t [Cfg.NoMstPorts-1:0] mst_resps; - slv_req_t [Cfg.NoSlvPorts-1:0] slv_reqs; - slv_resp_t [Cfg.NoSlvPorts-1:0] slv_resps; - - for (genvar i = 0; i < Cfg.NoMstPorts; i++) begin : gen_assign_mst - `AXI_ASSIGN_FROM_REQ(mst_ports[i], mst_reqs[i]) - `AXI_ASSIGN_TO_RESP(mst_resps[i], mst_ports[i]) - end - - for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_assign_slv - `AXI_ASSIGN_TO_REQ(slv_reqs[i], slv_ports[i]) - `AXI_ASSIGN_FROM_RESP(slv_ports[i], slv_resps[i]) - end - - axi_interleaved_xbar #( - .Cfg (Cfg), - .ATOPs ( ATOPS ), - .Connectivity ( CONNECTIVITY ), - .slv_aw_chan_t ( slv_aw_chan_t ), - .mst_aw_chan_t ( mst_aw_chan_t ), - .w_chan_t ( w_chan_t ), - .slv_b_chan_t ( slv_b_chan_t ), - .mst_b_chan_t ( mst_b_chan_t ), - .slv_ar_chan_t ( slv_ar_chan_t ), - .mst_ar_chan_t ( mst_ar_chan_t ), - .slv_r_chan_t ( slv_r_chan_t ), - .mst_r_chan_t ( mst_r_chan_t ), - .slv_req_t ( slv_req_t ), - .slv_resp_t ( slv_resp_t ), - .mst_req_t ( mst_req_t ), - .mst_resp_t ( mst_resp_t ), - .rule_t ( rule_t ) - ) i_interleaved_xbar ( - .clk_i, - .rst_ni, - .test_i, - .slv_ports_req_i (slv_reqs ), - .slv_ports_resp_o (slv_resps), - .mst_ports_req_o (mst_reqs ), - .mst_ports_resp_i (mst_resps), - .addr_map_i, - .interleaved_mode_ena_i, - .en_default_mst_port_i, - .default_mst_port_i - ); - -endmodule : axi_interleaved_xbar_intf diff --git a/hw/future/src/axi_zero_mem.sv b/hw/future/src/axi_zero_mem.sv deleted file mode 100644 index e5d0ba08a..000000000 --- a/hw/future/src/axi_zero_mem.sv +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2021 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Gianna Paulin - -`include "common_cells/registers.svh" -/// AXI4+ATOP slave module which translates AXI bursts into a memory stream -/// which behaves as a memory containing only `0` data which cannot be -/// overwritten by `write` operations. -/// - `read`: grants the request and returns data `0`. -/// - `write`: grants the request, write data goes into nothingness (can be used as data sink e.g. when measuring DMA power) -/// If both read and write channels of the AXI4+ATOP are active, both will have an -/// utilization of 50%. -module axi_zero_mem #( - /// AXI4+ATOP request type. See `include/axi/typedef.svh`. - parameter type axi_req_t = logic, - /// AXI4+ATOP response type. See `include/axi/typedef.svh`. - parameter type axi_resp_t = logic, - /// Address width, has to be less or equal than the width off the AXI address field. - /// Determines the width of `mem_addr_o`. Has to be wide enough to emit the memory region - /// which should be accessible. - parameter int unsigned AddrWidth = 0, - /// AXI4+ATOP data width. - parameter int unsigned DataWidth = 0, - /// AXI4+ATOP ID width. - parameter int unsigned IdWidth = 0, - /// Number of banks at output, must evenly divide `DataWidth`. - parameter int unsigned NumBanks = 0, - /// Depth of memory response buffer. This should be equal to the memory response latency. - parameter int unsigned BufDepth = 1, - /// Dependent parameter, do not override. Memory address type. - localparam type addr_t = logic [AddrWidth-1:0], - /// Dependent parameter, do not override. Memory data type. - localparam type mem_data_t = logic [DataWidth/NumBanks-1:0], - /// Dependent parameter, do not override. Memory write strobe type. - localparam type mem_strb_t = logic [DataWidth/NumBanks/8-1:0] -) ( - /// Clock input. - input logic clk_i, - /// Asynchronous reset, active low. - input logic rst_ni, - /// The unit is busy handling an AXI4+ATOP request. - output logic busy_o, - /// AXI4+ATOP slave port, request input. - input axi_req_t axi_req_i, - /// AXI4+ATOP slave port, response output. - output axi_resp_t axi_resp_o -); - - logic zero_mem_gnt, zero_mem_req, zero_mem_we; - logic zero_mem_valid_req_d, zero_mem_valid_req_q; - - axi_to_mem #( - .axi_req_t (axi_req_t), - .axi_resp_t (axi_resp_t), - .AddrWidth (AddrWidth), - .DataWidth (DataWidth), - .IdWidth (IdWidth), - .NumBanks (1), - .BufDepth (BufDepth) - ) i_axi_to_zeromem ( - .clk_i, - .rst_ni, - .busy_o (busy_o), - .axi_req_i (axi_req_i), - .axi_resp_o (axi_resp_o), - .mem_req_o (zero_mem_req), - .mem_gnt_i (zero_mem_gnt), - .mem_addr_o (/* ZeroMemory returns 0 whatever the address */), - .mem_wdata_o (/* ZeroMemory does ignores writes */), - .mem_strb_o (/* ZeroMemory does ignores writes */), - .mem_atop_o (/* The DMA does not support atomics */), - .mem_we_o (zero_mem_we), - .mem_rvalid_i (zero_mem_valid_req_q), - .mem_rdata_i ('0) - ); - - assign zero_mem_gnt = zero_mem_req; - assign zero_mem_valid_req_d = zero_mem_gnt & zero_mem_req; - - `FF(zero_mem_valid_req_q, zero_mem_valid_req_d, '0, clk_i, rst_ni) - -endmodule diff --git a/hw/future/src/dma/axi_dma_backend.sv b/hw/future/src/dma/axi_dma_backend.sv deleted file mode 100644 index b8cfa81dc..000000000 --- a/hw/future/src/dma/axi_dma_backend.sv +++ /dev/null @@ -1,601 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -/// The backend implements the generic 1D data transfer on an AXI BUS -module axi_dma_backend #( - /// Data width of the AXI bus - parameter int unsigned DataWidth = -1, - /// Address width of the AXI bus - parameter int unsigned AddrWidth = -1, - /// ID width of the AXI bus - parameter int unsigned IdWidth = -1, - /// Number of AX beats that can be in-flight - parameter int unsigned AxReqFifoDepth = -1, - /// Number of generic 1D requests that can be buffered - parameter int unsigned TransFifoDepth = -1, - /// Number of elements the realignment buffer can hold. To achieve - /// full performance a depth of 3 is minimally required. - parameter int unsigned BufferDepth = -1, - /// AXI4+ATOP request struct definition. - parameter type axi_req_t = logic, - /// AXI4+ATOP response struct definition. - parameter type axi_res_t = logic, - /// Arbitrary 1D burst request definition: - /// - `id`: the AXI id used - this id should be constant, as the DMA does not support reordering - /// - `src`, `dst`: source and destination address, same width as the AXI 4 channels - /// - `num_bytes`: the length of the contiguous 1D transfer requested, can be up to 32/64 bit long - /// num_bytes will be interpreted as an unsigned number - /// A value of 0 will cause the backend to discard the transfer prematurely - /// - `src_cache`, `dst_cache`: the configuration of the cache fields in the AX beats - /// - `src_burst`, `dst_burst`: currently only incremental bursts are supported (`2'b01`) - /// - `decouple_rw`: if set to true, there is no longer exactly one AXI write_request issued for - /// every read request. This mode can improve performance of unaligned transfers when crossing - /// the AXI page boundaries. - /// - `deburst`: if set, the DMA will split all bursts in single transfers - /// - `serialize`: if set, the DMA will only send AX belonging to a given Arbitrary 1D burst request - /// at a time. This is default behavior to prevent deadlocks. Setting `serialize` to - /// zero violates the AXI4+ATOP specification. - parameter type burst_req_t = logic, - /// Give each DMA backend a unique id - parameter int unsigned DmaIdWidth = -1, - /// Enable or disable tracing - parameter bit DmaTracing = 0 - -) ( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// AXI4+ATOP master request - output axi_req_t axi_dma_req_o, - /// AXI4+ATOP master response - input axi_res_t axi_dma_res_i, - /// Arbitrary 1D burst request - input burst_req_t burst_req_i, - /// Handshake: 1D burst request is valid - input logic valid_i, - /// Handshake: 1D burst can be accepted - output logic ready_o, - /// High if the backend is idle - output logic backend_idle_o, - /// Event: a 1D burst request has completed - output logic trans_complete_o, - /// unique DMA id - input logic [DmaIdWidth-1:0] dma_id_i -); - - /// Number of bytes per word - localparam int unsigned StrobeWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrobeWidth); - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Address Type - typedef logic [AddrWidth-1:0] addr_t; - /// AXI ID Type - typedef logic [IdWidth-1:0] axi_id_t; - - /// id: AXI id - /// last: last transaction in burst - /// address: address of burst - /// length: burst length - /// size: bytes in each burst - /// burst: burst type; only INC supported - /// cache: cache type - typedef struct packed { - axi_id_t id; - logic last; - addr_t addr; - axi_pkg::len_t len; - axi_pkg::size_t size; - axi_pkg::burst_t burst; - axi_pkg::cache_t cache; - } desc_ax_t; - - /// offset: initial misalignment - /// tailer: final misalignment - /// shift: amount the data needs to be shifted to realign it - typedef struct packed { - offset_t offset; - offset_t tailer; - offset_t shift; - } desc_r_t; - - /// offset: initial misalignment - /// tailer: final misalignment - /// num_beats: number of beats in the burst - /// is_single: burst length is 0 - typedef struct packed { - offset_t offset; - offset_t tailer; - axi_pkg::len_t num_beats; - logic is_single; - } desc_w_t; - - /// Write request definition - typedef struct packed { - desc_ax_t aw; - desc_w_t w; - } write_req_t; - - /// Read request definition - typedef struct packed { - desc_ax_t ar; - desc_r_t r; - } read_req_t; - - //-------------------------------------- - // Assertions - //-------------------------------------- - // pragma translate_off -`ifndef VERILATOR - initial begin - assert (DataWidth inside {16, 32, 64, 128, 256, 512, 1024}) - else $fatal(1, "16 <= DataWidth <= 1024"); - assert (AddrWidth >= 32 & AddrWidth <= 128) - else $fatal(1, " 8 <= AddrWidth <= 128"); - end -`endif - // pragma translate_on - - //-------------------------------------- - // Request Fifo - //-------------------------------------- - burst_req_t burst_req; - logic burst_req_empty; - logic burst_req_pop; - logic burst_req_full; - - // buffer the input requests in a fifo - fifo_v3 #( - .dtype(burst_req_t), - .DEPTH(TransFifoDepth) - ) i_burst_request_fifo ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (burst_req_full), - .empty_o (burst_req_empty), - .usage_o (), - .data_i (burst_req_i), - .push_i (valid_i && ready_o), - .data_o (burst_req), - .pop_i (burst_req_pop) - ); - - assign ready_o = !burst_req_full; - - //-------------------------------------- - // Burst reshaper - //-------------------------------------- - write_req_t write_req; - read_req_t read_req; - - logic read_req_valid; - logic read_req_ready; - logic write_req_valid; - logic write_req_ready; - - // send the next burst either immediately or once the last burst - // has been completed. The former mode is not AXI4+ATOP spec - // conform and may result in deadlocks! - logic in_flight_d, in_flight_q; - logic burst_valid; - always_comb begin : proc_select_burst_valid - if (burst_req.serialize) begin - // AXI4-conform behavior. As both the buffer and the memory system - // assume in-order operation. - burst_valid = ~burst_req_empty & (~in_flight_q | trans_complete_o); - end else begin - // legacy, non-AXI4-conform behavior. Send as many AX as possible - // This can lead to deadlocks due to in-memory reordering - burst_valid = ~burst_req_empty; - end - end - - // transforms arbitrary burst into AXI conform bursts - axi_dma_burst_reshaper #( - .DataWidth (DataWidth), - .AddrWidth (AddrWidth), - .IdWidth (IdWidth), - .burst_req_t(burst_req_t), - .read_req_t (read_req_t), - .write_req_t(write_req_t) - ) i_axi_dma_burst_reshaper ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .burst_req_i(burst_req), - .valid_i (burst_valid), - .ready_o (burst_req_pop), - .write_req_o(write_req), - .read_req_o (read_req), - .r_valid_o (read_req_valid), - .r_ready_i (read_req_ready), - .w_valid_o (write_req_valid), - .w_ready_i (write_req_ready) - ); - - //-------------------------------------- - // Data mover - //-------------------------------------- - axi_dma_data_mover #( - .DataWidth (DataWidth), - .ReqFifoDepth(AxReqFifoDepth), - .BufferDepth (BufferDepth), - .read_req_t (read_req_t), - .write_req_t (write_req_t), - .axi_req_t (axi_req_t), - .axi_res_t (axi_res_t), - .desc_ax_t (desc_ax_t), - .desc_r_t (desc_r_t), - .desc_w_t (desc_w_t) - ) i_axi_dma_data_mover ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .axi_dma_req_o (axi_dma_req_o), - .axi_dma_res_i (axi_dma_res_i), - .read_req_i (read_req), - .write_req_i (write_req), - .r_valid_i (read_req_valid), - .r_ready_o (read_req_ready), - .w_valid_i (write_req_valid), - .w_ready_o (write_req_ready), - .data_mover_idle_o(backend_idle_o), - .trans_complete_o (trans_complete_o) - ); - - //-------------------------------------- - // In-flight check - //-------------------------------------- - // to conform to the AXI4+ATOP spec: only send a burst - // once the last one has been completed . This check can be overridden - always_comb begin : proc_in_flight_check - - // default: last state - in_flight_d = in_flight_q; - - // new transfer: set in-flight to one - if (burst_req_pop & ~burst_req_empty) begin - in_flight_d = 1; - end else begin - // no new transfer and the old retires -> idle - if (trans_complete_o) begin - in_flight_d = 0; - end - end - end - - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_in_flight_check_state - if (~rst_ni) begin - in_flight_q <= 0; - end else begin - in_flight_q <= in_flight_d; - end - end - - //-------------------------------------- - // Tracer - //-------------------------------------- - //pragma translate_off -`ifndef SYNTHESYS -`ifndef VERILATOR - generate - if (DmaTracing) begin : gen_dma_tracer - string fn; - integer f; - - logic [DataWidth/8-1:0][BufferDepth-1:0][7:0] buffer_mem; - - // open file - initial begin - #1; - $sformat(fn, "dma_trace_%05x.log", dma_id_i); - f = $fopen(fn, "w"); - $display("[Tracer] Logging DMA %d to %s", dma_id_i, fn); - end - - // access buffer memory storage - for (genvar d = 0; d < BufferDepth; d++) begin : gen_buff_depth - for (genvar i = 0; i < DataWidth / 8 - 1; i++) begin : gen_data_width - assign buffer_mem[i][d] = - i_axi_dma_data_mover.i_axi_dma_data_path.gen_fifo_buffer[i].i_fifo_buffer.mem_q[d]; - end - end - - // do the tracing - always_ff @(posedge clk_i) begin : proc_tracer - // dict - automatic longint dma_meta [string]; - automatic longint dma_backend [string]; - automatic longint dma_burst_res [string]; - automatic longint dma_data_mover[string]; - automatic logic [DataWidth-1:0] dma_data_path [string]; - automatic string dma_string; - - // start of python dict - dma_string = "{"; - - // we do not dump while reset - if (rst_ni) begin - - // commented signals are currently not used by the python golden model :) - - //-------------------------------------- - // Metadata - //-------------------------------------- - dma_meta = '{ - // time - "time" : $time(), - "DataWidth" : DataWidth, - "AddrWidth" : AddrWidth, - "IdWidth" : IdWidth, - "AxReqFifoDepth" : AxReqFifoDepth, - "TransFifoDepth" : TransFifoDepth, - "BufferDepth" : BufferDepth - }; - - //-------------------------------------- - // Backend - //-------------------------------------- - dma_backend = '{ - // dma backend interface - "backend_burst_req_id" : burst_req_i.id, - "backend_burst_req_src" : burst_req_i.src, - "backend_burst_req_dst" : burst_req_i.dst, - "backend_burst_req_num_bytes" : burst_req_i.num_bytes, - // "backend_burst_req_cache_src" : burst_req_i.cache_src, - // "backend_burst_req_cache_dst" : burst_req_i.cache_dst, - // "backend_burst_req_burst_src" : burst_req_i.burst_src, - // "backend_burst_req_burst_dst" : burst_req_i.burst_dst, - "backend_burst_req_burst_decouple_rw" : burst_req_i.decouple_rw, - "backend_burst_req_burst_deburst" : burst_req_i.deburst, - "backend_burst_req_valid" : valid_i, - "backend_burst_req_ready" : ready_o, - "backend_idle" : backend_idle_o, - "transfer_completed" : trans_complete_o - }; - - //-------------------------------------- - // Burst Reshaper - //-------------------------------------- - dma_burst_res = '{ - // burst request - "burst_reshaper_burst_req_id" : i_axi_dma_burst_reshaper.burst_req_i.id, - "burst_reshaper_burst_req_src" : i_axi_dma_burst_reshaper.burst_req_i.src, - "burst_reshaper_burst_req_dst" : i_axi_dma_burst_reshaper.burst_req_i.dst, - "burst_reshaper_burst_req_num_bytes" : i_axi_dma_burst_reshaper.burst_req_i.num_bytes, - // "burst_reshaper_burst_req_cache_src" : i_axi_dma_burst_reshaper.burst_req_i.cache_src, - // "burst_reshaper_burst_req_cache_dst" : i_axi_dma_burst_reshaper.burst_req_i.cache_dst, - // "burst_reshaper_burst_req_burst_src" : i_axi_dma_burst_reshaper.burst_req_i.burst_src, - // "burst_reshaper_burst_req_burst_dst" : i_axi_dma_burst_reshaper.burst_req_i.burst_dst, - "burst_reshaper_burst_req_decouple_rw" : i_axi_dma_burst_reshaper.burst_req_i.decouple_rw, - "burst_reshaper_burst_req_deburst" : i_axi_dma_burst_reshaper.burst_req_i.deburst, - "burst_reshaper_burst_req_valid" : i_axi_dma_burst_reshaper.valid_i, - "burst_reshaper_burst_req_ready" : i_axi_dma_burst_reshaper.ready_o, - // write request - "burst_reshaper_write_req_aw_id" : i_axi_dma_burst_reshaper.write_req_o.aw.id, - "burst_reshaper_write_req_aw_last" : i_axi_dma_burst_reshaper.write_req_o.aw.last, - "burst_reshaper_write_req_aw_addr" : i_axi_dma_burst_reshaper.write_req_o.aw.addr, - "burst_reshaper_write_req_aw_len" : i_axi_dma_burst_reshaper.write_req_o.aw.len, - "burst_reshaper_write_req_aw_size" : i_axi_dma_burst_reshaper.write_req_o.aw.size, - "burst_reshaper_write_req_aw_burst" : i_axi_dma_burst_reshaper.write_req_o.aw.burst, - "burst_reshaper_write_req_aw_cache" : i_axi_dma_burst_reshaper.write_req_o.aw.cache, - "burst_reshaper_write_req_w_offset" : i_axi_dma_burst_reshaper.write_req_o.w.offset, - "burst_reshaper_write_req_w_tailer" : i_axi_dma_burst_reshaper.write_req_o.w.tailer, - "burst_reshaper_write_req_w_num_beats" : i_axi_dma_burst_reshaper.write_req_o.w.num_beats, - // "burst_reshaper_write_req_w_is_single" : i_axi_dma_burst_reshaper.write_req_o.w.is_single, - "burst_reshaper_write_req_valid" : i_axi_dma_burst_reshaper.w_valid_o, - "burst_reshaper_write_req_ready" : i_axi_dma_burst_reshaper.w_ready_i, - // read request - "burst_reshaper_read_req_ar_id" : i_axi_dma_burst_reshaper.read_req_o.ar.id, - "burst_reshaper_read_req_ar_last" : i_axi_dma_burst_reshaper.read_req_o.ar.last, - "burst_reshaper_read_req_ar_addr" : i_axi_dma_burst_reshaper.read_req_o.ar.addr, - "burst_reshaper_read_req_ar_len" : i_axi_dma_burst_reshaper.read_req_o.ar.len, - "burst_reshaper_read_req_ar_size" : i_axi_dma_burst_reshaper.read_req_o.ar.size, - "burst_reshaper_read_req_ar_burst" : i_axi_dma_burst_reshaper.read_req_o.ar.burst, - "burst_reshaper_read_req_ar_cache" : i_axi_dma_burst_reshaper.read_req_o.ar.cache, - "burst_reshaper_read_req_r_offset" : i_axi_dma_burst_reshaper.read_req_o.r.offset, - "burst_reshaper_read_req_r_tailer" : i_axi_dma_burst_reshaper.read_req_o.r.tailer, - "burst_reshaper_read_req_r_shift" : i_axi_dma_burst_reshaper.read_req_o.r.shift, - "burst_reshaper_read_req_valid" : i_axi_dma_burst_reshaper.r_valid_o, - "burst_reshaper_read_req_ready" : i_axi_dma_burst_reshaper.r_ready_i// , - // current burst - // "burst_reshaper_burst_src_id" : i_axi_dma_burst_reshaper.burst_q.src.id, - // "burst_reshaper_burst_src_addr" : i_axi_dma_burst_reshaper.burst_q.src.addr, - // "burst_reshaper_burst_src_num_bytes" : i_axi_dma_burst_reshaper.burst_q.src.num_bytes, - // "burst_reshaper_burst_src_cache" : i_axi_dma_burst_reshaper.burst_q.src.cache, - // "burst_reshaper_burst_src_burst" : i_axi_dma_burst_reshaper.burst_q.src.burst, - // "burst_reshaper_burst_src_valid" : i_axi_dma_burst_reshaper.burst_q.src.valid, - // "burst_reshaper_burst_dst_id" : i_axi_dma_burst_reshaper.burst_q.dst.id, - // "burst_reshaper_burst_dst_addr" : i_axi_dma_burst_reshaper.burst_q.dst.addr, - // "burst_reshaper_burst_dst_num_bytes" : i_axi_dma_burst_reshaper.burst_q.dst.num_bytes, - // "burst_reshaper_burst_dst_cache" : i_axi_dma_burst_reshaper.burst_q.dst.cache, - // "burst_reshaper_burst_dst_burst" : i_axi_dma_burst_reshaper.burst_q.dst.burst, - // "burst_reshaper_burst_dst_valid" : i_axi_dma_burst_reshaper.burst_q.dst.valid, - // "burst_reshaper_burst_shift" : i_axi_dma_burst_reshaper.burst_q.shift, - // "burst_reshaper_burst_decouple_rw" : i_axi_dma_burst_reshaper.burst_q.decouple_rw, - // "burst_reshaper_burst_deburst" : i_axi_dma_burst_reshaper.burst_q.deburst, - // page - // "burst_reshaper_r_page_offset" : i_axi_dma_burst_reshaper.r_page_offset, - // "burst_reshaper_r_num_bytes_to_pb" : i_axi_dma_burst_reshaper.r_num_bytes_to_pb, - // "burst_reshaper_w_page_offset" : i_axi_dma_burst_reshaper.w_page_offset, - // "burst_reshaper_w_num_bytes_to_pb" : i_axi_dma_burst_reshaper.w_num_bytes_to_pb, - // "burst_reshaper_c_num_bytes_to_pb" : i_axi_dma_burst_reshaper.c_num_bytes_to_pb, - // issue process - // "burst_reshaper_r_num_bytes_possible" : i_axi_dma_burst_reshaper.r_num_bytes_possible, - // "burst_reshaper_r_num_bytes" : i_axi_dma_burst_reshaper.r_num_bytes, - // "burst_reshaper_r_finish" : i_axi_dma_burst_reshaper.r_finish, - // "burst_reshaper_r_addr_offset" : i_axi_dma_burst_reshaper.r_addr_offset, - // "burst_reshaper_w_num_bytes_possible" : i_axi_dma_burst_reshaper.w_num_bytes_possible, - // "burst_reshaper_w_num_bytes" : i_axi_dma_burst_reshaper.w_num_bytes, - // "burst_reshaper_w_finish" : i_axi_dma_burst_reshaper.w_finish, - // "burst_reshaper_w_addr_offset" : i_axi_dma_burst_reshaper.w_addr_offset - }; - - //-------------------------------------- - // Data Mover - //-------------------------------------- - dma_data_mover = '{ - // AR emitter - // "data_mover_ar_emitter_full" : i_axi_dma_data_mover.ar_emitter_full, - // "data_mover_ar_emitter_empty" : i_axi_dma_data_mover.ar_emitter_empty, - // "data_mover_ar_emitter_push" : i_axi_dma_data_mover.ar_emitter_push, - // "data_mover_ar_emitter_pop" : i_axi_dma_data_mover.ar_emitter_pop, - // AW emitter - // "data_mover_aw_emitter_full" : i_axi_dma_data_mover.aw_emitter_full, - // "data_mover_aw_emitter_empty" : i_axi_dma_data_mover.aw_emitter_empty, - // "data_mover_aw_emitter_push" : i_axi_dma_data_mover.aw_emitter_push, - // "data_mover_aw_emitter_pop" : i_axi_dma_data_mover.aw_emitter_pop, - // "data_mover_is_last_aw" : i_axi_dma_data_mover.is_last_aw, - // R emitter - // "data_mover_r_emitter_full" : i_axi_dma_data_mover.r_emitter_full, - // "data_mover_r_emitter_empty" : i_axi_dma_data_mover.r_emitter_empty, - // "data_mover_r_emitter_push" : i_axi_dma_data_mover.r_emitter_push, - // "data_mover_r_emitter_pop" : i_axi_dma_data_mover.r_emitter_pop, - // W emitter - // "data_mover_w_emitter_full" : i_axi_dma_data_mover.w_emitter_full, - // "data_mover_w_emitter_empty" : i_axi_dma_data_mover.w_emitter_empty, - // "data_mover_w_emitter_push" : i_axi_dma_data_mover.w_emitter_push, - // "data_mover_w_emitter_pop" : i_axi_dma_data_mover.w_emitter_pop, - // AW AXI signals - // "axi_dma_bus_aw_id" : i_axi_dma_data_mover.axi_dma_req_o.aw.id, - // "axi_dma_bus_aw_addr" : i_axi_dma_data_mover.axi_dma_req_o.aw.addr, - "axi_dma_bus_aw_len" : i_axi_dma_data_mover.axi_dma_req_o.aw.len, - "axi_dma_bus_aw_size" : i_axi_dma_data_mover.axi_dma_req_o.aw.size, - // "axi_dma_bus_aw_burst" : i_axi_dma_data_mover.axi_dma_req_o.aw.burst, - // "axi_dma_bus_aw_cache" : i_axi_dma_data_mover.axi_dma_req_o.aw.cache, - "axi_dma_bus_aw_valid" : i_axi_dma_data_mover.axi_dma_req_o.aw_valid, - "axi_dma_bus_aw_ready" : i_axi_dma_data_mover.axi_dma_res_i.aw_ready, - // B AXI signals - "axi_dma_bus_b_ready" : i_axi_dma_data_mover.axi_dma_req_o.b_ready, - "axi_dma_bus_b_valid" : i_axi_dma_data_mover.axi_dma_res_i.b_valid, - // AR AXI signals - // "axi_dma_bus_ar_id" : i_axi_dma_data_mover.axi_dma_req_o.ar.id, - // "axi_dma_bus_ar_addr" : i_axi_dma_data_mover.axi_dma_req_o.ar.addr, - "axi_dma_bus_ar_len" : i_axi_dma_data_mover.axi_dma_req_o.ar.len, - "axi_dma_bus_ar_size" : i_axi_dma_data_mover.axi_dma_req_o.ar.size, - // "axi_dma_bus_ar_burst" : i_axi_dma_data_mover.axi_dma_req_o.ar.burst, - // "axi_dma_bus_ar_cache" : i_axi_dma_data_mover.axi_dma_req_o.ar.cache, - "axi_dma_bus_ar_valid" : i_axi_dma_data_mover.axi_dma_req_o.ar_valid, - "axi_dma_bus_ar_ready" : i_axi_dma_data_mover.axi_dma_res_i.ar_ready - }; - - //-------------------------------------- - // Data Path - //-------------------------------------- - dma_data_path = '{ - // r channel - "data_path_r_dp_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.r_dp_valid_i, - "data_path_r_dp_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.r_dp_ready_o, - "data_path_r_tailer_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_tailer_i, - "data_path_r_offset_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_offset_i, - "data_path_r_shift_i" : i_axi_dma_data_mover.i_axi_dma_data_path.r_shift_i, - "axi_dma_bus_r_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.r_valid_i, - // "axi_dma_bus_r_data" : i_axi_dma_data_mover.i_axi_dma_data_path.r_data_i, - // "axi_dma_bus_r_last" : i_axi_dma_data_mover.i_axi_dma_data_path.r_last_i, - // "axi_dma_bus_r_resp" : i_axi_dma_data_mover.i_axi_dma_data_path.r_resp_i, - "axi_dma_bus_r_ready" : - i_axi_dma_data_mover.i_axi_dma_data_path.r_ready_o, - // w channel - "data_path_w_dp_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_dp_valid_i, - "data_path_w_dp_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.w_dp_ready_o, - "data_path_w_tailer_i" : i_axi_dma_data_mover.i_axi_dma_data_path.w_tailer_i, - "data_path_w_offset_i" : i_axi_dma_data_mover.i_axi_dma_data_path.w_offset_i, - "data_path_w_num_beats" : i_axi_dma_data_mover.i_axi_dma_data_path.w_num_beats_i, - "data_path_w_is_single" : i_axi_dma_data_mover.i_axi_dma_data_path.w_is_single_i, - "axi_dma_bus_w_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_valid_o, - // "axi_dma_bus_w_data" : i_axi_dma_data_mover.i_axi_dma_data_path.w_data_o, - "axi_dma_bus_w_strb" : i_axi_dma_data_mover.i_axi_dma_data_path.w_strb_o, - // "axi_dma_bus_w_last" : i_axi_dma_data_mover.i_axi_dma_data_path.w_last_o, - "axi_dma_bus_w_ready" : i_axi_dma_data_mover.i_axi_dma_data_path.w_ready_i, - // mask pre-calculation - "data_path_r_first_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.r_first_mask, - "data_path_r_last_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.r_last_mask, - "data_path_w_first_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.w_first_mask, - "data_path_w_last_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.w_last_mask, - // barrel shifter - // "data_path_buffer_in" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_in, - "data_path_read_aligned_in_mask" : - i_axi_dma_data_mover.i_axi_dma_data_path.read_aligned_in_mask, - "data_path_write_aligned_in_mask" : - i_axi_dma_data_mover.i_axi_dma_data_path.in_mask, - // in mask generation - // "data_path_is_first_r" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r, - // "data_path_is_first_r_d" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r_d, - // "data_path_is_first_r_d" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_r_d, - // read control - // "data_path_buffer_full" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_full, - // "data_path_buffer_push" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_push, - // "data_path_full" : i_axi_dma_data_mover.i_axi_dma_data_path.full, - "data_path_push" : i_axi_dma_data_mover.i_axi_dma_data_path.push, - // out mask generation - "data_path_out_mask" : i_axi_dma_data_mover.i_axi_dma_data_path.out_mask, - // "data_path_is_first_w" : i_axi_dma_data_mover.i_axi_dma_data_path.is_first_w, - // "data_path_is_last_w" : i_axi_dma_data_mover.i_axi_dma_data_path.is_last_w, - // write control - // "data_path_buffer_out" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_out, - // "data_path_buffer_empty" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_empty, - // "data_path_buffer_pop" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_pop, - // "data_path_w_num_beats" : i_axi_dma_data_mover.i_axi_dma_data_path.w_num_beats_q, - // "data_path_w_cnt_valid" : i_axi_dma_data_mover.i_axi_dma_data_path.w_cnt_valid_q, - "data_path_pop" : i_axi_dma_data_mover.i_axi_dma_data_path.pop // , - // "data_path_write_happening" : i_axi_dma_data_mover.i_axi_dma_data_path.write_happening, - // "data_path_ready_to_write" : i_axi_dma_data_mover.i_axi_dma_data_path.ready_to_write, - // "data_path_first_possible" : i_axi_dma_data_mover.i_axi_dma_data_path.first_possible, - // "data_path_buffer_clean" : i_axi_dma_data_mover.i_axi_dma_data_path.buffer_clean - }; - - // write dicts to string - foreach (dma_meta[key]) - dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_meta[key]); - // only write bulk of data if dma is actually active :) - if (!backend_idle_o | valid_i & ready_o | - i_axi_dma_burst_reshaper.valid_i & i_axi_dma_burst_reshaper.ready_o | - i_axi_dma_burst_reshaper.burst_q.src.valid | - i_axi_dma_burst_reshaper.burst_q.dst.valid | - trans_complete_o) begin - foreach (dma_backend[key]) - dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_backend[key]); - foreach (dma_burst_res[key]) - dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_burst_res[key]); - foreach (dma_data_mover[key]) - dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_data_mover[key]); - foreach (dma_data_path[key]) - dma_string = $sformatf("%s'%s': 0x%0x, ", dma_string, key, dma_data_path[key]); - - //-------------------------------------- - // Realign Buffer Data Store - //-------------------------------------- - // for(int d = 0; d < BUFFER_DEPTH; d++) begin - // for(int i = 0; i < DATA_WIDTH/8; i++) begin - // dma_string = $sformatf("%s'buffer_mem_%0d_level_%0d': 0x%0x, ", - // dma_string, i, d, buffer_mem[i][d] - // ); - // end - // end - end - dma_string = $sformatf("%s}", dma_string); - $fwrite(f, dma_string); - $fwrite(f, "\n"); - end - end - // close the file - final begin - $fclose(f); - end - end - endgenerate -`endif -`endif - //pragma translate_on -endmodule : axi_dma_backend diff --git a/hw/future/src/dma/axi_dma_burst_reshaper.sv b/hw/future/src/dma/axi_dma_burst_reshaper.sv deleted file mode 100644 index fbea23819..000000000 --- a/hw/future/src/dma/axi_dma_burst_reshaper.sv +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -/// Splits a generic 1D transfer in AXI-conform transfers -module axi_dma_burst_reshaper #( - /// Data width of the AXI bus - parameter int unsigned DataWidth = -1, - /// Address width of the AXI bus - parameter int unsigned AddrWidth = -1, - /// ID width of the AXI bus - parameter int unsigned IdWidth = -1, - /// Arbitrary 1D burst request definition: - /// - id: the AXI id used - this id should be constant, as the DMA does not support reordering - /// - src, dst: source and destination address, same width as the AXI 4 interface - /// - num_bytes: the length of the contiguous 1D transfer requested, can be up to 32/64 bit long - /// num_bytes will be interpreted as an unsigned number - /// A value of 0 will cause the backend to discard the transfer prematurely - /// - src_cache, dst_cache: the configuration of the cache fields in the AX beats - /// - src_burst, dst_burst: currently only incremental bursts are supported (2'b01) - /// - decouple_rw: if set to true, there is no longer exactly one AXI write_request issued for - /// every read request. This mode can improve performance of unaligned transfers when crossing - /// the AXI page boundaries. - /// - deburst: if set, the DMA will split all bursts in single transfers - parameter type burst_req_t = logic, - /// Read request definition. Includes: - /// - ax descriptor - /// - id: AXI id - /// - last: last transaction in burst - /// - address: address of burst - /// - length: burst length - /// - size: bytes in each burst - /// - burst: burst type; only INC supported - /// - cache: cache type - /// - r descriptor - /// - offset: initial misalignment - /// - tailer: final misalignment - /// - shift: amount the data needs to be shifted to realign it - parameter type read_req_t = logic, - /// Write request definition. Includes: - /// - ax descriptor - /// - id: AXI id - /// - last: last transaction in burst - /// - address: address of burst - /// - length: burst length - /// - size: bytes in each burst - /// - burst: burst type; only INC supported - /// - cache: cache type - /// - w descriptor - /// - offset: initial misalignment - /// - tailer: final misalignment - /// - num_beats: number of beats in the burst - /// - is_single: burst length is 0 - parameter type write_req_t = logic - -) ( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Arbitrary 1D burst request - input burst_req_t burst_req_i, - - /// Handshake: burst request is valid - input logic valid_i, - /// Handshake: burst request can be accepted - output logic ready_o, - - /// Write transfer request - output write_req_t write_req_o, - /// Read transfer request - output read_req_t read_req_o, - - /// Handshake: read transfer request valid - output logic r_valid_o, - /// Handshake: read transfer request ready - input logic r_ready_i, - /// Handshake: write transfer request valid - output logic w_valid_o, - /// Handshake: write transfer request ready - input logic w_ready_i -); - - localparam int unsigned StrbWidth = DataWidth / 8; - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - localparam int unsigned PageSize = (256 * StrbWidth > 4096) ? 4096 : 256 * StrbWidth; - localparam int unsigned PageAddrWidth = $clog2(PageSize); - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Address Type - typedef logic [AddrWidth-1:0] addr_t; - /// AXI ID Type - typedef logic [IdWidth-1:0] axi_id_t; - - /// Type containing burst description for each channel independently - typedef struct packed { - axi_id_t id; - addr_t addr; - addr_t num_bytes; - axi_pkg::cache_t cache; - axi_pkg::burst_t burst; - logic valid; - } burst_chan_t; - - /// Type containing burst description - typedef struct packed { - burst_chan_t src; - burst_chan_t dst; - offset_t shift; - logic decouple_rw; - logic deburst; - } burst_decoupled_t; - - //-------------------------------------- - // state; internally hold one transfer - //-------------------------------------- - burst_decoupled_t burst_d, burst_q; - - //-------------------------------------- - // page boundary check - //-------------------------------------- - logic [PageAddrWidth-1:0] r_page_offset; - logic [PageAddrWidth : 0] r_num_bytes_to_pb; - logic [PageAddrWidth-1:0] w_page_offset; - logic [PageAddrWidth : 0] w_num_bytes_to_pb; - logic [PageAddrWidth : 0] c_num_bytes_to_pb; - - always_comb begin : proc_write_page_boundry_check - // implement deburst operation - if (burst_q.deburst) begin - // deburst - // read pages - r_page_offset = burst_q.src.addr[OffsetWidth-1:0]; - // how many transfers are remaining until the end of the bus? - r_num_bytes_to_pb = (StrbWidth - r_page_offset) % (2 * StrbWidth); - - // write pages - w_page_offset = burst_q.dst.addr[OffsetWidth-1:0]; - // how many transfers are remaining until the end of the bus? - w_num_bytes_to_pb = (StrbWidth - w_page_offset) % (2 * StrbWidth); - end else begin - // bursts allowed - // read pages - r_page_offset = burst_q.src.addr[PageAddrWidth-1:0]; - // how many transfers are remaining in current page? - r_num_bytes_to_pb = PageSize - r_page_offset; - - // write pages - w_page_offset = burst_q.dst.addr[PageAddrWidth-1:0]; - // how many transfers are remaining in current page? - w_num_bytes_to_pb = PageSize - w_page_offset; - end - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - end - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - logic [PageAddrWidth:0] r_num_bytes_possible; - logic [PageAddrWidth:0] r_num_bytes; - logic r_finish; - logic [OffsetWidth-1:0] r_addr_offset; - - logic [PageAddrWidth:0] w_num_bytes_possible; - logic [PageAddrWidth:0] w_num_bytes; - logic w_finish; - logic [OffsetWidth-1:0] w_addr_offset; - - always_comb begin : proc_read_write_transaction - - // default: keep last state - burst_d = burst_q; - - //-------------------------------------- - // Specify read transaction - //-------------------------------------- - // max num bytes according to page(s) - r_num_bytes_possible = (burst_q.decouple_rw == 1'b1) ? r_num_bytes_to_pb : c_num_bytes_to_pb; - - // more bytes remaining than we can send - if (burst_q.src.num_bytes > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - burst_d.src.num_bytes = burst_q.src.num_bytes - r_num_bytes_possible; - // not finished - r_finish = 1'b0; - // next address, depends on burst type. only type 01 is supported yet - burst_d.src.addr = (burst_q.src.burst == axi_pkg::BURST_INCR) ? - burst_q.src.addr + r_num_bytes : burst_q.src.addr; - - // remaining bytes fit in one burst - // reset storage for the read channel to stop this channel - end else begin - r_num_bytes = burst_q.src.num_bytes[PageAddrWidth:0]; - // default: when a transfer is finished, set it to 0 - burst_d.src = '0; - // finished - r_finish = 1'b1; - end - - // calculate the address offset aligned to transfer sizes. - r_addr_offset = burst_q.src.addr[OffsetWidth-1:0]; - - // create the AR request - read_req_o.ar.addr = {burst_q.src.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth} {1'b0}}}; - read_req_o.ar.len = ((r_num_bytes + r_addr_offset - 1) >> OffsetWidth); - read_req_o.ar.size = axi_pkg::size_t'(OffsetWidth); - read_req_o.ar.id = burst_q.src.id; - read_req_o.ar.last = r_finish; - read_req_o.ar.burst = burst_q.src.burst; - read_req_o.ar.cache = burst_q.src.cache; - r_valid_o = burst_q.decouple_rw ? burst_q.src.valid : burst_q.src.valid & w_ready_i; - - // create the R request - read_req_o.r.offset = r_addr_offset; - read_req_o.r.tailer = OffsetWidth'(r_num_bytes + r_addr_offset); - // shift is determined on a per 1D request base - read_req_o.r.shift = burst_q.shift; - - //-------------------------------------- - // Specify write transaction - //-------------------------------------- - // max num bytes according to page(s) - w_num_bytes_possible = (burst_q.decouple_rw == 1'b1) ? w_num_bytes_to_pb : c_num_bytes_to_pb; - - // more bytes remaining than we can send - if (burst_q.dst.num_bytes > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - burst_d.dst.num_bytes = burst_q.dst.num_bytes - w_num_bytes_possible; - // not finished - w_finish = 1'b0; - // next address, depends on burst type. only type 01 is supported yet - burst_d.dst.addr = (burst_q.dst.burst == axi_pkg::BURST_INCR) ? - burst_q.dst.addr + w_num_bytes : burst_q.dst.addr; - - // remaining bytes fit in one burst - // reset storage for the write channel to stop this channel - end else begin - w_num_bytes = burst_q.dst.num_bytes[PageAddrWidth:0]; - // default: when a transfer is finished, set it to 0 - burst_d.dst = '0; - // finished - w_finish = 1'b1; - end - - // calculate the address offset aligned to transfer sizes. - w_addr_offset = burst_q.dst.addr[OffsetWidth-1:0]; - - // create the AW request - write_req_o.aw.addr = {burst_q.dst.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth} {1'b0}}}; - write_req_o.aw.len = ((w_num_bytes + w_addr_offset - 1) >> OffsetWidth); - write_req_o.aw.size = axi_pkg::size_t'(OffsetWidth); - write_req_o.aw.id = burst_q.dst.id; - // hand over internal transaction id - write_req_o.aw.last = w_finish; - write_req_o.aw.burst = burst_q.dst.burst; - write_req_o.aw.cache = burst_q.dst.cache; - w_valid_o = burst_q.decouple_rw ? burst_q.dst.valid : burst_q.dst.valid & r_ready_i; - - // create the W request - write_req_o.w.offset = w_addr_offset; - write_req_o.w.tailer = OffsetWidth'(w_num_bytes + w_addr_offset); - write_req_o.w.num_beats = write_req_o.aw.len; - // is the transfer be only one beat in length? Counters don't have to be initialized then. - write_req_o.w.is_single = (write_req_o.aw.len == '0); - - //-------------------------------------- - // Module control - //-------------------------------------- - ready_o = r_finish & w_finish & valid_i & r_ready_i & w_ready_i; - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o) begin - // unfortunately this is unpacked - burst_d.src.id = burst_req_i.id; - burst_d.src.addr = burst_req_i.src; - burst_d.src.num_bytes = burst_req_i.num_bytes; - burst_d.src.cache = burst_req_i.cache_src; - burst_d.src.burst = burst_req_i.burst_src; - // check if transfer is possible -> num_bytes has to be larger than 0 - burst_d.src.valid = (burst_req_i.num_bytes == '0) ? 1'b0 : valid_i; - - burst_d.dst.id = burst_req_i.id; - burst_d.dst.addr = burst_req_i.dst; - burst_d.dst.num_bytes = burst_req_i.num_bytes; - burst_d.dst.cache = burst_req_i.cache_dst; - burst_d.dst.burst = burst_req_i.burst_dst; - // check if transfer is possible -> num_bytes has to be larger than 0 - burst_d.dst.valid = (burst_req_i.num_bytes == '0) ? 1'b0 : valid_i; - - burst_d.decouple_rw = burst_req_i.decouple_rw; - burst_d.deburst = burst_req_i.deburst; - // shift is calculated for each 1D transfer - burst_d.shift = burst_req_i.src[OffsetWidth-1:0] - burst_req_i.dst[OffsetWidth-1:0]; - - // assertions - // pragma translate_off -`ifndef VERILATOR - assert property (@(posedge clk_i) disable iff (~rst_ni) - (valid_i |-> burst_req_i.burst_src inside {axi_pkg::BURST_INCR})) - else $fatal(1, "Unsupported DMA src_burst request.."); - assert property (@(posedge clk_i) disable iff (~rst_ni) - (valid_i |-> burst_req_i.burst_dst inside {axi_pkg::BURST_INCR})) - else $fatal(1, "Unsupported DMA dst_burst request."); -`endif - // pragma translate_on - end - end - - //-------------------------------------- - // State - //-------------------------------------- - always_ff @(posedge clk_i or negedge rst_ni) begin - if (!rst_ni) begin - burst_q.decouple_rw <= '0; - burst_q.deburst <= '0; - burst_q.shift <= '0; - burst_q.src <= '0; - burst_q.dst <= '0; - end else begin - burst_q.decouple_rw <= burst_d.decouple_rw; - burst_q.deburst <= burst_d.deburst; - burst_q.shift <= burst_d.shift; - // couple read and write machines in the coupled test - if (burst_d.decouple_rw) begin - if (r_ready_i) burst_q.src <= burst_d.src; - if (w_ready_i) burst_q.dst <= burst_d.dst; - end else begin - if (r_ready_i & w_ready_i) burst_q.src <= burst_d.src; - if (w_ready_i & r_ready_i) burst_q.dst <= burst_d.dst; - end - end - end -endmodule : axi_dma_burst_reshaper diff --git a/hw/future/src/dma/axi_dma_data_mover.sv b/hw/future/src/dma/axi_dma_data_mover.sv deleted file mode 100644 index 9c11f72f9..000000000 --- a/hw/future/src/dma/axi_dma_data_mover.sv +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -/// Module, that controls the AXI bus. Takes two configuration structs (R/W) as an -/// input. Implements the DMA functionality on the AXI bus. -/// R and W config structs need to appear at the input simultaneously; sending a -/// R config w/o the corresponding W could lead to wrong AXI transfers. -module axi_dma_data_mover #( - /// Data width of the AXI bus - parameter int unsigned DataWidth = -1, - /// Number of AX beats that can be in-flight - parameter int unsigned ReqFifoDepth = -1, - /// Number of elements the realignment buffer can hold. To achieve - /// full performance a depth of 3 is minimally required. - parameter int unsigned BufferDepth = -1, - /// AXI4+ATOP request struct definition. - parameter type axi_req_t = logic, - /// AXI4+ATOP response struct definition. - parameter type axi_res_t = logic, - /// ax descriptor - /// - `id`: AXI id - /// - `last`: last transaction in burst - /// - `address`: address of burst - /// - `length`: burst length - /// - `size`: bytes in each burst - /// - `burst`: burst type; only INC supported - /// - `cache`: cache type - parameter type desc_ax_t = logic, - /// r descriptor - /// - `offset`: initial misalignment - /// - `tailer`: final misalignment - /// - `shift`: amount the data needs to be shifted to realign it - parameter type desc_r_t = logic, - /// w descriptor - /// - `offset`: initial misalignment - /// - `tailer`: final misalignment - /// - `num_beats`: number of beats in the burst - /// - `is_single`: burst length is 0 - parameter type desc_w_t = logic, - /// Read request definition. Includes: - /// - ax descriptor - /// - `id`: AXI id - /// - `last`: last transaction in burst - /// - `address`: address of burst - /// - `length`: burst length - /// - `size`: bytes in each burst - /// - `burst`: burst type; only INC supported - /// - `cache`: cache type - /// - r descriptor - /// - `offset`: initial misalignment - /// - `tailer`: final misalignment - /// - `shift`: amount the data needs to be shifted to realign it - parameter type read_req_t = logic, - /// Write request definition. Includes: - /// - ax descriptor - /// - `id`: AXI id - /// - `last`: last transaction in burst - /// - `address`: address of burst - /// - `length`: burst length - /// - `size`: bytes in each burst - /// - `burst`: burst type; only INC supported - /// - `cache`: cache type - /// - w descriptor - /// - `offset`: initial misalignment - /// - `tailer`: final misalignment - /// - `num_beats`: number of beats in the burst - /// - `is_single`: burst length is 0 - parameter type write_req_t = logic -) ( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// AXI4+ATOP master request - output axi_req_t axi_dma_req_o, - /// AXI4+ATOP master response - input axi_res_t axi_dma_res_i, - /// Read transfer request - input read_req_t read_req_i, - /// Write transfer request - input write_req_t write_req_i, - /// Handshake: read transfer request valid - input logic r_valid_i, - /// Handshake: read transfer request ready - output logic r_ready_o, - /// Handshake: write transfer request valid - input logic w_valid_i, - /// Handshake: write transfer request ready - output logic w_ready_o, - /// High if the data mover is idle - output logic data_mover_idle_o, - /// Event: a transaction has completed - output logic trans_complete_o -); - - localparam int unsigned StrbWidth = DataWidth / 8; - // local types - typedef logic [DataWidth-1:0] data_t; - typedef logic [StrbWidth-1:0] strb_t; - - //-------------------------------------- - // AR emitter - //-------------------------------------- - // object currently at the tail of the fifo - desc_ax_t current_ar_req; - // control signals - logic ar_emitter_full; - logic ar_emitter_empty; - logic ar_emitter_push; - logic ar_emitter_pop; - - // instanciate a fifo to buffer the address read requests - fifo_v3 #( - .FALL_THROUGH(1'b0), - .DEPTH (ReqFifoDepth), - .dtype (desc_ax_t) - ) i_fifo_ar_emitter ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (ar_emitter_full), - .empty_o (ar_emitter_empty), - .usage_o (), - .data_i (read_req_i.ar), - .push_i (ar_emitter_push), - .data_o (current_ar_req), - .pop_i (ar_emitter_pop) - ); - - //-------------------------------------- - // AW emitter - //-------------------------------------- - // object currently at the tail of the fifo - desc_ax_t current_aw_req; - // control signals - logic aw_emitter_full; - logic aw_emitter_empty; - logic aw_emitter_push; - logic aw_emitter_pop; - logic aw_last_full; - - // instantiate a fifo to buffer the address write requests - fifo_v3 #( - .FALL_THROUGH(1'b0), - .dtype (desc_ax_t), - .DEPTH (ReqFifoDepth) - ) i_fifo_aw_emitter ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (aw_emitter_full), - .empty_o (aw_emitter_empty), - .usage_o (), - .data_i (write_req_i.aw), - .push_i (aw_emitter_push), - .data_o (current_aw_req), - .pop_i (aw_emitter_pop) - ); - - //-------------------------------------- - // R emitter - //-------------------------------------- - // object currently at the tail of the fifo - desc_r_t current_r_req; - // control signals - logic r_emitter_full; - logic r_emitter_empty; - logic r_emitter_push; - logic r_emitter_pop; - - // instantiate a fifo to buffer the read requests - fifo_v3 #( - .FALL_THROUGH(1'b0), - .dtype (desc_r_t), - .DEPTH (ReqFifoDepth) - ) i_fifo_r_emitter ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (r_emitter_full), - .empty_o (r_emitter_empty), - .usage_o (), - .data_i (read_req_i.r), - .push_i (r_emitter_push), - .data_o (current_r_req), - .pop_i (r_emitter_pop) - ); - - //-------------------------------------- - // W emitter - //-------------------------------------- - // object currently at the tail of the fifo - desc_w_t current_w_req; - // control signals - logic w_emitter_full; - logic w_emitter_empty; - logic w_emitter_push; - logic w_emitter_pop; - - // instanciate a fifo to buffer the read requests - fifo_v3 #( - .FALL_THROUGH(1'b0), - .dtype (desc_w_t), - .DEPTH (ReqFifoDepth) - ) i_fifo_w_emitter ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (w_emitter_full), - .empty_o (w_emitter_empty), - .usage_o (), - .data_i (write_req_i.w), - .push_i (w_emitter_push), - .data_o (current_w_req), - .pop_i (w_emitter_pop) - ); - - //-------------------------------------- - // instantiate of the data path - //-------------------------------------- - // AXI bus signals from and to the datapath - data_t r_data; - axi_pkg::resp_t r_resp; - logic r_last; - logic r_valid; - logic r_ready; - data_t w_data; - strb_t w_strb; - logic w_valid; - logic w_last; - logic w_ready; - - logic w_next; - - axi_dma_data_path #( - .DataWidth (DataWidth), - .BufferDepth(BufferDepth) - ) i_axi_dma_data_path ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .r_dp_valid_i (~r_emitter_empty), - .r_dp_ready_o (r_emitter_pop), - .w_dp_valid_i (~w_emitter_empty), - .w_dp_ready_o (w_emitter_pop), - .data_path_idle_o(data_mover_idle_o), - // AXI R signals - .r_data_i (r_data), - .r_valid_i (r_valid), - .r_last_i (r_last), - .r_resp_i (r_resp), - .r_ready_o (r_ready), - // R control - .r_tailer_i (current_r_req.tailer), - .r_offset_i (current_r_req.offset), - .r_shift_i (current_r_req.shift), - // AXI W signals - .w_data_o (w_data), - .w_strb_o (w_strb), - .w_valid_o (w_valid), - .w_last_o (w_last), - .w_ready_i (w_ready), - // W control - .w_offset_i (current_w_req.offset), - .w_tailer_i (current_w_req.tailer), - .w_num_beats_i (current_w_req.num_beats), - .w_is_single_i (current_w_req.is_single) - ); - - //-------------------------------------- - // Refill control - //-------------------------------------- - // the ax and x fifos of both channels are filled - // together, as request come bundled. - always_comb begin : proc_refill - // Read related channels - r_ready_o = ~ar_emitter_full & ~r_emitter_full; - r_emitter_push = r_valid_i & r_ready_o; - ar_emitter_push = r_valid_i & r_ready_o; - - // Write related channels - w_ready_o = ~aw_emitter_full & ~w_emitter_full & ~aw_last_full; - w_emitter_push = w_valid_i & w_ready_o; - aw_emitter_push = w_valid_i & w_ready_o; - end - - //-------------------------------------- - // Bus control - //-------------------------------------- - // here the AXI bus is unpacked/packed. - always_comb begin : proc_bus_packer - // defaults: not used signals -> 0 - axi_dma_req_o = '0; - - // assign R signals - r_data = axi_dma_res_i.r.data; - r_resp = axi_dma_res_i.r.resp; - r_last = axi_dma_res_i.r.last; - r_valid = axi_dma_res_i.r_valid; - axi_dma_req_o.r_ready = r_ready; - - // assign W signals - axi_dma_req_o.w.data = w_data; - axi_dma_req_o.w.strb = w_strb; - axi_dma_req_o.w.last = w_last; - axi_dma_req_o.w_valid = w_valid; - w_ready = axi_dma_res_i.w_ready; - - // AW signals - axi_dma_req_o.aw.id = current_aw_req.id; - axi_dma_req_o.aw.addr = current_aw_req.addr; - axi_dma_req_o.aw.len = current_aw_req.len; - axi_dma_req_o.aw.size = current_aw_req.size; - axi_dma_req_o.aw.burst = current_aw_req.burst; - axi_dma_req_o.aw.cache = current_aw_req.cache; - // flow control - axi_dma_req_o.aw_valid = ~aw_emitter_empty; - aw_emitter_pop = axi_dma_res_i.aw_ready & axi_dma_req_o.aw_valid; - - // B signals - // we are always ready to accept b signals, as we do not need them - // inside the DMA (we don't care if write failed) - axi_dma_req_o.b_ready = 1'b1; - - // AR signals - axi_dma_req_o.ar.id = current_ar_req.id; - axi_dma_req_o.ar.addr = current_ar_req.addr; - axi_dma_req_o.ar.len = current_ar_req.len; - axi_dma_req_o.ar.size = current_ar_req.size; - axi_dma_req_o.ar.burst = current_ar_req.burst; - axi_dma_req_o.ar.cache = current_ar_req.cache; - // flow control - axi_dma_req_o.ar_valid = ~ar_emitter_empty; - ar_emitter_pop = axi_dma_res_i.ar_ready & axi_dma_req_o.ar_valid; - end - - //-------------------------------------- - // ID control - //-------------------------------------- - logic is_last_aw; - fifo_v3 #( - .DEPTH(ReqFifoDepth + BufferDepth), - .dtype(logic) - ) i_last_transaction_queue ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (aw_last_full), - .empty_o (), - .usage_o (), - .data_i (write_req_i.aw.last), - .push_i (aw_emitter_push), - .data_o (is_last_aw), - .pop_i (axi_dma_res_i.b_valid) - ); - assign trans_complete_o = is_last_aw & axi_dma_res_i.b_valid; - -endmodule : axi_dma_data_mover diff --git a/hw/future/src/dma/axi_dma_data_path.sv b/hw/future/src/dma/axi_dma_data_path.sv deleted file mode 100644 index 5e5386b8c..000000000 --- a/hw/future/src/dma/axi_dma_data_path.sv +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -/// Data path for the AXI DMA. This modules handles the R/W channel of the -/// AXI protocol. -/// Module gets read stream, realigns data and emits a write stream. -/// AXI-like valid/ready handshaking is used to communicate with the rest -/// of the backend. -module axi_dma_data_path #( - /// Data width of the AXI bus - parameter int DataWidth = -1, - /// Number of elements the realignment buffer can hold. To achieve - /// full performance a depth of 3 is minimally required. - parameter int BufferDepth = -1, - // DO NOT OVERWRITE THIS PARAMETER - parameter int StrbWidth = DataWidth / 8, - parameter int OffsetWidth = $clog2(StrbWidth) -) ( - // status signals - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - // handshaking signals - /// Handshake: read side of data path is presented with a valid request - input logic r_dp_valid_i, - /// Handshake: read side of data path is ready to accept new requests - output logic r_dp_ready_o, - /// Handshake: write side of data path is presented with a valid request - input logic w_dp_valid_i, - /// Handshake: write side of data path is ready to accept new requests - output logic w_dp_ready_o, - - // status signal - /// High if the data path is idle - output logic data_path_idle_o, - - // r-channel - /// Read data from the AXI bus - input logic [DataWidth-1:0] r_data_i, - /// Valid signal of the AXI r channel - input logic r_valid_i, - /// Last signal of the AXI r channel - input logic r_last_i, - /// Response signal of the AXI r channel - input logic [ 1:0] r_resp_i, - /// Ready signal of the AXI r channel - output logic r_ready_o, - - /// number of bytes the end of the read transfer is short to reach a - /// Bus-aligned boundary - input logic [OffsetWidth-1:0] r_tailer_i, - /// number of bytes the read transfers starts after a - /// Bus-aligned boundary - input logic [OffsetWidth-1:0] r_offset_i, - /// The amount the read data has to be shifted to write-align it - input logic [OffsetWidth-1:0] r_shift_i, - - // w-channel - /// Write data of the AXI bus - output logic [DataWidth-1:0] w_data_o, - /// Write strobe of the AXI bus - output logic [StrbWidth-1:0] w_strb_o, - /// Valid signal of the AXI w channel - output logic w_valid_o, - /// Last signal of the AXI w channel - output logic w_last_o, - /// Ready signal of the AXI w channel - input logic w_ready_i, - - /// number of bytes the write transfers starts after a - /// Bus-aligned boundary - input logic [OffsetWidth-1:0] w_offset_i, - /// number of bytes the end of the write transfer is short to reach a - /// Bus-aligned boundary - input logic [OffsetWidth-1:0] w_tailer_i, - /// Number of beats requested by this transfer - input logic [ 7:0] w_num_beats_i, - /// True if the transfer only consists of a single beat - input logic w_is_single_i -); - - // buffer contains 8 data bits per FIFO - // buffer is at least 3 deep to prevent stalls - - // 64 bit DATA Width example: - // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD <- head - // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD - // DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD <- tail - // -byte7--|-byte6--|-byte5--|-byte4--|-byte3--|-byte2--|-byte1--|-byte0--| - - - //-------------------------------------- - // Mask pre-calculation - //-------------------------------------- - // in contiguous transfers that are unaligned, there will be some - // invalid bytes at the beginning and the end of the stream - // example: 25B in 64 bit system - // iiiivvvv|vvvvvvvv|vvvvvvvv|vvvvviii - // last msk|----full mask----|first msk - - // offsets needed for masks to fill/empty buffer - logic [StrbWidth-1:0] r_first_mask; - logic [StrbWidth-1:0] r_last_mask; - logic [StrbWidth-1:0] w_first_mask; - logic [StrbWidth-1:0] w_last_mask; - - // read align masks - assign r_first_mask = '1 << r_offset_i; - assign r_last_mask = '1 >> (StrbWidth - r_tailer_i); - - // write align masks - assign w_first_mask = '1 << w_offset_i; - assign w_last_mask = '1 >> (StrbWidth - w_tailer_i); - - - //-------------------------------------- - // Barrel shifter - //-------------------------------------- - // data arrives in chuncks of length DATA_WDITH, the buffer will be filled with - // the realigned data. StrbWidth bytes will be inserted starting from the - // provided address, overflows will naturally wrap - - // signals connected to the buffer - logic [StrbWidth-1:0][7:0] buffer_in; - - // read aligned in mask. needs to be rotated together with the data before - // it can be used to fill in valid data into the buffer - logic [StrbWidth-1:0] read_aligned_in_mask; - - // in mask is write aligned, so it is the result of the read aligned in mask - // that is rotated together with the data in the barrel shifter - logic [StrbWidth-1:0] in_mask; - - // a barrel shifter is a concatenation of the same array with itself and a normal - // shift. - assign buffer_in = {r_data_i, r_data_i} >> (r_shift_i * 8); - assign in_mask = {read_aligned_in_mask, read_aligned_in_mask} >> r_shift_i; - - //-------------------------------------- - // In mask generation - //-------------------------------------- - // in the case of unaligned reads -> not all data is valid - logic is_first_r, is_first_r_d; - - always_comb begin : proc_in_mask_generator - // default case: all ones - read_aligned_in_mask = '1; - // is first word: some bytes at the beginning may be invalid - read_aligned_in_mask = is_first_r ? read_aligned_in_mask & r_first_mask : read_aligned_in_mask; - // is last word in write burst: some bytes at the end may be invalid - if (r_tailer_i != '0) begin - read_aligned_in_mask = r_last_i ? read_aligned_in_mask & r_last_mask : read_aligned_in_mask; - end - end - - //-------------------------------------- - // Read control - //-------------------------------------- - logic [StrbWidth-1:0] buffer_full; - logic [StrbWidth-1:0] buffer_push; - logic full; - // this signal is used for pushing data to the control fifo - logic push; - - always_comb begin : proc_read_control - // sticky is first bit for read - if (r_valid_i & !r_last_i) begin - // new transfer has started - is_first_r_d = 1'b0; - end else if (r_last_i & r_valid_i) begin - // finish read burst - is_first_r_d = 1'b1; - end else begin - // no change - is_first_r_d = is_first_r; - end - - // the buffer can be pushed to if all the masked fifo buffers (in_mask) are not full. - full = |(buffer_full & in_mask); - // the read can accept data if the buffer is not full - r_ready_o = ~full; - - // once valid data is applied, it can be pushed in all the selected (in_mask) buffers - push = r_valid_i && ~full; - buffer_push = push ? in_mask : '0; - - // r_dp_ready_o is triggered by the last element arriving from the read - r_dp_ready_o = r_dp_valid_i && r_last_i && r_valid_i && ~full; - end - - //-------------------------------------- - // Out mask generation -> wstrb mask - //-------------------------------------- - // only pop the data actually needed for write from the buffer, - // determine valid data to pop by calculation the wstrb - logic [StrbWidth-1:0] out_mask; - logic is_first_w; - logic is_last_w; - - always_comb begin : proc_out_mask_generator - // default case: all ones - out_mask = '1; - // is first word: some bytes at the beginning may be invalid - out_mask = is_first_w ? (out_mask & w_first_mask) : out_mask; - // is last word in write burst: some bytes at the end may be invalid - if (w_tailer_i != '0) begin - out_mask = is_last_w ? out_mask & w_last_mask : out_mask; - end - end - - //-------------------------------------- - // Write control - //-------------------------------------- - // once buffer contains a full line -> all fifos are non-empty - // push it out. - // signals connected to the buffer - logic [StrbWidth-1:0][7:0] buffer_out; - logic [StrbWidth-1:0] buffer_empty; - logic [StrbWidth-1:0] buffer_pop; - - // write is decoupled from read, due to misalignments in the read/write - // addresses, page crossing can be encountered at any time. - // To handle this efficiently, a 2-to-1 or 1-to-2 mapping of r/w beats - // is required. The write unit needs to keep track of progress through - // a counter and cannot use `r_last` for that. - logic [7:0] w_num_beats_d, w_num_beats_q; - logic w_cnt_valid_d, w_cnt_valid_q; - - // data from buffer is popped - logic pop; - // write happens - logic write_happening; - // buffer is ready to write the requested data - logic ready_to_write; - // first transfer is possible - this signal is used to detect - // the first write transfer in a burst - logic first_possible; - // buffer is completely empty - logic buffer_clean; - - always_comb begin : proc_write_control - // counter - w_num_beats_d = w_num_beats_q; - w_cnt_valid_d = w_cnt_valid_q; - // buffer ctrl - pop = 1'b0; - buffer_pop = 'b0; - write_happening = 1'b0; - ready_to_write = 1'b0; - first_possible = 1'b0; - // bus signals - w_valid_o = 1'b0; - w_data_o = '0; - w_strb_o = '0; - w_last_o = 1'b0; - // mask control - is_first_w = 1'b0; - is_last_w = 1'b0; - // data flow - w_dp_ready_o = 1'b0; - - - // all elements needed (defined by the mask) are in the buffer and the buffer is non-empty - ready_to_write = ((~buffer_empty & out_mask) == out_mask) && (buffer_empty != '1); - - // data needed by the first mask is available in the buffer -> r_first happened for sure - // this signal can be high during a transfer as well, it needs to be masked - first_possible = ((~buffer_empty & w_first_mask) == w_first_mask) && (buffer_empty != '1); - - // the buffer is completely empty (debug only signal) - buffer_clean = &(buffer_empty); - - // write happening: both the bus (w_ready) and the buffer (ready_to_write) is high - write_happening = ready_to_write & w_ready_i; - - // signal the control fifo it could be popped - pop = write_happening; - - // the main buffer is conditionally to the write mask popped - buffer_pop = write_happening ? out_mask : '0; - - // signal the bus that we are ready - w_valid_o = ready_to_write; - - // control the write to the bus apply data to the bus only if data should be written - if (ready_to_write == 1'b1) begin - // assign data from buffers, mask out non valid entries - for (int i = 0; i < StrbWidth; i++) begin - w_data_o[i*8+:8] = out_mask[i] ? buffer_out[i] : 8'b0; - end - // assign the out mask to the strobe - w_strb_o = out_mask; - end - - // differentiate between the burst and non-burst case. If a transfer - // consists just of one beat the counters are disabled - if (w_is_single_i) begin - // in the single case the transfer is both first and last. - is_first_w = 1'b1; - is_last_w = 1'b1; - - // in the bursted case the counters are needed to keep track of the progress of sending - // beats. The w_last_o depends on the state of the counter - end else begin - // first transfer happens as soon as a) the buffer is ready for a first transfer and b) - // the counter is currently invalid - is_first_w = first_possible & ~w_cnt_valid_q; - - // last happens as soon as a) the counter is valid and b) the counter is now down to 1 - is_last_w = w_cnt_valid_q & (w_num_beats_q == 8'h01); - - // load the counter with data in a first cycle, only modifying state if bus is ready - if (is_first_w && write_happening) begin - w_num_beats_d = w_num_beats_i; - w_cnt_valid_d = 1'b1; - end - - // if we hit the last element, invalidate the counter, only modifying state - // if bus is ready - if (is_last_w && write_happening) begin - w_cnt_valid_d = 1'b0; - end - - // count down the beats if the counter is valid and valid data is written to the bus - if (w_cnt_valid_q && write_happening) w_num_beats_d = w_num_beats_q - 8'h01; - end - - // the w_last_o signal should only be applied to the bus if an actual transfer happens - w_last_o = is_last_w & ready_to_write; - - // we are ready for the next transfer internally, once the w_last_o signal is applied - w_dp_ready_o = is_last_w & write_happening; - end - - - //-------------------------------------- - // Buffer - implemented as fifo - //-------------------------------------- - logic control_empty; - - for (genvar i = 0; i < StrbWidth; i++) begin : gen_fifo_buffer - fifo_v3 #( - .FALL_THROUGH(1'b0), - .DATA_WIDTH (8), - .DEPTH (BufferDepth) - ) i_fifo_buffer ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .flush_i (1'b0), - .testmode_i(1'b0), - .full_o (buffer_full[i]), - .empty_o (buffer_empty[i]), - .usage_o (), - .data_i (buffer_in[i]), - .push_i (buffer_push[i]), - .data_o (buffer_out[i]), - .pop_i (buffer_pop[i]) - ); - end - - //-------------------------------------- - // Module Control - //------------------------------------- - assign data_path_idle_o = !(r_dp_valid_i | r_dp_ready_o | - w_dp_valid_i | w_dp_ready_o | !buffer_clean); - - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ff - if (!rst_ni) begin - is_first_r <= 1'b1; - w_cnt_valid_q <= 1'b0; - w_num_beats_q <= 8'h0; - end else begin - // running_q <= running_d; - if (r_valid_i & r_ready_o) is_first_r <= is_first_r_d; - w_cnt_valid_q <= w_cnt_valid_d; - w_num_beats_q <= w_num_beats_d; - end - end - -endmodule : axi_dma_data_path diff --git a/hw/future/src/idma_reg64_frontend.sv b/hw/future/src/idma_reg64_frontend.sv deleted file mode 100644 index 581c88b19..000000000 --- a/hw/future/src/idma_reg64_frontend.sv +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// Author: Michael Rogenmoser -// -// Description: DMA frontend module that includes 64bit config and status reg handling - -module idma_reg64_frontend #( - /// address width of the DMA AXI Master port - parameter int unsigned DmaAddrWidth = -1, - /// register_interface request type - parameter type dma_regs_req_t = logic, - /// register_interface response type - parameter type dma_regs_rsp_t = logic, - /// dma burst request type - parameter type burst_req_t = logic -) ( - input logic clk_i, - input logic rst_ni, - /// register interface control slave - input dma_regs_req_t dma_ctrl_req_i, - output dma_regs_rsp_t dma_ctrl_rsp_o, - /// DMA backend signals - output burst_req_t burst_req_o, - output logic valid_o, - input logic ready_i, - input logic backend_idle_i, - input logic trans_complete_i -); - - localparam int unsigned DmaRegisterWidth = 64; - - /* - * Signal and register definitions - */ - idma_reg64_frontend_reg_pkg::idma_reg64_frontend_reg2hw_t dma_reg2hw; - idma_reg64_frontend_reg_pkg::idma_reg64_frontend_hw2reg_t dma_hw2reg; - - // transaction id - logic [DmaAddrWidth-1:0] next_id, done_id; - logic issue; - - dma_regs_rsp_t dma_ctrl_rsp_tmp; - - /* - * DMA registers - */ - idma_reg64_frontend_reg_top #( - .reg_req_t( dma_regs_req_t ), - .reg_rsp_t( dma_regs_rsp_t ) - ) i_dma_conf_regs ( - .clk_i, - .rst_ni, - .reg_req_i ( dma_ctrl_req_i ), - .reg_rsp_o ( dma_ctrl_rsp_tmp ), - .reg2hw ( dma_reg2hw ), - .hw2reg ( dma_hw2reg ), - .devmode_i ( 1'b0 ) // if 1, explicit error return for unmapped register access - ); - - /* - * DMA Control Logic - */ - always_comb begin : proc_process_regs - - // reset state - valid_o = '0; - dma_hw2reg.next_id.d = '0; - dma_hw2reg.done.d = '0; - dma_hw2reg.status.d = ~backend_idle_i; - - dma_ctrl_rsp_o = dma_ctrl_rsp_tmp; - - // start transaction upon next_id read (and having a valid config) - if (dma_reg2hw.next_id.re) begin - if (dma_reg2hw.num_bytes.q != '0) begin - valid_o = 1'b1; - dma_hw2reg.next_id.d = next_id; - dma_ctrl_rsp_o.ready = ready_i; - end - end - - // use full width id from generator - dma_hw2reg.done.d = done_id; - end : proc_process_regs - - - // map hw register onto generic burst request - always_comb begin : hw_req_conv - burst_req_o = '0; - burst_req_o.src = dma_reg2hw.src_addr.q; - burst_req_o.dst = dma_reg2hw.dst_addr.q; - burst_req_o.num_bytes = dma_reg2hw.num_bytes.q; - burst_req_o.burst_src = axi_pkg::BURST_INCR; - burst_req_o.burst_dst = axi_pkg::BURST_INCR; - burst_req_o.cache_src = axi_pkg::CACHE_MODIFIABLE; - burst_req_o.cache_dst = axi_pkg::CACHE_MODIFIABLE; - burst_req_o.decouple_rw = dma_reg2hw.conf.decouple.q; - burst_req_o.deburst = dma_reg2hw.conf.deburst.q; - burst_req_o.serialize = dma_reg2hw.conf.serialize.q; - end : hw_req_conv - - // only increment issue counter if we have a valid transfer - assign issue = ready_i && valid_o; - - // transfer id generator - idma_tf_id_gen #( - .IdWidth ( DmaRegisterWidth ) - ) i_idma_tf_id_gen ( - .clk_i, - .rst_ni, - .issue_i ( issue ), - .retire_i ( trans_complete_i ), - .next_o ( next_id ), - .completed_o ( done_id ) - ); - -endmodule : idma_reg64_frontend diff --git a/hw/future/src/idma_reg64_frontend_reg_pkg.sv b/hw/future/src/idma_reg64_frontend_reg_pkg.sv deleted file mode 100644 index ef5346d54..000000000 --- a/hw/future/src/idma_reg64_frontend_reg_pkg.sv +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// Register Package auto-generated by `reggen` containing data structure - -package idma_reg64_frontend_reg_pkg; - - // Address widths within the block - parameter int BlockAw = 6; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic [63:0] q; - } idma_reg64_frontend_reg2hw_src_addr_reg_t; - - typedef struct packed { - logic [63:0] q; - } idma_reg64_frontend_reg2hw_dst_addr_reg_t; - - typedef struct packed { - logic [63:0] q; - } idma_reg64_frontend_reg2hw_num_bytes_reg_t; - - typedef struct packed { - logic q; - } idma_reg64_frontend_logic_struct_t; - - typedef struct packed { - idma_reg64_frontend_logic_struct_t decouple; - idma_reg64_frontend_logic_struct_t deburst; - idma_reg64_frontend_logic_struct_t serialize; - } idma_reg64_frontend_reg2hw_conf_reg_t; - - typedef struct packed { - logic [63:0] q; - logic re; - } idma_reg64_frontend_reg2hw_next_id_reg_t; - - typedef struct packed { - logic [63:0] q; - logic re; - } idma_reg64_frontend_reg2hw_done_reg_t; - - typedef struct packed { - logic d; - } idma_reg64_frontend_hw2reg_status_reg_t; - - typedef struct packed { - logic [63:0] d; - } idma_reg64_frontend_hw2reg_next_id_reg_t; - - typedef struct packed { - logic [63:0] d; - } idma_reg64_frontend_hw2reg_done_reg_t; - - // Register -> HW type - typedef struct packed { - idma_reg64_frontend_reg2hw_src_addr_reg_t src_addr; // [324:261] - idma_reg64_frontend_reg2hw_dst_addr_reg_t dst_addr; // [260:197] - idma_reg64_frontend_reg2hw_num_bytes_reg_t num_bytes; // [196:133] - idma_reg64_frontend_reg2hw_conf_reg_t conf; // [132:130] - idma_reg64_frontend_reg2hw_next_id_reg_t next_id; // [129:65] - idma_reg64_frontend_reg2hw_done_reg_t done; // [64:0] - } idma_reg64_frontend_reg2hw_t; - - // HW -> register type - typedef struct packed { - idma_reg64_frontend_hw2reg_status_reg_t status; // [128:128] - idma_reg64_frontend_hw2reg_next_id_reg_t next_id; // [127:64] - idma_reg64_frontend_hw2reg_done_reg_t done; // [63:0] - } idma_reg64_frontend_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_SRC_ADDR_OFFSET = 6'h 0; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_DST_ADDR_OFFSET = 6'h 8; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_NUM_BYTES_OFFSET = 6'h 10; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_CONF_OFFSET = 6'h 18; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_STATUS_OFFSET = 6'h 20; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_NEXT_ID_OFFSET = 6'h 28; - parameter logic [BlockAw-1:0] IDMA_REG64_FRONTEND_DONE_OFFSET = 6'h 30; - - // Reset values for hwext registers and their fields - parameter logic [0:0] IDMA_REG64_FRONTEND_STATUS_RESVAL = 1'h 0; - parameter logic [63:0] IDMA_REG64_FRONTEND_NEXT_ID_RESVAL = 64'h 0; - parameter logic [63:0] IDMA_REG64_FRONTEND_DONE_RESVAL = 64'h 0; - - // Register index - typedef enum int { - IDMA_REG64_FRONTEND_SRC_ADDR, - IDMA_REG64_FRONTEND_DST_ADDR, - IDMA_REG64_FRONTEND_NUM_BYTES, - IDMA_REG64_FRONTEND_CONF, - IDMA_REG64_FRONTEND_STATUS, - IDMA_REG64_FRONTEND_NEXT_ID, - IDMA_REG64_FRONTEND_DONE - } idma_reg64_frontend_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] IDMA_REG64_FRONTEND_PERMIT [7] = '{ - 4'b 1111, // index[0] IDMA_REG64_FRONTEND_SRC_ADDR - 4'b 1111, // index[1] IDMA_REG64_FRONTEND_DST_ADDR - 4'b 1111, // index[2] IDMA_REG64_FRONTEND_NUM_BYTES - 4'b 0001, // index[3] IDMA_REG64_FRONTEND_CONF - 4'b 0001, // index[4] IDMA_REG64_FRONTEND_STATUS - 4'b 1111, // index[5] IDMA_REG64_FRONTEND_NEXT_ID - 4'b 1111 // index[6] IDMA_REG64_FRONTEND_DONE - }; - -endpackage - diff --git a/hw/future/src/idma_reg64_frontend_reg_top.sv b/hw/future/src/idma_reg64_frontend_reg_top.sv deleted file mode 100644 index e24612ce5..000000000 --- a/hw/future/src/idma_reg64_frontend_reg_top.sv +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module idma_reg64_frontend_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 6 -) ( - input clk_i, - input rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output idma_reg64_frontend_reg_pkg::idma_reg64_frontend_reg2hw_t reg2hw, // Write - input idma_reg64_frontend_reg_pkg::idma_reg64_frontend_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import idma_reg64_frontend_reg_pkg::* ; - - localparam int DW = 64; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [AW-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic [63:0] src_addr_qs; - logic [63:0] src_addr_wd; - logic src_addr_we; - logic [63:0] dst_addr_qs; - logic [63:0] dst_addr_wd; - logic dst_addr_we; - logic [63:0] num_bytes_qs; - logic [63:0] num_bytes_wd; - logic num_bytes_we; - logic conf_decouple_qs; - logic conf_decouple_wd; - logic conf_decouple_we; - logic conf_deburst_qs; - logic conf_deburst_wd; - logic conf_deburst_we; - logic conf_serialize_qs; - logic conf_serialize_wd; - logic conf_serialize_we; - logic status_qs; - logic status_re; - logic [63:0] next_id_qs; - logic next_id_re; - logic [63:0] done_qs; - logic done_re; - - // Register instances - // R[src_addr]: V(False) - - prim_subreg #( - .DW (64), - .SWACCESS("RW"), - .RESVAL (64'h0) - ) u_src_addr ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_we), - .wd (src_addr_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr.q ), - - // to register interface (read) - .qs (src_addr_qs) - ); - - - // R[dst_addr]: V(False) - - prim_subreg #( - .DW (64), - .SWACCESS("RW"), - .RESVAL (64'h0) - ) u_dst_addr ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_we), - .wd (dst_addr_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr.q ), - - // to register interface (read) - .qs (dst_addr_qs) - ); - - - // R[num_bytes]: V(False) - - prim_subreg #( - .DW (64), - .SWACCESS("RW"), - .RESVAL (64'h0) - ) u_num_bytes ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (num_bytes_we), - .wd (num_bytes_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.num_bytes.q ), - - // to register interface (read) - .qs (num_bytes_qs) - ); - - - // R[conf]: V(False) - - // F[decouple]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_we), - .wd (conf_decouple_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple.q ), - - // to register interface (read) - .qs (conf_decouple_qs) - ); - - - // F[deburst]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_deburst ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_deburst_we), - .wd (conf_deburst_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.deburst.q ), - - // to register interface (read) - .qs (conf_deburst_qs) - ); - - - // F[serialize]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_serialize ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_serialize_we), - .wd (conf_serialize_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.serialize.q ), - - // to register interface (read) - .qs (conf_serialize_qs) - ); - - - // R[status]: V(True) - - prim_subreg_ext #( - .DW (1) - ) u_status ( - .re (status_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status.d), - .qre (), - .qe (), - .q (), - .qs (status_qs) - ); - - - // R[next_id]: V(True) - - prim_subreg_ext #( - .DW (64) - ) u_next_id ( - .re (next_id_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id.d), - .qre (reg2hw.next_id.re), - .qe (), - .q (reg2hw.next_id.q ), - .qs (next_id_qs) - ); - - - // R[done]: V(True) - - prim_subreg_ext #( - .DW (64) - ) u_done ( - .re (done_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done.d), - .qre (reg2hw.done.re), - .qe (), - .q (reg2hw.done.q ), - .qs (done_qs) - ); - - - - - logic [6:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == IDMA_REG64_FRONTEND_SRC_ADDR_OFFSET); - addr_hit[1] = (reg_addr == IDMA_REG64_FRONTEND_DST_ADDR_OFFSET); - addr_hit[2] = (reg_addr == IDMA_REG64_FRONTEND_NUM_BYTES_OFFSET); - addr_hit[3] = (reg_addr == IDMA_REG64_FRONTEND_CONF_OFFSET); - addr_hit[4] = (reg_addr == IDMA_REG64_FRONTEND_STATUS_OFFSET); - addr_hit[5] = (reg_addr == IDMA_REG64_FRONTEND_NEXT_ID_OFFSET); - addr_hit[6] = (reg_addr == IDMA_REG64_FRONTEND_DONE_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[0] & (|(IDMA_REG64_FRONTEND_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(IDMA_REG64_FRONTEND_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(IDMA_REG64_FRONTEND_PERMIT[2] & ~reg_be))) | - (addr_hit[3] & (|(IDMA_REG64_FRONTEND_PERMIT[3] & ~reg_be))) | - (addr_hit[4] & (|(IDMA_REG64_FRONTEND_PERMIT[4] & ~reg_be))) | - (addr_hit[5] & (|(IDMA_REG64_FRONTEND_PERMIT[5] & ~reg_be))) | - (addr_hit[6] & (|(IDMA_REG64_FRONTEND_PERMIT[6] & ~reg_be))))); - end - - assign src_addr_we = addr_hit[0] & reg_we & !reg_error; - assign src_addr_wd = reg_wdata[63:0]; - - assign dst_addr_we = addr_hit[1] & reg_we & !reg_error; - assign dst_addr_wd = reg_wdata[63:0]; - - assign num_bytes_we = addr_hit[2] & reg_we & !reg_error; - assign num_bytes_wd = reg_wdata[63:0]; - - assign conf_decouple_we = addr_hit[3] & reg_we & !reg_error; - assign conf_decouple_wd = reg_wdata[0]; - - assign conf_deburst_we = addr_hit[3] & reg_we & !reg_error; - assign conf_deburst_wd = reg_wdata[1]; - - assign conf_serialize_we = addr_hit[3] & reg_we & !reg_error; - assign conf_serialize_wd = reg_wdata[2]; - - assign status_re = addr_hit[4] & reg_re & !reg_error; - - assign next_id_re = addr_hit[5] & reg_re & !reg_error; - - assign done_re = addr_hit[6] & reg_re & !reg_error; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[63:0] = src_addr_qs; - end - - addr_hit[1]: begin - reg_rdata_next[63:0] = dst_addr_qs; - end - - addr_hit[2]: begin - reg_rdata_next[63:0] = num_bytes_qs; - end - - addr_hit[3]: begin - reg_rdata_next[0] = conf_decouple_qs; - reg_rdata_next[1] = conf_deburst_qs; - reg_rdata_next[2] = conf_serialize_qs; - end - - addr_hit[4]: begin - reg_rdata_next[0] = status_qs; - end - - addr_hit[5]: begin - reg_rdata_next[63:0] = next_id_qs; - end - - addr_hit[6]: begin - reg_rdata_next[63:0] = done_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule diff --git a/hw/future/src/idma_tf_id_gen.sv b/hw/future/src/idma_tf_id_gen.sv deleted file mode 100644 index 33917e58a..000000000 --- a/hw/future/src/idma_tf_id_gen.sv +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// Author: Thomas Benz -// Author: Andreas Kuster -// -// Description: DMA transaction id generator. Increases the transaction id on every request. - -module idma_tf_id_gen #( - parameter int unsigned IdWidth = -1 -) ( - input logic clk_i, - input logic rst_ni, - // new request is pushed - input logic issue_i, - // request is popped - input logic retire_i, - // next id is - output logic [IdWidth-1:0] next_o, - // last id completed is - output logic [IdWidth-1:0] completed_o -); - - //-------------------------------------- - // counters - //-------------------------------------- - logic [IdWidth-1:0] next_d, next_q, completed_d, completed_q; - - // count up on events - always_comb begin : proc_next_id - // default - next_d = next_q; - // overflow - if (next_q == '1) begin - if (issue_i) - next_d = 'h2; - else - next_d = 'h1; - // request - end else begin - if (issue_i) - next_d = 'h1 + next_q; - end - end - - always_comb begin : proc_next_completed - // default - completed_d = completed_q; - // overflow - if (completed_q == '1) begin - if (retire_i) - completed_d = 'h2; - else - completed_d = 'h1; - // request - end else begin - if (retire_i) - completed_d = 'h1 + completed_q; - end - end - - // assign outputs - assign next_o = next_q; - assign completed_o = completed_q; - - //-------------------------------------- - // state - //-------------------------------------- - always_ff @(posedge clk_i or negedge rst_ni) begin : proc_id_gen - if(~rst_ni) begin - next_q <= 2; - completed_q <= 1; - end else begin - next_q <= next_d; - completed_q <= completed_d; - end - end - -endmodule : idma_tf_id_gen - diff --git a/hw/future/src/mem_to_axi_lite.sv b/hw/future/src/mem_to_axi_lite.sv deleted file mode 100644 index 4a3fe090b..000000000 --- a/hw/future/src/mem_to_axi_lite.sv +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Author: Wolfgang Roenninger - -/// Protocol adapter which translates memory requests to the AXI4-Lite protocol. -/// -/// This module acts like an SRAM and makes AXI4-Lite requests downstream. -/// -/// Supports multiple outstanding requests and will have responses for reads **and** writes. -/// Response latency is not fixed and for sure **not 1** and depends on the AXI4-Lite memory system. -/// The `mem_rsp_valid_o` can have multiple cycles of latency from the corresponding `mem_gnt_o`. -module mem_to_axi_lite #( - /// Memory request address width. - parameter int unsigned MemAddrWidth = 32'd0, - /// AXI4-Lite address width. - parameter int unsigned AxiAddrWidth = 32'd0, - /// Data width in bit of the memory request data **and** the Axi4-Lite data channels. - parameter int unsigned DataWidth = 32'd0, - /// How many requests can be in flight at the same time. (Depth of the response mux FIFO). - parameter int unsigned MaxRequests = 32'd0, - /// Protection signal the module should emit on the AXI4-Lite transactions. - parameter axi_pkg::prot_t AxiProt = 3'b000, - /// AXI4-Lite request struct definition. - parameter type axi_req_t = logic, - /// AXI4-Lite response struct definition. - parameter type axi_rsp_t = logic, - /// Dependent parameter do **not** overwrite! - /// - /// Memory address type, derived from `MemAddrWidth`. - parameter type mem_addr_t = logic[MemAddrWidth-1:0], - /// Dependent parameter do **not** overwrite! - /// - /// AXI4-Lite address type, derived from `AxiAddrWidth`. - parameter type axi_addr_t = logic[AxiAddrWidth-1:0], - /// Dependent parameter do **not** overwrite! - /// - /// Data type for read and write data, derived from `DataWidth`. - /// This is the same for the memory request side **and** the AXI4-Lite `W` and `R` channels. - parameter type data_t = logic[DataWidth-1:0], - /// Dependent parameter do **not** overwrite! - /// - /// Byte enable / AXI4-Lite strobe type, derived from `DataWidth`. - parameter type strb_t = logic[DataWidth/8-1:0] -) ( - /// Clock input, positive edge triggered. - input logic clk_i, - /// Asynchronous reset, active low. - input logic rst_ni, - /// Memory slave port, request is active. - input logic mem_req_i, - /// Memory slave port, request address. - /// - /// Byte address, will be extended or truncated to match `AxiAddrWidth`. - input mem_addr_t mem_addr_i, - /// Memory slave port, request is a write. - /// - /// `0`: Read request. - /// `1`: Write request. - input logic mem_we_i, - /// Memory salve port, write data for request. - input data_t mem_wdata_i, - /// Memory slave port, write byte enable for request. - /// - /// Active high. - input strb_t mem_be_i, - /// Memory request is granted. - output logic mem_gnt_o, - /// Memory slave port, response is valid. For each request, regardless if read or write, - /// this will be active once for one cycle. - output logic mem_rsp_valid_o, - /// Memory slave port, response read data. This is forwarded directly from the AXI4-Lite - /// `R` channel. Only valid for responses generated by a read request. - output data_t mem_rsp_rdata_o, - /// Memory request encountered an error. This is forwarded from the AXI4-Lite error response. - output logic mem_rsp_error_o, - /// AXI4-Lite master port, request output. - output axi_req_t axi_req_o, - /// AXI4-Lite master port, response input. - input axi_rsp_t axi_rsp_i -); - `include "common_cells/registers.svh" - - // Response FIFO control signals. - logic fifo_full, fifo_empty; - // Bookkeeping for sent write beats. - logic aw_sent_q, aw_sent_d; - logic w_sent_q, w_sent_d; - - // Control for translating request to the AXI4-Lite `AW`, `W` and `AR` channels. - always_comb begin - // Default assignments. - axi_req_o.aw = '0; - axi_req_o.aw.addr = axi_addr_t'(mem_addr_i); - axi_req_o.aw.prot = AxiProt; - axi_req_o.aw_valid = 1'b0; - axi_req_o.w = '0; - axi_req_o.w.data = mem_wdata_i; - axi_req_o.w.strb = mem_be_i; - axi_req_o.w_valid = 1'b0; - axi_req_o.ar = '0; - axi_req_o.ar.addr = axi_addr_t'(mem_addr_i); - axi_req_o.ar.prot = AxiProt; - axi_req_o.ar_valid = 1'b0; - // This is also the push signal for the response FIFO. - mem_gnt_o = 1'b0; - // Bookkeeping about sent write channels. - aw_sent_d = aw_sent_q; - w_sent_d = w_sent_q; - - // Control for Request to AXI4-Lite translation. - if (mem_req_i && !fifo_full) begin - if (!mem_we_i) begin - // It is a read request. - axi_req_o.ar_valid = 1'b1; - mem_gnt_o = axi_rsp_i.ar_ready; - end else begin - // Is is a write request, decouple `AW` and `W` channels. - unique case ({aw_sent_q, w_sent_q}) - 2'b00 : begin - // None of the AXI4-Lite writes have been sent jet. - axi_req_o.aw_valid = 1'b1; - axi_req_o.w_valid = 1'b1; - unique case ({axi_rsp_i.aw_ready, axi_rsp_i.w_ready}) - 2'b01 : begin // W is sent, still needs AW. - w_sent_d = 1'b1; - end - 2'b10 : begin // AW is sent, still needs W. - aw_sent_d = 1'b1; - end - 2'b11 : begin // Both are transmitted, grant the write request. - mem_gnt_o = 1'b1; - end - default : /* do nothing */; - endcase - end - 2'b10 : begin - // W has to be sent. - axi_req_o.w_valid = 1'b1; - if (axi_rsp_i.w_ready) begin - aw_sent_d = 1'b0; - mem_gnt_o = 1'b1; - end - end - 2'b01 : begin - // AW has to be sent. - axi_req_o.aw_valid = 1'b1; - if (axi_rsp_i.aw_ready) begin - w_sent_d = 1'b0; - mem_gnt_o = 1'b1; - end - end - default : begin - // Failsafe go to IDLE. - aw_sent_d = 1'b0; - w_sent_d = 1'b0; - end - endcase - end - end - end - - `FFARN(aw_sent_q, aw_sent_d, 1'b0, clk_i, rst_ni) - `FFARN(w_sent_q, w_sent_d, 1'b0, clk_i, rst_ni) - - // Select which response should be forwarded. `1` write response, `0` read response. - logic rsp_sel; - - fifo_v3 #( - .FALL_THROUGH ( 1'b0 ), // No fallthrough for one cycle delay before ready on AXI. - .DEPTH ( MaxRequests ), - .dtype ( logic ) - ) i_fifo_rsp_mux ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( fifo_full ), - .empty_o ( fifo_empty ), - .usage_o ( /*not used*/ ), - .data_i ( mem_we_i ), - .push_i ( mem_gnt_o ), - .data_o ( rsp_sel ), - .pop_i ( mem_rsp_valid_o ) - ); - - // Response selection control. - // If something is in the FIFO, the corresponding channel is ready. - assign axi_req_o.b_ready = !fifo_empty && rsp_sel; - assign axi_req_o.r_ready = !fifo_empty && !rsp_sel; - // Read data is directly forwarded. - assign mem_rsp_rdata_o = axi_rsp_i.r.data; - // Error is taken from the respective channel. - assign mem_rsp_error_o = rsp_sel ? - (axi_rsp_i.b.resp inside {axi_pkg::RESP_SLVERR, axi_pkg::RESP_DECERR}) : - (axi_rsp_i.r.resp inside {axi_pkg::RESP_SLVERR, axi_pkg::RESP_DECERR}); - // Mem response is valid if the handshaking on the respective channel occurs. - // Can not happen at the same time as ready is set from the FIFO. - // This serves as the pop signal for the FIFO. - assign mem_rsp_valid_o = (axi_rsp_i.b_valid && axi_req_o.b_ready) || - (axi_rsp_i.r_valid && axi_req_o.r_ready); - - // pragma translate_off - `ifndef VERILATOR - initial begin : proc_assert - assert (MemAddrWidth > 32'd0) else $fatal(1, "MemAddrWidth has to be greater than 0!"); - assert (AxiAddrWidth > 32'd0) else $fatal(1, "AxiAddrWidth has to be greater than 0!"); - assert (DataWidth inside {32'd32, 32'd64}) else - $fatal(1, "DataWidth has to be either 32 or 64 bit!"); - assert (MaxRequests > 32'd0) else $fatal(1, "MaxRequests has to be greater than 0!"); - assert (AxiAddrWidth == $bits(axi_req_o.aw.addr)) else - $fatal(1, "AxiAddrWidth has to match axi_req_o.aw.addr!"); - assert (AxiAddrWidth == $bits(axi_req_o.ar.addr)) else - $fatal(1, "AxiAddrWidth has to match axi_req_o.ar.addr!"); - assert (DataWidth == $bits(axi_req_o.w.data)) else - $fatal(1, "DataWidth has to match axi_req_o.w.data!"); - assert (DataWidth/8 == $bits(axi_req_o.w.strb)) else - $fatal(1, "DataWidth / 8 has to match axi_req_o.w.strb!"); - assert (DataWidth == $bits(axi_rsp_i.r.data)) else - $fatal(1, "DataWidth has to match axi_rsp_i.r.data!"); - end - default disable iff (~rst_ni); - assert property (@(posedge clk_i) (mem_req_i && !mem_gnt_o) |=> mem_req_i) else - $fatal(1, "It is not allowed to deassert the request if it was not granted!"); - assert property (@(posedge clk_i) (mem_req_i && !mem_gnt_o) |=> $stable(mem_addr_i)) else - $fatal(1, "mem_addr_i has to be stable if request is not granted!"); - assert property (@(posedge clk_i) (mem_req_i && !mem_gnt_o) |=> $stable(mem_we_i)) else - $fatal(1, "mem_we_i has to be stable if request is not granted!"); - assert property (@(posedge clk_i) (mem_req_i && !mem_gnt_o) |=> $stable(mem_wdata_i)) else - $fatal(1, "mem_wdata_i has to be stable if request is not granted!"); - assert property (@(posedge clk_i) (mem_req_i && !mem_gnt_o) |=> $stable(mem_be_i)) else - $fatal(1, "mem_be_i has to be stable if request is not granted!"); - `endif - // pragma translate_on -endmodule diff --git a/hw/future/test/fixture_axi_dma_backend.sv b/hw/future/test/fixture_axi_dma_backend.sv deleted file mode 100644 index 0b55f7b6b..000000000 --- a/hw/future/test/fixture_axi_dma_backend.sv +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -// fixture for the AXi DMA backend -// the fixture instantiates the DMA backend, a golden model of the backend , and tasks controlling -// both. - -module fixture_axi_dma_backend (); - - // `include "../axi/include/axi/assign.svh" - // `define MEM_DEBUG 1 - `include "axi/assign.svh" - `include "axi/typedef.svh" - - //-------------------------------------- - // Parameters - //-------------------------------------- - localparam time TA = 0.2ns; // must be nonzero to avoid Snitch load fifo double pop glitch - localparam time TT = 0.8ns; - localparam time HalfPeriod = 50ns; - localparam time Reset = 75ns; - - localparam int unsigned DataWidth = 512; - localparam int unsigned AddrWidth = 64; - localparam int unsigned StrbWidth = DataWidth / 8; - localparam int unsigned IdWidth = 6; - localparam int unsigned UserWidth = 1; - - typedef union packed { - logic [StrbWidth-1:0][7:0] bytes; - logic [DataWidth-1:0] data; - } block_t; - - /// Address Type - typedef logic [AddrWidth-1:0] addr_t; - /// Data Type - typedef logic [DataWidth-1:0] data_t; - /// Strobe Type - typedef logic [StrbWidth-1:0] strb_t; - /// AXI ID Type - typedef logic [IdWidth-1:0] axi_id_t; - /// AXI USER Type - typedef logic [UserWidth-1:0] user_t; - /// 1D burst request - typedef struct packed { - axi_id_t id; - addr_t src, dst, num_bytes; - axi_pkg::cache_t cache_src, cache_dst; - axi_pkg::burst_t burst_src, burst_dst; - logic decouple_rw; - logic deburst; - logic serialize; - } burst_req_t; - - `AXI_TYPEDEF_AW_CHAN_T(aw_chan_dma_t, addr_t, axi_id_t, user_t) - `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_B_CHAN_T(b_chan_dma_t, axi_id_t, user_t) - - `AXI_TYPEDEF_AR_CHAN_T(ar_chan_dma_t, addr_t, axi_id_t, user_t) - `AXI_TYPEDEF_R_CHAN_T(r_chan_dma_t, data_t, axi_id_t, user_t) - - `AXI_TYPEDEF_REQ_T(dma_req_t, aw_chan_dma_t, w_chan_t, ar_chan_dma_t) - `AXI_TYPEDEF_RESP_T(dma_resp_t, b_chan_dma_t, r_chan_dma_t) - - //-------------------------------------- - // Clock and Reset - //-------------------------------------- - logic clk; - initial begin - forever begin - clk = 0; - #HalfPeriod; - clk = 1; - #HalfPeriod; - end - end - - logic rst_n; - initial begin - rst_n = 0; - #Reset; - rst_n = 1; - end - - task wait_for_reset; - @(posedge rst_n); - @(posedge clk); - endtask - - //-------------------------------------- - // DUT Axi busses - //-------------------------------------- - dma_req_t axi_dma_req; - dma_resp_t axi_dma_res; - - AXI_BUS_DV #( - .AXI_ADDR_WIDTH(AddrWidth), - .AXI_DATA_WIDTH(DataWidth), - .AXI_ID_WIDTH (IdWidth), - .AXI_USER_WIDTH(1) - ) dma ( - clk - ); - - AXI_BUS #( - .AXI_ADDR_WIDTH(AddrWidth), - .AXI_DATA_WIDTH(DataWidth), - .AXI_ID_WIDTH (IdWidth), - .AXI_USER_WIDTH(1) - ) mem (); - - `AXI_ASSIGN(dma, mem) - `AXI_ASSIGN_FROM_REQ(mem, axi_dma_req) - `AXI_ASSIGN_TO_RESP(axi_dma_res, mem) - - //-------------------------------------- - // DUT AXI Memory System - //-------------------------------------- - // lfsr - logic [784:0] lfsr_dut_q, lfsr_dut_d; - - // transaction id - logic [7:0] transaction_id = 0; - - // Memory - block_t dma_memory[bit [64-$clog2($bits(block_t))-1:0]]; - - // Handle the data output from dma. Model of the memory acting as AXI slave. - typedef axi_test::axi_driver#( - .AW(AddrWidth), - .DW(DataWidth), - .IW(IdWidth), - .UW(1), - .TA(0.1 * 2 * HalfPeriod), - .TT(0.9 * 2 * HalfPeriod) - ) driver_dma_t; - driver_dma_t driver_dma = new(dma); - initial begin - automatic driver_dma_t::ax_beat_t aw_dma_queue[$], ar_dma_queue[$]; - automatic driver_dma_t::b_beat_t b_dma_queue[$]; - automatic string sb = ""; - - event ar_dma_received, aw_dma_received, b_dma_ready; - event lfsr_dut_read; - event lfsr_dut_read_completed; - - driver_dma.reset_slave(); - @(posedge rst_n); - $display("AXI reset done"); - - fork - // AW - forever begin - automatic driver_dma_t::ax_beat_t dma_tx; - driver_dma.recv_aw(dma_tx); -`ifdef MEM_DEBUG - $display("%d: AW - id: %4d - addr: %d - len: %4d - size: %4d - burst: %b", $time(), - dma_tx.ax_id, dma_tx.ax_addr, dma_tx.ax_len, dma_tx.ax_size, dma_tx.ax_burst); -`endif - aw_dma_queue.push_back(dma_tx); - ->aw_dma_received; - end - // AR - forever begin - automatic driver_dma_t::ax_beat_t dma_tx; - driver_dma.recv_ar(dma_tx); -`ifdef MEM_DEBUG - $display("%d: AR - id: %4d - addr: %d - len: %4d - size: %4d - burst: %b", $time(), - dma_tx.ax_id, dma_tx.ax_addr, dma_tx.ax_len, dma_tx.ax_size, dma_tx.ax_burst); -`endif - ar_dma_queue.push_back(dma_tx); - ->ar_dma_received; - end - // R - forever begin - automatic driver_dma_t::r_beat_t dma_tx = new(); - automatic driver_dma_t::ax_beat_t dma_ax; - automatic bit [AddrWidth-1:0] word; - while (ar_dma_queue.size() == 0) @ar_dma_received; - dma_ax = ar_dma_queue[0]; - word = dma_ax.ax_addr >> 6; - dma_tx.r_id = dma_ax.ax_id; - if (!dma_memory.exists(word)) begin - dma_memory[word].data = lfsr_dut_q[784:273]; - //shift 513x - repeat (513) begin - // next state - for (int i = 1; i < 785; i = i + 1) lfsr_dut_d[i-1] = lfsr_dut_q[i]; - lfsr_dut_d[784] = lfsr_dut_q[0]; - lfsr_dut_d[692] = lfsr_dut_q[0] ^ lfsr_dut_q[693]; - lfsr_dut_q = lfsr_dut_d; - end - end - dma_tx.r_data = dma_memory[word].data; - dma_tx.r_resp = axi_pkg::RESP_OKAY; - dma_tx.r_last = (dma_ax.ax_len == 0); -`ifdef MEM_DEBUG - $display("%d: R - id: %4d - data: %x - resp: %x - last: %b (0x%x)", $time(), - dma_tx.r_id, dma_tx.r_data, dma_tx.r_resp, dma_tx.r_last, word << 6); -`endif - dma_ax.ax_addr >>= dma_ax.ax_size; - dma_ax.ax_addr += (dma_ax.ax_burst !== 0); - dma_ax.ax_addr <<= dma_ax.ax_size; - dma_ax.ax_len -= 1; - if (dma_tx.r_last) begin - ar_dma_queue.pop_front(); - end - driver_dma.send_r(dma_tx); - end - // W - forever begin - automatic driver_dma_t::w_beat_t dma_tx; - automatic driver_dma_t::ax_beat_t dma_ax; - automatic bit [AddrWidth-1:0] word; - driver_dma.recv_w(dma_tx); - while (aw_dma_queue.size() == 0) @ar_dma_received; - dma_ax = aw_dma_queue[0]; - word = dma_ax.ax_addr >> 6; - //$display("Ready to write"); - //$display("%x", word); - for (int i = 0; i < StrbWidth; i++) begin - if (dma_tx.w_strb[i]) begin - dma_memory[word].bytes[i] = dma_tx.w_data[i*8+:8]; - end - end -`ifdef MEM_DEBUG - $display("%d: W - data: %x - strb: %x - last: %b (0x%x)", $time(), - dma_tx.w_data, dma_tx.w_strb, dma_tx.w_last, word << 6); -`endif - dma_ax.ax_addr >>= dma_ax.ax_size; - dma_ax.ax_addr += (dma_ax.ax_burst !== 0); - dma_ax.ax_addr <<= dma_ax.ax_size; - dma_ax.ax_len -= 1; - if (dma_tx.w_last) begin - automatic driver_dma_t::b_beat_t dma_tx = new(); - dma_tx.b_id = dma_ax.ax_id; - dma_tx.b_user = dma_ax.ax_user; - aw_dma_queue.pop_front(); - b_dma_queue.push_back(dma_tx); - ->b_dma_ready; - end - end - // B - forever begin - automatic driver_dma_t::b_beat_t dma_tx; - while (b_dma_queue.size() == 0) @b_dma_ready; - driver_dma.send_b(b_dma_queue[0]); - b_dma_queue.pop_front(); - end - join_any - end - - //-------------------------------------- - // DMA instantiation - //-------------------------------------- - burst_req_t burst_req; - logic burst_req_valid; - logic burst_req_ready; - logic backend_idle; - - axi_dma_backend #( - .DataWidth (DataWidth), - .AddrWidth (AddrWidth), - .IdWidth (IdWidth), - .DmaIdWidth (32), - .AxReqFifoDepth(3), - .TransFifoDepth(2), - .BufferDepth (3), - .axi_req_t (dma_req_t), - .axi_res_t (dma_resp_t), - .burst_req_t (burst_req_t), - .DmaTracing (1) - ) i_dut_axi_backend ( - .clk_i (clk), - .rst_ni (rst_n), - .axi_dma_req_o (axi_dma_req), - .axi_dma_res_i (axi_dma_res), - .burst_req_i (burst_req), - .valid_i (burst_req_valid), - .ready_o (burst_req_ready), - .backend_idle_o (backend_idle), - .trans_complete_o(), - .dma_id_i ('0) - ); - - //-------------------------------------- - // DMA DUT tasks - //-------------------------------------- - task oned_dut_launch( - input logic [IdWidth-1:0] transf_id_i, input logic [AddrWidth-1:0] src_addr_i, dst_addr_i, - num_bytes_i, input logic [1:0] src_burst_i, dst_burst_i, input logic [3:0] src_cache_i, - dst_cache_i, input logic decouple_rw_i, input logic serialize_i, input logic deburst_i); - burst_req_valid <= 1'b0; - burst_req <= '0; - @(posedge clk); - while (burst_req_ready !== 1) @(posedge clk); - // write data - burst_req.id <= transf_id_i; - burst_req.src <= src_addr_i; - burst_req.dst <= dst_addr_i; - burst_req.num_bytes <= num_bytes_i; - burst_req.cache_src <= src_cache_i; - burst_req.cache_dst <= dst_cache_i; - burst_req.burst_src <= src_burst_i; - burst_req.burst_dst <= dst_burst_i; - burst_req.decouple_rw <= decouple_rw_i; - burst_req.deburst <= deburst_i; - burst_req.serialize <= serialize_i; - burst_req_valid <= 1'b1; - // wait and set to 0 - @(posedge clk); - burst_req_valid <= 1'b0; - burst_req <= '0; - endtask - - task oned_reset(); - burst_req_valid <= 1'b0; - burst_req <= '0; - endtask - - task wait_for_dut_completion(); - repeat (10) @(posedge clk); - while (backend_idle === 0) @(posedge clk); - repeat (50) @(posedge clk); - endtask - - task clear_dut_memory(); - dma_memory.delete(); - endtask - - task reset_dut_lfsr(); - lfsr_dut_q <= 'hc0a232c162b2bab5b960668030f4efce27940bd0de965f0b8d4315f15b79704195e4e0a6b495fc269f65ae17e10e9ca98510fc143327a292b418597f9dd175fc91c3d61be287d5462a23e00fa7ae906ae9eb339ab5225021356138cd46b6e5a73540c5591116b6b5e08d2c0e54eaf0d5143b33b2186b6cf841c076a98c412a63981f0e323dce93481ed1c37e4f1d7553b6c2fba1a3af6c3ad88b15ad58812ba07d1753917ac4e6ab1e8c4f67a47b4b0f48a34f42a52c546e979f4e4968e80a732a0a5e7a51146cf08482f349f94336752b765c0b1d70803d883d5058d127264335213da4163c62f65a4e65501b90fa5f177675c0747cfca328e131bfb3f7bcc5c27680c7bf86491f4ed3d36c25531edfa74b1e32fafe426958ae356eb8ef0fd818eaca4227a667b7c934ebfa282ab6bfc6db89b927c91a41e63a9554dced774f30268d0725a1a565368703b9f81d5c027ba196ef8b803a51c639c7ead834e1d6bc537d33800fe5eb12f1ed67758f1dfe85ffdbae56e8ef27f2ecedcee75b8dbb5f5f1a629ba3b755; - endtask - - //-------------------------------------- - // Osmium Model - //-------------------------------------- - // Memory - block_t osmium_memory[bit [64-$clog2($bits(block_t))-1:0]]; - // lfsr - logic [784:0] lfsr_osmium_q, lfsr_osmium_d; - - task oned_osmium_launch( - input logic [IdWidth-1:0] transf_id_i, input logic [AddrWidth-1:0] src_addr_i, dst_addr_i, - num_bytes_i, input logic [1:0] src_burst_i, dst_burst_i, input logic [3:0] src_cache_i, - dst_cache_i, input logic decouple_rw_i, input logic deburst_i, input logic serialize_i); - logic [63:0] read_addr, write_addr; - logic [63:0] read_word, write_word; - logic [6:0] read_offset, write_offset; - // perform the transfer - for (int i = 0; i < num_bytes_i; i = i + 1) begin - read_addr = src_addr_i + i; - write_addr = dst_addr_i + i; - read_word = src_burst_i == 2'b00 ? src_addr_i >> 6 : read_addr >> 6; - write_word = dst_burst_i == 2'b00 ? dst_addr_i >> 6 : write_addr >> 6; - read_offset = read_addr[5:0]; - write_offset = write_addr[5:0]; - - // do the read - if (!osmium_memory.exists(read_word) === 1) begin - osmium_memory[read_word].data = lfsr_osmium_q[784:273]; - //shift 513x - repeat (513) begin - // next state - for (int i = 1; i < 785; i = i + 1) lfsr_osmium_d[i-1] = lfsr_osmium_q[i]; - lfsr_osmium_d[784] = lfsr_osmium_q[0]; - lfsr_osmium_d[692] = lfsr_osmium_q[0] ^ lfsr_osmium_q[693]; - lfsr_osmium_q = lfsr_osmium_d; - end - end - // do the write - osmium_memory[write_word].bytes[write_offset] = osmium_memory[read_word].bytes[read_offset]; - // $display("W: %d - %d R: %d - %d", write_word, write_offset, read_word, read_offset); - end - - endtask - - task clear_osmium_memory(); - osmium_memory.delete(); - endtask - - task reset_osmium_lfsr(); - lfsr_osmium_q = 'hc0a232c162b2bab5b960668030f4efce27940bd0de965f0b8d4315f15b79704195e4e0a6b495fc269f65ae17e10e9ca98510fc143327a292b418597f9dd175fc91c3d61be287d5462a23e00fa7ae906ae9eb339ab5225021356138cd46b6e5a73540c5591116b6b5e08d2c0e54eaf0d5143b33b2186b6cf841c076a98c412a63981f0e323dce93481ed1c37e4f1d7553b6c2fba1a3af6c3ad88b15ad58812ba07d1753917ac4e6ab1e8c4f67a47b4b0f48a34f42a52c546e979f4e4968e80a732a0a5e7a51146cf08482f349f94336752b765c0b1d70803d883d5058d127264335213da4163c62f65a4e65501b90fa5f177675c0747cfca328e131bfb3f7bcc5c27680c7bf86491f4ed3d36c25531edfa74b1e32fafe426958ae356eb8ef0fd818eaca4227a667b7c934ebfa282ab6bfc6db89b927c91a41e63a9554dced774f30268d0725a1a565368703b9f81d5c027ba196ef8b803a51c639c7ead834e1d6bc537d33800fe5eb12f1ed67758f1dfe85ffdbae56e8ef27f2ecedcee75b8dbb5f5f1a629ba3b755; - endtask - - //-------------------------------------- - // Compare Memory content - //-------------------------------------- - task compare_memories(); - - // go through osmium memory and compare contents - foreach (osmium_memory[i]) begin - if (osmium_memory[i] !== dma_memory[i]) - $fatal("Memory mismatch @ %x\nexpect: %x\ngot :%x\n", i << 6, osmium_memory[i], - dma_memory[i]); - end - // go through dma memory and compare contents - foreach (dma_memory[i]) begin - if (osmium_memory[i] !== dma_memory[i]) - $fatal("Memory mismatch @ %x\nexpect: %x\ngot :%x\n", i << 6, osmium_memory[i], - dma_memory[i]); - end - - // it worked :P - $display(" - :D"); - - endtask - - //-------------------------------------- - // Master tasks - //-------------------------------------- - - task clear_memory(); - clear_dut_memory(); - clear_osmium_memory(); - endtask - - task reset_lfsr(); - reset_dut_lfsr(); - reset_osmium_lfsr(); - endtask - - task oned_launch(input logic [IdWidth-1:0] transf_id_i, - input logic [AddrWidth-1:0] src_addr_i, dst_addr_i, num_bytes_i, - input logic decouple_rw_i, input logic deburst_i, input logic serialize_i, - input logic wait_for_completion_i); - // keep a log file - int my_file; - my_file = $fopen("dma_transfers.txt", "a+"); - $write("ID: %d SRC: 0x%x DST: 0x%x LEN: %d DECOUPLE: %1b DEBURST: %1b SERIALIZE: %1b", - transf_id_i, src_addr_i, dst_addr_i, num_bytes_i, decouple_rw_i, deburst_i, serialize_i); - $fwrite(my_file, - "ID: %d SRC: 0x%x DST: 0x%x LEN: %d DECOUPLE: %1b DEBURST: %1b SERIALIZE: %1b\n", - transf_id_i, src_addr_i, dst_addr_i, num_bytes_i, decouple_rw_i, deburst_i, - serialize_i); - $fclose(my_file); - - // cache and burst is ignored - oned_dut_launch(transf_id_i, src_addr_i, dst_addr_i, num_bytes_i, 2'b01, 2'b01, 4'h0, 4'h0, - decouple_rw_i, deburst_i, serialize_i); - // wait if requested - if (wait_for_completion_i) wait_for_dut_completion(); - // run model - oned_osmium_launch(transf_id_i, src_addr_i, dst_addr_i, num_bytes_i, 2'b01, 2'b01, 4'h0, 4'h0, - decouple_rw_i, deburst_i, serialize_i); - endtask - - task reset(); - int my_file; - oned_reset(); - wait_for_reset(); - // clear trace file - my_file = $fopen("dma_transfers.txt", "w"); - $fwrite(my_file, "Transfers launched:\n"); - $fclose(my_file); - endtask - - task oned_random_launch(input logic [15:0] max_len, input logic wait_for_completion); - - logic [IdWidth-1:0] transf_id; - logic [AddrWidth-1:0] src_addr, dst_addr, num_bytes; - logic decouple_rw; - logic deburst; - logic serialize; - - transf_id = $urandom(); - // transf_id = transaction_id; - src_addr[63:32] = $urandom(); - src_addr[31:0] = $urandom(); - dst_addr[63:32] = $urandom(); - dst_addr[31:0] = $urandom(); - num_bytes = 0; - num_bytes[15:0] = $urandom_range(max_len, 1); - decouple_rw = $urandom(); - deburst = $urandom(); - serialize = $urandom(); - - // transaction_id = transaction_id + 1; - - oned_launch(transf_id, src_addr, dst_addr, num_bytes, decouple_rw, deburst, serialize, - wait_for_completion); - - endtask - -endmodule : fixture_axi_dma_backend diff --git a/hw/future/test/tb_axi_dma_backend.sv b/hw/future/test/tb_axi_dma_backend.sv deleted file mode 100644 index 6f6d46495..000000000 --- a/hw/future/test/tb_axi_dma_backend.sv +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 -// -// This code is under development and not yet released to the public. -// Until it is released, the code is under the copyright of ETH Zurich and -// the University of Bologna, and may contain confidential and/or unpublished -// work. Any reuse/redistribution is strictly forbidden without written -// permission from ETH Zurich. -// -// Thomas Benz - -// top level of the simulation for the AXI DMA backend - -module tb_axi_dma_backend; - - fixture_axi_dma_backend fix (); - initial begin - - fix.reset(); - fix.clear_memory(); - fix.reset_lfsr(); - - // ultra short transfers - for (int i = 0; i < 20000; i = i + 1) begin - fix.oned_random_launch(4, 0); - $display(); - end - fix.oned_random_launch(4, 1); - fix.compare_memories(); - - // medium short transfers - for (int i = 0; i < 20000; i = i + 1) begin - fix.oned_random_launch(10, 0); - $display(); - end - fix.oned_random_launch(10, 1); - fix.compare_memories(); - - // // short transfers - for (int i = 0; i < 25000; i = i + 1) begin - fix.oned_random_launch(100, 0); - $display(); - end - fix.oned_random_launch(100, 1); - fix.compare_memories(); - - // // medium transfers - for (int i = 0; i < 1000; i = i + 1) begin - fix.oned_random_launch(1000, 0); - $display(); - end - fix.oned_random_launch(1000, 1); - fix.compare_memories(); - - // long transfers - for (int i = 0; i < 250; i = i + 1) begin - fix.oned_random_launch(10000, 0); - $display(); - end - fix.oned_random_launch(10000, 1); - fix.compare_memories(); - - // ultra long transfers - for (int i = 0; i < 100; i = i + 1) begin - fix.oned_random_launch(65000, 0); - $display(); - end - fix.oned_random_launch(65000, 1); - fix.compare_memories(); - - $display("\nDone :D (in %18.9f seconds", $time() / 1000000.0); - $display("SUCCESS"); - $stop(); - end - -endmodule diff --git a/hw/snitch_cluster/src/snitch_cc.sv b/hw/snitch_cluster/src/snitch_cc.sv index 38739a454..15d8abff5 100644 --- a/hw/snitch_cluster/src/snitch_cc.sv +++ b/hw/snitch_cluster/src/snitch_cc.sv @@ -19,7 +19,9 @@ module snitch_cc #( parameter int unsigned DMADataWidth = 0, /// Id width of the AXI DMA bus. parameter int unsigned DMAIdWidth = 0, - parameter int unsigned DMAAxiReqFifoDepth = 0, + /// User width of the AXI DMA bus. + parameter int unsigned DMAUserWidth = 0, + parameter int unsigned DMANumAxInFlight = 0, parameter int unsigned DMAReqFifoDepth = 0, /// Data port request type. parameter type dreq_t = logic, @@ -33,6 +35,8 @@ module snitch_cc #( parameter type tcdm_rsp_t = logic, /// TCDM User Payload parameter type tcdm_user_t = logic, + parameter type axi_ar_chan_t = logic, + parameter type axi_aw_chan_t = logic, parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, parameter type hive_req_t = logic, @@ -130,7 +134,6 @@ module snitch_cc #( output axi_req_t axi_dma_req_o, input axi_rsp_t axi_dma_res_i, output logic axi_dma_busy_o, - output axi_dma_pkg::dma_perf_t axi_dma_perf_o, output dma_events_t axi_dma_events_o, // Core event strobes output snitch_pkg::core_events_t core_events_o, @@ -375,52 +378,46 @@ module snitch_cc #( ); if (Xdma) begin : gen_dma - axi_dma_tc_snitch_fe #( - .AddrWidth (AddrWidth), - .DataWidth (DataWidth), - .DMADataWidth (DMADataWidth), - .IdWidth (DMAIdWidth), - .DMAAxiReqFifoDepth (DMAAxiReqFifoDepth), + idma_inst64_top #( + .AxiAddrWidth (AddrWidth), + .AxiDataWidth (DMADataWidth), + .AxiIdWidth (DMAIdWidth), + .AxiUserWidth (DMAUserWidth), + .NumAxInFlight (DMANumAxInFlight), .DMAReqFifoDepth (DMAReqFifoDepth), + .axi_ar_chan_t (axi_ar_chan_t), + .axi_aw_chan_t (axi_aw_chan_t), .axi_req_t (axi_req_t), .axi_res_t (axi_rsp_t), - .acc_resp_t (acc_resp_t), + .acc_req_t (acc_req_t), + .acc_res_t (acc_resp_t), .dma_events_t (dma_events_t) - ) i_axi_dma_tc_snitch_fe ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .axi_dma_req_o ( axi_dma_req_o ), - .axi_dma_res_i ( axi_dma_res_i ), - .dma_busy_o ( axi_dma_busy_o ), - .acc_qaddr_i ( acc_snitch_req.addr ), - .acc_qid_i ( acc_snitch_req.id ), - .acc_qdata_op_i ( acc_snitch_req.data_op ), - .acc_qdata_arga_i ( acc_snitch_req.data_arga ), - .acc_qdata_argb_i ( acc_snitch_req.data_argb ), - .acc_qdata_argc_i ( acc_snitch_req.data_argc ), - .acc_qvalid_i ( dma_qvalid ), - .acc_qready_o ( dma_qready ), - .acc_pdata_o ( dma_resp.data ), - .acc_pid_o ( dma_resp.id ), - .acc_perror_o ( dma_resp.error ), - .acc_pvalid_o ( dma_pvalid ), - .acc_pready_i ( dma_pready ), - .hart_id_i ( hart_id_i ), - .dma_perf_o ( axi_dma_perf_o ), - .dma_events_o ( axi_dma_events_o ) + ) i_idma_inst64_top ( + .clk_i, + .rst_ni, + .testmode_i ( 1'b0 ), + .axi_req_o ( axi_dma_req_o ), + .axi_res_i ( axi_dma_res_i ), + .busy_o ( axi_dma_busy_o ), + .acc_req_i ( acc_snitch_req ), + .acc_req_valid_i ( dma_qvalid ), + .acc_req_ready_o ( dma_qready ), + .acc_res_o ( dma_resp ), + .acc_res_valid_o ( dma_pvalid ), + .acc_res_ready_i ( dma_pready ), + .hart_id_i ( hart_id_i ), + .events_o ( axi_dma_events_o ) ); // no DMA instanciated end else begin : gen_no_dma // tie-off unused signals - assign axi_dma_req_o = '0; - assign axi_dma_busy_o = 1'b0; - - assign dma_qready = '0; - assign dma_pvalid = '0; - - assign dma_resp = '0; - assign axi_dma_perf_o = '0; + assign axi_dma_req_o = '0; + assign axi_dma_busy_o = '0; + assign dma_qready = '0; + assign dma_resp = '0; + assign dma_pvalid = '0; + assign axi_dma_events_o = '0; end if (Xipu) begin : gen_ipu diff --git a/hw/snitch_cluster/src/snitch_cluster.sv b/hw/snitch_cluster/src/snitch_cluster.sv index 752062676..fa657e52a 100644 --- a/hw/snitch_cluster/src/snitch_cluster.sv +++ b/hw/snitch_cluster/src/snitch_cluster.sv @@ -54,7 +54,7 @@ module snitch_cluster /// banks. parameter int unsigned NrBanks = NrCores, /// Size of DMA AXI buffer. - parameter int unsigned DMAAxiReqFifoDepth = 3, + parameter int unsigned DMANumAxInFlight = 3, /// Size of DMA request fifo. parameter int unsigned DMAReqFifoDepth = 3, /// Width of a single icache line. @@ -859,14 +859,17 @@ module snitch_cluster .DataWidth (NarrowDataWidth), .DMADataWidth (WideDataWidth), .DMAIdWidth (WideIdWidthIn), + .DMAUserWidth (WideUserWidth), .SnitchPMACfg (SnitchPMACfg), - .DMAAxiReqFifoDepth (DMAAxiReqFifoDepth), + .DMANumAxInFlight (DMANumAxInFlight), .DMAReqFifoDepth (DMAReqFifoDepth), .dreq_t (reqrsp_req_t), .drsp_t (reqrsp_rsp_t), .tcdm_req_t (tcdm_req_t), .tcdm_rsp_t (tcdm_rsp_t), .tcdm_user_t (tcdm_user_t), + .axi_ar_chan_t (axi_mst_dma_ar_chan_t), + .axi_aw_chan_t (axi_mst_dma_aw_chan_t), .axi_req_t (axi_mst_dma_req_t), .axi_rsp_t (axi_mst_dma_resp_t), .hive_req_t (hive_req_t), @@ -934,7 +937,6 @@ module snitch_cluster .axi_dma_req_o (axi_dma_req), .axi_dma_res_i (axi_dma_res), .axi_dma_busy_o (), - .axi_dma_perf_o (), .axi_dma_events_o (dma_core_events), .core_events_o (core_events[i]), .tcdm_addr_base_i (tcdm_start_address), diff --git a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl index 05c891657..293417ff6 100644 --- a/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl +++ b/hw/snitch_cluster/src/snitch_cluster_wrapper.sv.tpl @@ -276,7 +276,7 @@ module ${cfg['name']}_wrapper ( .ZeroMemorySize (${cfg['zero_mem_size']}), .ClusterPeriphSize (${cfg['cluster_periph_size']}), .NrBanks (${cfg['tcdm']['banks']}), - .DMAAxiReqFifoDepth (${cfg['dma_axi_req_fifo_depth']}), + .DMANumAxInFlight (${cfg['dma_axi_req_fifo_depth']}), .DMAReqFifoDepth (${cfg['dma_req_fifo_depth']}), .ICacheLineWidth (${cfg['pkg_name']}::ICacheLineWidth), .ICacheLineCount (${cfg['pkg_name']}::ICacheLineCount), diff --git a/hw/snitch_dma/src/axi_dma_error_handler.sv b/hw/snitch_dma/src/axi_dma_error_handler.sv deleted file mode 100644 index 5a9fab2e2..000000000 --- a/hw/snitch_dma/src/axi_dma_error_handler.sv +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -// Sample implementation to report errors from the AXI bus. -// This module provides the address of errors on a handshaked interface - -module axi_dma_error_handler #( - parameter int unsigned ADDR_WIDTH = -1, - parameter int unsigned BUFFER_DEPTH = -1, - parameter int unsigned AXI_REQ_FIFO_DEPTH = -1, - parameter bit WAIT_FOR_READ = 1, - parameter type axi_req_t = logic, - parameter type axi_res_t = logic -) ( - input logic clk_i, - input logic rst_ni, - // AXI4 to/from SoC - output axi_req_t axi_dma_req_o, - input axi_res_t axi_dma_res_i, - // AXI4 to/from DMA backend - input axi_req_t axi_dma_req_i, - output axi_res_t axi_dma_res_o, - // write error - output logic [ADDR_WIDTH-1:0] w_error_addr_o, - output logic w_error_valid_o, - input logic w_error_ready_i, - // read error - output logic [ADDR_WIDTH-1:0] r_error_addr_o, - output logic r_error_valid_o, - input logic r_error_ready_i -); - - logic mask_write; - - //-------------------------------------- - // AR buffer - //-------------------------------------- - // the units needs to keep track of the reads issued - // to the system. Important information to keep is only the address - logic [ADDR_WIDTH-1:0] current_ar_addr; - // control signals - logic ar_queue_push; - logic ar_queue_pop; - - // instanciate a fifo to buffer the address read requests - fifo_v3 #( - .FALL_THROUGH ( 1'b0 ), - .DATA_WIDTH ( ADDR_WIDTH ), - .DEPTH ( AXI_REQ_FIFO_DEPTH ) - ) i_fifo_ar_queue ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( ), - .empty_o ( ), - .usage_o ( ), - .data_i ( axi_dma_req_i.ar.addr ), - .push_i ( ar_queue_push ), - .data_o ( current_ar_addr ), - .pop_i ( ar_queue_pop ) - ); - - // this fifo is working in tandem with the ar emittor in the main - // dma core. Therefore is should never overflow... - assign ar_queue_push = axi_dma_req_o.ar_valid && axi_dma_res_o.ar_ready; - assign ar_queue_pop = axi_dma_req_o.r_ready && axi_dma_res_o.r_valid && axi_dma_res_o.r.last; - - //-------------------------------------- - // AW buffer - //-------------------------------------- - // the units needs to keep track of the writes issued - // to the system. Important information to keep is only the address - logic [ADDR_WIDTH-1:0] current_aw_addr; - // control signals - logic aw_queue_push; - logic aw_queue_pop; - - // instanciate a fifo to buffer the address write requests - fifo_v3 #( - .FALL_THROUGH ( 1'b0 ), - .DATA_WIDTH ( ADDR_WIDTH ), - .DEPTH ( AXI_REQ_FIFO_DEPTH ) - ) i_fifo_aw_queue ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( ), - .empty_o ( ), - .usage_o ( ), - .data_i ( axi_dma_req_i.aw.addr ), - .push_i ( aw_queue_push ), - .data_o ( current_aw_addr ), - .pop_i ( aw_queue_pop ) - ); - - // this fifo is working in tandem with the aw emittor in the main - // dma core. Therefore is should never overflow... - assign aw_queue_push = axi_dma_req_o.aw_valid && axi_dma_res_o.aw_ready; - assign aw_queue_pop = axi_dma_req_o.b_ready && axi_dma_res_o.b_valid; - - //-------------------------------------- - // Read Errors - //-------------------------------------- - logic read_error; - - always_comb begin : proc_read_errors - - // defaults: mask signals - r_error_addr_o = '0; - r_error_valid_o = 1'b0; - - // read errors -> r.resp is != 2'b00; - read_error = axi_dma_req_o.r_ready & - axi_dma_res_o.r_valid & (axi_dma_res_o.r.resp != 2'b00); - - // report read error - if (read_error == 1'b1) begin - r_error_valid_o = 1'b1; - r_error_addr_o = current_ar_addr; - end - - end - - //-------------------------------------- - // Write Errors - //-------------------------------------- - logic write_error; - - always_comb begin : proc_write_errors - - // defaults: mask signals - w_error_addr_o = '0; - w_error_valid_o = 1'b0; - - // write errors -> b.resp is != 2'b00; - write_error = - axi_dma_req_o.b_ready & axi_dma_res_o.b_valid & (axi_dma_res_o.b.resp != 2'b00); - - // report write error - if (write_error == 1'b1) begin - w_error_valid_o = 1'b1; - w_error_addr_o = current_aw_addr; - end - - end - - //-------------------------------------- - // Request Modifier - //-------------------------------------- - always_comb begin : proc_req_modifier - - // default: just feed signals through - axi_dma_req_o = axi_dma_req_i; - - // set strobe to 0 if write is blocked - if (mask_write == 1'b1) axi_dma_req_o.w.strb = '0; - - // aw_valid from the DMA core should be masked until - // the DMA core is ready to write (w_valid) - if (WAIT_FOR_READ == 1'b1) begin - axi_dma_req_o.aw_valid = axi_dma_req_i.aw_valid && axi_dma_req_i.w_valid; - end - - // R's will be blocked if no more read errors can be reported - axi_dma_req_o.r_ready = axi_dma_req_i.r_ready && r_error_ready_i; - - // B's will be blocked if no more write errors can be reported - axi_dma_req_o.b_ready = w_error_ready_i; - - end - - //-------------------------------------- - // Response Modifier - //-------------------------------------- - always_comb begin : proc_res_modifier - - // default: just feed signals through - axi_dma_res_o = axi_dma_res_i; - - // aw_ready to the DMA core should be masked until - // the DMA core is ready to write (w_valid) - if (WAIT_FOR_READ == 1'b1) begin - axi_dma_res_o.aw_ready = axi_dma_res_i.aw_ready && axi_dma_req_i.w_valid; - end - - // R's will be blocked if no more read errors can be reported - axi_dma_res_o.r_valid = axi_dma_res_i.r_valid && r_error_ready_i; - - end - -endmodule diff --git a/hw/snitch_dma/src/axi_dma_perf_counters.sv b/hw/snitch_dma/src/axi_dma_perf_counters.sv deleted file mode 100644 index 0e9f762d1..000000000 --- a/hw/snitch_dma/src/axi_dma_perf_counters.sv +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -`include "common_cells/registers.svh" - -// Sample implementation of performance counters. -module axi_dma_perf_counters #( - parameter int unsigned TRANSFER_ID_WIDTH = -1, - parameter int unsigned DATA_WIDTH = -1, - parameter type axi_req_t = logic, - parameter type axi_res_t = logic, - parameter type dma_events_t = logic, - localparam bit EnablePerfCounters = 0 -) ( - input logic clk_i, - input logic rst_ni, - // AXI4 bus - input axi_req_t axi_dma_req_i, - input axi_res_t axi_dma_res_i, - // ID input - input logic [TRANSFER_ID_WIDTH-1:0] next_id_i, - input logic [TRANSFER_ID_WIDTH-1:0] completed_id_i, - // DMA busy - input logic dma_busy_i, - // performance bus - output axi_dma_pkg::dma_perf_t dma_perf_o, - output dma_events_t dma_events_o -); - - localparam int unsigned StrbWidth = DATA_WIDTH / 8; - - // internal state - axi_dma_pkg::dma_perf_t dma_perf_d, dma_perf_q; - - // Event counter - dma_events_t dma_events; - - // need popcount common cell to get the number of bytes active in the strobe signal - logic [$clog2(StrbWidth)+1-1:0] num_bytes_written; - popcount #( - .INPUT_WIDTH ( StrbWidth ) - ) i_popcount ( - .data_i ( axi_dma_req_i.w.strb ), - .popcount_o ( num_bytes_written ) - ); - - // see if counters should be increased - always_comb begin : proc_next_perf_state - - // default: keep old value - dma_perf_d = dma_perf_q; - dma_events = '0; - - // aw - if ( axi_dma_req_i.aw_valid) begin - dma_perf_d.aw_valid_cnt = dma_perf_q.aw_valid_cnt + 'h1; - dma_events.aw_valid = 1'b1; - end - - if ( axi_dma_res_i.aw_ready) begin - dma_perf_d.aw_ready_cnt = dma_perf_q.aw_ready_cnt + 'h1; - dma_events.aw_ready = 1'b1; - end - - if ( axi_dma_res_i.aw_ready && axi_dma_req_i.aw_valid) begin - dma_perf_d.aw_done_cnt = dma_perf_q.aw_done_cnt + 'h1; - dma_events.aw_done = 1'b1; - end - - if ( axi_dma_res_i.aw_ready && axi_dma_req_i.aw_valid) begin - dma_perf_d.aw_bw = - dma_perf_q.aw_bw + ((axi_dma_req_i.aw.len + 1) << axi_dma_req_i.aw.size); - dma_events.aw_len = axi_dma_req_i.aw.len; - dma_events.aw_size = axi_dma_req_i.aw.size; - end - - if (!axi_dma_res_i.aw_ready && axi_dma_req_i.aw_valid) begin - dma_perf_d.aw_stall_cnt = dma_perf_q.aw_stall_cnt + 'h1; - dma_events.aw_stall = 1'b1; - end - - - // ar - if (axi_dma_req_i.ar_valid) begin - dma_perf_d.ar_valid_cnt = dma_perf_q.ar_valid_cnt + 'h1; - dma_events.ar_valid = 1'b1; - end - if (axi_dma_res_i.ar_ready) begin - dma_perf_d.ar_ready_cnt = dma_perf_q.ar_ready_cnt + 'h1; - dma_events.ar_ready = 1'b1; - end - if (axi_dma_res_i.ar_ready && axi_dma_req_i.ar_valid) begin - dma_perf_d.ar_done_cnt = dma_perf_q.ar_done_cnt + 'h1; - dma_events.ar_done = 1'b1; - end - if (axi_dma_res_i.ar_ready && axi_dma_req_i.ar_valid) begin - dma_perf_d.ar_bw = - dma_perf_q.ar_bw + ((axi_dma_req_i.ar.len + 1) << axi_dma_req_i.ar.size); - dma_events.ar_len = axi_dma_req_i.ar.len; - dma_events.ar_size = axi_dma_req_i.ar.size; - end - if (!axi_dma_res_i.ar_ready && axi_dma_req_i.ar_valid) begin - dma_perf_d.ar_stall_cnt = dma_perf_q.ar_stall_cnt + 'h1; - dma_events.ar_stall = 1'b1; - end - - // r - if (axi_dma_res_i.r_valid) begin - dma_perf_d.r_valid_cnt = dma_perf_q.r_valid_cnt + 'h1; - dma_events.r_valid = 1'b1; - end - if (axi_dma_req_i.r_ready) begin - dma_perf_d.r_ready_cnt = dma_perf_q.r_ready_cnt + 'h1; - dma_events.r_ready = 1'b1; - end - if (axi_dma_req_i.r_ready && axi_dma_res_i.r_valid) begin - dma_perf_d.r_done_cnt = dma_perf_q.r_done_cnt + 'h1; - dma_events.r_done = 1'b1; - end - if (axi_dma_req_i.r_ready && axi_dma_res_i.r_valid) begin - dma_perf_d.r_bw = dma_perf_q.r_bw + DATA_WIDTH / 8; - dma_events.r_bw = 1'b1; - end - if (axi_dma_req_i.r_ready && !axi_dma_res_i.r_valid) begin - dma_perf_d.r_stall_cnt = dma_perf_q.r_stall_cnt + 'h1; - dma_events.r_stall = 1'b1; - end - - // w - if (axi_dma_req_i.w_valid) begin - dma_perf_d.w_valid_cnt = dma_perf_q.w_valid_cnt + 'h1; - dma_events.w_valid = 1'b1; - end - if (axi_dma_res_i.w_ready) begin - dma_perf_d.w_ready_cnt = dma_perf_q.w_ready_cnt + 'h1; - dma_events.w_ready = 1'b1; - end - if (axi_dma_res_i.w_ready && axi_dma_req_i.w_valid) begin - dma_perf_d.w_done_cnt = dma_perf_q.w_done_cnt + 'h1; - dma_events.w_done = 1'b1; - end - if (axi_dma_res_i.w_ready && axi_dma_req_i.w_valid) begin - dma_perf_d.w_bw = dma_perf_q.w_bw + num_bytes_written; - dma_events.num_bytes_written = num_bytes_written; - end - if (!axi_dma_res_i.w_ready && axi_dma_req_i.w_valid) begin - dma_perf_d.w_stall_cnt = dma_perf_q.w_stall_cnt + 'h1; - dma_events.w_stall = 1'b1; - end - - // b - if (axi_dma_res_i.b_valid) begin - dma_perf_d.b_valid_cnt = dma_perf_q.b_valid_cnt + 'h1; - dma_events.b_valid = 1'b1; - end - if (axi_dma_req_i.b_ready) begin - dma_perf_d.b_ready_cnt = dma_perf_q.b_ready_cnt + 'h1; - dma_events.b_ready = 1'b1; - end - if (axi_dma_req_i.b_ready && axi_dma_res_i.b_valid) begin - dma_perf_d.b_done_cnt = dma_perf_q.b_done_cnt + 'h1; - dma_events.b_done = 1'b1; - end - - // buffer - if ( axi_dma_res_i.w_ready && !axi_dma_req_i.w_valid) begin - dma_perf_d.buf_w_stall_cnt = dma_perf_q.buf_w_stall_cnt + 'h1; - dma_events.w_stall = 1'b1; - end - if (!axi_dma_req_i.r_ready && axi_dma_res_i.r_valid) begin - dma_perf_d.buf_r_stall_cnt = dma_perf_q.buf_r_stall_cnt + 'h1; - dma_events.r_stall = 1'b1; - end - - // ids - dma_perf_d.next_id = 32'h0 + next_id_i; - dma_perf_d.completed_id = 32'h0 + completed_id_i; - - // busy - if (dma_busy_i) begin - dma_perf_d.dma_busy_cnt = dma_perf_q.dma_busy_cnt + 'h1; - dma_events.dma_busy = 1'b1; - end - end - - assign dma_events_o = dma_events; - - if (EnablePerfCounters) begin : gen_perf_counters - `FF(dma_perf_q, dma_perf_d, 0); - assign dma_perf_o = dma_perf_q; - end - - - -endmodule diff --git a/hw/snitch_dma/src/axi_dma_pkg.sv b/hw/snitch_dma/src/axi_dma_pkg.sv deleted file mode 100644 index 06cdd0a19..000000000 --- a/hw/snitch_dma/src/axi_dma_pkg.sv +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -`include "axi/typedef.svh" - -// for now this is an extended copy of the axi_pkg -// eventually the DMA specific parts should be moved in axi_pkg aswell -package axi_dma_pkg; - - typedef struct packed { - logic [63:0] aw_stall_cnt, ar_stall_cnt, r_stall_cnt, w_stall_cnt, - buf_w_stall_cnt, buf_r_stall_cnt; - logic [63:0] aw_valid_cnt, aw_ready_cnt, aw_done_cnt, aw_bw; - logic [63:0] ar_valid_cnt, ar_ready_cnt, ar_done_cnt, ar_bw; - logic [63:0] r_valid_cnt, r_ready_cnt, r_done_cnt, r_bw; - logic [63:0] w_valid_cnt, w_ready_cnt, w_done_cnt, w_bw; - logic [63:0] b_valid_cnt, b_ready_cnt, b_done_cnt; - logic [63:0] next_id, completed_id; - logic [63:0] dma_busy_cnt; - } dma_perf_t; - -endpackage diff --git a/hw/snitch_dma/src/axi_dma_tc_snitch_fe.sv b/hw/snitch_dma/src/axi_dma_tc_snitch_fe.sv deleted file mode 100644 index 7fcb9d56f..000000000 --- a/hw/snitch_dma/src/axi_dma_tc_snitch_fe.sv +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -// Implements the tightly-coupled frontend. This module can directly be connected -// to an accelerator bus in the snitch system - -`include "common_cells/registers.svh" - -module axi_dma_tc_snitch_fe #( - parameter int unsigned AddrWidth = 0, - parameter int unsigned DataWidth = 0, - parameter int unsigned DMADataWidth = 0, - parameter int unsigned IdWidth = 0, - parameter int unsigned DMAAxiReqFifoDepth = 3, - parameter int unsigned DMAReqFifoDepth = 3, - parameter type axi_req_t = logic, - parameter type axi_res_t = logic, - parameter type acc_resp_t = logic, - parameter type dma_events_t = logic, - /// Derived parameter *Do not override* - parameter type addr_t = logic [AddrWidth-1:0], - parameter type data_t = logic [DataWidth-1:0] -) ( - input logic clk_i, - input logic rst_ni, - // AXI4 bus - output axi_req_t axi_dma_req_o, - input axi_res_t axi_dma_res_i, - // debug output - output logic dma_busy_o, - // accelerator interface - input logic [31:0] acc_qaddr_i, - input logic [ 4:0] acc_qid_i, - input logic [31:0] acc_qdata_op_i, - input data_t acc_qdata_arga_i, - input data_t acc_qdata_argb_i, - input addr_t acc_qdata_argc_i, - input logic acc_qvalid_i, - output logic acc_qready_o, - - output data_t acc_pdata_o, - output logic [ 4:0] acc_pid_o, - output logic acc_perror_o, - output logic acc_pvalid_o, - input logic acc_pready_i, - - // hart id of the frankensnitch - input logic [31:0] hart_id_i, - - // performance output - output axi_dma_pkg::dma_perf_t dma_perf_o, - output dma_events_t dma_events_o -); - - typedef logic [IdWidth-1:0] id_t; - - typedef struct packed { - id_t id; - addr_t src, dst, num_bytes; - axi_pkg::cache_t cache_src, cache_dst; - axi_pkg::burst_t burst_src, burst_dst; - logic decouple_rw; - logic deburst; - logic serialize; - } burst_req_t; - - typedef struct packed { - id_t id; - addr_t src, dst, num_bytes; - axi_pkg::cache_t cache_src, cache_dst; - addr_t stride_src, stride_dst, num_repetitions; - axi_pkg::burst_t burst_src, burst_dst; - logic decouple_rw; - logic deburst; - logic is_twod; - } twod_req_t; - - //-------------------------------------- - // Backend Instanciation - //-------------------------------------- - logic backend_idle; - burst_req_t burst_req; - logic burst_req_valid; - logic burst_req_ready; - logic oned_trans_complete; - - axi_dma_backend #( - .DataWidth ( DMADataWidth ), - .AddrWidth ( AddrWidth ), - .IdWidth ( IdWidth ), - .AxReqFifoDepth ( DMAAxiReqFifoDepth ), - .TransFifoDepth ( DMAReqFifoDepth ), - .BufferDepth ( 3 ), - .axi_req_t ( axi_req_t ), - .axi_res_t ( axi_res_t ), - .burst_req_t ( burst_req_t ), - .DmaIdWidth ( 32 ), - .DmaTracing ( 1 ) - ) i_axi_dma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .axi_dma_req_o ( axi_dma_req_o ), - .axi_dma_res_i ( axi_dma_res_i ), - .burst_req_i ( burst_req ), - .valid_i ( burst_req_valid ), - .ready_o ( burst_req_ready ), - .backend_idle_o ( backend_idle ), - .trans_complete_o ( oned_trans_complete ), - .dma_id_i ( hart_id_i ) - ); - - //-------------------------------------- - // 2D Extension - //-------------------------------------- - twod_req_t twod_req_d, twod_req_q; - logic twod_req_valid; - logic twod_req_ready; - logic twod_req_last; - - axi_dma_twod_ext #( - .ADDR_WIDTH ( AddrWidth ), - .REQ_FIFO_DEPTH ( DMAReqFifoDepth ), - .burst_req_t ( burst_req_t ), - .twod_req_t ( twod_req_t ) - ) i_axi_dma_twod_ext ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .twod_req_i ( twod_req_d ), - .twod_req_valid_i ( twod_req_valid ), - .twod_req_ready_o ( twod_req_ready ), - .burst_req_o ( burst_req ), - .burst_req_valid_o ( burst_req_valid ), - .burst_req_ready_i ( burst_req_ready ), - .twod_req_last_o ( twod_req_last ) - ); - - //-------------------------------------- - // Buffer twod last - //-------------------------------------- - localparam int unsigned TwodBufferDepth = 2 * (DMAReqFifoDepth + - DMAAxiReqFifoDepth) + 3 + 1; - logic twod_req_last_realigned; - fifo_v3 # ( - .DATA_WIDTH ( 1 ), - .DEPTH ( TwodBufferDepth ) - ) i_fifo_v3_last_twod_buffer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( ), - .empty_o ( ), - .usage_o ( ), - .data_i ( twod_req_last ), - .push_i ( burst_req_valid & burst_req_ready ), - .data_o ( twod_req_last_realigned ), - .pop_i ( oned_trans_complete ) - ); - - //-------------------------------------- - // ID gen - //-------------------------------------- - logic [31:0] next_id; - logic [31:0] completed_id; - - `FFL(next_id, next_id + 'h1, twod_req_valid & twod_req_ready, 0) - `FFL(completed_id, completed_id + 'h1, oned_trans_complete & twod_req_last_realigned, 0) - - // dma is busy when it is not idle - assign dma_busy_o = next_id != completed_id; - - //-------------------------------------- - // Performance counters - //-------------------------------------- - axi_dma_perf_counters #( - .TRANSFER_ID_WIDTH ( 32 ), - .DATA_WIDTH ( DMADataWidth ), - .axi_req_t ( axi_req_t ), - .axi_res_t ( axi_res_t ), - .dma_events_t ( dma_events_t ) - ) i_axi_dma_perf_counters ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .axi_dma_req_i ( axi_dma_req_o ), - .axi_dma_res_i ( axi_dma_res_i ), - .next_id_i ( next_id ), - .completed_id_i ( completed_id ), - .dma_busy_i ( dma_busy_o ), - .dma_perf_o ( dma_perf_o ), - .dma_events_o ( dma_events_o ) - ); - - //-------------------------------------- - // Spill register for response channel - //-------------------------------------- - acc_resp_t acc_pdata_spill, acc_pdata; - logic acc_pvalid_spill; - logic acc_pready_spill; - - // the response path needs to be decoupled - spill_register #( - .T ( acc_resp_t ) - ) i_spill_register_dma_resp ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( acc_pvalid_spill ), - .ready_o ( acc_pready_spill ), - .data_i ( acc_pdata_spill ), - .valid_o ( acc_pvalid_o ), - .ready_i ( acc_pready_i ), - .data_o ( acc_pdata ) - ); - - assign acc_pdata_o = acc_pdata.data; - assign acc_pid_o = acc_pdata.id; - assign acc_perror_o = acc_pdata.error; - - //-------------------------------------- - // Instruction decode - //-------------------------------------- - logic is_dma_op; - logic [12*8-1:0] dma_op_name; - - always_comb begin : proc_fe_inst_decode - twod_req_d = twod_req_q; - twod_req_d.burst_src = axi_pkg::BURST_INCR; - twod_req_d.burst_dst = axi_pkg::BURST_INCR; - twod_req_d.cache_src = axi_pkg::CACHE_MODIFIABLE; - twod_req_d.cache_dst = axi_pkg::CACHE_MODIFIABLE; - twod_req_valid = 1'b0; - acc_qready_o = 1'b0; - acc_pdata_spill = '0; - acc_pdata_spill.error = 1'b1; - acc_pvalid_spill = 1'b0; - - // debug signal - is_dma_op = 1'b0; - dma_op_name = "Invalid"; - - // decode - if (acc_qvalid_i == 1'b1) begin - unique casez (acc_qdata_op_i) - - // manipulate the source register - riscv_instr::DMSRC : begin - twod_req_d.src[31: 0] = acc_qdata_arga_i[31:0]; - twod_req_d.src[AddrWidth-1:32] = acc_qdata_argb_i[AddrWidth-1-32: 0]; - acc_qready_o = 1'b1; - is_dma_op = 1'b1; - dma_op_name = "DMSRC"; - end - - // manipulate the destination register - riscv_instr::DMDST : begin - twod_req_d.dst[31: 0] = acc_qdata_arga_i[31:0]; - twod_req_d.dst[AddrWidth-1:32] = acc_qdata_argb_i[AddrWidth-1-32: 0]; - acc_qready_o = 1'b1; - is_dma_op = 1'b1; - dma_op_name = "DMDST"; - end - - // start the DMA - riscv_instr::DMCPYI, - riscv_instr::DMCPY : begin - automatic logic [1:0] cfg; - - // Parse the transfer parameters from the register or immediate. - cfg = '0; - unique casez (acc_qdata_op_i) - riscv_instr::DMCPYI : cfg = acc_qdata_op_i[24:20]; - riscv_instr::DMCPY : cfg = acc_qdata_argb_i; - default:; - endcase - dma_op_name = "DMCPY"; - is_dma_op = 1'b1; - - twod_req_d.num_bytes = acc_qdata_arga_i; - twod_req_d.decouple_rw = cfg[0]; - twod_req_d.is_twod = cfg[1]; - - // Perform the following sequence: - // 1. wait for acc response channel to be ready (pready) - // 2. request twod transfer (valid) - // 3. wait for twod transfer to be accepted (ready) - // 4. send acc response (pvalid) - // 5. acknowledge acc request (qready) - if (acc_pready_spill) begin - twod_req_valid = 1'b1; - if (twod_req_ready) begin - acc_pdata_spill.id = acc_qid_i; - acc_pdata_spill.data = next_id; - acc_pdata_spill.error = 1'b0; - acc_pvalid_spill = 1'b1; - acc_qready_o = twod_req_ready; - end - end - end - - // status of the DMA - riscv_instr::DMSTATI, - riscv_instr::DMSTAT: begin - automatic logic [1:0] status; - - // Parse the status index from the register or immediate. - status = '0; - unique casez (acc_qdata_op_i) - riscv_instr::DMSTATI: status = acc_qdata_op_i[24:20]; - riscv_instr::DMSTAT: status = acc_qdata_argb_i; - default:; - endcase - dma_op_name = "DMSTAT"; - is_dma_op = 1'b1; - - // Compose the response. - acc_pdata_spill.id = acc_qid_i; - acc_pdata_spill.error = 1'b0; - case (status) - 2'b00 : acc_pdata_spill.data = completed_id; - 2'b01 : acc_pdata_spill.data = next_id; - 2'b10 : acc_pdata_spill.data = {{{8'd63}{1'b0}}, dma_busy_o}; - 2'b11 : acc_pdata_spill.data = {{{8'd63}{1'b0}}, !twod_req_ready}; - default:; - endcase - - // Wait for acc response channel to become ready, then ack the - // request. - if (acc_pready_spill) begin - acc_pvalid_spill = 1'b1; - acc_qready_o = 1'b1; - end - end - - // manipulate the strides - riscv_instr::DMSTR : begin - twod_req_d.stride_src = acc_qdata_arga_i; - twod_req_d.stride_dst = acc_qdata_argb_i; - acc_qready_o = 1'b1; - is_dma_op = 1'b1; - dma_op_name = "DMSTR"; - end - - // manipulate the strides - riscv_instr::DMREP : begin - twod_req_d.num_repetitions = acc_qdata_arga_i; - acc_qready_o = 1'b1; - is_dma_op = 1'b1; - dma_op_name = "DMREP"; - end - - default:; - endcase - end - end - - //-------------------------------------- - // State - //-------------------------------------- - `FF(twod_req_q, twod_req_d, '0) - -endmodule diff --git a/hw/snitch_dma/src/axi_dma_twod_ext.sv b/hw/snitch_dma/src/axi_dma_twod_ext.sv deleted file mode 100644 index 8ca8b29d7..000000000 --- a/hw/snitch_dma/src/axi_dma_twod_ext.sv +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -`include "common_cells/registers.svh" - -/// Accept 2D requests and flatten them to 1D requests. -module axi_dma_twod_ext #( - parameter int unsigned ADDR_WIDTH = -1, - parameter int unsigned REQ_FIFO_DEPTH = -1, - parameter type burst_req_t = logic, - parameter type twod_req_t = logic -) ( - input logic clk_i, - input logic rst_ni, - /// Arbitrary burst request - output burst_req_t burst_req_o, - output logic burst_req_valid_o, - input logic burst_req_ready_i, - /// 2D Request - input twod_req_t twod_req_i, - input logic twod_req_valid_i, - output logic twod_req_ready_o, - /// 2D Request Completed - output logic twod_req_last_o -); - - //-------------------------------------- - // 2D Request Fifo - //-------------------------------------- - // currently worked on element - twod_req_t twod_req_current; - // control signals - logic req_fifo_full; - logic req_fifo_empty; - logic req_fifo_push; - logic req_fifo_pop; - - fifo_v3 #( - .DEPTH ( REQ_FIFO_DEPTH ), - .dtype ( twod_req_t ) - ) i_twod_req_fifo_v3 ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( 1'b0 ), - .testmode_i ( 1'b0 ), - .full_o ( req_fifo_full ), - .empty_o ( req_fifo_empty ), - .usage_o ( ), - .data_i ( twod_req_i ), - .push_i ( req_fifo_push ), - .data_o ( twod_req_current ), - .pop_i ( req_fifo_pop ) - ); - - // handshaking to fill the fifo - assign twod_req_ready_o = !req_fifo_full; - assign req_fifo_push = twod_req_valid_i & twod_req_ready_o; - - //-------------------------------------- - // Counter - //-------------------------------------- - logic [ADDR_WIDTH-1:0] num_bursts_d, num_bursts_q; - logic [ADDR_WIDTH-1:0] src_address_d, src_address_q; - logic [ADDR_WIDTH-1:0] dst_address_d, dst_address_q; - - //-------------------------------------- - // 2D Extension - //-------------------------------------- - always_comb begin : proc_twod_ext - // defaults - req_fifo_pop = 1'b0; - burst_req_o = '0; - burst_req_valid_o = 1'b0; - twod_req_last_o = 1'b0; - - // counter keeps its value - num_bursts_d = num_bursts_q; - src_address_d = src_address_q; - dst_address_d = dst_address_q; - - //-------------------------------------- - // 1D Case - //-------------------------------------- - // in the case that we have a 1D transfer, hand the transfer out - if (!twod_req_current.is_twod || twod_req_current.num_repetitions == 'h1) begin - // bypass the 1D parameters - burst_req_o.id = twod_req_current.id; - burst_req_o.src = twod_req_current.src; - burst_req_o.dst = twod_req_current.dst; - burst_req_o.num_bytes = twod_req_current.num_bytes; - burst_req_o.cache_src = twod_req_current.cache_src; - burst_req_o.cache_dst = twod_req_current.cache_dst; - burst_req_o.burst_src = twod_req_current.burst_src; - burst_req_o.burst_dst = twod_req_current.burst_dst; - burst_req_o.decouple_rw = twod_req_current.decouple_rw; - burst_req_o.deburst = twod_req_current.deburst; - - // handshaking - req_fifo_pop = burst_req_ready_i & ~req_fifo_empty; - burst_req_valid_o = ~req_fifo_empty; - twod_req_last_o = 1'b1; - - //-------------------------------------- - // 2D Case - Counter Management - //-------------------------------------- - // in the 2D case: we need to work with a counter - end else begin - // some signals are bypassed - burst_req_o.id = twod_req_current.id; - burst_req_o.num_bytes = twod_req_current.num_bytes; - burst_req_o.cache_src = twod_req_current.cache_src; - burst_req_o.cache_dst = twod_req_current.cache_dst; - burst_req_o.burst_src = twod_req_current.burst_src; - burst_req_o.burst_dst = twod_req_current.burst_dst; - burst_req_o.decouple_rw = twod_req_current.decouple_rw; - burst_req_o.deburst = twod_req_current.deburst; - - // check if the counter can be loaded - if ((num_bursts_q == '0) & !req_fifo_empty & burst_req_ready_i) begin - // load the counters - // check first if num_repetitions is 0. Start the counters if the input is != 0 - if (twod_req_current.num_repetitions != '0) begin - num_bursts_d = twod_req_current.num_repetitions - 'h1; - src_address_d = twod_req_current.src; - dst_address_d = twod_req_current.dst; - // signal that the counter has now valid data - burst_req_valid_o = 1'b1; - - // the num_repetitions is 0. - end else begin - // just pop the invalid request out of the fifo - req_fifo_pop = 1'b1; - end - - // check if we should count down - end else if ((num_bursts_q != '0) & !req_fifo_empty & burst_req_ready_i) begin - // we can send out an request - num_bursts_d = num_bursts_q - 'h1; - // modify addresses - src_address_d = src_address_q + twod_req_current.stride_src; - dst_address_d = dst_address_q + twod_req_current.stride_dst; - // request is valid - burst_req_valid_o = 1'b1; - // if counter has finished -> pop fifo - if (num_bursts_d == '0) begin - req_fifo_pop = 1'b1; - twod_req_last_o = 1'b1; - end - end - - // present modified signals - burst_req_o.src = src_address_d; - burst_req_o.dst = dst_address_d; - end - end - - //-------------------------------------- - // Update Counters - //-------------------------------------- - `FF(num_bursts_q, num_bursts_d, '0) - `FF(src_address_q, src_address_d, '0) - `FF(dst_address_q, dst_address_d, '0) - -endmodule diff --git a/hw/snitch_dma/test/sdma_synth_wrapper.sv b/hw/snitch_dma/test/sdma_synth_wrapper.sv deleted file mode 100644 index cb90c38b8..000000000 --- a/hw/snitch_dma/test/sdma_synth_wrapper.sv +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Thomas Benz - -// defines a type for the axi bus to allow a ooc synthesis - -module sdma_synth_wrapper ( - - input logic clk_i, - input logic rst_ni, - output axi_dma_pkg::req_t axi_dma_req_o, - input axi_dma_pkg::res_t axi_dma_res_i, - output logic dma_busy_o, - input logic [31:0] acc_qaddr_i, - input logic [ 4:0] acc_qid_i, - input logic [31:0] acc_qdata_op_i, - input logic [63:0] acc_qdata_arga_i, - input logic [63:0] acc_qdata_argb_i, - input logic [63:0] acc_qdata_argc_i, - input logic acc_qvalid_i, - output logic acc_qready_o, - output logic [63:0] acc_pdata_o, - output logic [ 4:0] acc_pid_o, - output logic acc_perror_o, - output logic acc_pvalid_o, - input logic acc_pready_i -); - - axi_dma_tc_snitch_fe #( - .axi_req_t(axi_dma_pkg::req_t), - .axi_res_t(axi_dma_pkg::res_t) - ) i_axi_dma_tc_snitch_fe ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .axi_dma_req_o (axi_dma_req_o), - .axi_dma_res_i (axi_dma_res_i), - .dma_busy_o (dma_busy_o), - .acc_qaddr_i (acc_qaddr_i), - .acc_qid_i (acc_qid_i), - .acc_qdata_op_i (acc_qdata_op_i), - .acc_qdata_arga_i(acc_qdata_arga_i), - .acc_qdata_argb_i(acc_qdata_argb_i), - .acc_qdata_argc_i(acc_qdata_argc_i), - .acc_qvalid_i (acc_qvalid_i), - .acc_qready_o (acc_qready_o), - .acc_pdata_o (acc_pdata_o), - .acc_pid_o (acc_pid_o), - .acc_perror_o (acc_perror_o), - .acc_pvalid_o (acc_pvalid_o), - .acc_pready_i (acc_pready_i) - ); - -endmodule : sdma_synth_wrapper