16 #ifndef __AXI_ARBITER_H__
17 #define __AXI_ARBITER_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>
27 #include "TypeToBits.h"
57 template <
typename axiCfg,
int numManagers,
int maxOutstandingRequests>
60 static const int kDebugLevel = 5;
62 sc_in<bool> reset_bar;
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;
81 typename axi_::read::template manager<> axi_rd_s;
82 typename axi_::write::template manager<> axi_wr_s;
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;
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") {
107 sensitive << clk.pos();
108 async_reset_signal_is(reset_bar,
false);
111 sensitive << clk.pos();
112 async_reset_signal_is(reset_bar,
false);
115 sensitive << clk.pos();
116 async_reset_signal_is(reset_bar,
false);
119 sensitive << clk.pos();
120 async_reset_signal_is(reset_bar,
false);
123 sensitive << clk.pos();
124 async_reset_signal_is(reset_bar,
false);
128 #pragma hls_unroll yes
129 for (
int i = 0; i < numManagers; i++) {
130 axi_rd_m_ar[i].Reset();
133 read_in_flight.ResetWrite();
136 NVUINTW(numManagers) valid_mask = 0;
137 NVUINTW(numManagers) select_mask = 0;
140 #pragma hls_pipeline_init_interval 1
141 #pragma pipeline_stall_mode flush
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);
153 select_mask = arb.pick(valid_mask);
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]);
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);
171 #pragma hls_unroll yes
172 for (
int i = 0; i < numManagers; i++) {
173 axi_rd_m_r[i].Reset();
176 read_in_flight.ResetRead();
180 inFlight_t inFlight_reg;
181 inFlight_t inFlight_resp_reg;
183 bool read_inProgress = 0;
185 #pragma hls_pipeline_init_interval 1
186 #pragma pipeline_stall_mode flush
190 if (!readQ.isFull()) {
191 if (read_in_flight.PopNB(inFlight_reg)) {
192 readQ.push(inFlight_reg);
196 if (!read_inProgress) {
197 if (!readQ.isEmpty()) {
198 inFlight_resp_reg = readQ.pop();
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);
216 #pragma hls_unroll yes
217 for (
int i = 0; i < numManagers; i++) {
218 axi_wr_m_aw[i].Reset();
221 write_in_flight.ResetWrite();
222 active_write_manager.ResetWrite();
225 inFlight_t active_manager;
228 NVUINTW(numManagers) valid_mask = 0;
229 NVUINTW(numManagers) select_mask = 0;
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);
244 select_mask = arb.pick(valid_mask);
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) {
254 axi_wr_s.aw.Push(AW_reg[active_manager]);
255 active_write_manager.Push(active_manager);
256 write_in_flight.Push(active_manager);
258 #pragma hls_pipeline_init_interval 1
259 #pragma pipeline_stall_mode flush
260 while (w_last.Pop() ==
false) {
264 valid_mask = ~(~valid_mask | (1 << active_manager));
271 active_write_manager.ResetRead();
274 #pragma hls_unroll yes
275 for (
int i = 0; i < numManagers; i++) {
276 axi_wr_m_w[i].Reset();
282 inFlight_t active_manager = active_write_manager.Pop();
284 #pragma hls_pipeline_init_interval 1
285 #pragma pipeline_stall_mode flush
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);
295 #pragma hls_unroll yes
296 for (
int i = 0; i < numManagers; i++) {
297 axi_wr_m_b[i].Reset();
300 write_in_flight.ResetRead();
304 inFlight_t inFlight_reg;
305 inFlight_t inFlight_resp_reg;
306 bool write_inProgress = 0;
308 #pragma hls_pipeline_init_interval 1
309 #pragma pipeline_stall_mode flush
313 if (!writeQ.isFull()) {
314 if (write_in_flight.PopNB(inFlight_reg)) {
315 writeQ.push(inFlight_reg);
319 if (!write_inProgress) {
320 if (!writeQ.isEmpty()) {
321 inFlight_resp_reg = writeQ.pop();
322 write_inProgress = 1;
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;
331 write_inProgress = 0;
A generalized implementation of generic n-way roundrobin arbiter.
An n-way arbiter that connects multiple AXI manager ports to a single AXI subordinate port.
The base axi4 class parameterized according a valid config.
A struct composed of the signals associated with an AXI read response.
A struct composed of the signals associated with an AXI write response.
A struct composed of the signals associated with AXI write data.
Compute Celing of log2 of a constant.