17 #ifndef __AXIMANAGERGATE_H__
18 #define __AXIMANAGERGATE_H__
21 #include <ac_reset_signal_is.h>
23 #include <mem_array.h>
25 #include <ReorderBuf.h>
26 #include <axi/AxiManagerGate/ReorderBufWBeats.h>
27 #include <nvhls_connections.h>
28 #include <nvhls_assert.h>
29 #include <axi/AxiManagerGate/AxiManagerGateIf.h>
59 template <
typename Cfg,
int ROBDepth = 8,
int MaxInFlightTrans = 4>
64 typedef NVUINTW(axi4_::DATA_WIDTH) Data;
72 static_assert(MaxInFlightTrans <= (1 << axi4_::ID_WIDTH) ,
"Number of inflight transactions cannot exceed number of unique IDs");
75 static const int kDebugLevel = 2;
76 typename axi4_::read::template manager<> if_rd;
77 typename axi4_::write::template manager<> if_wr;
79 sc_in<bool> reset_bar;
81 Connections::In<WrRequest<Cfg> > wrRequestIn;
82 Connections::Out<WrResp<Cfg> > wrRespOut;
83 Connections::In<RdRequest<Cfg> > rdRequestIn;
84 Connections::Out<RdResp<Cfg> > rdRespOut;
87 : if_rd(
"if_rd"), if_wr(
"if_wr"), reset_bar(
"reset_bar"), clk(
"clk") {
89 sensitive << clk.pos();
90 async_reset_signal_is(reset_bar,
false);
93 sensitive << clk.pos();
94 async_reset_signal_is(reset_bar,
false);
98 typedef sc_uint<axi4_::ID_WIDTH> Id;
108 bool addr_sent =
false;
110 bool wrRequestValid =
false;
112 bool wrRequestIdValid =
false;
113 bool isBurstInFlight =
false;
115 #pragma hls_pipeline_init_interval 1
116 #pragma pipeline_stall_mode flush
119 CDCOUT(
"@" << sc_time_stamp() <<
"\t wr_rob is empty? "
120 << wr_rob.isEmpty() << endl, kDebugLevel);
122 if (wr_rob.topResponseReady()) {
124 wrResp = wr_rob.popResponse();
126 CDCOUT(
"@" << sc_time_stamp()
127 <<
"\t\t Pop first response from rob and push it into host"
128 <<
"\tresp = " << wrResp.resp << endl, kDebugLevel);
130 wrRespOut.Push(wrResp);
132 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t Done pushing resp to host"
133 << endl, kDebugLevel);
137 bool wrRequestValid_local = wrRequestValid;
138 Id wrRequestId_local = wrRequestId;
139 bool wrRequestIdValid_local = wrRequestIdValid;
140 bool wrReqFifo_isFull = wrReqFifo.isFull();
143 if (!wrRequestValid_local && !wrReqFifo.isEmpty()) {
144 wrRequest_local = wrReqFifo.pop();
145 wrRequestValid_local =
true;
146 wrRequestIdValid_local =
false;
148 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t wr:pop wrReqFifo" << endl, kDebugLevel);
154 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t Receiving resp from subordinate"
155 << endl, kDebugLevel);
156 if (if_wr.b.PopNB(resp_pld)) {
158 wrResp.resp = resp_pld.resp;
160 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t wr:Post response to rob"
161 <<
"\tid = " << resp_pld.id <<
"\tresp = " << resp_pld.resp
162 << endl, kDebugLevel);
163 wr_rob.addResponse(
static_cast<sc_uint<axi4_::ID_WIDTH>
>(resp_pld.id), wrResp);
167 if (wrRequestValid_local) {
168 bool isBurstInFlight_local = isBurstInFlight;
169 wrRequestIdValid_local =
170 wrRequestIdValid_local || isBurstInFlight_local;
173 if (!wrRequestIdValid_local && wr_rob.canAcceptRequest()) {
174 wrRequestId_local = wr_rob.addRequest();
175 wrRequestIdValid_local =
true;
176 CDCOUT(
"@" << sc_time_stamp()
177 <<
"\t\t wr:new id allocated = " << wrRequestId_local << endl, kDebugLevel);
180 if (wrRequestIdValid_local) {
181 NVHLS_ASSERT_MSG(wrRequestValid_local,
"Should be impossible to reach this state");
183 bool addr_sent_local = addr_sent;
184 if (!addr_sent_local) {
187 wrRequest_local.copyToAddrPayload(addr_pld);
188 addr_pld.id =
static_cast<typename axi4_::Id
>(wrRequestId_local);
190 addr_sent_local = if_wr.aw.PushNB(addr_pld);
191 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t wr:sending addr pass? "
192 << addr_sent_local <<
"\taddr = " << wrRequest_local.addr
193 <<
"\tid = " << wrRequestId_local
194 <<
"\tlen = " << wrRequest_local.len
195 <<
"\tsize = " << wrRequest_local.size
196 <<
"\tburst = " << wrRequest_local.burst << endl, kDebugLevel);
200 write_pld.data = wrRequest_local.data;
201 write_pld.last = wrRequest_local.last;
202 write_pld.wstrb = ~0;
205 pushed = if_wr.w.PushNB(write_pld);
206 wrRequestValid_local = wrRequestValid_local && !pushed;
207 wrRequestIdValid_local = wrRequestIdValid_local && !pushed;
208 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t sending data pass? "
209 << !addr_sent_local <<
"\tdata = " << wrRequest_local.data
210 <<
"\tlast = " << wrRequest_local.last << endl, kDebugLevel);
211 isBurstInFlight_local = (wrRequest_local.last != 1);
215 bool sendWNext = isBurstInFlight_local || !pushed;
218 addr_sent_local = sendWNext;
220 addr_sent = addr_sent_local;
222 isBurstInFlight = isBurstInFlight_local;
225 wrRequest = wrRequest_local;
226 wrRequestValid = wrRequestValid_local;
227 wrRequestId = wrRequestId_local;
228 wrRequestIdValid = wrRequestIdValid_local;
230 if (!wrReqFifo_isFull) {
233 if (wrRequestIn.PopNB(wrRequest1)) {
234 wrReqFifo.push(wrRequest1);
236 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t wr:m got request!" << endl, kDebugLevel);
250 bool rdRequestValid =
false;
252 bool rdRequestIdValid =
false;
253 bool rdBurstInFlight =
false;
254 bool rdReceivingBurstBeats =
false;
256 #pragma hls_pipeline_init_interval 1
257 #pragma pipeline_stall_mode flush
261 CDCOUT(
"@" << sc_time_stamp() <<
"\t rd_rob is empty? "
262 << rd_rob.isEmpty() << endl, kDebugLevel);
264 if (rd_rob.topResponseReady()) {
266 rdResp = rd_rob.popResponse();
268 CDCOUT(
"@" << sc_time_stamp()
269 <<
"\t\t rd:Pop first response from rob and push it into host"
271 << endl, kDebugLevel);
273 rdRespOut.Push(rdResp);
275 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t rd:Done pushing resp to host"
276 << endl, kDebugLevel);
280 bool rdRequestValid_local = rdRequestValid;
281 Id rdRequestId_local = rdRequestId;
282 bool rdRequestIdValid_local = rdRequestIdValid;
283 bool rdReqFifo_isFull = rdReqFifo.isFull();
284 bool rdBurstInFlight_local = rdBurstInFlight;
286 if (!rdRequestValid_local && !rdReqFifo.isEmpty()) {
287 rdRequest_local = rdReqFifo.pop();
288 rdRequestValid_local =
true;
289 rdRequestIdValid_local =
false;
290 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t rd:pop rdReqFifo" << endl, kDebugLevel);
293 if (rdRequestValid_local) {
299 bool isBurst = (rdRequest_local.len != 0);
301 (isBurst ? rd_rob.isEmpty() : rd_rob.canAcceptRequest());
303 if (!rdRequestIdValid_local && robReady && !rdBurstInFlight_local) {
304 rdRequestId_local = rd_rob.addRequest();
305 rdRequestIdValid_local =
true;
306 rdBurstInFlight_local = isBurst;
307 CDCOUT(
"@" << sc_time_stamp()
308 <<
"\t\t rd:new id allocated = " << rdRequestId << endl, kDebugLevel);
311 if (rdRequestIdValid_local) {
313 rdRequest_local.copyToAddrPayload(addr_pld);
314 addr_pld.id =
static_cast<typename axi4_::Id
>(rdRequestId_local);
316 bool pushed = if_rd.ar.PushNB(addr_pld);
317 rdRequestValid_local = !pushed;
318 rdRequestIdValid_local = !pushed;
322 rdRequest = rdRequest_local;
323 rdRequestValid = rdRequestValid_local;
324 rdRequestId = rdRequestId_local;
325 rdRequestIdValid = rdRequestIdValid_local;
327 if (!rdReqFifo_isFull) {
330 if (rdRequestIn.PopNB(rdRequest1)) {
331 rdReqFifo.push(rdRequest1);
333 CDCOUT(
"@" << sc_time_stamp() <<
"\t\t rd:m got request ? "
334 << rdRequestValid << endl, kDebugLevel);
339 bool rdReceivingBurstBeats_local = rdReceivingBurstBeats;
345 if (!rdReceivingBurstBeats_local || rd_rob.canReceiveBeats()) {
346 if (if_rd.r.PopNB(data_pld)) {
348 rdResp.data = data_pld.data;
349 rdResp.resp = data_pld.resp;
350 rdResp.last = data_pld.last;
352 if (!rdReceivingBurstBeats_local) {
353 rd_rob.addResponse(
static_cast<sc_uint<axi4_::ID_WIDTH>
>(data_pld.id), rdResp);
355 rd_rob.addBeat(rdResp);
356 if (
static_cast<sc_uint<1>
>(data_pld.last) == 1) {
358 rdBurstInFlight_local =
false;
364 rdReceivingBurstBeats_local = rdBurstInFlight_local;
367 rdReceivingBurstBeats = rdReceivingBurstBeats_local;
369 rdBurstInFlight = rdBurstInFlight_local;
An AXI manager that converts from a simple request/response interface to AXI with reordering support.
Reorder Buffer that allows out-of-order writes to queue and in-order reads.
An extension of ReorderBuf that allows one entry to contain multiple beats of data.
The base axi4 class parameterized according a valid config.
#define NVHLS_ASSERT_MSG(X, MSG)
The struct for read requests for AxiManagerGate.
The struct for read responses for AxiManagerGate.
The struct for write requests for AxiManagerGate.
The struct for write responses for AxiManagerGate.
A struct composed of the signals associated with AXI read and write requests.
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.