Skip to content

Commit a68925b

Browse files
midend: Add RT midend (#24)
* Add first version of the real-time (RT) midend #24 --------- Co-authored-by: Alessandro Ottaviano <[email protected]>
1 parent 7ad44ec commit a68925b

File tree

7 files changed

+473
-0
lines changed

7 files changed

+473
-0
lines changed

Diff for: Bender.yml

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ sources:
5353
files:
5454
# Level 0
5555
- src/midend/idma_nd_midend.sv
56+
- src/midend/idma_rt_midend.sv
5657

5758
# Frontends (without inst64)
5859
- target: rtl
@@ -75,8 +76,10 @@ sources:
7576
# Level 0
7677
- src/frontend/desc64/idma_desc64_synth_pkg.sv
7778
- src/midend/idma_nd_midend_synth.sv
79+
- src/midend/idma_rt_midend_synth_pkg.sv
7880
# Level 1
7981
- src/frontend/desc64/idma_desc64_synth.sv
82+
- src/midend/idma_rt_midend_synth.sv
8083

8184
# Testbenches
8285
- target: test
@@ -89,6 +92,7 @@ sources:
8992
- test/future/TLToAXI4.v
9093
- test/future/tb_idma_improved_fifo.sv
9194
- test/midend/tb_idma_nd_midend.sv
95+
- test/midend/tb_idma_rt_midend.sv
9296
# Level 1
9397
- test/future/idma_obi2axi_bridge.sv
9498
- test/future/idma_tilelink2axi_bridge.sv

Diff for: idma.mk

+5
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ IDMA_RTL_DOC_ALL += $(IDMA_DOC_FIG_DIR)/graph/idma_desc64_synth.png
241241
IDMA_RTL_DOC_ALL += $(IDMA_HTML_DIR)/idma_desc64_synth/index.html
242242
IDMA_PICKLE_ALL += $(IDMA_PICKLE_DIR)/idma_desc64_synth.sv
243243

244+
# RT midend
245+
IDMA_RTL_DOC_ALL += $(IDMA_DOC_FIG_DIR)/graph/idma_rt_midend_synth.png
246+
IDMA_RTL_DOC_ALL += $(IDMA_HTML_DIR)/idma_rt_midend_synth/index.html
247+
IDMA_PICKLE_ALL += $(IDMA_PICKLE_DIR)/idma_rt_midend_synth.sv
248+
244249

245250
# --------------
246251
# QuestaSim

Diff for: jobs/jobs.json

+10
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,15 @@
151151
"proc_id" : "rw_axi",
152152
"testbench" : "tb_idma_desc64_bench",
153153
"synth_top" : "idma_desc64_synth"
154+
},
155+
"rt_midend": {
156+
"jobs" : {
157+
"simple" : "jobs.json"
158+
},
159+
"params" : {
160+
},
161+
"proc_id" : "rw_axi",
162+
"testbench" : "tb_idma_rt_midend",
163+
"synth_top" : "idma_rt_midend_synth"
154164
}
155165
}

