cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
ack_delay.cpp
Go to the documentation of this file.
1 
17 
43 
56 #include "ack_delay.hpp"
57 #include "../../toe_utils.hpp"
58 
59 using namespace hls;
60 
61 
65 #ifndef __SYNTHESIS__
66  extern bool gTraceEvent;
67 #endif
68 
69 #define THIS_NAME "TOE/AKd"
70 
71 #define TRACE_OFF 0x0000
72 #define TRACE_AKD 1 << 1
73 #define TRACE_ALL 0xFFFF
74 
75 #define DEBUG_LEVEL (TRACE_OFF)
76 
77 
78 
95 void ack_delay(
96  stream<ExtendedEvent> &siEVe_Event,
97  stream<SigBit> &soEVe_RxEventSig,
98  stream<SigBit> &soEVe_TxEventSig,
99  stream<ExtendedEvent> &soTXe_Event)
100 {
101  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
102  #pragma HLS PIPELINE II=1 enable_flush
103 
104  const char *myName = THIS_NAME;
105 
106  //-- STATIC ARRAYS ---------------------------------------------------------
107  static AckEntry ACK_TABLE[TOE_MAX_SESSIONS];
108  #pragma HLS RESOURCE variable=ACK_TABLE core=RAM_T2P_BRAM
109  #pragma HLS DEPENDENCE variable=ACK_TABLE inter false
110 
111  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
112  // [TODO - The type of 'akd_Ptr' could be configured as a functions of 'MAX_SESSIONS']
113  // [ E.g. - static const int NR_BITS = ceil(log10(MAX_SESSIONS)/log10(2));
114  static SessionId akd_Ptr;
115  #pragma HLS RESET variable=akd_Ptr
116 
117  //-- DYNAMIC VARIABLES -----------------------------------------------------
118  ExtendedEvent ev;
119 
120  if (!siEVe_Event.empty()) {
121 
122  // Read incoming event and inform [EVe] that the FiFo stream was read
123  siEVe_Event.read(ev);
124  assessSize(myName, soEVe_RxEventSig, "soEVe_RxEventSig", cDepth_AKdToEVe_Event);
125  soEVe_RxEventSig.write(1);
126 
127  if (ev.type == ACK_EVENT) {
128 
176  if (ACK_TABLE[ev.sessionID].delay == 0) {
177  // There is no delayed ACK pending --> Schedule a new one
178  ACK_TABLE[ev.sessionID] = AckEntry(ACKD_64us, 1);
179  }
180  else if (ACK_TABLE[ev.sessionID].count == 1) {
181  // Received a second ACK --> Decrease the delay
182  if (ACK_TABLE[ev.sessionID].delay > ACKD_32us) {
183  ACK_TABLE[ev.sessionID].delay = ACKD_32us;
184  }
185  ACK_TABLE[ev.sessionID].count++;
186  }
187  else if (ACK_TABLE[ev.sessionID].count == 2) {
188  // Received a third ACK --> Decrease the delay
189  if (ACK_TABLE[ev.sessionID].delay > ACKD_16us) {
190  ACK_TABLE[ev.sessionID].delay = ACKD_16us;
191  }
192  ACK_TABLE[ev.sessionID].count++;
193  }
194  else if (ACK_TABLE[ev.sessionID].count == 3) {
195  // Received a fourth ACK --> Decrease the delay
196  if (ACK_TABLE[ev.sessionID].delay > ACKD_8us) {
197  ACK_TABLE[ev.sessionID].delay = ACKD_8us;
198  }
199  ACK_TABLE[ev.sessionID].count++;
200  }
201  else if (ACK_TABLE[ev.sessionID].count == 4) {
202  // Received a fifth ACK --> Decrease the delay
203  if (ACK_TABLE[ev.sessionID].delay > ACKD_4us) {
204  ACK_TABLE[ev.sessionID].delay = ACKD_4us;
205  }
206  ACK_TABLE[ev.sessionID].count++;
207  }
208  else if (ACK_TABLE[ev.sessionID].count == 5) {
209  // Received a sixth ACK --> Decrease the delay
210  if (ACK_TABLE[ev.sessionID].delay > ACKD_2us) {
211  ACK_TABLE[ev.sessionID].delay = ACKD_2us;
212  }
213  ACK_TABLE[ev.sessionID].count++;
214  }
215  else if (ACK_TABLE[ev.sessionID].count == 6) {
216  // Received a seventh ACK --> Decrease the delay
217  if (ACK_TABLE[ev.sessionID].delay > ACKD_1us) {
218  ACK_TABLE[ev.sessionID].delay = ACKD_1us;
219  }
220  ACK_TABLE[ev.sessionID].count++;
221  }
222  else if (ACK_TABLE[ev.sessionID].count == 7) {
223  // Received a eight+ ACK --> Set delay to ONE
224  ACK_TABLE[ev.sessionID].delay = 1;
225  ACK_TABLE[ev.sessionID].count = 8;
226  }
227  // Debug trace
228  if (DEBUG_LEVEL & TRACE_AKD) {
229  printInfo(myName, "S%d - Received \'%s\' - Setting ACK_TABLE[%d]={D=%4.4d,C=%2.2d}\n",
230  ev.sessionID.to_int(), getEventName(ev.type),
231  ev.sessionID.to_uint(),
232  ACK_TABLE[ev.sessionID].delay.to_uint(),
233  ACK_TABLE[ev.sessionID].count.to_uint());
234  }
235  }
236  else {
237  // Received any other event --> Reset current entry
238  ACK_TABLE[ev.sessionID] = AckEntry(0, 0);
239  // Forward event to TxEngine
240  assessSize(myName, soTXe_Event, "soTXe_Event", cDepth_AKdToTXe_Event);
241  soTXe_Event.write(ev);
242  // Tell the EventEngine that we just forwarded an none-ACK event to TXe
243  assessSize(myName, soEVe_TxEventSig, "soEVe_TxEventSig", cDepth_AKdToEVe_Event);
244  soEVe_TxEventSig.write(1);
245  // Debug trace
246  if (DEBUG_LEVEL & TRACE_AKD) {
247  printInfo(myName, "S%d - Received '%s' - Clearing ACK_TABLE[%d]={D=%4.4d,C=%2.2d}\n",
248  ev.sessionID.to_int(), getEventName(ev.type),
249  ev.sessionID.to_uint(),
250  ACK_TABLE[ev.sessionID].delay.to_uint(),
251  ACK_TABLE[ev.sessionID].count.to_uint());
252  }
253  }
254  }
255  else {
256  if (ACK_TABLE[akd_Ptr].delay > 0 and !soTXe_Event.full()) {
257  if (ACK_TABLE[akd_Ptr].delay == 1) {
258  soTXe_Event.write(Event(ACK_EVENT, akd_Ptr));
259  // Tell the EventEngine that we just forwarded an event to TXe
260  assessSize(myName, soEVe_TxEventSig, "soEVe_TxEventSig", cDepth_AKdToEVe_Event);
261  soEVe_TxEventSig.write(1);
262  // Do not clear the received ACK counter here. It will anyhow be
263  // cleared whenever a new event comes in. Until then, it gives
264  // us a good indication of its usage in the trace.
265  if (DEBUG_LEVEL & TRACE_AKD) {
266  printInfo(myName, "S%d - It's ACK Time (count=%d) - Requesting [TXe] to generate an new ACK\n",
267  akd_Ptr.to_int(), ACK_TABLE[akd_Ptr].count.to_uint());
268  }
269  }
270  ACK_TABLE[akd_Ptr].delay -= 1;
271  }
272  akd_Ptr++;
273  if (akd_Ptr == TOE_MAX_SESSIONS) {
274  akd_Ptr = 0;
275  }
276  }
277 }
278 
279 
281  stream<ExtendedEvent> &siEVe_Event,
282  stream<SigBit> &soEVe_RxEventSig,
283  stream<SigBit> &soEVe_TxEventSig,
284  stream<ExtendedEvent> &soTXe_Event)
285 {
286  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
287  #pragma HLS PIPELINE II=1 enable_flush
288 
289  const char *myName = THIS_NAME;
290 
291  //-- STATIC ARRAYS ---------------------------------------------------------
292  // [TODO - The type of 'ACK_TABLE' can be configured as a functions of 'TIME_XXX' and 'MAX_SESSIONS']
293  // [ E.g. - TIME_64us = ( 64.000/0.0064/32) + 1 = 313 = 0x139 ( 9-bits)
294  // [ E.g. - TIME_64us = ( 64.000/0.0064/ 8) + 1 = 1251 = 0x4E3 (11-bits)
295  // [ E.g. - TIME_128us = (128.000/0.0064/32) + 1 = 626 = 0x271 (10-bits)
296  static ap_uint<12> ACK_TABLE[TOE_MAX_SESSIONS];
297  #pragma HLS RESOURCE variable=ACK_TABLE core=RAM_T2P_BRAM
298  #pragma HLS DEPENDENCE variable=ACK_TABLE inter false
299  #pragma HLS RESET variable=ACK_TABLE
300 
301  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
302  // [TODO - The type of 'akd_Ptr' could be configured as a functions of 'MAX_SESSIONS']
303  // [ E.g. - static const int NR_BITS = ceil(log10(MAX_SESSIONS)/log10(2));
304  static SessionId akd_Ptr;
305  #pragma HLS RESET variable=akd_Ptr
306 
307  //-- DYNAMIC VARIABLES -----------------------------------------------------
308  ExtendedEvent ev;
309 
310  if (!siEVe_Event.empty()) {
311 
312  // Read incoming event and inform [EVe] that the FiFo stream was read
313  siEVe_Event.read(ev);
314  assessSize(myName, soEVe_RxEventSig, "soEVe_RxEventSig", cDepth_AKdToEVe_Event);
315  soEVe_RxEventSig.write(1);
316 
317  if (ev.type == ACK_EVENT) {
318  if (ACK_TABLE[ev.sessionID] == 0) {
319  // There is no delayed ACK pending --> Schedule a new one
320  ACK_TABLE[ev.sessionID] = ACKD_64us;
321  if (DEBUG_LEVEL & TRACE_AKD) {
322  printInfo(myName, "S%d - Received \'%s\' - Setting ACK_TABLE[%d]=%d\n",
323  ev.sessionID.to_int(), getEventName(ev.type), ev.sessionID.to_uint(), ACK_TABLE[ev.sessionID].to_uint());
324  }
325  }
326  else {
327  if (DEBUG_LEVEL & TRACE_AKD) {
328  printInfo(myName, "S%d - Received \'%s\' - Current ACK_TABLE[%d]=%d\n",
329  ev.sessionID.to_int(), getEventName(ev.type), ev.sessionID.to_uint(), ACK_TABLE[ev.sessionID].to_uint());
330  }
331  }
332  }
333  else {
334  // Any other event
335  ACK_TABLE[ev.sessionID] = 0;
336  // Forward event to TxEngine
337  assessSize(myName, soTXe_Event, "soTXe_Event", cDepth_AKdToTXe_Event);
338  soTXe_Event.write(ev);
339  // Tell the EventEngine that we just forwarded an mone-ACK event to TXe
340  assessSize(myName, soEVe_TxEventSig, "soEVe_TxEventSig", cDepth_AKdToEVe_Event);
341  soEVe_TxEventSig.write(1);
342  // Debug trace
343  if (DEBUG_LEVEL & TRACE_AKD) {
344  printInfo(myName, "S%d - Received '%s' - Clearing ACK_TABLE[%d]=%d\n",
345  ev.sessionID.to_int(), getEventName(ev.type), ev.sessionID.to_uint(), ACK_TABLE[ev.sessionID].to_uint());
346  }
347  }
348  }
349  else {
350  if (ACK_TABLE[akd_Ptr] > 0 and !soTXe_Event.full()) {
351  if (ACK_TABLE[akd_Ptr] == 1) {
352  soTXe_Event.write(Event(ACK_EVENT, akd_Ptr));
353  // Tell the EventEngine that we just forwarded an event to TXe
354  assessSize(myName, soEVe_TxEventSig, "soEVe_TxEventSig", cDepth_AKdToEVe_Event);
355  soEVe_TxEventSig.write(1);
356  if (DEBUG_LEVEL & TRACE_AKD) {
357  printInfo(myName, "S%d - It's ACK Time - Requesting [TXe] to generate an new ACK\n",
358  akd_Ptr.to_int());
359  }
360  }
361  ACK_TABLE[akd_Ptr] -= 1;
362  }
363  akd_Ptr++;
364  if (akd_Ptr == TOE_MAX_SESSIONS) {
365  akd_Ptr = 0;
366  }
367  }
368 }
369 
: ACK Delayer (AKd) of the TCP Offload Engine (TOE)
ap_uint< 4 > count
Definition: ack_delay.hpp:76
ap_uint< 12 > delay
Definition: ack_delay.hpp:75
Definition: toe.hpp:661
SessionId sessionID
Definition: toe.hpp:664
EventType type
Definition: toe.hpp:663
void delay(unsigned int mseconds)
Definition: common.hpp:85
#define TRACE_AKD
Definition: ack_delay.cpp:72
const int cDepth_AKdToTXe_Event
Definition: toe.hpp:207
void ack_delay(stream< ExtendedEvent > &siEVe_Event, stream< SigBit > &soEVe_RxEventSig, stream< SigBit > &soEVe_TxEventSig, stream< ExtendedEvent > &soTXe_Event)
ACK Delayer (AKd)
Definition: ack_delay.cpp:95
void ack_delay_OBSO(stream< ExtendedEvent > &siEVe_Event, stream< SigBit > &soEVe_RxEventSig, stream< SigBit > &soEVe_TxEventSig, stream< ExtendedEvent > &soTXe_Event)
Definition: ack_delay.cpp:280
const char * getEventName(EventType evType)
Returns the name of an enum-based event as a user friendly string.
Definition: toe_utils.cpp:43
const int cDepth_AKdToEVe_Event
Definition: toe.hpp:206
bool gTraceEvent
Definition: tb_nal.cpp:151
#define THIS_NAME
Definition: ack_delay.cpp:69
#define DEBUG_LEVEL
Definition: ack_delay.cpp:75
@ ACK_EVENT
Definition: toe.hpp:273
#define assessSize(callerName, stream, streamName, depth)
A macro that checks if a stream is full.
Definition: nts_utils.hpp:223
ap_uint< 16 > SessionId
Definition: nts_types.hpp:136
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169