17 #ifndef __AXIMASTERGATE_H__ 18 #define __AXIMASTERGATE_H__ 21 #include <ac_reset_signal_is.h> 23 #include <mem_array.h> 25 #include <ReorderBuf.h> 26 #include <axi/AxiMasterGate/ReorderBufWBeats.h> 27 #include <nvhls_connections.h> 28 #include <nvhls_assert.h> 29 #include <axi/AxiMasterGate/AxiMasterGateIf.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 typename axi4_::read::template master<> if_rd;
76 typename axi4_::write::template master<> if_wr;
78 sc_in<bool> reset_bar;
80 Connections::In<WrRequest<Cfg> > wrRequestIn;
81 Connections::Out<WrResp<Cfg> > wrRespOut;
82 Connections::In<RdRequest<Cfg> > rdRequestIn;
83 Connections::Out<RdResp<Cfg> > rdRespOut;
86 : if_rd(
"if_rd"), if_wr(
"if_wr"), reset_bar(
"reset_bar"), clk(
"clk") {
88 sensitive << clk.pos();
89 async_reset_signal_is(reset_bar,
false);
92 sensitive << clk.pos();
93 async_reset_signal_is(reset_bar,
false);
97 typedef sc_uint<axi4_::ID_WIDTH> Id;
107 bool addr_sent =
false;
109 bool wrRequestValid =
false;
111 bool wrRequestIdValid =
false;
112 bool isBurstInFlight =
false;
114 #pragma hls_pipeline_init_interval 1 115 #pragma pipeline_stall_mode flush 119 cout <<
"@" << sc_time_stamp() <<
"\t wr_rob is empty? " 120 << wr_rob.isEmpty() << endl;
123 if (wr_rob.topResponseReady()) {
125 wrResp = wr_rob.popResponse();
128 cout <<
"@" << sc_time_stamp()
129 <<
"\t\t Pop first response from rob and push it into host" 130 <<
"\tresp = " << wrResp.resp << endl;
133 wrRespOut.Push(wrResp);
136 cout <<
"@" << sc_time_stamp() <<
"\t\t Done pushing resp to host" 142 bool wrRequestValid_local = wrRequestValid;
143 Id wrRequestId_local = wrRequestId;
144 bool wrRequestIdValid_local = wrRequestIdValid;
145 bool wrReqFifo_isFull = wrReqFifo.isFull();
148 if (!wrRequestValid_local && !wrReqFifo.isEmpty()) {
149 wrRequest_local = wrReqFifo.pop();
150 wrRequestValid_local =
true;
151 wrRequestIdValid_local =
false;
154 cout <<
"@" << sc_time_stamp() <<
"\t\t wr:pop wrReqFifo" << endl;
162 cout <<
"@" << sc_time_stamp() <<
"\t\t Receiving resp from slave" 165 if (if_wr.b.PopNB(resp_pld)) {
167 wrResp.resp = resp_pld.resp;
170 cout <<
"@" << sc_time_stamp() <<
"\t\t wr:Post response to rob" 171 <<
"\tid = " << resp_pld.id <<
"\tresp = " << resp_pld.resp
174 wr_rob.addResponse(
static_cast<sc_uint<axi4_::ID_WIDTH>
>(resp_pld.id), wrResp);
178 if (wrRequestValid_local) {
179 bool isBurstInFlight_local = isBurstInFlight;
180 wrRequestIdValid_local =
181 wrRequestIdValid_local || isBurstInFlight_local;
184 if (!wrRequestIdValid_local && wr_rob.canAcceptRequest()) {
185 wrRequestId_local = wr_rob.addRequest();
186 wrRequestIdValid_local =
true;
188 cout <<
"@" << sc_time_stamp()
189 <<
"\t\t wr:new id allocated = " << wrRequestId_local << endl;
193 if (wrRequestIdValid_local) {
194 NVHLS_ASSERT_MSG(wrRequestValid_local,
"Should be impossible to reach this state");
196 bool addr_sent_local = addr_sent;
197 if (!addr_sent_local) {
200 wrRequest_local.copyToAddrPayload(addr_pld);
201 addr_pld.id =
static_cast<typename axi4_::Id
>(wrRequestId_local);
203 addr_sent_local = if_wr.aw.PushNB(addr_pld);
205 cout <<
"@" << sc_time_stamp() <<
"\t\t wr:sending addr pass? " 206 << addr_sent_local <<
"\taddr = " << wrRequest_local.addr
207 <<
"\tid = " << wrRequestId_local
208 <<
"\tlen = " << wrRequest_local.len
209 <<
"\tsize = " << wrRequest_local.size
210 <<
"\tburst = " << wrRequest_local.burst << endl;
215 write_pld.data = wrRequest_local.data;
216 write_pld.last = wrRequest_local.last;
217 write_pld.wstrb = ~0;
220 pushed = if_wr.w.PushNB(write_pld);
221 wrRequestValid_local = wrRequestValid_local && !pushed;
222 wrRequestIdValid_local = wrRequestIdValid_local && !pushed;
224 cout <<
"@" << sc_time_stamp() <<
"\t\t sending data pass? " 225 << !addr_sent_local <<
"\tdata = " << wrRequest_local.data
226 <<
"\tlast = " << wrRequest_local.last << endl;
228 isBurstInFlight_local = (wrRequest_local.last != 1);
232 bool sendWNext = isBurstInFlight_local || !pushed;
235 addr_sent_local = sendWNext;
237 addr_sent = addr_sent_local;
239 isBurstInFlight = isBurstInFlight_local;
242 wrRequest = wrRequest_local;
243 wrRequestValid = wrRequestValid_local;
244 wrRequestId = wrRequestId_local;
245 wrRequestIdValid = wrRequestIdValid_local;
247 if (!wrReqFifo_isFull) {
250 if (wrRequestIn.PopNB(wrRequest1)) {
251 wrReqFifo.push(wrRequest1);
254 cout <<
"@" << sc_time_stamp() <<
"\t\t wr:m got request!" << endl;
269 bool rdRequestValid =
false;
271 bool rdRequestIdValid =
false;
272 bool rdBurstInFlight =
false;
273 bool rdReceivingBurstBeats =
false;
275 #pragma hls_pipeline_init_interval 1 276 #pragma pipeline_stall_mode flush 281 cout <<
"@" << sc_time_stamp() <<
"\t rd_rob is empty? " 282 << rd_rob.isEmpty() << endl;
285 if (rd_rob.topResponseReady()) {
287 rdResp = rd_rob.popResponse();
290 cout <<
"@" << sc_time_stamp()
291 <<
"\t\t rd:Pop first response from rob and push it into host" 296 rdRespOut.Push(rdResp);
299 cout <<
"@" << sc_time_stamp() <<
"\t\t rd:Done pushing resp to host" 305 bool rdRequestValid_local = rdRequestValid;
306 Id rdRequestId_local = rdRequestId;
307 bool rdRequestIdValid_local = rdRequestIdValid;
308 bool rdReqFifo_isFull = rdReqFifo.isFull();
309 bool rdBurstInFlight_local = rdBurstInFlight;
311 if (!rdRequestValid_local && !rdReqFifo.isEmpty()) {
312 rdRequest_local = rdReqFifo.pop();
313 rdRequestValid_local =
true;
314 rdRequestIdValid_local =
false;
316 cout <<
"@" << sc_time_stamp() <<
"\t\t rd:pop rdReqFifo" << endl;
320 if (rdRequestValid_local) {
326 bool isBurst = (rdRequest_local.len != 0);
328 (isBurst ? rd_rob.isEmpty() : rd_rob.canAcceptRequest());
330 if (!rdRequestIdValid_local && robReady && !rdBurstInFlight_local) {
331 rdRequestId_local = rd_rob.addRequest();
332 rdRequestIdValid_local =
true;
333 rdBurstInFlight_local = isBurst;
335 cout <<
"@" << sc_time_stamp()
336 <<
"\t\t rd:new id allocated = " << rdRequestId << endl;
340 if (rdRequestIdValid_local) {
342 rdRequest_local.copyToAddrPayload(addr_pld);
343 addr_pld.id =
static_cast<typename axi4_::Id
>(rdRequestId_local);
345 bool pushed = if_rd.ar.PushNB(addr_pld);
346 rdRequestValid_local = !pushed;
347 rdRequestIdValid_local = !pushed;
351 rdRequest = rdRequest_local;
352 rdRequestValid = rdRequestValid_local;
353 rdRequestId = rdRequestId_local;
354 rdRequestIdValid = rdRequestIdValid_local;
356 if (!rdReqFifo_isFull) {
359 if (rdRequestIn.PopNB(rdRequest1)) {
360 rdReqFifo.push(rdRequest1);
363 cout <<
"@" << sc_time_stamp() <<
"\t\t rd:m got request ? " 364 << rdRequestValid << endl;
370 bool rdReceivingBurstBeats_local = rdReceivingBurstBeats;
376 if (!rdReceivingBurstBeats_local || rd_rob.canReceiveBeats()) {
377 if (if_rd.r.PopNB(data_pld)) {
379 rdResp.data = data_pld.data;
380 rdResp.resp = data_pld.resp;
381 rdResp.last = data_pld.last;
383 if (!rdReceivingBurstBeats_local) {
384 rd_rob.addResponse(
static_cast<sc_uint<axi4_::ID_WIDTH>
>(data_pld.id), rdResp);
386 rd_rob.addBeat(rdResp);
387 if (
static_cast<sc_uint<1>
>(data_pld.last) == 1) {
389 rdBurstInFlight_local =
false;
395 rdReceivingBurstBeats_local = rdBurstInFlight_local;
398 rdReceivingBurstBeats = rdReceivingBurstBeats_local;
400 rdBurstInFlight = rdBurstInFlight_local;
The struct for read responses for AxiMasterGate.
The struct for read requests for AxiMasterGate.
An extension of ReorderBuf that allows one entry to contain multiple beats of data.
The struct for write requests for AxiMasterGate.
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 AXI read and write requests.
A struct composed of the signals associated with an AXI read response.
The base axi4 class parameterized according a valid config.
The struct for write responses for AxiMasterGate.
#define NVHLS_ASSERT_MSG(X, MSG)
Reorder Buffer that allows out-of-order writes to queue and in-order reads.
An AXI master that converts from a simple request/response interface to AXI with reordering support...