Diff for: src/midend/idma_rt_midend.sv

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
// Copyright 2023 ETH Zurich and University of Bologna.
2+
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
// SPDX-License-Identifier: SHL-0.51
4+
5+
// Authors:
6+
// - Thomas Benz <[email protected]>
7+
8+
/// RT midend for the iDMA
9+
module idma_rt_midend #(
10+
/// Number of parallel events
11+
parameter int unsigned NumEvents = 32'd1,
12+
/// The width of the event counters (count multiple of clock period)
13+
parameter int unsigned EventCntWidth = 32'd32,
14+
/// Number of outstanding DMA events
15+
parameter int unsigned NumOutstanding = 32'd2,
16+
/// Address type
17+
parameter type addr_t = logic,
18+
/// ND iDMA request type
19+
parameter type idma_nd_req_t = logic,
20+
/// iDMA response type
21+
parameter type idma_rsp_t = logic,
22+
/// *DO NOT OVERWRITE*: Derived event counter type.
23+
parameter type event_cnt_t = logic [EventCntWidth-1:0]
24+
)(
25+
/// Clock
26+
input logic clk_i,
27+
/// Asynchronous reset, active low
28+
input logic rst_ni,
29+
/// The threshold an event is triggered
30+
input event_cnt_t [NumEvents-1:0] event_counts_i,
31+
/// The source address of the event
32+
input addr_t [NumEvents-1:0] src_addr_i,
33+
/// The destination address of the event
34+
input addr_t [NumEvents-1:0] dst_addr_i,
35+
/// The length of the event
36+
input addr_t [NumEvents-1:0] length_i,
37+
/// The source stride of the event
38+
input addr_t [NumEvents-1:0] src_1d_stride_i,
39+
/// The destination stride of the event
40+
input addr_t [NumEvents-1:0] dst_1d_stride_i,
41+
/// The number of repetitions of the event
42+
input addr_t [NumEvents-1:0] num_1d_reps_i,
43+
/// The source stride of the event
44+
input addr_t [NumEvents-1:0] src_2d_stride_i,
45+
/// The destination stride of the event
46+
input addr_t [NumEvents-1:0] dst_2d_stride_i,
47+
/// The number of repetitions of the event
48+
input addr_t [NumEvents-1:0] num_2d_reps_i,
49+
/// Enable the given event
50+
input logic [NumEvents-1:0] event_ena_i,
51+
/// Current state of the counters (debugging)
52+
output event_cnt_t [NumEvents-1:0] event_counts_o,
53+
/// ND iDMA request
54+
output idma_nd_req_t nd_req_o,
55+
/// ND iDMA request valid
56+
output logic nd_req_valid_o,
57+
/// ND iDMA request ready
58+
input logic nd_req_ready_i,
59+
/// iDMA 1D response
60+
input idma_rsp_t burst_rsp_i,
61+
/// iDMA 1D response valid
62+
input logic burst_rsp_valid_i,
63+
/// iDMA 1D response ready
64+
output logic burst_rsp_ready_o,
65+
/// Bypass: ND iDMA request
66+
input idma_nd_req_t nd_req_i,
67+
/// Bypass: ND iDMA request valid
68+
input logic nd_req_valid_i,
69+
/// Bypass: ND iDMA request ready
70+
output logic nd_req_ready_o,
71+
/// Bypass: iDMA 1D response
72+
output idma_rsp_t burst_rsp_o,
73+
/// Bypass: iDMA 1D response valid
74+
output logic burst_rsp_valid_o,
75+
/// Bypass: iDMA 1D response ready
76+
input logic burst_rsp_ready_i
77+
);
78+
79+
typedef struct packed {
80+
idma_nd_req_t req;
81+
logic src;
82+
} ext_arb_t;
83+
84+
// signals around the external arbiter
85+
ext_arb_t ext_req, int_req, out_req;
86+
87+
// the choice signal
88+
logic choice, choice_head;
89+
90+
// counter overflow -> event is valid
91+
logic [NumEvents-1:0] event_valid;
92+
93+
// handshake the event
94+
logic [NumEvents-1:0] event_ready;
95+
96+
// clear signal for the counter
97+
logic [NumEvents-1:0] cnt_load;
98+
99+
// enable signal for the counter
100+
logic [NumEvents-1:0] cnt_ena;
101+
102+
// each counter assembles the struct
103+
idma_nd_req_t [NumEvents-1:0] idma_nd_req;
104+
105+
// internal request and its handshake signals
106+
idma_nd_req_t idma_nd_req_int;
107+
logic nd_req_valid_int;
108+
logic nd_req_ready_int;
109+
110+
// internal response stub
111+
idma_rsp_t int_rsp;
112+
logic int_valid;
113+
114+
// generate the counters timing the events and assemble the transfers
115+
for (genvar c = 0; c < NumEvents; c++) begin : gen_counters
116+
// counter instance
117+
counter #(
118+
.WIDTH ( EventCntWidth ),
119+
.STICKY_OVERFLOW ( 1'b0 )
120+
) i_counter (
121+
.clk_i,
122+
.rst_ni,
123+
.clear_i ( 1'b0 ),
124+
.en_i ( cnt_ena [c] ),
125+
.load_i ( cnt_load [c] ),
126+
.down_i ( 1'b1 ),
127+
.d_i ( event_counts_i [c] ),
128+
.q_o ( event_counts_o [c] ),
129+
.overflow_o ( event_valid [c] )
130+
);
131+
132+
// n-d assignment
133+
assign idma_nd_req[c].d_req[0].reps = num_1d_reps_i [c];
134+
assign idma_nd_req[c].d_req[0].src_strides = src_1d_stride_i [c];
135+
assign idma_nd_req[c].d_req[0].dst_strides = dst_1d_stride_i [c];
136+
assign idma_nd_req[c].d_req[1].reps = num_1d_reps_i [c];
137+
assign idma_nd_req[c].d_req[1].src_strides = src_1d_stride_i [c];
138+
assign idma_nd_req[c].d_req[1].dst_strides = dst_1d_stride_i [c];
139+
140+
// 1D assignment
141+
assign idma_nd_req[c].burst_req.length = length_i [c];
142+
assign idma_nd_req[c].burst_req.src_addr = src_addr_i [c];
143+
assign idma_nd_req[c].burst_req.dst_addr = dst_addr_i [c];
144+
assign idma_nd_req[c].burst_req.opt = '0;
145+
146+
end
147+
148+
// clear on handshake
149+
assign cnt_load = event_ready & event_valid;
150+
151+
// disable counters if they are valid
152+
assign cnt_ena = event_ena_i & ~(event_valid);
153+
154+
// arbitrates the events
155+
stream_arbiter #(
156+
.DATA_T ( idma_nd_req_t ),
157+
.N_INP ( NumEvents ),
158+
.ARBITER ( "rr" )
159+
) i_stream_arbiter (
160+
.clk_i,
161+
.rst_ni,
162+
.inp_data_i ( idma_nd_req ),
163+
.inp_valid_i ( event_valid ),
164+
.inp_ready_o ( event_ready ),
165+
.oup_data_o ( idma_nd_req_int ),
166+
.oup_valid_o ( nd_req_valid_int ),
167+
.oup_ready_i ( nd_req_ready_int )
168+
);
169+
170+
// arbitrates the events
171+
stream_arbiter #(
172+
.DATA_T ( ext_arb_t ),
173+
.N_INP ( 32'd2 ),
174+
.ARBITER ( "rr" )
175+
) i_stream_arbiter_bypass (
176+
.clk_i,
177+
.rst_ni,
178+
.inp_data_i ( { ext_req, int_req } ),
179+
.inp_valid_i ( { nd_req_valid_i, nd_req_valid_int } ),
180+
.inp_ready_o ( { nd_req_ready_o, nd_req_ready_int } ),
181+
.oup_data_o ( out_req ),
182+
.oup_valid_o ( nd_req_valid_o ),
183+
.oup_ready_i ( nd_req_ready_i )
184+
);
185+
186+
// assemble arbiter inputs
187+
assign ext_req.req = nd_req_i;
188+
assign ext_req.src = 1'b1;
189+
190+
assign int_req.req = idma_nd_req_int;
191+
assign int_req.src = 1'b0;
192+
193+
// arbiters outputs
194+
assign nd_req_o = out_req.req;
195+
assign choice = out_req.src;
196+
197+
// safe the choice in a fifo
198+
stream_fifo #(
199+
.FALL_THROUGH ( 1'b0 ),
200+
.DATA_WIDTH ( 32'd1 ),
201+
.DEPTH ( NumOutstanding )
202+
) i_stream_fifo (
203+
.clk_i,
204+
.rst_ni,
205+
.flush_i ( 1'b0 ),
206+
.testmode_i ( 1'b0 ),
207+
.usage_o ( /* NC */ ),
208+
.data_i ( choice ),
209+
.valid_i ( nd_req_valid_i & nd_req_ready_o ),
210+
.ready_o ( /* HACK: NC */ ),
211+
.data_o ( choice_head ),
212+
.valid_o ( /* HACK: NC */ ),
213+
.ready_i ( burst_rsp_valid_o & burst_rsp_ready_i )
214+
);
215+
216+
// arbitration of responses
217+
stream_demux #(
218+
.N_OUP ( 32'd2 )
219+
) i_stream_demux (
220+
.inp_valid_i ( burst_rsp_valid_i ),
221+
.inp_ready_o ( burst_rsp_ready_o ),
222+
.oup_sel_i ( choice_head ),
223+
.oup_valid_o ( { burst_rsp_valid_o, int_valid } ),
224+
.oup_ready_i ( { burst_rsp_ready_i, 1'b1 } )
225+
);
226+
227+
assign burst_rsp_o = burst_rsp_i;
228+
229+
endmodule

0 commit comments

Comments
 (0)