diff --git a/Bender.yml b/Bender.yml index 7c8dbd29..47520609 100644 --- a/Bender.yml +++ b/Bender.yml @@ -53,6 +53,7 @@ sources: files: # Level 0 - src/midend/idma_nd_midend.sv + - src/midend/idma_rt_midend.sv # Frontends (without inst64) - target: rtl @@ -74,21 +75,24 @@ sources: files: # Level 0 - src/frontend/desc64/idma_desc64_synth_pkg.sv + - src/midend/idma_rt_midend_synth_pkg.sv - src/synth/idma_nd_backend_synth.sv # Level 1 - src/frontend/desc64/idma_desc64_synth.sv + - src/midend/idma_rt_midend_synth.sv # Testbenches - target: test files: # Level 0 - - test/tb_idma_improved_fifo.sv - test/tb_idma_nd_backend.sv - test/frontend/tb_idma_desc64_top.sv - test/frontend/tb_idma_desc64_bench.sv - test/future/idma_tb_per2axi.sv - test/future/idma_obi_asserter.sv - test/future/TLToAXI4.v + - test/future/tb_idma_improved_fifo.sv + - test/midend/tb_idma_rt_midend.sv # Level 1 - test/future/idma_obi2axi_bridge.sv - test/future/idma_tilelink2axi_bridge.sv diff --git a/jobs/jobs.json b/jobs/jobs.json index 4ad85c42..059a9751 100644 --- a/jobs/jobs.json +++ b/jobs/jobs.json @@ -151,5 +151,15 @@ "proc_id" : "rw_axi", "testbench" : "tb_idma_desc64_bench", "synth_top" : "idma_desc64_synth" + }, + "rt_midend": { + "jobs" : { + "simple" : "jobs.json" + }, + "params" : { + }, + "proc_id" : "rw_axi", + "testbench" : "tb_idma_rt_midend", + "synth_top" : "idma_rt_midend_synth" } } diff --git a/src/midend/idma_rt_midend.sv b/src/midend/idma_rt_midend.sv new file mode 100644 index 00000000..1ab81cc4 --- /dev/null +++ b/src/midend/idma_rt_midend.sv @@ -0,0 +1,229 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz + +/// RT midend for the iDMA +module idma_rt_midend #( + /// Number of parallel events + parameter int unsigned NumEvents = 32'd1, + /// The width of the event counters (count multiple of clock period) + parameter int unsigned EventCntWidth = 32'd32, + /// Number of outstanding DMA events + parameter int unsigned NumOutstanding = 32'd2, + /// Address type + parameter type addr_t = logic, + /// ND iDMA request type + parameter type idma_nd_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// *DO NOT OVERWRITE*: Derived event counter type. + parameter type event_cnt_t = logic [EventCntWidth-1:0] +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// The threshold an event is triggered + input event_cnt_t [NumEvents-1:0] event_counts_i, + /// The source address of the event + input addr_t [NumEvents-1:0] src_addr_i, + /// The destination address of the event + input addr_t [NumEvents-1:0] dst_addr_i, + /// The length of the event + input addr_t [NumEvents-1:0] length_i, + /// The source stride of the event + input addr_t [NumEvents-1:0] src_1d_stride_i, + /// The destination stride of the event + input addr_t [NumEvents-1:0] dst_1d_stride_i, + /// The number of repetitions of the event + input addr_t [NumEvents-1:0] num_1d_reps_i, + /// The source stride of the event + input addr_t [NumEvents-1:0] src_2d_stride_i, + /// The destination stride of the event + input addr_t [NumEvents-1:0] dst_2d_stride_i, + /// The number of repetitions of the event + input addr_t [NumEvents-1:0] num_2d_reps_i, + /// Enable the given event + input logic [NumEvents-1:0] event_ena_i, + /// Current state of the counters (debugging) + output event_cnt_t [NumEvents-1:0] event_counts_o, + /// ND iDMA request + output idma_nd_req_t nd_req_o, + /// ND iDMA request valid + output logic nd_req_valid_o, + /// ND iDMA request ready + input logic nd_req_ready_i, + /// iDMA 1D response + input idma_rsp_t burst_rsp_i, + /// iDMA 1D response valid + input logic burst_rsp_valid_i, + /// iDMA 1D response ready + output logic burst_rsp_ready_o, + /// Bypass: ND iDMA request + input idma_nd_req_t nd_req_i, + /// Bypass: ND iDMA request valid + input logic nd_req_valid_i, + /// Bypass: ND iDMA request ready + output logic nd_req_ready_o, + /// Bypass: iDMA 1D response + output idma_rsp_t burst_rsp_o, + /// Bypass: iDMA 1D response valid + output logic burst_rsp_valid_o, + /// Bypass: iDMA 1D response ready + input logic burst_rsp_ready_i +); + + typedef struct packed { + idma_nd_req_t req; + logic src; + } ext_arb_t; + + // signals around the external arbiter + ext_arb_t ext_req, int_req, out_req; + + // the choice signal + logic choice, choice_head; + + // counter overflow -> event is valid + logic [NumEvents-1:0] event_valid; + + // handshake the event + logic [NumEvents-1:0] event_ready; + + // clear signal for the counter + logic [NumEvents-1:0] cnt_load; + + // enable signal for the counter + logic [NumEvents-1:0] cnt_ena; + + // each counter assembles the struct + idma_nd_req_t [NumEvents-1:0] idma_nd_req; + + // internal request and its handshake signals + idma_nd_req_t idma_nd_req_int; + logic nd_req_valid_int; + logic nd_req_ready_int; + + // internal response stub + idma_rsp_t int_rsp; + logic int_valid; + + // generate the counters timing the events and assemble the transfers + for (genvar c = 0; c < NumEvents; c++) begin : gen_counters + // counter instance + counter #( + .WIDTH ( EventCntWidth ), + .STICKY_OVERFLOW ( 1'b0 ) + ) i_counter ( + .clk_i, + .rst_ni, + .clear_i ( 1'b0 ), + .en_i ( cnt_ena [c] ), + .load_i ( cnt_load [c] ), + .down_i ( 1'b1 ), + .d_i ( event_counts_i [c] ), + .q_o ( event_counts_o [c] ), + .overflow_o ( event_valid [c] ) + ); + + // n-d assignment + assign idma_nd_req[c].d_req[0].reps = num_1d_reps_i [c]; + assign idma_nd_req[c].d_req[0].src_strides = src_1d_stride_i [c]; + assign idma_nd_req[c].d_req[0].dst_strides = dst_1d_stride_i [c]; + assign idma_nd_req[c].d_req[1].reps = num_1d_reps_i [c]; + assign idma_nd_req[c].d_req[1].src_strides = src_1d_stride_i [c]; + assign idma_nd_req[c].d_req[1].dst_strides = dst_1d_stride_i [c]; + + // 1D assignment + assign idma_nd_req[c].burst_req.length = length_i [c]; + assign idma_nd_req[c].burst_req.src_addr = src_addr_i [c]; + assign idma_nd_req[c].burst_req.dst_addr = dst_addr_i [c]; + assign idma_nd_req[c].burst_req.opt = '0; + + end + + // clear on handshake + assign cnt_load = event_ready & event_valid; + + // disable counters if they are valid + assign cnt_ena = event_ena_i & ~(event_valid); + + // arbitrates the events + stream_arbiter #( + .DATA_T ( idma_nd_req_t ), + .N_INP ( NumEvents ), + .ARBITER ( "rr" ) + ) i_stream_arbiter ( + .clk_i, + .rst_ni, + .inp_data_i ( idma_nd_req ), + .inp_valid_i ( event_valid ), + .inp_ready_o ( event_ready ), + .oup_data_o ( idma_nd_req_int ), + .oup_valid_o ( nd_req_valid_int ), + .oup_ready_i ( nd_req_ready_int ) + ); + + // arbitrates the events + stream_arbiter #( + .DATA_T ( ext_arb_t ), + .N_INP ( 32'd2 ), + .ARBITER ( "rr" ) + ) i_stream_arbiter_bypass ( + .clk_i, + .rst_ni, + .inp_data_i ( { ext_req, int_req } ), + .inp_valid_i ( { nd_req_valid_i, nd_req_valid_int } ), + .inp_ready_o ( { nd_req_ready_o, nd_req_ready_int } ), + .oup_data_o ( out_req ), + .oup_valid_o ( nd_req_valid_o ), + .oup_ready_i ( nd_req_ready_i ) + ); + + // assemble arbiter inputs + assign ext_req.req = nd_req_i; + assign ext_req.src = 1'b1; + + assign int_req.req = idma_nd_req_int; + assign int_req.src = 1'b0; + + // arbiters outputs + assign nd_req_o = out_req.req; + assign choice = out_req.src; + + // safe the choice in a fifo + stream_fifo #( + .FALL_THROUGH ( 1'b0 ), + .DATA_WIDTH ( 32'd1 ), + .DEPTH ( NumOutstanding ) + ) i_stream_fifo ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( 1'b0 ), + .usage_o ( /* NC */ ), + .data_i ( choice ), + .valid_i ( nd_req_valid_i & nd_req_ready_o ), + .ready_o ( /* HACK: NC */ ), + .data_o ( choice_head ), + .valid_o ( /* HACK: NC */ ), + .ready_i ( burst_rsp_valid_o & burst_rsp_ready_i ) + ); + + // arbitration of responses + stream_demux #( + .N_OUP ( 32'd2 ) + ) i_stream_demux ( + .inp_valid_i ( burst_rsp_valid_i ), + .inp_ready_o ( burst_rsp_ready_o ), + .oup_sel_i ( choice_head ), + .oup_valid_o ( { burst_rsp_valid_o, int_valid } ), + .oup_ready_i ( { burst_rsp_ready_i, 1'b1 } ) + ); + + assign burst_rsp_o = burst_rsp_i; + +endmodule diff --git a/src/midend/idma_rt_midend_synth.sv b/src/midend/idma_rt_midend_synth.sv new file mode 100644 index 00000000..3ce20ddb --- /dev/null +++ b/src/midend/idma_rt_midend_synth.sv @@ -0,0 +1,115 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz + +/// Synth wrapper for the RT midend for the iDMA +module idma_rt_midend_synth #( + /// Number of parallel events + parameter int unsigned NumEvents = 32'd1, + /// The width of the event counters (count multiple of clock period) + parameter int unsigned EventCntWidth = 32'd32, + /// Number of outstanding DMA events + parameter int unsigned NumOutstanding = 32'd2, + /// Address type + parameter type addr_t = idma_rt_midend_synth_pkg::axi_addr_t, + /// ND iDMA request type + parameter type idma_nd_req_t = idma_rt_midend_synth_pkg::idma_ned_req_t, + /// iDMA response type + parameter type idma_rsp_t = idma_rt_midend_synth_pkg::idma_rsp_t, + /// *DO NOT OVERWRITE*: Derived event counter type. + parameter type event_cnt_t = logic [EventCntWidth-1:0] +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// The threshold an event is triggered + input event_cnt_t [NumEvents-1:0] event_counts_i, + /// The source address of the event + input addr_t [NumEvents-1:0] src_addr_i, + /// The destination address of the event + input addr_t [NumEvents-1:0] dst_addr_i, + /// The length of the event + input addr_t [NumEvents-1:0] length_i, + /// The source stride of the event + input addr_t [NumEvents-1:0] src_1d_stride_i, + /// The destination stride of the event + input addr_t [NumEvents-1:0] dst_1d_stride_i, + /// The number of repetitions of the event + input addr_t [NumEvents-1:0] num_1d_reps_i, + /// The source stride of the event + input addr_t [NumEvents-1:0] src_2d_stride_i, + /// The destination stride of the event + input addr_t [NumEvents-1:0] dst_2d_stride_i, + /// The number of repetitions of the event + input addr_t [NumEvents-1:0] num_2d_reps_i, + /// Enable the given event + input logic [NumEvents-1:0] event_ena_i, + /// Current state of the counters (debugging) + output event_cnt_t [NumEvents-1:0] event_counts_o, + /// ND iDMA request + output idma_nd_req_t nd_req_o, + /// ND iDMA request valid + output logic nd_req_valid_o, + /// ND iDMA request ready + input logic nd_req_ready_i, + /// iDMA 1D response + input idma_rsp_t burst_rsp_i, + /// iDMA 1D response valid + input logic burst_rsp_valid_i, + /// iDMA 1D response ready + output logic burst_rsp_ready_o, + /// Bypass: ND iDMA request + input idma_nd_req_t nd_req_i, + /// Bypass: ND iDMA request valid + input logic nd_req_valid_i, + /// Bypass: ND iDMA request ready + output logic nd_req_ready_o, + /// Bypass: iDMA 1D response + output idma_rsp_t burst_rsp_o, + /// Bypass: iDMA 1D response valid + output logic burst_rsp_valid_o, + /// Bypass: iDMA 1D response ready + input logic burst_rsp_ready_i +); + + idma_rt_midend #( + .NumEvents ( NumEvents ), + .EventCntWidth ( EventCntWidth ), + .NumOutstanding ( NumOutstanding ), + .addr_t ( addr_t ), + .idma_nd_req_t ( idma_nd_req_t ), + .idma_rsp_t ( idma_rsp_t ) + ) i_idma_rt_midend ( + .clk_i, + .rst_ni, + .event_counts_i, + .src_addr_i, + .dst_addr_i, + .length_i, + .src_1d_stride_i, + .dst_1d_stride_i, + .num_1d_reps_i, + .src_2d_stride_i, + .dst_2d_stride_i, + .num_2d_reps_i, + .event_ena_i, + .event_counts_o, + .nd_req_o, + .nd_req_valid_o, + .nd_req_ready_i, + .burst_rsp_i, + .burst_rsp_valid_i, + .burst_rsp_ready_o, + .nd_req_i, + .nd_req_valid_i, + .nd_req_ready_o, + .burst_rsp_o, + .burst_rsp_valid_o, + .burst_rsp_ready_i + ); + +endmodule diff --git a/src/midend/idma_rt_midend_synth_pkg.sv b/src/midend/idma_rt_midend_synth_pkg.sv new file mode 100644 index 00000000..a8fcba90 --- /dev/null +++ b/src/midend/idma_rt_midend_synth_pkg.sv @@ -0,0 +1,25 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz + +`include "idma/typedef.svh" + +/// Synthesis package for the RT midend +package idma_rt_midend_synth_pkg; + + localparam int unsigned NumDim = 3; + + typedef logic [5:0] axi_id_t; + typedef logic [31:0] tf_len_t; + typedef logic [31:0] axi_addr_t; + typedef logic [31:0] reps_t; + typedef logic [31:0] strides_t; + + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, axi_addr_t) + `IDMA_TYPEDEF_FULL_ND_REQ_T(idma_nd_req_t, idma_req_t, reps_t, strides_t) + +endpackage diff --git a/test/frontend/tb_idma_desc64_bench.sv b/test/frontend/tb_idma_desc64_bench.sv index 8283d3be..370395df 100644 --- a/test/frontend/tb_idma_desc64_bench.sv +++ b/test/frontend/tb_idma_desc64_bench.sv @@ -1,8 +1,9 @@ -// Copyright 2022 ETH Zurich and University of Bologna. +// Copyright 2023 ETH Zurich and University of Bologna. // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 -// Axel Vanoni +// Authors: +// - Axel Vanoni `include "register_interface/typedef.svh" `include "register_interface/assign.svh" diff --git a/test/frontend/tb_idma_desc64_top.sv b/test/frontend/tb_idma_desc64_top.sv index 9391b0d4..f1c0f907 100644 --- a/test/frontend/tb_idma_desc64_top.sv +++ b/test/frontend/tb_idma_desc64_top.sv @@ -1,8 +1,9 @@ -// Copyright 2022 ETH Zurich and University of Bologna. +// Copyright 2023 ETH Zurich and University of Bologna. // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 -// Axel Vanoni +// Authors: +// - Axel Vanoni `include "register_interface/typedef.svh" `include "register_interface/assign.svh" diff --git a/test/tb_idma_improved_fifo.sv b/test/future/tb_idma_improved_fifo.sv similarity index 100% rename from test/tb_idma_improved_fifo.sv rename to test/future/tb_idma_improved_fifo.sv diff --git a/test/midend/tb_idma_rt_midend.sv b/test/midend/tb_idma_rt_midend.sv new file mode 100644 index 00000000..93337f5f --- /dev/null +++ b/test/midend/tb_idma_rt_midend.sv @@ -0,0 +1,85 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz + +`include "idma/typedef.svh" + +/// Sanity testbench for the RT midend +module tb_idma_rt_midend; + + logic clk; + logic rst_n; + + localparam int unsigned NumEvents = 5; + localparam int unsigned NumDim = 3; + + typedef logic [5:0] axi_id_t; + typedef logic [31:0] tf_len_t; + typedef logic [31:0] axi_addr_t; + typedef logic [31:0] reps_t; + typedef logic [31:0] strides_t; + + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, axi_addr_t) + `IDMA_TYPEDEF_FULL_ND_REQ_T(idma_nd_req_t, idma_req_t, reps_t, strides_t) + + tf_len_t [NumEvents-1:0] event_counts = '0; + logic [NumEvents-1:0] event_ena = '0; + + clk_rst_gen #( + .ClkPeriod ( 1ns ), + .RstClkCycles ( 1 ) + ) i_clk_rst_gen ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + // DUT + idma_rt_midend #( + .NumEvents ( NumEvents ), + .EventCntWidth ( tf_len_t ), + .NumOutstanding ( 32'd2 ), + .addr_t ( axi_addr_t ), + .idma_nd_req_t ( idma_nd_req_t ), + .idma_rsp_t ( idma_rsp_t ) + ) i_idma_rt_midend ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .event_counts_i ( event_counts ), + .src_addr_i ( '0 ), + .dst_addr_i ( '0 ), + .length_i ( {32'd1, 32'd2, 32'd3, 32'd4, 32'd5} ), + .src_1d_stride_i ( '0 ), + .dst_1d_stride_i ( '0 ), + .num_1d_reps_i ( '0 ), + .src_2d_stride_i ( '0 ), + .dst_2d_stride_i ( '0 ), + .num_2d_reps_i ( '0 ), + .event_ena_i ( event_ena ), + .event_counts_o (), + .nd_req_o (), + .nd_req_valid_o (), + .nd_req_ready_i ( 1'b1 ), + .burst_rsp_i ( '1 ), + .burst_rsp_valid_i ( 1'b1 ), + .burst_rsp_ready_o (), + .nd_req_i ( '1 ), + .nd_req_ready_o (), + .nd_req_valid_i ( 1'b0 ), + .burst_rsp_o ( ), + .burst_rsp_valid_o ( ), + .burst_rsp_ready_i ( 1'b1 ) + ); + + initial begin + event_counts = {32'd17, 32'd300, 32'd800, 32'd1000, 32'd2000}; + #10ns; + event_ena = {1'd1, 1'd1, 1'd1, 1'd1, 1'd1}; + #5000ns; + $finish(); + end + +endmodule