MatchLib
All Classes Namespaces Files Functions Modules Pages
AxiArbiter.h
1/*
2 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef __AXI_ARBITER_H__
17#define __AXI_ARBITER_H__
18
19#include <systemc.h>
20#include <nvhls_connections.h>
21#include <nvhls_serdes.h>
22#include <nvhls_packet.h>
23#include <nvhls_int.h>
24#include <nvhls_array.h>
25#include <axi/axi4.h>
26#include "Arbiter.h"
27#include "TypeToBits.h"
28
57template <typename axiCfg, int numManagers, int maxOutstandingRequests>
58class AxiArbiter : public sc_module {
59 public:
60 static const int kDebugLevel = 5;
61 sc_in<bool> clk;
62 sc_in<bool> reset_bar;
63
64 typedef typename axi::axi4<axiCfg> axi_;
65 static const int numManagers_width = nvhls::log2_ceil<numManagers>::val;
66
67 typedef typename axi_::read::template subordinate<>::ARPort axi_rd_subordinate_ar;
68 typedef typename axi_::read::template subordinate<>::RPort axi_rd_subordinate_r;
69 typedef typename axi_::write::template subordinate<>::AWPort axi_wr_subordinate_aw;
70 typedef typename axi_::write::template subordinate<>::WPort axi_wr_subordinate_w;
71 typedef typename axi_::write::template subordinate<>::BPort axi_wr_subordinate_b;
72
73 // [ben] Unfortunately HLS cannot handle an nv_array of the manager/subordinate wrapper classes.
74 // It will work fine in C but die mysteriously in Catapult 10.1b when methods of the
75 // bundled connections are accessed.
81 typename axi_::read::template manager<> axi_rd_s;
82 typename axi_::write::template manager<> axi_wr_s;
83
84 typedef NVUINTW(numManagers_width) inFlight_t;
86 Connections::Combinational<inFlight_t> read_in_flight;
88 Connections::Combinational<inFlight_t> write_in_flight;
89 Connections::Combinational<inFlight_t> active_write_manager;
90 Connections::Combinational<NVUINT1> w_last; // true iff w item last bit is set
91
92 SC_HAS_PROCESS(AxiArbiter);
93
94 AxiArbiter(sc_module_name name)
95 : sc_module(name),
96 clk("clk"),
97 reset_bar("reset_bar"),
98 axi_rd_m_ar("axi_rd_m_ar"),
99 axi_rd_m_r("axi_rd_m_r"),
100 axi_wr_m_aw("axi_wr_m_aw"),
101 axi_wr_m_w("axi_wr_m_w"),
102 axi_wr_m_b("axi_wr_m_b"),
103 axi_rd_s("axi_rd_s"),
104 axi_wr_s("axi_wr_s") {
105
106 SC_THREAD(run_ar);
107 sensitive << clk.pos();
108 async_reset_signal_is(reset_bar, false);
109
110 SC_THREAD(run_r);
111 sensitive << clk.pos();
112 async_reset_signal_is(reset_bar, false);
113
114 SC_THREAD(run_w);
115 sensitive << clk.pos();
116 async_reset_signal_is(reset_bar, false);
117
118 SC_THREAD(run_aw);
119 sensitive << clk.pos();
120 async_reset_signal_is(reset_bar, false);
121
122 SC_THREAD(run_b);
123 sensitive << clk.pos();
124 async_reset_signal_is(reset_bar, false);
125 }
126
127 void run_ar() {
128 #pragma hls_unroll yes
129 for (int i = 0; i < numManagers; i++) {
130 axi_rd_m_ar[i].Reset();
131 }
132 axi_rd_s.ar.Reset();
133 read_in_flight.ResetWrite();
134
136 NVUINTW(numManagers) valid_mask = 0;
137 NVUINTW(numManagers) select_mask = 0;
139
140 #pragma hls_pipeline_init_interval 1
141 #pragma pipeline_stall_mode flush
142 while (1) {
143 wait();
144
145 for (int i = 0; i < numManagers; i++) {
146 if (nvhls::get_slc<1>(valid_mask, i) == 0) {
147 if (axi_rd_m_ar[i].PopNB(AR_reg[i])) {
148 valid_mask = valid_mask | (1 << i);
149 }
150 }
151 }
152
153 select_mask = arb.pick(valid_mask);
154
155 for (int i = 0; i < numManagers; i++) {
156 if (nvhls::get_slc<1>(select_mask, i) == 1) {
157 axi_rd_s.ar.Push(AR_reg[i]);
158 select_mask = 0;
159 valid_mask = ~(~valid_mask | (1 << i));
160 CDCOUT(sc_time_stamp() << " " << name() << " Pushed read request:"
161 << " from_port=" << i
162 << " request=[" << AR_reg[i] << "]"
163 << endl, kDebugLevel);
164 read_in_flight.Push(i);
165 }
166 }
167 }
168 }
169
170 void run_r() {
171 #pragma hls_unroll yes
172 for (int i = 0; i < numManagers; i++) {
173 axi_rd_m_r[i].Reset();
174 }
175 axi_rd_s.r.Reset();
176 read_in_flight.ResetRead();
177 readQ.reset();
178
179 typename axi_::ReadPayload R_reg;
180 inFlight_t inFlight_reg;
181 inFlight_t inFlight_resp_reg;
182
183 bool read_inProgress = 0;
184
185 #pragma hls_pipeline_init_interval 1
186 #pragma pipeline_stall_mode flush
187 while (1) {
188 wait();
189
190 if (!readQ.isFull()) {
191 if (read_in_flight.PopNB(inFlight_reg)) {
192 readQ.push(inFlight_reg);
193 }
194 }
195
196 if (!read_inProgress) {
197 if (!readQ.isEmpty()) {
198 inFlight_resp_reg = readQ.pop();
199 read_inProgress = 1;
200 }
201 } else {
202 if (axi_rd_s.r.PopNB(R_reg)) {
203 axi_rd_m_r[inFlight_resp_reg].Push(R_reg);
204 CDCOUT(sc_time_stamp() << " " << name() << " Pushed read response:"
205 << " to_port=" << inFlight_resp_reg
206 << " response=[" << R_reg << "]"
207 << endl, kDebugLevel);
208 if (R_reg.last == 1)
209 read_inProgress = 0;
210 }
211 }
212 }
213 }
214
215 void run_aw() {
216 #pragma hls_unroll yes
217 for (int i = 0; i < numManagers; i++) {
218 axi_wr_m_aw[i].Reset();
219 }
220 axi_wr_s.aw.Reset();
221 write_in_flight.ResetWrite();
222 active_write_manager.ResetWrite();
223 w_last.ResetRead();
224
225 inFlight_t active_manager;
226
228 NVUINTW(numManagers) valid_mask = 0;
229 NVUINTW(numManagers) select_mask = 0;
231
232 while (1) {
233 wait();
234
235 #pragma hls_unroll yes
236 for (int i = 0; i < numManagers; i++) {
237 if (nvhls::get_slc<1>(valid_mask, i) == 0) {
238 if (axi_wr_m_aw[i].PopNB(AW_reg[i])) {
239 valid_mask = valid_mask | (1 << i);
240 }
241 }
242 }
243
244 select_mask = arb.pick(valid_mask);
245
246 if (select_mask != 0) {
247 #pragma hls_unroll yes
248 for (int i = 0; i < numManagers; i++) {
249 if (nvhls::get_slc<1>(select_mask, i) == 1) {
250 active_manager = i;
251 }
252 }
253
254 axi_wr_s.aw.Push(AW_reg[active_manager]);
255 active_write_manager.Push(active_manager);
256 write_in_flight.Push(active_manager);
257
258 #pragma hls_pipeline_init_interval 1
259 #pragma pipeline_stall_mode flush
260 while (w_last.Pop() == false) {
261 }
262
263 select_mask = 0;
264 valid_mask = ~(~valid_mask | (1 << active_manager));
265 }
266 }
267 }
268
269 void run_w() {
270 typename axi_::WritePayload W_reg;
271 active_write_manager.ResetRead();
272 w_last.ResetWrite();
273 axi_wr_s.w.Reset();
274 #pragma hls_unroll yes
275 for (int i = 0; i < numManagers; i++) {
276 axi_wr_m_w[i].Reset();
277 }
278
279 wait();
280
281 while (1) {
282 inFlight_t active_manager = active_write_manager.Pop();
283
284 #pragma hls_pipeline_init_interval 1
285 #pragma pipeline_stall_mode flush
286 do {
287 W_reg = axi_wr_m_w[active_manager].Pop();
288 axi_wr_s.w.Push(W_reg);
289 w_last.Push(W_reg.last.to_uint64());
290 } while (W_reg.last != 1);
291 }
292 }
293
294 void run_b() {
295 #pragma hls_unroll yes
296 for (int i = 0; i < numManagers; i++) {
297 axi_wr_m_b[i].Reset();
298 }
299 axi_wr_s.b.Reset();
300 write_in_flight.ResetRead();
301 writeQ.reset();
302
303 typename axi_::WRespPayload B_reg;
304 inFlight_t inFlight_reg;
305 inFlight_t inFlight_resp_reg;
306 bool write_inProgress = 0;
307
308 #pragma hls_pipeline_init_interval 1
309 #pragma pipeline_stall_mode flush
310 while (1) {
311 wait();
312
313 if (!writeQ.isFull()) {
314 if (write_in_flight.PopNB(inFlight_reg)) {
315 writeQ.push(inFlight_reg);
316 }
317 }
318
319 if (!write_inProgress) {
320 if (!writeQ.isEmpty()) {
321 inFlight_resp_reg = writeQ.pop();
322 write_inProgress = 1;
323 }
324 } else {
325 if (axiCfg::useWriteResponses) {
326 if (axi_wr_s.b.PopNB(B_reg)) {
327 axi_wr_m_b[inFlight_resp_reg].Push(B_reg);
328 write_inProgress = 0;
329 }
330 } else {
331 write_inProgress = 0;
332 }
333 }
334 }
335 }
336};
337
338#endif
A generalized implementation of generic n-way roundrobin arbiter.
Definition Arbiter.h:61
An n-way arbiter that connects multiple AXI manager ports to a single AXI subordinate port.
Definition AxiArbiter.h:58
Configurable FIFO class.
Definition fifo.h:65
The base axi4 class parameterized according a valid config.
Definition axi4.h:64
An implementation of array that declares VectorLength variables for array of size VectorLength.
#define CDCOUT(x, y)
Definition hls_globals.h:73
#define NVUINTW(width)
Definition nvhls_types.h:35
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition nvhls_int.h:437
A struct composed of the signals associated with an AXI read response.
Definition axi4.h:157
A struct composed of the signals associated with an AXI write response.
Definition axi4.h:190
A struct composed of the signals associated with AXI write data.
Definition axi4.h:215
Compute Celing of log2 of a constant.
Definition nvhls_int.h:174