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 numMasters,
int maxOutstandingRequests>
60 static const int kDebugLevel = 5;
62 sc_in<bool> reset_bar;
67 typedef typename axi_::read::template slave<>::ARPort axi_rd_slave_ar;
68 typedef typename axi_::read::template slave<>::RPort axi_rd_slave_r;
69 typedef typename axi_::write::template slave<>::AWPort axi_wr_slave_aw;
70 typedef typename axi_::write::template slave<>::WPort axi_wr_slave_w;
71 typedef typename axi_::write::template slave<>::BPort axi_wr_slave_b;
81 typename axi_::read::template master<> axi_rd_s;
82 typename axi_::write::template master<> axi_wr_s;
84 typedef NVUINTW(numMasters_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_master;
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 < numMasters; i++) {
130 axi_rd_m_ar[i].Reset();
133 read_in_flight.ResetWrite();
136 NVUINTW(numMasters) valid_mask = 0;
137 NVUINTW(numMasters) select_mask = 0;
140 #pragma hls_pipeline_init_interval 1 141 #pragma pipeline_stall_mode flush 145 for (
int i = 0; i < numMasters; 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 < numMasters; 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 < numMasters; 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 < numMasters; i++) {
218 axi_wr_m_aw[i].Reset();
221 write_in_flight.ResetWrite();
222 active_write_master.ResetWrite();
225 inFlight_t active_master;
228 NVUINTW(numMasters) valid_mask = 0;
229 NVUINTW(numMasters) select_mask = 0;
235 #pragma hls_unroll yes 236 for (
int i = 0; i < numMasters; 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 < numMasters; i++) {
249 if (nvhls::get_slc<1>(select_mask, i) == 1) {
254 axi_wr_s.aw.Push(AW_reg[active_master]);
255 active_write_master.Push(active_master);
256 write_in_flight.Push(active_master);
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_master));
271 active_write_master.ResetRead();
274 #pragma hls_unroll yes 275 for (
int i = 0; i < numMasters; i++) {
276 axi_wr_m_w[i].Reset();
282 inFlight_t active_master = active_write_master.Pop();
284 #pragma hls_pipeline_init_interval 1 285 #pragma pipeline_stall_mode flush 287 W_reg = axi_wr_m_w[active_master].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 < numMasters; 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 struct composed of the signals associated with an AXI write response.
A struct composed of the signals associated with AXI write data.
A struct composed of the signals associated with an AXI read response.
The base axi4 class parameterized according a valid config.
An n-way arbiter that connects multiple AXI master ports to a single AXI slave port.
Compute Celing of log2 of a constant.
A generalized implementation of generic n-way roundrobin arbiter.