cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
tx_app_interface.cpp
Go to the documentation of this file.
1 
17 
43 
56 #include "tx_app_interface.hpp"
57 
58 using namespace hls;
59 
60 
64 #ifndef __SYNTHESIS__
65  extern bool gTraceEvent;
66 #endif
67 
68 #define THIS_NAME "TOE/TAi"
69 
70 #define TRACE_OFF 0x0000
71 #define TRACE_SML 1 << 1
72 #define TRACE_SLG 1 << 2
73 #define TRACE_MWR 1 << 3
74 #define TRACE_TAC 1 << 4
75 #define TRACE_TAS 1 << 5
76 #define TRACE_TAT 1 << 6
77 #define TRACE_TASH 1 << 7
78 #define TRACE_ALL 0xFFFF
79 
80 #define DEBUG_LEVEL (TRACE_OFF)
81 
82 
83 
95 template<typename T> void pStreamMux(
96  stream<T> &si1,
97  stream<T> &si2,
98  stream<T> &so)
99 {
100  //-- DIRECTIVES FOR THIS PROCESS --------------------------------------------
101  #pragma HLS PIPELINE II=1 enable_flush
102  #pragma HLS INLINE off
103 
104  if (!si1.empty())
105  so.write(si1.read());
106  else if (!si2.empty())
107  so.write(si2.read());
108 }
109 
110 
151  stream<TcpAppOpnReq> &siTAIF_OpnReq,
152  stream<TcpAppOpnRep> &soTAIF_OpnRep,
153  stream<TcpAppClsReq> &siTAIF_ClsReq,
154  stream<SocketPair> &soSLc_SessLookupReq,
155  stream<SessionLookupReply> &siSLc_SessLookupRep,
156  stream<ReqBit> &soPRt_GetFreePortReq,
157  stream<TcpPort> &siPRt_GetFreePortRep,
158  stream<StateQuery> &soSTt_ConnectStateQry,
159  stream<TcpState> &siSTt_ConnectStateRep,
160  stream<SessState> &siRXe_ActSessState,
161  stream<Event> &soEVe_Event,
162  stream<SessState> &siTIm_Notif,
163  Ip4Address piMMIO_IpAddr)
164 {
165  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
166  #pragma HLS pipeline II=1 enable_flush
167  #pragma HLS INLINE off
168 
169  const char *myName = concat3(THIS_NAME, "/", "Tac");
170 
171  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
172  static enum FsmStates {TAC_IDLE=0, TAC_GET_FREE_PORT, TAC_CLOSE_CONN } \
173  tac_fsmState=TAC_IDLE;
174  #pragma HLS RESET variable=tac_fsmState
175 
176  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
177  static SessionId tac_closeSessionID;
178 
179  //-- LOCAL STREAMS ---------------------------------------------------------
180  static stream<SockAddr> tac_localFifo ("tac_localFifo");
181  const int tac_localFifo_depth = 4;
182  #pragma HLS stream variable=tac_localFifo depth=tac_localFifo_depth
183 
184  SessState activeSessState;
185 
186  switch (tac_fsmState) {
187  case TAC_IDLE:
188  if (!siTAIF_OpnReq.empty() and !soPRt_GetFreePortReq.full()) {
189  assessSize(myName, tac_localFifo, "tac_localFifo", tac_localFifo_depth);
190  tac_localFifo.write(siTAIF_OpnReq.read());
191  soPRt_GetFreePortReq.write(1);
192  tac_fsmState = TAC_GET_FREE_PORT;
193  }
194  else if (!siSLc_SessLookupRep.empty()) {
195  // Read the session lookup reply and check its state
196  SessionLookupReply sessLkpRep = siSLc_SessLookupRep.read();
197  if (sessLkpRep.hit) {
198  soEVe_Event.write(Event(SYN_EVENT, sessLkpRep.sessionID));
199  soSTt_ConnectStateQry.write(StateQuery(sessLkpRep.sessionID, SYN_SENT, QUERY_WR));
200  }
201  else {
202  // Tell the [APP ]that opening of the active connection failed
203  if (!soTAIF_OpnRep.full()) {
204  soTAIF_OpnRep.write(TcpAppOpnRep(sessLkpRep.sessionID, CLOSED));
205  }
206  else {
207  // Drop this reply
208  printFatal(myName, "Cannot write 'soTAIF_OpnRep()'. Stream is full!");
209  }
210  }
211  }
212  else if (!siRXe_ActSessState.empty()) {
213  // If pending, read the state of the on-going active session (.i.e, initiated by [TOE])
214  siRXe_ActSessState.read(activeSessState);
215  // And forward it to [TAIF]
216  // [TODO-FIXME We should check if [TAIF] is actually waiting for such a status]
217  if (!soTAIF_OpnRep.full()) {
218  soTAIF_OpnRep.write(activeSessState);
219  }
220  else {
221  // Drop this reply
222  printFatal(myName, "Cannot write 'soTAIF_OpnRep()'. Stream is full!");
223  }
224  }
225  else if (!siTIm_Notif.empty()) {
226  if (!soTAIF_OpnRep.full()) {
227  soTAIF_OpnRep.write(siTIm_Notif.read());
228  }
229  else {
230  // Drop this reply
231  printFatal(myName, "Cannot write 'soTAIF_OpnRep()'. Stream is full!");
232  }
233  }
234  else if(!siTAIF_ClsReq.empty()) {
235  siTAIF_ClsReq.read(tac_closeSessionID);
236  soSTt_ConnectStateQry.write(StateQuery(tac_closeSessionID));
237  tac_fsmState = TAC_CLOSE_CONN;
238  }
239  break;
240  case TAC_GET_FREE_PORT:
241  if (!siPRt_GetFreePortRep.empty() and !soSLc_SessLookupReq.full()) {
242  TcpPort freePort = siPRt_GetFreePortRep.read();
243  SockAddr serverAddr = tac_localFifo.read();
244  // Request the [SLc] to create a new entry in its session table
245  soSLc_SessLookupReq.write(SocketPair(
246  SockAddr(piMMIO_IpAddr, freePort),
247  SockAddr(serverAddr.addr, serverAddr.port)));
248  tac_fsmState = TAC_IDLE;
249  }
250  break;
251  case TAC_CLOSE_CONN:
252  if (!siSTt_ConnectStateRep.empty()) {
253  TcpState tcpState = siSTt_ConnectStateRep.read();
254  // [FIXME-TODO Not yet tested]
255  if ((tcpState == ESTABLISHED) or (tcpState == FIN_WAIT_2) or (tcpState == FIN_WAIT_1)) {
256  // [TODO - Why if FIN already SENT]
257  soSTt_ConnectStateQry.write(StateQuery(tac_closeSessionID, FIN_WAIT_1, QUERY_WR));
258  soEVe_Event.write(Event(FIN_EVENT, tac_closeSessionID));
259  }
260  else {
261  soSTt_ConnectStateQry.write(StateQuery(tac_closeSessionID, tcpState, QUERY_WR));
262  }
263  tac_fsmState = TAC_IDLE;
264  }
265  break;
266  }
267 }
268 
269 
285  stream<DmSts> &siMEM_TxP_WrSts,
286  stream<Event> &siEmx_Event,
287  stream<TAiTxSarPush> &soTSt_PushCmd,
288  stream<Event> &soEVe_Event)
289 {
290  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
291  #pragma HLS pipeline II=1
292  #pragma HLS INLINE off
293 
294  const char *myName = concat3(THIS_NAME, "/", "Tash");
295 
296  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
297  static enum FsmStates { TASH_IDLE=0, TASH_RD_MEM_STATUS_1, TASH_RD_MEM_STATUS_2 } \
298  tash_fsmState=TASH_IDLE;
299  #pragma HLS reset variable=tash_fsmState
300 
301  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
302  static Event ev;
303 
304  switch (tash_fsmState) {
305  case TASH_IDLE: //-- Read the Event
306  if (!siEmx_Event.empty()) {
307  siEmx_Event.read(ev);
308  if (ev.type == TX_EVENT) {
309  tash_fsmState = TASH_RD_MEM_STATUS_1;
310  }
311  else {
312  soEVe_Event.write(ev);
313  }
314  if (DEBUG_LEVEL & TRACE_TASH) {
315  printInfo(myName, "Received event \'%s\' from [Emx].\n",
316  getEventName(ev.type));
317  }
318  }
319  break;
320  case TASH_RD_MEM_STATUS_1: //-- Read the Memory Write Status #1 (this might also be the last)
321  if (!siMEM_TxP_WrSts.empty()) {
322  DmSts status = siMEM_TxP_WrSts.read();
323  if (status.okay) {
324  ap_uint<TOE_WINDOW_BITS+1> txAppPtr = ev.address + ev.length;
325  if (txAppPtr[TOE_WINDOW_BITS] == 1) {
326  // The TCP buffer wrapped around
327  tash_fsmState = TASH_RD_MEM_STATUS_2;
328  }
329  else {
330  // Update the 'txAppPtr' of the TX_SAR_TABLE
331  soTSt_PushCmd.write(TAiTxSarPush(ev.sessionID, txAppPtr.range(TOE_WINDOW_BITS-1, 0)));
332  // Forward event to [EVe] which will signal [TXe]
333  soEVe_Event.write(ev);
334  if (DEBUG_LEVEL & TRACE_TASH) {
335  printInfo(myName, "Received TXMEM write status = %d.\n", status.okay.to_int());
336  }
337  tash_fsmState = TASH_IDLE;
338  }
339  }
340  }
341  break;
342  case TASH_RD_MEM_STATUS_2: //-- Read the Memory Write Status #2
343  if (!siMEM_TxP_WrSts.empty()) {
344  DmSts status = siMEM_TxP_WrSts.read();
345  TxBufPtr txAppPtr = (ev.address + ev.length);
346  if (status.okay) {
347  // Update the 'txAppPtr' of the TX_SAR_TABLE
348  soTSt_PushCmd.write(TAiTxSarPush(ev.sessionID, txAppPtr));
349  // Forward event to [EVe] which will signal [TXe]
350  soEVe_Event.write(ev);
351  if (DEBUG_LEVEL & TRACE_TASH) {
352  printInfo(myName, "Received TXMEM write status = %d (this was a split access).\n", status.okay.to_int());
353  }
354  }
355  tash_fsmState = TASH_IDLE;
356  }
357  break;
358  } // End of: switch
359 }
360 
361 
373  stream<TStTxSarPush> &siTSt_PushCmd,
374  stream<TxAppTableQuery> &siTas_AccessQry,
375  stream<TxAppTableReply> &siTas_AccessRep)
376 {
377  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
378  #pragma HLS PIPELINE II=1 enable_flush
379  #pragma HLS INLINE off
380 
381  const char *myName = concat3(THIS_NAME, "/", "Tat");
382 
383  //-- STATIC ARRAYS ---------------------------------------------------------
384  static TxAppTableEntry TX_APP_TABLE[TOE_MAX_SESSIONS];
385  #pragma HLS DEPENDENCE variable=TX_APP_TABLE inter false
386  #pragma HLS reset variable=TX_APP_TABLE
387 
388  //-- DYNAMIC VARIABLES -----------------------------------------------------
389  TStTxSarPush ackPush;
390  TxAppTableQuery txAppUpdate;
391 
392  if (!siTSt_PushCmd.empty()) {
393  siTSt_PushCmd.read(ackPush);
394  if (ackPush.init) {
395  // At init this is actually not_ackd
396  TX_APP_TABLE[ackPush.sessionID].ackd = ackPush.ackd-1;
397  TX_APP_TABLE[ackPush.sessionID].mempt = ackPush.ackd;
398  }
399  else {
400  TX_APP_TABLE[ackPush.sessionID].ackd = ackPush.ackd;
401  }
402  }
403  else if (!siTas_AccessQry.empty()) {
404  siTas_AccessQry.read(txAppUpdate);
405  if(txAppUpdate.write) {
406  TX_APP_TABLE[txAppUpdate.sessId].mempt = txAppUpdate.mempt;
407  }
408  else {
409  siTas_AccessRep.write(TxAppTableReply(txAppUpdate.sessId,
410  TX_APP_TABLE[txAppUpdate.sessId].ackd,
411  TX_APP_TABLE[txAppUpdate.sessId].mempt));
412  }
413  }
414 }
415 
416 
457  stream<TcpAppSndReq> &siTAIF_SndReq,
458  stream<TcpAppSndRep> &soTAIF_SndRep,
459  stream<SessionId> &soSTt_SessStateReq,
460  stream<TcpState> &siSTt_SessStateRep,
461  stream<TxAppTableQuery> &soTat_AccessReq,
462  stream<TxAppTableReply> &siTat_AccessRep,
463  stream<AppMemMeta> &soMwr_AppMeta,
464  stream<Event> &soEmx_Event)
465 {
466  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
467  #pragma HLS pipeline II=1 enable_flush
468 
469  const char *myName = concat3(THIS_NAME, "/", "Mdl");
470 
471  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
472  static enum FsmStates { READ_REQUEST=0, READ_META } \
473  mdl_fsmState = READ_REQUEST;
474  #pragma HLS reset variable = mdl_fsmState
475 
476  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
477  static TcpAppSndReq mdl_appSndReq;
478 
479  //-- DYNAMIC VARIABLES -----------------------------------------------------
480  TxAppTableReply txAppTableReply;
481  TcpState sessState;
482 
483  switch(mdl_fsmState) {
484  case READ_REQUEST:
485  if (!siTAIF_SndReq.empty()) {
486  // Read the request to send
487  siTAIF_SndReq.read(mdl_appSndReq);
488  // Request state of the session
489  assessSize(myName, soSTt_SessStateReq, "soSTt_SessStateReq", 2); // [FIXME-Use constant for the length]
490  soSTt_SessStateReq.write(mdl_appSndReq.sessId);
491  // Request the value of ACK and MemPtr from TxAppTable
492  assessSize(myName, soTat_AccessReq, "soTat_AccessReq", 2); // [FIXME-Use constant for the length]
493  soTat_AccessReq.write(TxAppTableQuery(mdl_appSndReq.sessId));
494  if (DEBUG_LEVEL & TRACE_SML) {
495  printInfo(myName, "Received new Tx request for session %d.\n", mdl_appSndReq.sessId.to_int());
496  }
497  mdl_fsmState = READ_META;
498  }
499  break;
500  case READ_META:
501  if (!siTat_AccessRep.empty() and !siSTt_SessStateRep.empty()) {
502  siSTt_SessStateRep.read(sessState);
503  siTat_AccessRep.read(txAppTableReply);
504  TcpDatLen maxWriteLength = (txAppTableReply.ackd - txAppTableReply.mempt) - 1;
505 
514  if (!soTAIF_SndRep.full()) {
515  if (sessState != ESTABLISHED) {
516  // Notify APP about the none-established connection
517  soTAIF_SndRep.write(TcpAppSndRep(mdl_appSndReq.sessId, mdl_appSndReq.length, maxWriteLength, NO_CONNECTION));
518  printError(myName, "Session %d is not established. Current session state is \'%s\'.\n",
519  mdl_appSndReq.sessId.to_uint(), getTcpStateName(sessState));
520  }
521  else if (mdl_appSndReq.length > maxWriteLength) {
522  // Notify APP about the lack of space
523  soTAIF_SndRep.write(TcpAppSndRep(mdl_appSndReq.sessId, mdl_appSndReq.length, maxWriteLength, NO_SPACE));
524  printError(myName, "There is not enough TxBuf memory space available for session %d.\n",
525  mdl_appSndReq.sessId.to_uint());
526  }
527  else { //-- Session is ESTABLISHED and data-length <= maxWriteLength
528  // Forward the metadata to the SegmentMemoryWriter (Mwr)
529  soMwr_AppMeta.write(AppMemMeta(mdl_appSndReq.sessId, txAppTableReply.mempt, mdl_appSndReq.length));
530  // Notify APP about acceptance of the transmission
531  soTAIF_SndRep.write(TcpAppSndRep(mdl_appSndReq.sessId, mdl_appSndReq.length, maxWriteLength, NO_ERROR));
532  // Notify [TXe] about new data to be sent via an event to [EVe]
533  assessSize(myName, soEmx_Event, "soEmx_Event", 2); // [FIXME-Use constant for the length]
534  soEmx_Event.write(Event(TX_EVENT, mdl_appSndReq.sessId, txAppTableReply.mempt, mdl_appSndReq.length));
535  // Update the 'txMemPtr' in TxAppTable
536  soTat_AccessReq.write(TxAppTableQuery(mdl_appSndReq.sessId, txAppTableReply.mempt + mdl_appSndReq.length));
537  }
538  }
539  else {
540  // Drop this reply
541  printFatal(myName, "Cannot write 'soTAIF_SndRep()'. Stream is full!");
542  }
543  mdl_fsmState = READ_REQUEST;
544  }
545  break;
546  }
547 }
548 
549 
567  stream<TcpAppData> &siTAIF_Data,
568  stream<AppMemMeta> &siSml_AppMeta,
569  stream<DmCmd> &soMEM_WrCmd,
570  stream<AxisApp> &soMEM_WrData)
571 {
572  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
573  #pragma HLS INLINE off
574  #pragma HLS pipeline II=1 enable_flush
575 
576  const char *myName = concat3(THIS_NAME, "/", "Mwr");
577 
578  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
579  static enum FsmStates { MWR_IDLE=0,
580  MWR_FWD_ALIGNED, MWR_SPLIT_1ST_CMD,
581  MWR_FWD_1ST_BUF, MWR_FWD_2ND_BUF, MWR_RESIDUE } \
582  mwr_fsmState=MWR_IDLE;
583  #pragma HLS RESET variable = mwr_fsmState
584 
585  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
586  static AppMemMeta mwr_appMemMeta;
587  static DmCmd mwr_memWrCmd;
588  static AxisApp mwr_currChunk;
589  static TxBufPtr mwr_firstAccLen;
590  static TcpDatLen mwr_nrBytesToWr;
591  static ap_uint<4> mwr_splitOffset;
592  static uint16_t mwr_debugCounter=1;
593 
594  //-- DYNAMIC VARIABLES -----------------------------------------------------
595  static uint8_t lengthBuffer;
596  static ap_uint<3> accessResidue;
597 
598  switch (mwr_fsmState) {
599  case MWR_IDLE:
600  if (!siSml_AppMeta.empty() and !soMEM_WrCmd.full()) {
601  siSml_AppMeta.read(mwr_appMemMeta);
602  //-- Build a memory address for this segment
603  TxMemPtr memSegAddr = TOE_TX_MEMORY_BASE; // 0x40000000
604  memSegAddr(29, 16) = mwr_appMemMeta.sessId(13, 0);
605  memSegAddr(15, 0) = mwr_appMemMeta.addr;
606  // Build a data mover command for this segment
607  mwr_memWrCmd = DmCmd(memSegAddr, mwr_appMemMeta.len);
608  if ((mwr_memWrCmd.saddr(TOE_WINDOW_BITS-1, 0) + mwr_memWrCmd.btt) > TOE_TX_BUFFER_SIZE) {
609  // This segment must be broken in two memory accesses because TCP Tx memory buffer wraps around
610  if (DEBUG_LEVEL & TRACE_MWR) {
611  printInfo(myName, "TCP Tx memory buffer wraps around: This segment must be broken in two memory accesses.\n");
612  }
613  mwr_fsmState = MWR_SPLIT_1ST_CMD;
614  }
615  else {
616  soMEM_WrCmd.write(mwr_memWrCmd);
617  mwr_firstAccLen = mwr_memWrCmd.btt;
618  mwr_nrBytesToWr = mwr_firstAccLen;
619  mwr_fsmState = MWR_FWD_ALIGNED;
620  if (DEBUG_LEVEL & TRACE_MWR) {
621  printInfo(myName, "Issuing memory write command #%d - SADDR=0x%9.9x - BTT=%d\n",
622  mwr_debugCounter, mwr_memWrCmd.saddr.to_uint(), mwr_memWrCmd.btt.to_uint());
623  mwr_debugCounter++;
624  }
625  }
626  }
627  break;
628  case MWR_SPLIT_1ST_CMD:
629  if (!soMEM_WrCmd.full()) {
630  mwr_firstAccLen = TOE_TX_BUFFER_SIZE - mwr_memWrCmd.saddr;
631  mwr_nrBytesToWr = mwr_firstAccLen;
632  soMEM_WrCmd.write(DmCmd(mwr_memWrCmd.saddr, mwr_firstAccLen));
633  if (DEBUG_LEVEL & TRACE_MWR) {
634  printInfo(myName, "Issuing 1st memory write command #%d - SADDR=0x%9.9x - BTT=%d\n",
635  mwr_debugCounter, mwr_memWrCmd.saddr.to_uint(), mwr_firstAccLen.to_uint());
636  }
637  mwr_fsmState = MWR_FWD_1ST_BUF;
638  }
639  break;
640  case MWR_FWD_ALIGNED:
641  if (!siTAIF_Data.empty() and !soMEM_WrData.full()) {
642  //-- Default streaming state used to forward APP data or splitted
643  //-- buffers that are aligned with to the Axis raw width.
644  AxisApp memChunk = siTAIF_Data.read();
645  soMEM_WrData.write(memChunk);
646  if (memChunk.getTLast()) {
647  mwr_fsmState = MWR_IDLE;
648  }
649  }
650  break;
651  case MWR_FWD_1ST_BUF:
652  if (!siTAIF_Data.empty() and !soMEM_WrData.full()) {
653  //-- Create 1st splitted data buffer and stream it to memory
654  siTAIF_Data.read(mwr_currChunk);
655  AxisApp memChunk = mwr_currChunk;
656  if (mwr_nrBytesToWr > (ARW/8)) {
657  mwr_nrBytesToWr -= (ARW/8);
658  }
659  else if (!soMEM_WrCmd.full()) {
660  if (mwr_nrBytesToWr == (ARW/8)) {
661  memChunk.setLE_TLast(TLAST);
662 
663  mwr_memWrCmd.saddr(TOE_WINDOW_BITS-1, 0) = 0;
664  mwr_memWrCmd.btt -= mwr_firstAccLen;
665  soMEM_WrCmd.write(mwr_memWrCmd);
666  if (DEBUG_LEVEL & TRACE_MWR) {
667  printInfo(myName, "Issuing 2nd memory write command #%d - SADDR=0x%9.9x - BTT=%d\n",
668  mwr_debugCounter, mwr_memWrCmd.saddr.to_uint(), mwr_memWrCmd.btt.to_uint());
669  mwr_debugCounter++;
670  }
671  mwr_fsmState = MWR_FWD_ALIGNED;
672  }
673  else {
674  memChunk.setLE_TLast(TLAST);
675  memChunk.setLE_TKeep(lenToLE_tKeep(mwr_nrBytesToWr));
676  #ifndef __SYNTHESIS__
677  memChunk.setLE_TData(0, (ARW-1), ((int)mwr_nrBytesToWr*8));
678  #endif
679 
680  mwr_memWrCmd.saddr(TOE_WINDOW_BITS-1, 0) = 0;
681  mwr_memWrCmd.btt -= mwr_firstAccLen;
682  soMEM_WrCmd.write(mwr_memWrCmd);
683  if (DEBUG_LEVEL & TRACE_MWR) {
684  printInfo(myName, "Issuing 2nd memory write command #%d - SADDR=0x%9.9x - BTT=%d\n",
685  mwr_debugCounter, mwr_memWrCmd.saddr.to_uint(), mwr_memWrCmd.btt.to_uint());
686  mwr_debugCounter++;
687  }
688  mwr_splitOffset = (ARW/8) - mwr_nrBytesToWr;
689  mwr_fsmState = MWR_FWD_2ND_BUF;
690  }
691  }
692  soMEM_WrData.write(memChunk);
693  if (DEBUG_LEVEL & TRACE_MWR) { printAxisRaw(myName, "soMEM_WrData =", memChunk); }
694  }
695  break;
696  case MWR_FWD_2ND_BUF:
697  if (!siTAIF_Data.empty() and !soMEM_WrData.full()) {
698  //-- Alternate streaming state used to re-align a splitted second buffer
699  AxisApp prevChunk = mwr_currChunk;
700  mwr_currChunk = siTAIF_Data.read();
701 
702  AxisApp joinedChunk(0,0,0); // [FIXME-Create a join method in AxisRaw]
703  // Set lower-part of the joined chunk with the last bytes of the previous chunk
704  joinedChunk.setLE_TData(prevChunk.getLE_TData((ARW )-1, ((ARW )-((int)mwr_splitOffset*8))),
705  ((int)mwr_splitOffset*8)-1, 0);
706  joinedChunk.setLE_TKeep(prevChunk.getLE_TKeep((ARW/8)-1, ((ARW/8)-((int)mwr_splitOffset ))),
707  ((int)mwr_splitOffset )-1, 0);
708  // Set higher part of the joined chunk with the first bytes of the current chunk
709  joinedChunk.setLE_TData(mwr_currChunk.getLE_TData((ARW )-((int)mwr_splitOffset*8)-1, 0),
710  (ARW ) -1, ((int)mwr_splitOffset*8));
711  joinedChunk.setLE_TKeep(mwr_currChunk.getLE_TKeep((ARW/8)-((int)mwr_splitOffset )-1, 0),
712  (ARW/8) -1, ((int)mwr_splitOffset ));
713  if (mwr_currChunk.getLE_TLast()) {
714  if (mwr_currChunk.getLen() > mwr_nrBytesToWr) {
715  // This cannot be the last chunk because the current one plus
716  // the remainder of the previous one do not fit into a single chunk.
717  // Goto the 'MWR_RESIDUE' and handle the remainder of that chunk.
718  mwr_fsmState = MWR_RESIDUE;
719  }
720  else {
721  // The entire current chunk and the remainder of the previous chunk
722  // fit into a single chunk. We are done with this 2nd memory buffer.
723  joinedChunk.setLE_TLast(TLAST);
724  mwr_fsmState = MWR_IDLE;
725  }
726  }
727  soMEM_WrData.write(joinedChunk);
728  if (DEBUG_LEVEL & TRACE_MWR) {
729  printAxisRaw(myName, "soMEM_WrData =", joinedChunk);
730  }
731  }
732  break;
733  case MWR_RESIDUE:
734  if (!soMEM_WrData.full()) {
735  //-- Output the very last unaligned chunk
736  AxisApp prevChunk = mwr_currChunk;
737  AxisApp lastChunk(0,0,0);
738 
739  // Set lower-part of the last chunk with the last bytes of the previous chunk
740  lastChunk.setLE_TData(prevChunk.getLE_TData((ARW )-1, ((ARW )-((int)mwr_splitOffset*8))),
741  ((int)mwr_splitOffset*8)-1, 0);
742  lastChunk.setLE_TKeep(prevChunk.getLE_TKeep((ARW/8)-1, ((ARW/8)-((int)mwr_splitOffset ))),
743  ((int)mwr_splitOffset )-1, 0);
744  lastChunk.setLE_TLast(TLAST);
745  soMEM_WrData.write(lastChunk);
746  if (DEBUG_LEVEL & TRACE_MWR) {
747  printAxisRaw(myName, "soMEM_TxP_Data =", lastChunk);
748  }
749  mwr_fsmState = MWR_IDLE;
750  }
751  break;
752  } // End-of switch
753 }
754 
755 
792  //-- TAIF / Open-Close Interfaces
793  stream<TcpAppOpnReq> &siTAIF_OpnReq,
794  stream<TcpAppOpnRep> &soTAIF_OpnRep,
795  stream<TcpAppClsReq> &siTAIF_ClsReq,
796  //-- TAIF / Send Data Interfaces
797  stream<TcpAppData> &siTAIF_Data,
798  stream<TcpAppSndReq> &siTAIF_SndReq,
799  stream<TcpAppSndRep> &soTAIF_SndRep,
800  //-- MEM / Tx PATH Interface
801  stream<DmCmd> &soMEM_TxP_WrCmd,
802  stream<AxisApp> &soMEM_TxP_Data,
803  stream<DmSts> &siMEM_TxP_WrSts,
804  //-- State Table Interfaces
805  stream<SessionId> &soSTt_SessStateReq,
806  stream<TcpState> &siSTt_SessStateRep,
807  stream<StateQuery> &soSTt_ConnectStateQry,
808  stream<TcpState> &siSTt_ConnectStateRep,
809  //-- Session Lookup Controller Interface
810  stream<SocketPair> &soSLc_SessLookupReq,
811  stream<SessionLookupReply> &siSLc_SessLookupRep,
812  //-- Port Table Interfaces
813  stream<ReqBit> &soPRt_GetFreePortReq,
814  stream<TcpPort> &siPRt_GetFreePortRep,
815  //-- Tx SAR TAble Interfaces
816  stream<TStTxSarPush> &siTSt_PushCmd,
817  stream<TAiTxSarPush> &soTSt_PushCmd,
818  //-- Rx Engine Interface
819  stream<SessState> &siRXe_ActSessState,
820  //-- Event Engine Interface
821  stream<Event> &soEVe_Event,
822  //-- Timers Interface
823  stream<SessState> &siTIm_Notif,
824  //-- MMIO / IPv4 Address
825  Ip4Addr piMMIO_IpAddr)
826 {
827  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
828  #pragma HLS DATAFLOW
829  #pragma HLS INTERFACE ap_ctrl_none port=return
830 
831  //--------------------------------------------------------------------------
832  //-- LOCAL STREAMS (Sorted by the name of the modules which generate them)
833  //--------------------------------------------------------------------------
834 
835  //-- Event Multiplexer (Emx) ----------------------------------------------
836  static stream<Event> ssEmxToTash_Event ("ssEmxToTash_Event");
837  #pragma HLS stream variable=ssEmxToTash_Event depth=2
838  #pragma HLS DATA_PACK variable=ssEmxToTash_Event
839 
840  //-- Tx App Connect (Tac) --------------------------------------------------
841  static stream<Event> ssTacToEmx_Event ("ssTacToEmx_Event");
842  #pragma HLS stream variable=ssTacToEmx_Event depth=2
843  #pragma HLS DATA_PACK variable=ssTacToEmx_Event
844 
845  //-- Tx App Table (Tat)----------------------------------------------------
846  static stream<TxAppTableReply> ssTatToSml_AccessRep ("ssTatToSml_AccessRep");
847  #pragma HLS stream variable=ssTatToSml_AccessRep depth=2
848  #pragma HLS DATA_PACK variable=ssTatToSml_AccessRep
849 
850  //-- StreamMetaLoader (Sml)------------------------------------------------
851  static stream<TxAppTableQuery> ssSmlToTat_AccessQry ("ssSmlToTat_AccessQry");
852  #pragma HLS stream variable=ssSmlToTat_AccessQry depth=2
853  #pragma HLS DATA_PACK variable=ssSmlToTat_AccessQry
854 
855  static stream<AppMemMeta> ssSmlToMwr_AppMeta ("ssSmlToMwr_AppMeta");
856  #pragma HLS stream variable=ssSmlToMwr_AppMeta depth=32
857  #pragma HLS DATA_PACK variable=ssSmlToMwr_AppMeta
858 
859  static stream<Event> ssSmlToEmx_Event ("ssSmlToEmx_Event");
860  #pragma HLS stream variable=ssSmlToEmx_Event depth=2
861  #pragma HLS DATA_PACK variable=ssSmlToEmx_Event
862 
863  //-------------------------------------------------------------------------
864  //-- PROCESS FUNCTIONS
865  //-------------------------------------------------------------------------
866 
867  // Event Multiplexer (Emx)
868  pStreamMux(
869  ssTacToEmx_Event,
870  ssSmlToEmx_Event,
871  ssEmxToTash_Event);
872 
873  // Tx Application Status Handler (Tash)
875  siMEM_TxP_WrSts,
876  ssEmxToTash_Event,
877  soTSt_PushCmd,
878  soEVe_Event);
879 
881  siTAIF_SndReq,
882  soTAIF_SndRep,
883  soSTt_SessStateReq,
884  siSTt_SessStateRep,
885  ssSmlToTat_AccessQry,
886  ssTatToSml_AccessRep,
887  ssSmlToMwr_AppMeta,
888  ssSmlToEmx_Event);
889 
891  siTAIF_Data,
892  ssSmlToMwr_AppMeta,
893  soMEM_TxP_WrCmd,
894  soMEM_TxP_Data);
895 
896  // Tx Application Connect (Tac)
898  siTAIF_OpnReq,
899  soTAIF_OpnRep,
900  siTAIF_ClsReq,
901  soSLc_SessLookupReq,
902  siSLc_SessLookupRep,
903  soPRt_GetFreePortReq,
904  siPRt_GetFreePortRep,
905  soSTt_ConnectStateQry,
906  siSTt_ConnectStateRep,
907  siRXe_ActSessState,
908  ssTacToEmx_Event,
909  siTIm_Notif,
910  piMMIO_IpAddr);
911 
912  // Tx Application Table (Tat)
913  pTxAppTable(
914  siTSt_PushCmd,
915  ssSmlToTat_AccessQry,
916  ssTatToSml_AccessRep);
917 }
918 
TcpSessId sessId
tLast getTLast() const
Definition: AxisRaw.hpp:219
LE_tKeep getLE_TKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:264
LE_tData getLE_TData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:260
void setLE_TLast(LE_tLast last)
Definition: AxisRaw.hpp:280
void setLE_TData(LE_tData data, int leHi=64 -1, int leLo=0)
Definition: AxisRaw.hpp:272
int getLen() const
Definition: AxisRaw.hpp:411
void setLE_TKeep(LE_tKeep keep, int leHi=64/8-1, int leLo=0)
Definition: AxisRaw.hpp:276
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
ap_uint< 40 > saddr
ap_uint< 23 > btt
Definition: mem.hpp:85
ap_uint< 1 > okay
Definition: toe.hpp:661
TcpBufAdr address
Definition: toe.hpp:665
SessionId sessionID
Definition: toe.hpp:664
EventType type
Definition: toe.hpp:663
TcpSegLen length
Definition: toe.hpp:666
SessionId sessionID
Definition: toe.hpp:334
HitState hit
Definition: toe.hpp:335
Ip4Addr addr
Definition: nts_types.hpp:209
Ly4Port port
Definition: nts_types.hpp:210
SessionId sessionID
Definition: toe.hpp:559
CmdBit init
Definition: toe.hpp:564
ap_uint< 16 > ackd
Definition: toe.hpp:560
TcpDatLen length
Definition: nts.hpp:130
SessionId sessId
Definition: nts.hpp:129
bool write
Definition: toe.hpp:590
SessionId sessId
Definition: toe.hpp:588
TxBufPtr mempt
Definition: toe.hpp:589
ap_uint< 16 > ackd
Definition: toe.hpp:604
TxBufPtr mempt
Definition: toe.hpp:605
void pStreamMux(stream< T > &si1, stream< T > &si2, stream< T > &so)
A 2-to-1 generic Stream Multiplexer.
Definition: timers.cpp:90
ap_uint< 32 > TxMemPtr
Definition: toe.hpp:296
void pStreamMetaLoader(stream< TcpAppSndReq > &siTAIF_SndReq, stream< TcpAppSndRep > &soTAIF_SndRep, stream< SessionId > &soSTt_SessStateReq, stream< TcpState > &siSTt_SessStateRep, stream< TxAppTableQuery > &soTat_AccessReq, stream< TxAppTableReply > &siTat_AccessRep, stream< AppMemMeta > &soMwr_AppMeta, stream< Event > &soEmx_Event)
Stream Metadata Loader (Sml)
void pTxAppConnect(stream< TcpAppOpnReq > &siTAIF_OpnReq, stream< TcpAppOpnRep > &soTAIF_OpnRep, stream< TcpAppClsReq > &siTAIF_ClsReq, stream< SocketPair > &soSLc_SessLookupReq, stream< SessionLookupReply > &siSLc_SessLookupRep, stream< ReqBit > &soPRt_GetFreePortReq, stream< TcpPort > &siPRt_GetFreePortRep, stream< StateQuery > &soSTt_ConnectStateQry, stream< TcpState > &siSTt_ConnectStateRep, stream< SessState > &siRXe_ActSessState, stream< Event > &soEVe_Event, stream< SessState > &siTIm_Notif, Ip4Address piMMIO_IpAddr)
Tx Application Connect (Tac)
const char * getEventName(EventType evType)
Returns the name of an enum-based event as a user friendly string.
Definition: toe_utils.cpp:43
void tx_app_interface(stream< TcpAppOpnReq > &siTAIF_OpnReq, stream< TcpAppOpnRep > &soTAIF_OpnRep, stream< TcpAppClsReq > &siTAIF_ClsReq, stream< TcpAppData > &siTAIF_Data, stream< TcpAppSndReq > &siTAIF_SndReq, stream< TcpAppSndRep > &soTAIF_SndRep, stream< DmCmd > &soMEM_TxP_WrCmd, stream< AxisApp > &soMEM_TxP_Data, stream< DmSts > &siMEM_TxP_WrSts, stream< SessionId > &soSTt_SessStateReq, stream< TcpState > &siSTt_SessStateRep, stream< StateQuery > &soSTt_ConnectStateQry, stream< TcpState > &siSTt_ConnectStateRep, stream< SocketPair > &soSLc_SessLookupReq, stream< SessionLookupReply > &siSLc_SessLookupRep, stream< ReqBit > &soPRt_GetFreePortReq, stream< TcpPort > &siPRt_GetFreePortRep, stream< TStTxSarPush > &siTSt_PushCmd, stream< TAiTxSarPush > &soTSt_PushCmd, stream< SessState > &siRXe_ActSessState, stream< Event > &soEVe_Event, stream< SessState > &siTIm_Notif, Ip4Addr piMMIO_IpAddr)
Tx Application Interface (TAi)
void pTxAppStatusHandler(stream< DmSts > &siMEM_TxP_WrSts, stream< Event > &siEmx_Event, stream< TAiTxSarPush > &soTSt_PushCmd, stream< Event > &soEVe_Event)
Tx Application Status Handler (Tash)
#define TRACE_SML
bool gTraceEvent
Definition: tb_nal.cpp:151
#define THIS_NAME
TcpBufAdr TxBufPtr
Definition: toe.hpp:299
#define TRACE_TASH
void pTxMemoryWriter(stream< TcpAppData > &siTAIF_Data, stream< AppMemMeta > &siSml_AppMeta, stream< DmCmd > &soMEM_WrCmd, stream< AxisApp > &soMEM_WrData)
Tx Memory Writer (Mwr)
#define DEBUG_LEVEL
void pTxAppTable(stream< TStTxSarPush > &siTSt_PushCmd, stream< TxAppTableQuery > &siTas_AccessQry, stream< TxAppTableReply > &siTas_AccessRep)
Tx Application Table (Tat)
#define TRACE_MWR
@ SYN_EVENT
Definition: toe.hpp:273
@ FIN_EVENT
Definition: toe.hpp:274
@ TX_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 printError(callerName, format,...)
A macro to print an error message.
Definition: nts_utils.hpp:195
LE_tKeep lenToLE_tKeep(ap_uint< 4 > noValidBytes)
A function to set a number of '1' in an 8-bit field. It is used here to set the number of valid bytes...
Definition: nts_utils.cpp:307
TcpState
Definition: nts_types.hpp:296
void printAxisRaw(const char *callerName, AxisRaw chunk)
Prints an Axis raw data chunk (used for debugging).
Definition: nts_utils.cpp:46
#define ARW
Definition: AxisRaw.hpp:114
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
#define QUERY_WR
Definition: nts_types.hpp:66
ap_uint< 16 > TcpPort
Definition: AxisTcp.hpp:105
ap_uint< 16 > TcpDatLen
Definition: AxisTcp.hpp:123
const char * getTcpStateName(TcpState tcpState)
Returns the name of an enum-based TCP-State as a user friendly string.
Definition: nts_utils.cpp:272
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
ap_uint< 32 > Ip4Address
Definition: AxisIp4.hpp:168
#define printFatal(callerName, format,...)
A macro to print a fatal error message and exit.
Definition: nts_utils.hpp:208
#define TLAST
Definition: AxisRaw.hpp:116
@ FIN_WAIT_2
Definition: nts_types.hpp:297
@ FIN_WAIT_1
Definition: nts_types.hpp:297
@ SYN_SENT
Definition: nts_types.hpp:296
@ ESTABLISHED
Definition: nts_types.hpp:296
@ CLOSED
Definition: nts_types.hpp:296
@ NO_ERROR
Definition: nts_types.hpp:304
@ NO_CONNECTION
Definition: nts_types.hpp:304
@ NO_SPACE
Definition: nts_types.hpp:304
: Tx Application Interface (TAi)