cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
test_toe.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016 -- 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
30 #include "test_toe.hpp"
31 
32 using namespace hls;
33 using namespace std;
34 
35 //---------------------------------------------------------
36 // HELPERS FOR THE DEBUGGING TRACES
37 // .e.g: DEBUG_LEVEL = (MDL_TRACE | IPS_TRACE)
38 //---------------------------------------------------------
39 #define THIS_NAME "TB"
40 
41 #define TRACE_OFF 0x0000
42 #define TRACE_CAM 1 << 1
43 #define TRACE_IPRX 1 << 2
44 #define TRACE_IPTX 1 << 3
45 #define TRACE_MAIN 1 << 4
46 #define TRACE_RXMEM 1 << 5
47 #define TRACE_TAIF 1 << 6
48 #define TRACE_TAr 1 << 7
49 #define TRACE_TAs 1 << 8
50 #define TRACE_Tac 1 << 9
51 #define TRACE_Tae 1 << 10
52 #define TRACE_Tal 1 << 11
53 #define TRACE_TXMEM 1 << 12
54 #define TRACE_ALL 0xFFFF
55 #define DEBUG_LEVEL (TRACE_OFF)
56 
57 
58 
61 void stepSim() {
62  gSimCycCnt++;
63  if (gTraceEvent || ((gSimCycCnt % 1000) == 0)) {
64  printInfo(THIS_NAME, "-- [@%4.4d] -----------------------------\n", gSimCycCnt);
65  gTraceEvent = false;
66  }
67  else if (0) {
68  printInfo(THIS_NAME, "------------------- [@%d] ------------\n", gSimCycCnt);
69  }
70 }
71 
72 
77 void increaseSimTime(unsigned int cycles) {
78  gMaxSimCycles += cycles;
79 }
80 
81 const char *camAccessorStrings[] = { "RXe", "TAi" };
82 
83 
89 const char *myCamAccessToString(int initiator) {
90  return camAccessorStrings[initiator];
91 }
92 
93 
101 template<typename T> int drainMmioDropCounter(stream<T> &ss, string ssName) {
102  int nrDrops=0;
103  const char *myName = concat3(THIS_NAME, "/", "DMDC");
104  T currDropCount;
105  T prevDropCount=0;
106 
107  //-- READ FROM STREAM
108  while (!(ss.empty())) {
109  ss.read(currDropCount);
110  if (currDropCount != prevDropCount) {
111  printWarn(myName, "Detected a drop event on stream '%s' (currDropCounter=%d). \n",
112  ssName.c_str(), currDropCount.to_ushort());
113  nrDrops++;
114  }
115  prevDropCount = currDropCount;
116  }
117  return(nrDrops);
118 }
119 
120 
128 void pEmulateCam(
129  stream<CamSessionLookupRequest> &siTOE_SssLkpReq,
130  stream<CamSessionLookupReply> &soTOE_SssLkpRep,
131  stream<CamSessionUpdateRequest> &siTOE_SssUpdReq,
132  stream<CamSessionUpdateReply> &soTOE_SssUpdRep)
133 {
134  const char *myName = concat3(THIS_NAME, "/", "CAM");
135 
136  static map<FourTuple, ap_uint<14> > cam_lookupTable;
137 
138  static enum FsmStates { CAM_WAIT_4_REQ=0,
139  CAM_LOOKUP_REP, CAM_UPDATE_REP } cam_fsmState=CAM_WAIT_4_REQ;
140 
141  static CamSessionLookupRequest cam_request;
142  static CamSessionUpdateRequest cam_update;
143  static int cam_updateIdleCnt = 0;
144  volatile static int cam_lookupIdleCnt = 0;
145 
146  map<FourTuple, ap_uint<14> >::const_iterator findPos;
147 
148  //-----------------------------------------------------
149  //-- CONTENT ADDRESSABLE MEMORY PROCESS
150  //-----------------------------------------------------
151  switch (cam_fsmState) {
152  case CAM_WAIT_4_REQ:
153  if (!siTOE_SssLkpReq.empty()) {
154  siTOE_SssLkpReq.read(cam_request);
155  cam_lookupIdleCnt = CAM_LOOKUP_LATENCY;
156  cam_fsmState = CAM_LOOKUP_REP;
157  if (DEBUG_LEVEL & TRACE_CAM) {
158  printInfo(myName, "Received a session lookup request from [%s] for socket pair: \n",
159  myCamAccessToString(cam_request.source.to_int()));
160  printFourTuple(myName, cam_request.source.to_int(), cam_request.key);
161  }
162  }
163  else if (!siTOE_SssUpdReq.empty()) {
164  siTOE_SssUpdReq.read(cam_update);
165  cam_updateIdleCnt = CAM_UPDATE_LATENCY;
166  cam_fsmState = CAM_UPDATE_REP;
167  if (DEBUG_LEVEL & TRACE_CAM) {
168  printInfo(myName, "Received a session update request from [%s] for socket pair: \n",
169  myCamAccessToString(cam_update.source.to_int()));
170  printFourTuple(myName, cam_update.source.to_int(), cam_update.key);
171  }
172  }
173  break;
174  case CAM_LOOKUP_REP:
175  //-- Wait some cycles to match the co-simulation --
176  if (cam_lookupIdleCnt > 0) {
177  cam_lookupIdleCnt--;
178  }
179  else {
180  findPos = cam_lookupTable.find(cam_request.key);
181  if (findPos != cam_lookupTable.end()) { // hit
182  soTOE_SssLkpRep.write(CamSessionLookupReply(true, findPos->second, cam_request.source));
183  if (DEBUG_LEVEL & TRACE_CAM) {
184  printInfo(myName, "Result of session lookup = HIT \n");
185  }
186  }
187  else {
188  soTOE_SssLkpRep.write(CamSessionLookupReply(false, cam_request.source));
189  if (DEBUG_LEVEL & TRACE_CAM) {
190  printInfo(myName, "Result of session lookup = NO-HIT\n");
191  }
192  }
193  cam_fsmState = CAM_WAIT_4_REQ;
194  }
195  break;
196  case CAM_UPDATE_REP:
197  //-- Wait some cycles to match the co-simulation --
198  if (cam_updateIdleCnt > 0) {
199  cam_updateIdleCnt--;
200  }
201  else {
202  // [TODO - What if element does not exist]
203  if (cam_update.op == INSERT) {
204  //Is there a check if it already exists?
205  cam_lookupTable[cam_update.key] = cam_update.value;
206  soTOE_SssUpdRep.write(CamSessionUpdateReply(cam_update.value, INSERT, cam_update.source));
207  if (DEBUG_LEVEL & TRACE_CAM) {
208  printInfo(myName, "Successful insertion of session ID #%d for [%s].\n", cam_update.value.to_int(),
209  myCamAccessToString(cam_update.source.to_int()));
210  }
211  }
212  else { // DELETE
213  cam_lookupTable.erase(cam_update.key);
214  soTOE_SssUpdRep.write(CamSessionUpdateReply(cam_update.value, DELETE, cam_update.source));
215  if (DEBUG_LEVEL & TRACE_CAM) {
216  printInfo(myName, "Successful deletion of session ID #%d for [%s].\n", cam_update.value.to_int(),
217  myCamAccessToString(cam_update.source.to_int()));
218  }
219  }
220  cam_fsmState = CAM_WAIT_4_REQ;
221  }
222  break;
223  } // End-of: switch()
224 
225 } // End-of: pEmulateCam()
226 
227 
238 void pEmulateRxBufMem(
239  DummyMemory *memory,
240  int &nrError,
241  stream<DmCmd> &siTOE_RxP_WrCmd,
242  stream<AxisApp> &siTOE_RxP_Data,
243  stream<DmSts> &soTOE_RxP_WrSts,
244  stream<DmCmd> &siTOE_RxP_RdCmd,
245  stream<AxisApp> &soTOE_RxP_Data)
246 {
247  const char *myName = concat3(THIS_NAME, "/", "RXMEM");
248 
249  //-- STATIC VARIABLES ------------------------------------------------------
250  static int rxmem_wrCounter = 0;
251  static int rxmem_rdCounter = 0;
252  static int rxmem_noBytesToWrite = 0;
253  static int rxmem_noBytesToRead = 0;
254  static int rxmem_rdIdleCnt = 0;
255  static int rxmem_wrIdleCnt = 0;
256  static DmCmd rxmem_dmCmd; // Data Mover Command
257 
258  static enum WrStates { WAIT_4_WR_CMD, MWR_DATA, MWR_STS } rxmem_WrState;
259  static enum RdStates { WAIT_4_RD_CMD, MRD_DATA, MRD_STS } rxmem_RdState;
260 
261  //-- DYNAMIC VARIABLES -----------------------------------------------------
262  DmSts dmSts; // Data Mover Status
263 
264  AxisApp tmpInChunk = AxisApp(0, 0, 0);
265  AxisApp inChunk = AxisApp(0, 0, 0);
266  AxisApp outChunk = AxisApp(0, 0, 0);
267  AxisApp tmpOutChunk = AxisApp(0, 0, 0);
268 
269  //-----------------------------------------------------
270  //-- MEMORY WRITE PROCESS
271  //-----------------------------------------------------
272  switch (rxmem_WrState) {
273  case WAIT_4_WR_CMD:
274  if (!siTOE_RxP_WrCmd.empty()) {
275  // Memory Write Command
276  siTOE_RxP_WrCmd.read(rxmem_dmCmd);
277  if (DEBUG_LEVEL & TRACE_RXMEM) {
278  printInfo(myName, "Received memory write command from TOE: (addr=0x%llx, btt=%d).\n",
279  rxmem_dmCmd.saddr.to_uint64(), rxmem_dmCmd.btt.to_uint());
280  }
281  memory->setWriteCmd(rxmem_dmCmd);
282  rxmem_noBytesToWrite = rxmem_dmCmd.btt.to_int();
283  rxmem_wrCounter = 0;
284  rxmem_wrIdleCnt = MEM_WR_CMD_LATENCY;
285  rxmem_WrState = MWR_DATA;
286  }
287  break;
288  case MWR_DATA:
289  if (rxmem_wrIdleCnt > 0) {
290  //-- Emulate the latency of the memory --------
291  rxmem_wrIdleCnt--;
292  }
293  else if (!siTOE_RxP_Data.empty()) {
294  //-- Data Memory Write Transfer ---------------
295  siTOE_RxP_Data.read(tmpInChunk);
296  inChunk = tmpInChunk;
297  memory->writeChunk(inChunk);
298  rxmem_wrCounter += inChunk.getLen();
299  if (inChunk.getTLast() or (rxmem_wrCounter == rxmem_noBytesToWrite)) {
300  rxmem_wrIdleCnt = MEM_WR_STS_LATENCY;
301  rxmem_WrState = MWR_STS;
302  }
303  }
304  break;
305  case MWR_STS:
306  if (rxmem_wrIdleCnt > 0) {
307  //-- Emulate the latency of the memory --------
308  rxmem_wrIdleCnt--;
309  }
310  else if (!soTOE_RxP_WrSts.full()) {
311  //-- Data Memory Write Status -----------------
312  if (rxmem_noBytesToWrite != rxmem_wrCounter) {
313  printError(myName, "The number of bytes received from TOE (%d) does not match the expected number specified by the command (%d)!\n",
314  rxmem_wrCounter, rxmem_noBytesToWrite);
315  nrError += 1;
316  dmSts.okay = 0;
317  }
318  else {
319  dmSts.okay = 1;
320  }
321  soTOE_RxP_WrSts.write(dmSts);
322 
323  if (DEBUG_LEVEL & TRACE_RXMEM) {
324  printInfo(myName, "Sending memory status back to TOE: (OK=%d).\n",
325  dmSts.okay.to_int());
326  }
327  rxmem_WrState = WAIT_4_WR_CMD;
328  }
329  break;
330  } // End of: switch (rxmem_WrState)
331 
332  //-----------------------------------------------------
333  //-- MEMORY READ PROCESS
334  //-----------------------------------------------------
335  switch (rxmem_RdState) {
336  case WAIT_4_RD_CMD:
337  if (!siTOE_RxP_RdCmd.empty()) {
338  // Memory Read Command
339  siTOE_RxP_RdCmd.read(rxmem_dmCmd);
340  if (DEBUG_LEVEL & TRACE_RXMEM) {
341  printInfo(myName, "Received memory read command from TOE: (addr=0x%llx, btt=%d).\n",
342  rxmem_dmCmd.saddr.to_uint64(), rxmem_dmCmd.btt.to_uint());
343  }
344  memory->setReadCmd(rxmem_dmCmd);
345  rxmem_noBytesToRead = rxmem_dmCmd.btt.to_int();
346  rxmem_rdCounter = 0;
347  rxmem_rdIdleCnt = MEM_RD_CMD_LATENCY;
348  rxmem_RdState = MRD_DATA;
349  }
350  break;
351  case MRD_DATA:
352  if (rxmem_rdIdleCnt > 0) {
353  //-- Emulate the latency of the memory --------
354  rxmem_rdIdleCnt--;
355  }
356  else if (!soTOE_RxP_Data.full()) {
357  // Data Memory Read Transfer
358  memory->readChunk(tmpOutChunk);
359  outChunk = tmpOutChunk;
360  rxmem_rdCounter += outChunk.getLen();
361  soTOE_RxP_Data.write(outChunk);
362  if ((outChunk.getTLast()) or (rxmem_rdCounter == rxmem_noBytesToRead)) {
363  rxmem_rdIdleCnt = MEM_RD_STS_LATENCY;
364  rxmem_RdState = MRD_STS;
365  }
366  }
367  break;
368  case MRD_STS:
369  if (rxmem_wrIdleCnt > 0) {
370  //-- Emulate the latency of the memory --------
371  rxmem_wrIdleCnt--;
372  }
373  //-- [TOE] won't send a status back to us
374  rxmem_RdState = WAIT_4_RD_CMD;
375  break;
376  } // End-of: switch (memRdState)
377 
378 } // End of: pEmulateRxBufMem
379 
380 
391 void pEmulateTxBufMem(
392  DummyMemory *memory,
393  int &nrError,
394  stream<DmCmd> &siTOE_TxP_WrCmd,
395  stream<AxisApp> &siTOE_TxP_Data,
396  stream<DmSts> &soTOE_TxP_WrSts,
397  stream<DmCmd> &siTOE_TxP_RdCmd,
398  stream<AxisApp> &soTOE_TxP_Data)
399 {
400  const char *myName = concat3(THIS_NAME, "/", "TXMEM");
401 
402  //-- STATIC VARIABLES ------------------------------------------------------
403  static int txmem_wrCounter = 0;
404  static int txmem_rdCounter = 0;
405  static int txmem_noBytesToWrite = 0;
406  static int txmem_noBytesToRead = 0;
407  static int txmem_wrIdleCnt = 0;
408  static int txmem_rdIdleCnt = 0;
409  static DmCmd txmem_dmCmd; // Data Mover Command
410  static enum WrStates { WAIT_4_WR_CMD, MWR_DATA, MWR_STS } txmem_WrState;
411  static enum RdStates { WAIT_4_RD_CMD, MRD_DATA, MRD_STS } txmem_RdState;
412 
413  //-- DYNAMIC VARIABLES -----------------------------------------------------
414  DmSts dmSts; // Data Mover Status
415  AxisApp tmpInChunk = AxisApp(0, 0, 0);
416  AxisApp inChunk = AxisApp(0, 0, 0);
417  AxisApp outChunk = AxisApp(0, 0, 0);
418  AxisApp tmpOutChunk = AxisApp(0, 0, 0);
419 
420  //-----------------------------------------------------
421  //-- MEMORY WRITE PROCESS
422  //-----------------------------------------------------
423  switch (txmem_WrState) {
424  case WAIT_4_WR_CMD:
425  if (!siTOE_TxP_WrCmd.empty()) {
426  // Memory Write Command -----------------------
427  siTOE_TxP_WrCmd.read(txmem_dmCmd);
428  if (DEBUG_LEVEL & TRACE_TXMEM) {
429  printInfo(myName, "Received memory write command from TOE: (addr=0x%llx, btt=%d).\n",
430  txmem_dmCmd.saddr.to_uint64(), txmem_dmCmd.btt.to_uint());
431  }
432  memory->setWriteCmd(txmem_dmCmd);
433  txmem_noBytesToWrite = txmem_dmCmd.btt.to_int();
434  txmem_wrCounter = 0;
435  txmem_wrIdleCnt = MEM_WR_CMD_LATENCY;
436  txmem_WrState = MWR_DATA;
437  }
438  break;
439  case MWR_DATA:
440  if (txmem_wrIdleCnt > 0) {
441  //-- Emulate the latency of the memory --------
442  txmem_wrIdleCnt--;
443  }
444  else if (!siTOE_TxP_Data.empty()) {
445  //-- Data Memory Write Transfer ---------------
446  siTOE_TxP_Data.read(tmpInChunk);
447  inChunk = tmpInChunk;
448  memory->writeChunk(inChunk);
449  txmem_wrCounter += inChunk.getLen();
450  if (inChunk.getTLast() or (txmem_wrCounter == txmem_noBytesToWrite)) {
451  txmem_wrIdleCnt = MEM_WR_STS_LATENCY;
452  txmem_WrState = MWR_STS;
453  }
454  }
455  break;
456  case MWR_STS:
457  if (txmem_wrIdleCnt > 0) {
458  //-- Data Memory Write Transfer ---------------
459  txmem_wrIdleCnt--;
460  }
461  else if (!soTOE_TxP_WrSts.full()) {
462  //-- Data Memory Write Status -----------------
463  if (txmem_noBytesToWrite != txmem_wrCounter) {
464  printError(myName, "The number of bytes received from TOE (%d) does not match the expected number specified by the command (%d)!\n",
465  txmem_wrCounter, txmem_noBytesToWrite);
466  nrError += 1;
467  dmSts.okay = 0;
468  }
469  else {
470  dmSts.okay = 1;
471  }
472  soTOE_TxP_WrSts.write(dmSts);
473  if (DEBUG_LEVEL & TRACE_TXMEM) {
474  printInfo(myName, "Sending memory status back to TOE: (OK=%d).\n",
475  dmSts.okay.to_int());
476  }
477  txmem_WrState = WAIT_4_WR_CMD;
478  }
479  break;
480  } // End-of: switch(txmem_WrState)
481 
482  //-----------------------------------------------------
483  //-- MEMORY READ PROCESS
484  //-----------------------------------------------------
485  switch (txmem_RdState) {
486  case WAIT_4_WR_CMD:
487  if (!siTOE_TxP_RdCmd.empty()) {
488  // Memory Read Command
489  siTOE_TxP_RdCmd.read(txmem_dmCmd);
490  if (DEBUG_LEVEL & TRACE_TXMEM) {
491  printInfo(myName, "Received memory read command from TOE: (addr=0x%llx, btt=%d).\n",
492  txmem_dmCmd.saddr.to_uint64(), txmem_dmCmd.btt.to_uint());
493  }
494  memory->setReadCmd(txmem_dmCmd);
495  txmem_noBytesToRead = txmem_dmCmd.btt.to_int();
496  txmem_rdCounter = 0;
497  txmem_rdIdleCnt = MEM_RD_CMD_LATENCY;
498  txmem_RdState = MRD_DATA;
499  }
500  break;
501  case MRD_DATA:
502  if (txmem_rdIdleCnt > 0) {
503  //-- Emulate the latency of the memory --------
504  txmem_rdIdleCnt--;
505  }
506  else if (!soTOE_TxP_Data.full()) {
507  // Data Memory Read Transfer
508  memory->readChunk(tmpOutChunk);
509  outChunk = tmpOutChunk;
510  txmem_rdCounter += outChunk.getLen();
511  soTOE_TxP_Data.write(outChunk);
512  if (outChunk.getTLast() or (txmem_rdCounter == txmem_noBytesToRead)) {
513  txmem_rdIdleCnt = MEM_RD_STS_LATENCY;
514  txmem_RdState = MRD_STS;
515  }
516  }
517  break;
518  case MRD_STS:
519  //-- Wait some cycles to match the co-simulation --
520  if (txmem_rdIdleCnt > 0) {
521  //-- Emulate the latency of the memory --------
522  txmem_rdIdleCnt--;
523  }
524  //-- [TOE] won't send a status back to us
525  txmem_RdState = WAIT_4_RD_CMD;
526  break;
527  } // End-of: switch(memRdState)
528 
529 } // End of: pEmulateTxBufMem
530 
531 
548 bool setGlobalParameters(const char *callerName, unsigned int startupDelay, ifstream &inputFile)
549 {
550  char myName[120];
551  strcpy(myName, callerName);
552  strcat(myName, "/setGlobalParameters");
553 
554  string rxStringBuffer;
555  vector<string> stringVector;
556 
557  do {
558  //-- READ ONE LINE AT A TIME FROM INPUT FILE ---------------
559  getline(inputFile, rxStringBuffer);
560  stringVector = myTokenizer(rxStringBuffer, ' ');
561 
562  if (stringVector[0] == "") {
563  continue;
564  }
565  else if (stringVector[0].length() == 1) {
566  // By convention, a global parameter must start with a single 'G' character.
567  if ((stringVector[0] == "G") and (stringVector[1] == "PARAM")) {
568  if (stringVector[2] == "SimCycles") {
569  // The test vector file is specifying a minimum number of simulation cycles.
570  int noSimCycles = atoi(stringVector[3].c_str());
571  noSimCycles += startupDelay;
572  if (noSimCycles > gMaxSimCycles) {
573  gMaxSimCycles = noSimCycles;
574  }
575  if ((DEBUG_LEVEL & TRACE_IPRX) or (DEBUG_LEVEL & TRACE_TAIF)) {
576  printInfo(myName, "Requesting the simulation to last for %d cycles. \n", gMaxSimCycles);
577  }
578  }
579  else if (stringVector[2] == "FpgaIp4Addr") {
580  char * ptr;
581  // Retrieve the IPv4 address to set
582  unsigned int ip4Addr;
583  if (isDottedDecimal(stringVector[3]))
584  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
585  else if (isHexString(stringVector[3]))
586  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 16);
587  else
588  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 10);
589  gFpgaIp4Addr = ip4Addr;
590  printInfo(myName, "Redefining the default FPGA IPv4 address to be: ");
591  printIp4Addr(myName, gFpgaIp4Addr);
592  }
593  else if (stringVector[2] == "FpgaLsnPort") {
594  char * ptr;
595  // Retrieve the TCP-Port to set
596  unsigned int tcpPort;
597  if (isHexString(stringVector[3]))
598  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 16);
599  else
600  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 10);
601  gFpgaLsnPort = tcpPort;
602  printInfo(myName, "Redefining the default FPGA listen port to be: ");
603  printTcpPort(myName, gFpgaLsnPort);
604  }
605  else if (stringVector[2] == "HostIp4Addr") {
606  char * ptr;
607  // Retrieve the IPv4 address to set
608  unsigned int ip4Addr;
609  if (isDottedDecimal(stringVector[3]))
610  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
611  else if (isHexString(stringVector[3]))
612  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 16);
613  else
614  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 10);
615  gHostIp4Addr = ip4Addr;
616  printInfo(myName, "Redefining the default HOST IPv4 address to be: ");
617  printIp4Addr(myName, gHostIp4Addr);
618  }
619  else if (stringVector[2] == "HostLsnPort") {
620  char * ptr;
621  // Retrieve the TCP-Port to set
622  unsigned int tcpPort;
623  if (isHexString(stringVector[3]))
624  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 16);
625  else
626  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 10);
627  gHostLsnPort = tcpPort;
628  printInfo(myName, "Redefining the default HOST listen port to be: \n");
629  printTcpPort(myName, gHostLsnPort);
630  }
631  else if (stringVector[2] == "SortTaifGold") {
632  if (stringVector[3] == "true") {
633  gSortTaifGold = true;
634  printInfo(callerName, "Requesting the 'soTAIF.gold' file to be sorted.\n");
635  }
636  else {
637  gSortTaifGold = false;
638  printInfo(callerName, "Disabling the sorting of the 'soTAIF.gold' file.\n");
639  }
640  }
641  else if (stringVector[2] == "FpgaServerSocket") { // DEPRECATED
642  printFatal(myName, "The global parameter \'FpgaServerSockett\' is not supported anymore.\n\tPLEASE UPDATE YOUR TEST VECTOR FILE ACCORDINGLY.\n");
643  }
644  else if (stringVector[2] == "ForeignSocket") { // DEPRECATED
645  printFatal(myName, "The global parameter \'ForeignSocket\' is not supported anymore.\n\tPLEASE UPDATE YOUR TEST VECTOR FILE ACCORDINGLY.\n");
646  exit(1);
647  }
648  else if (stringVector[2] == "LocalSocket") { // DEPRECATED
649  printFatal(myName, "The global parameter \'LocalSocket\' is not supported anymore.\n\tPLEASE UPDATE YOUR TESTVECTOR FILE ACCORDINGLY.\n");
650  }
651  else {
652  printError(myName, "Unknown parameter \'%s\'.\n", stringVector[2].c_str());
653  return false;
654  }
655  }
656  else
657  continue;
658  }
659  } while(!inputFile.eof());
660 
661  if ((DEBUG_LEVEL & TRACE_IPRX) or (DEBUG_LEVEL & TRACE_TAIF)) {
662  printInfo(myName, "Done with the parsing of the input test file.\n");
663  }
664 
665  // Seek back to the start of stream
666  inputFile.clear();
667  inputFile.seekg(0, ios::beg);
668 
669  return true;
670 
671 } // End of: setGlopbalParameters
672 
673 
690 void cmdSetCommandParser(const char *callerName, vector<string> stringVector) {
691  if (stringVector[2] == "HostIp4Addr") {
692  //--------------------------------------------
693  //-- COMMAND = Set the active host IP address
694  //--------------------------------------------
695  char * ptr;
696  // Retrieve the IPv4 address to set
697  unsigned int ip4Addr;
698  if (isDottedDecimal(stringVector[3]))
699  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
700  else if (isHexString(stringVector[3]))
701  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 16);
702  else
703  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 10);
704  gHostIp4Addr = ip4Addr;
705  printInfo(callerName, "Setting the current HOST IPv4 address to be: \n");
706  printIp4Addr(callerName, gHostIp4Addr);
707  }
708  else if (stringVector[2] == "HostLsnPort") {
709  //---------------------------------------------
710  //-- COMMAND = Set the active host listen port
711  //---------------------------------------------
712  char * ptr;
713  // Retrieve the TCP-Port to set
714  unsigned int tcpPort;
715  if (isHexString(stringVector[3]))
716  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 16);
717  else
718  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 10);
719  gHostLsnPort = tcpPort;
720  printInfo(callerName, "Setting the current HOST listen port to be: \n");
721  printTcpPort(callerName, gHostLsnPort);
722  }
723  else if (stringVector[2] == "FpgaLsnPort") {
724  //---------------------------------------------
725  //-- COMMAND = Set the active fpga listen port
726  //---------------------------------------------
727  char * ptr;
728  // Retrieve the TCP-Port to set
729  unsigned int tcpPort;
730  if (isHexString(stringVector[3]))
731  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 16);
732  else
733  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 10);
734  gFpgaLsnPort = tcpPort;
735  printInfo(callerName, "Setting the current FPGA listen port to be: \n");
736  printTcpPort(callerName, gFpgaLsnPort);
737  }
738  else if (stringVector[2] == "HostServerSocket") {
739  //------------------------------------------------------
740  //-- COMMAND = Set the active host server socket
741  //-- If socket does not exist, host must create, bind,
742  //-- listen and accept new connections from the client.
743  //------------------------------------------------------
744  char *pEnd;
745  // Retrieve the current foreign IPv4 address to set
746  unsigned int ip4Addr;
747  if (isDottedDecimal(stringVector[3]))
748  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
749  else if (isHexString(stringVector[3]))
750  ip4Addr = strtoul(stringVector[3].c_str(), &pEnd, 16);
751  else
752  ip4Addr = strtoul(stringVector[3].c_str(), &pEnd, 10);
753  gHostIp4Addr = ip4Addr;
754  // Retrieve the current foreign TCP-Port to set
755  unsigned int tcpPort;
756  if (isHexString(stringVector[4]))
757  tcpPort = strtoul(stringVector[4].c_str(), &pEnd, 16);
758  else
759  tcpPort = strtoul(stringVector[4].c_str(), &pEnd, 10);
760  gHostLsnPort = tcpPort;
761  SockAddr newHostServerSocket(gHostIp4Addr, gHostLsnPort);
762  printInfo(callerName, "Setting current host server socket to be: \n");
763  printSockAddr(callerName, newHostServerSocket);
764  }
765  return;
766 }
767 
768 
787 void cmdTestCommandParser(const char *callerName, vector<string> stringVector) {
788  //-- RECEIVE CHECKERS -------------
789  if (stringVector[2] == "RcvdIp4Packet") {
790  if (stringVector[3] == "false") {
791  gTest_RcvdIp4Packet = false;
792  printWarn(callerName, "Disabling receive IPv4 checker.\n");
793  }
794  else {
795  gTest_RcvdIp4Packet = true;
796  printWarn(callerName, "Enabling receive IPv4 checker.\n");
797  }
798  }
799  else if (stringVector[2] == "RcvdIp4TotLen") {
800  if (stringVector[3] == "false") {
801  gTest_RcvdIp4TotLen = false;
802  printWarn(callerName, "Disabling receive IPv4-Total-Length checker.\n");
803  }
804  else {
805  gTest_RcvdIp4HdrCsum = true;
806  printWarn(callerName, "Enabling receive IPv4-Total_Length checker.\n");
807  }
808  }
809  else if (stringVector[2] == "RcvdIp4HdrCsum") {
810  if (stringVector[3] == "false") {
811  gTest_RcvdIp4HdrCsum = false;
812  printWarn(callerName, "Disabling receive IPv4-Header-Checksum checker.\n");
813  }
814  else {
815  gTest_RcvdIp4HdrCsum = true;
816  printWarn(callerName, "Enabling receive IPv4-Header-Checksum checker.\n");
817  }
818  }
819  else if (stringVector[2] == "RcvdUdpLen") {
820  if (stringVector[3] == "false") {
821  gTest_RcvdUdpLen = false;
822  printWarn(callerName, "Disabling receive UDP-Length Checker.\n");
823  }
824  else {
825  gTest_RcvdUdpLen = true;
826  printWarn(callerName, "Enabling receive IPv4-Header-Checksum checker.\n");
827  }
828  }
829  else if (stringVector[2] == "RcvdLy4Csum") {
830  if (stringVector[3] == "false") {
831  gTest_RcvdLy4Csum = false;
832  printWarn(callerName, "Disabling receive TCP|UDP-Checksum checker.\n");
833  }
834  else {
835  gTest_RcvdUdpLen = true;
836  printWarn(callerName, "Enabling receive TCP|UDP-Checksum checker.\n");
837  }
838  }
839  //-- SEND CHECKERS ----------------
840  if (stringVector[2] == "SentIp4TotLen") {
841  if (stringVector[3] == "false") {
842  gTest_SentIp4TotLen = false;
843  printWarn(callerName, "Disabling send IPv4-Total-Length checker.\n");
844  }
845  else {
846  gTest_SentIp4HdrCsum = true;
847  printWarn(callerName, "Enabling send IPv4-Total_Length checker.\n");
848  }
849  }
850  else if (stringVector[2] == "SentIp4HdrCsum") {
851  if (stringVector[3] == "false") {
852  gTest_SentIp4HdrCsum = false;
853  printWarn(callerName, "Disabling send IPv4-Header-Checksum checker.\n");
854  }
855  else {
856  gTest_SentIp4HdrCsum = true;
857  printWarn(callerName, "Enabling send IPv4-Header-Checksum checker.\n");
858  }
859  }
860  else if (stringVector[2] == "SentUdpLen") {
861  if (stringVector[3] == "false") {
862  gTest_SentUdpLen = false;
863  printWarn(callerName, "Disabling send UDP-Length Checker.\n");
864  }
865  else {
866  gTest_SentUdpLen = true;
867  printWarn(callerName, "Enabling send IPv4-Header-Checksum checker.\n");
868  }
869  }
870  else if (stringVector[2] == "SentLy4Csum") {
871  if (stringVector[3] == "false") {
872  gTest_SentLy4Csum = false;
873  printWarn(callerName, "Disabling send TCP|UDP-Checksum checker.\n");
874  }
875  else {
876  gTest_SentUdpLen = true;
877  printWarn(callerName, "Enabling send TCP|UDP-Checksum checker.\n");
878  }
879  }
880  return;
881 }
882 
883 
884 
894  SimIp4Packet &ipRxPacket,
895  map<SocketPair, TcpAckNum> &sessAckList)
896 {
897  const char *myName = concat3(THIS_NAME, "/", "IPRX/InjectAck");
898 
899  SockAddr srcSock = SockAddr(ipRxPacket.getIpSourceAddress(),
900  ipRxPacket.getTcpSourcePort());
901  SockAddr dstSock = SockAddr(ipRxPacket.getIpDestinationAddress(),
902  ipRxPacket.getTcpDestinationPort());
903  SocketPair newSockPair = SocketPair(srcSock, dstSock);
904 
905  if (ipRxPacket.isSYN()) {
906  // This packet is a SYN and there's no need to inject anything
907  if (DEBUG_LEVEL & TRACE_IPRX) { printInfo(myName, "Packet is SYN\n"); }
908  if (sessAckList.find(newSockPair) != sessAckList.end()) {
909  printWarn(myName, "Trying to open an existing session !\n");
910  printSockPair(myName, newSockPair);
911  return -1;
912  }
913  else {
914  // Let's check the pseudo-header checksum of the packet
915  int computedCsum = ipRxPacket.tcpRecalculateChecksum();
916  int embeddedCsum = ipRxPacket.getTcpChecksum();
917  if (computedCsum != embeddedCsum) {
918  printError(myName, "WRONG PSEUDO-HEADER CHECKSUM (0x%4.4X) - Expected 0x%4.4X \n",
919  embeddedCsum, byteSwap16(computedCsum).to_uint());
920  return -1;
921  }
922  else {
923  // Create a new entry (with TcpAckNum=0) in the session table
924  sessAckList[newSockPair] = 0;
925  if (DEBUG_LEVEL & TRACE_IPRX) {
926  printInfo(myName, "Successfully opened a new session for connection:\n");
927  printSockPair(myName, newSockPair);
928  }
929  return 0;
930  }
931  }
932  }
933  else if (ipRxPacket.isACK()) {
934  // This packet is an ACK and we must update the its acknowledgment number
935  if (DEBUG_LEVEL & TRACE_IPRX) { printInfo(myName, "Packet is ACK\n"); }
936  if (sessAckList.find(newSockPair) != sessAckList.end()) {
937  // Inject the oldest acknowledgment number in the ACK number field
938  TcpAckNum newAckNum = sessAckList[newSockPair];
939  ipRxPacket.setTcpAcknowledgeNumber(newAckNum);
940  if (DEBUG_LEVEL & TRACE_IPRX)
941  printInfo(myName, "Setting the TCP Acknowledge of this segment to: %u (0x%8.8X) \n",
942  newAckNum.to_uint(), byteSwap32(newAckNum).to_uint());
943  // Recalculate and update the checksum
944  int oldCsum = ipRxPacket.getTcpChecksum();
945  int newCsum = ipRxPacket.tcpRecalculateChecksum();
946  if (DEBUG_LEVEL & TRACE_IPRX)
947  printInfo(myName, "Updating the checksum of this packet from 0x%4.4X to 0x%4.4X\n",
948  oldCsum, newCsum);
949  if (DEBUG_LEVEL & TRACE_IPRX) { ipRxPacket.printRaw(myName); }
950  return 1;
951  }
952  else {
953  printWarn(myName, "Trying to send data to a non-existing session! \n");
954  return -1;
955  }
956  }
957  return -1;
958 } // End of: injectAckNumber()
959 
960 
961 
976 void pIPRX_FeedTOE(
977  deque<SimIp4Packet> &ipRxPacketizer,
978  int &ipRxPktCounter,
979  stream<AxisIp4> &soTOE_Data,
980  map<SocketPair, TcpAckNum> &sessAckList)
981 {
982  const char *myName = concat3(THIS_NAME, "/", "IPRX/FeedToe");
983 
984  if (ipRxPacketizer.size() != 0) {
985  // Insert proper ACK Number in packet at the head of the queue
986  pIPRX_InjectAckNumber(ipRxPacketizer[0], sessAckList);
987  // Assert proper SEQ Number in packet
988  // [TODO]
989  if (DEBUG_LEVEL & TRACE_IPRX) {
990  ipRxPacketizer[0].printHdr(myName);
991  }
992  // Write stream IPRX->TOE
993  int noPackets= ipRxPacketizer.size();
994  for (int p=0; p<noPackets; p++) {
995  SimIp4Packet ipRxPacket = ipRxPacketizer.front();
996  AxisIp4 ip4Chunk;
997  do {
998  ip4Chunk = ipRxPacket.pullChunk();
999  if (not soTOE_Data.full()) {
1000  soTOE_Data.write(ip4Chunk);
1001  }
1002  else {
1003  printFatal(myName, "Cannot write \'soTOE_Data\'. Stream is full!\n");
1004  }
1005  } while (!ip4Chunk.getTLast());
1006  ipRxPktCounter++;
1007  ipRxPacketizer.pop_front();
1008  }
1009  }
1010 }
1011 
1012 
1013 
1039 void pIPRX(
1040  ifstream &ifIPRX_Data,
1041  ofstream &ofTAIF_Gold,
1042  bool &testRxPath,
1043  int &ipRxPktCounter,
1044  int &tcpBytCntr_IPRX_TOE,
1045  deque<SimIp4Packet> &ipRxPacketizer,
1046  map<SocketPair, TcpAckNum> &sessAckList,
1047  StsBit &piTOE_Ready,
1048  stream<AxisIp4> &soTOE_Data)
1049 {
1050  const char *myName = concat3(THIS_NAME, "/", "IPRX");
1051 
1052  //-- STATIC VARIABLES ------------------------------------------------------
1053  static bool iprx_globParseDone = false;
1054  static bool iprx_idlingReq = false; // Request to idle (.i.e, do not feed TOE's input stream)
1055  static unsigned int iprx_idleCycReq = 0; // The requested number of idle cycles
1056  static unsigned int iprx_idleCycCnt = 0; // The count of idle cycles
1057  static unsigned int iprx_toeReadyDelay = 0; // The time it takes for TOE to be ready
1058  static int iprx_inpPackets = 0; // Counts the number of packets fed to [TOE].
1059 
1060  //-- DYNAMIC VARIABLES -----------------------------------------------------
1061  string rxStringBuffer;
1062  vector<string> stringVector;
1063 
1064  //---------------------------------------
1065  //-- STEP-0 : RETURN IF TOE IS NOT READY
1066  //---------------------------------------
1067  if (piTOE_Ready == 0) {
1068  iprx_toeReadyDelay++;
1069  return;
1070  }
1071 
1072  //-------------------------------------------------------------------------
1073  //-- STEP-1: PARSE THE IP RX FILE.
1074  // THIS FIRST PASS WILL SPECIFICALLY SEARCH FOR GLOBAL PARAMETERS.
1075  //-------------------------------------------------------------------------
1076  if (!iprx_globParseDone) {
1077  iprx_globParseDone = setGlobalParameters(myName, iprx_toeReadyDelay, ifIPRX_Data);
1078  if (iprx_globParseDone == false) {
1079  printInfo(myName, "Aborting testbench (check for previous error).\n");
1080  exit(1);
1081  }
1082  return;
1083  }
1084 
1085  //-----------------------------------------------------
1086  //-- STEP-2 : ALWAYS FEED the IP Rx INTERFACE
1087  //-----------------------------------------------------
1088  // Note: The IPv4 RxPacketizer may contain an ACK packet generated by the
1089  // process which emulates the Ip Tx Handler (.i.e, pITPX).
1090  // Therefore, we start by flushing these packets (if any) before reading a
1091  // new packet from the IP Rx input file.
1092  // We also drain any existing packet before emulating the IDLE time.
1093  pIPRX_FeedTOE(ipRxPacketizer, ipRxPktCounter, soTOE_Data, sessAckList);
1094 
1095  //------------------------------------------
1096  //-- STEP-3 : RETURN IF IDLING IS REQUESTED
1097  //------------------------------------------
1098  if (iprx_idlingReq == true) {
1099  if (iprx_idleCycCnt >= iprx_idleCycReq) {
1100  iprx_idleCycCnt = 0;
1101  iprx_idlingReq = false;
1102  }
1103  else {
1104  iprx_idleCycCnt++;
1105  }
1106  return;
1107  }
1108 
1109  //-------------------------------------------------------------------------
1110  //-- STEP-4: QUIT HERE IF RX TEST MODE IS DISABLED OR EOF IS REACHED
1111  //-------------------------------------------------------------------------
1112  if ((not testRxPath) || (ifIPRX_Data.eof()))
1113  return;
1114 
1115  //------------------------------------------------------
1116  //-- STEP-? : [TODO] CHECK IF CURRENT LOCAL SOCKET IS LISTENING
1117  //------------------------------------------------------
1118  // SocketPair currSocketPair(gLocalSocket, currForeignSocket);
1119  // isOpen = pTAIF_Send_OpenSess(currSocketPair, openSessList, soTOE_OpnReq, siTOE_OpnRep);
1120  // if (!isOpen)
1121  // return;
1122 
1123  //-----------------------------------------------------
1124  //-- STEP-5 : READ THE IP RX FILE
1125  //-----------------------------------------------------
1126  do {
1127  //-- READ A LINE FROM IPRX INPUT FILE -------------
1128  getline(ifIPRX_Data, rxStringBuffer);
1129  stringVector = myTokenizer(rxStringBuffer, ' ');
1130  if (stringVector[0] == "") {
1131  continue;
1132  }
1133  else if (stringVector[0].length() == 1) {
1134  //------------------------------------------------------
1135  //-- Process the command and comment lines
1136  //-- FYI: A command or a comment start with a single
1137  //-- character followed by a space character.
1138  //------------------------------------------------------
1139  if (stringVector[0] == "#") {
1140  // This is a comment line
1141  if (DEBUG_LEVEL & TRACE_IPRX) {
1142  for (int t=0; t<stringVector.size(); t++) {
1143  printf("%s ", stringVector[t].c_str());
1144  }
1145  printf("\n");
1146  }
1147  continue;
1148  }
1149  else if (stringVector[0] == "G") {
1150  // We can skip all the global parameters as they were already parsed.
1151  continue;
1152  }
1153  else if (stringVector[0] == ">") {
1154  // The test vector is issuing a command
1155  // FYI, don't forget to return at the end of command execution.
1156  if (stringVector[1] == "IDLE") {
1157  // COMMAND = Request to idle for <NUM> cycles.
1158  iprx_idleCycReq = atoi(stringVector[2].c_str());
1159  iprx_idlingReq = true;
1160  if (DEBUG_LEVEL & TRACE_IPRX) {
1161  printInfo(myName, "Request to idle for %d cycles. \n", iprx_idleCycReq);
1162  }
1163  increaseSimTime(iprx_idleCycReq);
1164  return;
1165  }
1166  if (stringVector[1] == "SET") {
1167  cmdSetCommandParser(myName, stringVector);
1168  return;
1169  }
1170  if (stringVector[1] == "TEST") {
1171  cmdTestCommandParser(myName, stringVector);
1172  return;
1173  }
1174  else {
1175  printFatal(myName, "Read unknown command \"> %s\".\n", stringVector[1].c_str());
1176  }
1177  }
1178  }
1179  else if (ifIPRX_Data.fail() == 1 || rxStringBuffer.empty()) {
1180  return;
1181  }
1182  else {
1183  SimIp4Packet ipRxPacket;
1184  AxisIp4 ipRxChunk;
1185  bool firstChunkFlag = true; // Flags the first chunk of a packet
1186  // Build a new packet from data file
1187  do {
1188  if (firstChunkFlag == false) {
1189  getline(ifIPRX_Data, rxStringBuffer);
1190  stringVector = myTokenizer(rxStringBuffer, ' ');
1191  }
1192  if (stringVector[0] == "#") {
1193  // This is a comment line
1194  if (DEBUG_LEVEL & TRACE_IPRX) {
1195  for (int t=0; t<stringVector.size(); t++) {
1196  printf("%s ", stringVector[t].c_str());
1197  }
1198  printf("\n");
1199  }
1200  continue;
1201  }
1202  firstChunkFlag = false;
1203  bool rc = readAxisRawFromLine(ipRxChunk, rxStringBuffer);
1204  if (rc) {
1205  ipRxPacket.pushChunk(ipRxChunk);
1206  increaseSimTime(1);
1207  }
1208  } while (not ipRxChunk.getTLast());
1209  iprx_inpPackets++;
1210 
1211  // Check consistency of the assembled packet
1212  bool wellFormed = ipRxPacket.isWellFormed(myName,
1215  if (not wellFormed) {
1216  printFatal(myName, "IP packet #%d is malformed!\n", iprx_inpPackets);
1217  }
1218  else {
1219  // Count the number of data bytes contained in the TCP payload
1220  tcpBytCntr_IPRX_TOE += ipRxPacket.sizeOfTcpData();
1221  // Write to the Application Tx Gold file
1222  if (gTest_RcvdIp4Packet) {
1223  ipRxPacket.writeTcpDataToDatFile(ofTAIF_Gold);
1224  }
1225  // Push that packet into the packetizer queue and feed the TOE
1226  ipRxPacketizer.push_back(ipRxPacket);
1227  pIPRX_FeedTOE(ipRxPacketizer, ipRxPktCounter, soTOE_Data, sessAckList);
1228  }
1229  return;
1230  }
1231 
1232  } while(!ifIPRX_Data.eof());
1233 
1234 } // End of: pIPRX
1235 
1236 
1237 
1252 bool pIPTX_Parse(
1253  SimIp4Packet &ipTxPacket,
1254  map<SocketPair, TcpAckNum> &sessAckList,
1255  deque<SimIp4Packet> &ipRxPacketizer)
1256 {
1257  bool returnValue = false;
1258  bool isFinAck = false;
1259  bool isSynAck = false;
1260  static int currAckNum = 0;
1261 
1262  const char *myName = concat3(THIS_NAME, "/", "IPTX/Parse");
1263 
1264  if (DEBUG_LEVEL & TRACE_IPTX) {
1265  ipTxPacket.printHdr(myName);
1266  }
1267 
1268  if (ipTxPacket.isSYN() and !ipTxPacket.isACK()) {
1269  //------------------------------------------------------
1270  // This is a SYN segment. Reply with a SYN+ACK packet.
1271  //------------------------------------------------------
1272  if (DEBUG_LEVEL & TRACE_IPTX) {
1273  printInfo(myName, "Got a SYN from TOE. Replying with a SYN+ACK.\n");
1274  }
1275  SimIp4Packet synAckPacket;
1276  synAckPacket.clone(ipTxPacket);
1277  // Swap IP_SA and IP_DA
1278  synAckPacket.setIpDestinationAddress(ipTxPacket.getIpSourceAddress());
1279  synAckPacket.setIpSourceAddress(ipTxPacket.getIpDestinationAddress());
1280  // Swap TCP_SP and TCP_DP
1281  synAckPacket.setTcpDestinationPort(ipTxPacket.getTcpSourcePort());
1282  synAckPacket.setTcpSourcePort(ipTxPacket.getTcpDestinationPort());
1283  // Set the SEQ to zero (for simplicity) and ACK to (received SEQ+1)
1284  synAckPacket.setTcpSequenceNumber(0);
1285  synAckPacket.setTcpAcknowledgeNumber(ipTxPacket.getTcpSequenceNumber() + 1);
1286  // Set the ACK bit and Recalculate the Checksum
1287  synAckPacket.setTcpControlAck(1);
1288  int newTcpCsum = synAckPacket.tcpRecalculateChecksum();
1289  synAckPacket.setTcpChecksum(newTcpCsum);
1290  // Add the created SYN+ACK packet to the ipRxPacketizer
1291  ipRxPacketizer.push_back(synAckPacket);
1292  }
1293  else if (ipTxPacket.isFIN() and !ipTxPacket.isACK()) {
1294  //------------------------------------------------------
1295  // This is a FIN segment. Close the connection.
1296  //------------------------------------------------------
1297  // Retrieve the initial socket pair information.
1298  // Note how we call the constructor with swapped source and destination.
1299  // Destination is now the former source and vice-versa.
1300  SockAddr srcSock = SockAddr(ipTxPacket.getIpSourceAddress(),
1301  ipTxPacket.getTcpSourcePort());
1302  SockAddr dstSock = SockAddr(ipTxPacket.getIpDestinationAddress(),
1303  ipTxPacket.getTcpDestinationPort());
1304  SocketPair sockPair(dstSock, srcSock);
1305  if (DEBUG_LEVEL & TRACE_IPTX) {
1306  printInfo(myName, "Got a FIN from TOE. Closing the following connection:\n");
1307  printSockPair(myName, sockPair);
1308  }
1309  // Erase the socket pair for this session from the map.
1310  sessAckList.erase(sockPair);
1311  }
1312  else if (ipTxPacket.isACK()) {
1313  //---------------------------------------
1314  // This is an ACK segment.
1315  //---------------------------------------
1316  returnValue = true;
1317  // Retrieve IP packet length and TCP sequence numbers
1318  int ip4PktLen = ipTxPacket.getIpTotalLength();
1319  int nextAckNum = ipTxPacket.getTcpSequenceNumber();
1320  currAckNum = ipTxPacket.getTcpAcknowledgeNumber();
1321  // Retrieve the initial socket pair information.
1322  // Note how we call the constructor with swapped source and destination.
1323  // Destination is now the former source and vice-versa.
1324  SockAddr srcSock = SockAddr(ipTxPacket.getIpSourceAddress(),
1325  ipTxPacket.getTcpSourcePort());
1326  SockAddr dstSock = SockAddr(ipTxPacket.getIpDestinationAddress(),
1327  ipTxPacket.getTcpDestinationPort());
1328  SocketPair sockPair(dstSock, srcSock);
1329 
1330  if (ipTxPacket.isFIN() and !ipTxPacket.isSYN()) {
1331  // The FIN bit is also set
1332  nextAckNum++; // A FIN consumes 1 sequence #
1333  if (DEBUG_LEVEL & TRACE_IPTX)
1334  printInfo(myName, "Got a FIN+ACK from TOE.\n");
1335  }
1336  else if (ipTxPacket.isSYN() and !ipTxPacket.isFIN()) {
1337  // The SYN bit is also set
1338  nextAckNum++; // A SYN consumes 1 sequence #
1339  if (DEBUG_LEVEL & TRACE_IPTX)
1340  printInfo(myName, "Got a SYN+ACK from TOE.\n");
1341  }
1342  else if (ipTxPacket.isFIN() and ipTxPacket.isSYN()) {
1343  printError(myName, "Got a SYN+FIN+ACK from TOE.\n");
1344  // [FIXME - MUST CREATE AND INCREMENT A GLOBAL ERROR COUNTER]
1345  }
1346  else if (ip4PktLen >= 40) {
1347  // Decrement by 40B (.i.e, 20B of IP Header + 20B of TCP Header
1348  // [FIXME - What if we add options???]
1349  // [TODO - Print the TCP options ]
1350  ip4PktLen -= 40;
1351  nextAckNum += ip4PktLen;
1352  }
1353 
1354  // Update the Session List with the new sequence number
1355  sessAckList[sockPair] = nextAckNum;
1356  if (ipTxPacket.isFIN()) {
1357  //------------------------------------------------
1358  // This is an ACK+FIN segment.
1359  //------------------------------------------------
1360  isFinAck = true;
1361  if (DEBUG_LEVEL & TRACE_IPTX)
1362  printInfo(myName, "Got an ACK+FIN from TOE.\n");
1363  // Erase this session from the list
1364  int itemsErased = sessAckList.erase(sockPair);
1365  if (itemsErased != 1) {
1366  printError(myName, "Received a ACK+FIN segment for a non-existing session. \n");
1367  printSockPair(myName, sockPair);
1368  // [FIXME - MUST CREATE AND INCREMENT A GLOBAL ERROR COUNTER]
1369  }
1370  else {
1371  if (DEBUG_LEVEL & TRACE_IPTX) {
1372  printInfo(myName, "Connection was successfully closed.\n");
1373  printSockPair(myName, sockPair);
1374  }
1375  }
1376  } // End of: isFIN
1377  if (ip4PktLen > 0 and !isFinAck) {
1378  //--------------------------------------------------------
1379  // ACK segment contains more data and is not a FIN+ACK.
1380  // Reply with an empty ACK packet.
1381  //--------------------------------------------------------
1382  SimIp4Packet ackPacket(40); // [FIXME - What if we generate options ???]
1383  // [TODO - Add TCP Window option]
1384  // Set IP protocol field to TCP
1385  ackPacket.setIpProtocol(IP4_PROT_TCP);
1386  // Swap IP_SA and IP_DA
1387  ackPacket.setIpDestinationAddress(ipTxPacket.getIpSourceAddress());
1388  ackPacket.setIpSourceAddress(ipTxPacket.getIpDestinationAddress());
1389  // Swap TCP_SP and TCP_DP
1390  ackPacket.setTcpDestinationPort(ipTxPacket.getTcpSourcePort());
1391  ackPacket.setTcpSourcePort(ipTxPacket.getTcpDestinationPort());
1392  // Swap the SEQ and ACK Numbers while incrementing the ACK
1393  ackPacket.setTcpSequenceNumber(currAckNum);
1394  ackPacket.setTcpAcknowledgeNumber(nextAckNum);
1395  // Set the ACK bit and un-set the FIN bit
1396  ackPacket.setTcpControlAck(1);
1397  ackPacket.setTcpControlFin(0);
1398  // Set the Window size
1399  ackPacket.setTcpWindow(7777);
1400  // Recalculate the Checksum
1401  int newTcpCsum = ackPacket.tcpRecalculateChecksum();
1402  ackPacket.setTcpChecksum(newTcpCsum);
1403  // Add the created ACK packet to the ipRxPacketizer
1404  ipRxPacketizer.push_back(ackPacket);
1405  currAckNum = nextAckNum;
1406  }
1407  }
1408  return returnValue;
1409 } // End of: pIPTX_Parse()
1410 
1411 
1412 
1434 void pIPTX(
1435  StsBit &piTOE_Ready,
1436  stream<AxisIp4> &siTOE_Data,
1437  ofstream &ofIPTX_Data1,
1438  ofstream &ofIPTX_Data2,
1439  map<SocketPair, TcpAckNum> &sessAckList,
1440  int &pktCounter_TOE_IPTX,
1441  int &tcpBytCntr_TOE_IPTX,
1442  deque<SimIp4Packet> &ipRxPacketizer)
1443 {
1444  const char *myName = concat3(THIS_NAME, "/", "IPTX");
1445 
1446  //-- STATIC VARIABLES ------------------------------------------------------
1447  static SimIp4Packet iptx_ipPacket;
1448  static int iptx_rttSim = RTT_LINK;
1449  // [TODO] static ap_shift_reg<SimIp4Packet, RTT_LINK> rttPktBuffer; // A shift reg. holding RTT packets
1450 
1451 
1452  //-- DYNAMIC VARIABLES -----------------------------------------------------
1453  AxisIp4 ipTxChunk; // An IP4 chunk
1454  uint16_t ipTxChunkCounter = 0;
1455 
1456  //---------------------------------------
1457  //-- STEP-0 : RETURN IF TOE IS NOT READY
1458  //---------------------------------------
1459  if (piTOE_Ready == 0) {
1460  return;
1461  }
1462 
1463  if (!siTOE_Data.empty()) {
1464  //---------------------------------
1465  //-- STEP-0 : Emulate the link RTT [FIXME - Move before '!siTOE_Data.empty()' check
1466  //---------------------------------
1467  if (iptx_rttSim) {
1468  iptx_rttSim--;
1469  return;
1470  }
1471  //--------------------------
1472  //-- STEP-1 : Drain the TOE
1473  //--------------------------
1474  siTOE_Data.read(ipTxChunk);
1475  if (DEBUG_LEVEL & TRACE_IPTX) {
1476  printAxisRaw(myName, ipTxChunk);
1477  }
1478  //----------------------------
1479  //-- STEP-2 : Write to packet
1480  //----------------------------
1481  iptx_ipPacket.pushChunk(ipTxChunk);
1482 
1483  //--------------------------------------
1484  //-- STEP-3 : Parse the received packet
1485  //--------------------------------------
1486  if (ipTxChunk.getTLast()) {
1487  // The whole packet is now into the deque. Check its consistency
1488  // except for the IPv4-Header-Checksum which will be computed and
1489  // inserted later by IPTX.
1490  if (not iptx_ipPacket.isWellFormed(myName, gTest_SentIp4TotLen, false,
1492  printFatal(myName, "IP packet #%d is malformed!\n", pktCounter_TOE_IPTX);
1493  }
1494  if (pIPTX_Parse(iptx_ipPacket, sessAckList, ipRxPacketizer) == true) {
1495  // Found an ACK
1496  pktCounter_TOE_IPTX++;
1497  int tcpPayloadSize = iptx_ipPacket.sizeOfTcpData();
1498  if (tcpPayloadSize) {
1499  tcpBytCntr_TOE_IPTX += tcpPayloadSize;
1500  // Write to the IP Tx Gold file
1501  iptx_ipPacket.writeTcpDataToDatFile(ofIPTX_Data2);
1502  }
1503  }
1504  // Clear the chunk counter and the received IP packet
1505  ipTxChunkCounter = 0;
1506  iptx_ipPacket.clear();
1507  // Re-initialize the RTT counter
1508  iptx_rttSim = RTT_LINK;
1509  }
1510  else
1511  ipTxChunkCounter++;
1512 
1513  //--------------------------
1514  //-- STEP-4 : Write to file
1515  //--------------------------
1516  int writtenBytes = writeAxisRawToFile(ipTxChunk, ofIPTX_Data1);
1517  }
1518 } // End of: pIPTX
1519 
1520 
1521 
1533 bool pTcpAppListen(
1534  TcpPort lsnPortNum,
1535  set<TcpPort> &openedPorts,
1536  stream<TcpAppLsnReq> &soTOE_LsnReq,
1537  stream<TcpAppLsnRep> &siTOE_LsnRep)
1538 {
1539  const char *myName = concat3(THIS_NAME, "/", "Tal");
1540 
1541  //-- STATIC VARIABLES ------------------------------------------------------
1542  static ap_uint<1> tal_fsmState = 0;
1543  static TcpPort tal_portNum;
1544  static int tal_watchDogTimer = 100;
1545 
1546  //-- DYNAMIC VARIABLES -----------------------------------------------------
1547  StsBool rc = STS_KO;
1548 
1549  switch (tal_fsmState) {
1550  case 0:
1551  tal_portNum = lsnPortNum;
1552  soTOE_LsnReq.write(tal_portNum);
1553  if (DEBUG_LEVEL & TRACE_Tal) {
1554  printInfo(myName, "Request to listen on port %d (0x%4.4X).\n",
1555  tal_portNum.to_uint(), tal_portNum.to_uint());
1556  }
1557  tal_watchDogTimer = 100;
1558  tal_fsmState++;
1559  break;
1560  case 1:
1561  tal_watchDogTimer--;
1562  if (!siTOE_LsnRep.empty()) {
1563  siTOE_LsnRep.read(rc);
1564  if (rc) {
1565  // Add the current port # to the set of opened ports
1566  openedPorts.insert(tal_portNum);
1567  if (DEBUG_LEVEL & TRACE_Tal) {
1568  printInfo(myName, "TOE is now listening on port %d (0x%4.4X).\n",
1569  tal_portNum.to_uint(), tal_portNum.to_uint());
1570  }
1571  }
1572  else {
1573  printWarn(myName, "TOE denied listening on port %d (0x%4.4X).\n",
1574  tal_portNum.to_uint(), tal_portNum.to_uint());
1575  }
1576  tal_fsmState = 0;
1577  }
1578  else {
1579  if (tal_watchDogTimer == 0) {
1580  printError(myName, "Timeout: Failed to listen on port %d (0x%4.4X).\n",
1581  tal_portNum.to_uint(), tal_portNum.to_uint());
1582  tal_fsmState = 0;
1583  }
1584  }
1585  break;
1586  }
1587  return rc;
1588 }
1589 
1590 
1591 
1606 bool pTcpAppConnect(
1607  int &nrError,
1608  SocketPair &aSocketPair,
1609  map<SocketPair, SessionId> &openSessList,
1610  stream<SockAddr> &soTOE_OpnReq,
1611  stream<TcpAppOpnRep> &siTOE_OpnRep)
1612 {
1613  const char *myName = concat3(THIS_NAME, "/", "Tac");
1614 
1615  //-- STATIC VARIABLES ------------------------------------------------------
1616  static int tac_watchDogTimer = FPGA_CLIENT_CONNECT_TIMEOUT;
1617  // A set to keep track of the ports opened in transmission mode
1618  static TcpPort tac_ephemeralPortCounter = TOE_FIRST_EPHEMERAL_PORT_NUM;
1619  static set<TcpPort> tac_dynamicPorts;
1620  static int tac_fsmState = 0;
1621 
1622  //-- DYNAMIC VARIABLES -----------------------------------------------------
1623  bool rc = false;
1624  // Prepare to open a new connection
1625  SockAddr hostServerSocket(SockAddr(aSocketPair.dst.addr, aSocketPair.dst.port));
1626 
1627  switch (tac_fsmState) {
1628  case 0:
1629  // Let's search for an unused ephemeral port
1630  if (tac_dynamicPorts.empty()) {
1631  aSocketPair.src.port = tac_ephemeralPortCounter;
1632  tac_ephemeralPortCounter++;
1633  }
1634  else {
1635  do {
1636  aSocketPair.src.port = tac_ephemeralPortCounter;
1637  tac_ephemeralPortCounter++;
1638  } while(tac_dynamicPorts.find(aSocketPair.src.port) != tac_dynamicPorts.end());
1639  }
1640  soTOE_OpnReq.write(hostServerSocket);
1641  if (DEBUG_LEVEL & TRACE_Tac) {
1642  printInfo(myName, "The FPGA client is requesting to connect to the following HOST socket: \n");
1643  printSockAddr(myName, hostServerSocket);
1644  }
1645  tac_watchDogTimer = FPGA_CLIENT_CONNECT_TIMEOUT;
1646  tac_fsmState++;
1647  rc = false;
1648  break;
1649  case 1:
1650  tac_watchDogTimer--;
1651  if (!siTOE_OpnRep.empty()) {
1652  TcpAppOpnRep appOpenRep = siTOE_OpnRep.read();
1653  if(appOpenRep.tcpState == ESTABLISHED) {
1654  // Create a new entry in the list of established sessions
1655  openSessList[aSocketPair] = appOpenRep.sessId;
1656  if (DEBUG_LEVEL & TRACE_Tac) {
1657  printInfo(myName, "Successfully opened a new active session (%d) for connection:\n", appOpenRep.sessId.to_int());
1658  printSockPair(myName, aSocketPair);
1659  }
1660  // Add this port # to the set of opened ports
1661  tac_dynamicPorts.insert(aSocketPair.src.port);
1662  // Check maximum number of opened sessions
1663  if (tac_ephemeralPortCounter-0x8000 > TOE_MAX_SESSIONS) {
1664  printError(myName, "Trying to open too many FPGA client sessions. Max. is %d.\n", TOE_MAX_SESSIONS);
1665  nrError += 1;
1666  }
1667  rc = true;
1668  }
1669  else {
1670  printError(myName, "Failed to open a new active session (%d).\n", appOpenRep.sessId.to_uint());
1671  printInfo(myName, "The connection is in TCP state: %s.\n", getTcpStateName(appOpenRep.tcpState));
1672  rc = false;
1673  nrError += 1;
1674  }
1675  tac_fsmState = 0;
1676  }
1677  else {
1678  if (tac_watchDogTimer == 0) {
1679  printError(myName, "Timeout: Failed to open the following FPGA client session:\n");
1680  printSockPair(myName, aSocketPair);
1681  nrError += 1;
1682  tac_fsmState = 0;
1683  rc = false;
1684  }
1685  }
1686  break;
1687  } // End Of: switch
1688  return rc;
1689 } // End-of: Tac
1690 
1691 
1692 
1708 void pTcpAppEcho(
1709  int &nrError,
1710  ofstream &ofIPTX_Gold2,
1711  int &apRxBytCntr,
1712  stream<TcpAppData> &soTOE_Data,
1713  stream<TcpAppSndReq> &soTOE_SndReq,
1714  stream<TcpAppSndRep> &siTOE_SndRep,
1715  stream<TcpAppData> &siTAr_Data,
1716  stream<TcpAppSndReq> &siTAr_SndReq)
1717 {
1718  const char *myName = concat3(THIS_NAME, "/", "Tae");
1719 
1720  //-- STATIC VARIABLES ------------------------------------------------------
1721  static enum FsmStates { IDLE=0, START_OF_SEGMENT,
1722  CONTINUATION_OF_SEGMENT } tae_fsmState = IDLE;
1723  static int tae_mssCounter = 0; // Maximum Segment Size counter
1724 
1725  //-- DYNAMIC VARIABLES -----------------------------------------------------
1726  TcpAppData appChunk;
1727  TcpAppSndReq appSndReq;
1728 
1729  switch (tae_fsmState) {
1730  case IDLE:
1731  if ( !siTAr_SndReq.empty() and !soTOE_SndReq.full()) {
1732  //-- Forward the send request received from [TAr]
1733  siTAr_SndReq.read(appSndReq);
1734  soTOE_SndReq.write(appSndReq);
1735  tae_fsmState = START_OF_SEGMENT;
1736  }
1737  break;
1738  case START_OF_SEGMENT:
1739  if (!siTOE_SndRep.empty()) {
1740  //-- Read the request to send reply and continue accordingly
1741  TcpAppSndRep appSndRep = siTOE_SndRep.read();
1742  switch (appSndRep.error) {
1743  case NO_ERROR:
1744  tae_fsmState = CONTINUATION_OF_SEGMENT;
1745  break;
1746  case NO_SPACE:
1747  printError(THIS_NAME, "Not enough space for writing %d bytes in the Tx buffer of session #%d. Available space is %d bytes.\n",
1748  appSndRep.length.to_uint(), appSndRep.sessId.to_uint(), appSndRep.spaceLeft.to_uint());
1749  nrError++;
1750  tae_fsmState = IDLE;
1751  break;
1752  case NO_CONNECTION:
1753  printError(THIS_NAME, "Attempt to write data for a session that is not established.\n");
1754  nrError++;
1755  tae_fsmState = IDLE;
1756  break;
1757  default:
1758  printError(THIS_NAME, "Received unknown TCP request to send reply from [TOE].\n");
1759  nrError++;
1760  tae_fsmState = IDLE;
1761  break;
1762  }
1763  }
1764  break;
1765  case CONTINUATION_OF_SEGMENT:
1766  if ( !siTAr_Data.empty() and !soTOE_Data.full()) {
1767  //-- Feed the TOE with the data received from [TAr]
1768  siTAr_Data.read(appChunk);
1769  soTOE_Data.write(appChunk);
1770  apRxBytCntr += writeAxisAppToFile(appChunk, ofIPTX_Gold2, tae_mssCounter);
1771  if (appChunk.getTLast())
1772  tae_fsmState = IDLE;
1773  }
1774  break;
1775  } // End-of: switch()
1776 } // End-of: Tae
1777 
1778 
1798 void pTAIF_Recv(
1799  int &nrError,
1800  char &testMode,
1801  ofstream &ofTAIF_Data,
1802  int &appTxBytCntr,
1803  StsBit &piTOE_Ready,
1804  stream<TcpAppLsnReq> &soTOE_LsnReq,
1805  stream<TcpAppLsnRep> &siTOE_LsnRep,
1806  stream<TcpAppNotif> &siTOE_Notif,
1807  stream<TcpAppRdReq> &soTOE_DReq,
1808  stream<TcpAppData> &siTOE_Data,
1809  stream<TcpAppMeta> &siTOE_Meta,
1810  stream<TcpAppData> &soTAs_Data,
1811  stream<TcpAppSndReq> &soTAs_SndReq)
1812 {
1813  const char *myName = concat3(THIS_NAME, "/", "TAr");
1814 
1815  //-- STATIC VARIABLES ------------------------------------------------------
1816  static bool tar_idlingReq = false; // Request to idle (.i.e, do not feed TOE's input stream)
1817  static unsigned int tar_idleCycReq = 0; // The requested number of idle cycles
1818  static unsigned int tar_idleCycCnt = 0; // The count of idle cycles
1819  static int tar_startupDelay = 0;
1820  static bool tar_dualTest = false;
1821  static int tar_appRspIdle = 0;
1822  static ap_uint<32> tar_mAmount = 0;
1823  static set<TcpPort> tar_listeningPorts; // A set to keep track of the ports opened in listening mode
1824  static TcpAppNotif tar_notification;
1825  static vector<SessionId> tar_txSessIdVector; // A vector containing the Tx session IDs to be send from TAIF/Meta to TOE/Meta
1826  static enum FsmStates { WAIT_NOTIF=0, SEND_DREQ,
1827  WAIT_SEG, CONSUME } tar_fsmState = WAIT_NOTIF;
1828 
1829  //-- DYNAMIC VARIABLES -----------------------------------------------------
1830  string rxStringBuffer;
1831  vector<string> stringVector;
1832  TcpAppOpnRep newConStatus;
1833  SessionId tcpSessId;
1834  AxisApp currChunk;
1835 
1836  //---------------------------------------
1837  //-- STEP-0 : RETURN IF TOE IS NOT READY
1838  //---------------------------------------
1839  if (piTOE_Ready == 0) {
1840  return;
1841  }
1842 
1843  //------------------------------------------------
1844  //-- STEP-1 : REQUEST TO LISTEN ON A PORT
1845  //------------------------------------------------
1846  // Check if a port is already opened
1847  if (tar_listeningPorts.find(gFpgaLsnPort) == tar_listeningPorts.end()) {
1848  bool listenStatus = pTcpAppListen(
1849  gFpgaLsnPort,
1850  tar_listeningPorts,
1851  soTOE_LsnReq,
1852  siTOE_LsnRep);
1853  if (listenStatus == false) {
1854  return;
1855  }
1856  }
1857 
1858  //------------------------------------------------
1859  //-- STEP-2 : READ NOTIF and DRAIN TOE-->TAIF
1860  //------------------------------------------------
1861  currChunk.setTLast(0);
1862  switch (tar_fsmState) {
1863  case WAIT_NOTIF:
1864  if (!siTOE_Notif.empty()) {
1865  siTOE_Notif.read(tar_notification);
1866  if (DEBUG_LEVEL & TRACE_TAr) {
1867  printInfo(myName, "Received data notification from TOE: (sessId=%d, tcpDataLen=%d) and {IP_SA, TCP_DP} is:\n",
1868  tar_notification.sessionID.to_int(), tar_notification.tcpDatLen.to_int());
1869  printSockAddr(myName, SockAddr(tar_notification.ip4SrcAddr, tar_notification.tcpDstPort));
1870  }
1871  tar_appRspIdle = APP_RSP_LATENCY;
1872  tar_fsmState = SEND_DREQ;
1873  }
1874  break;
1875  case SEND_DREQ:
1876  //-- Wait some cycles to match the co-simulation
1877  if (tar_appRspIdle > 0) {
1878  tar_appRspIdle--;
1879  }
1880  else if (!soTOE_DReq.full()) {
1881  if (tar_notification.tcpDatLen != 0) {
1882  soTOE_DReq.write(TcpAppRdReq(tar_notification.sessionID,
1883  tar_notification.tcpDatLen));
1884  tar_fsmState = WAIT_SEG;
1885  }
1886  else {
1887  printWarn(myName, "Received a data notification of length \'0\'. Please double check!!!\n");
1888  nrError += 1;
1889  tar_fsmState = WAIT_NOTIF;
1890  }
1891  }
1892  break;
1893  case WAIT_SEG: // Wait for start of new segment
1894  switch (testMode) {
1895  case RX_MODE:
1896  if (!siTOE_Meta.empty()) {
1897  // Read the TCP session ID
1898  siTOE_Meta.read(tcpSessId);
1899  tar_fsmState = CONSUME;
1900  }
1901  break;
1902  case ECHO_MODE: // Forward sessId and data length a send request to TAIF_Send (Snd) process
1903  if (!siTOE_Meta.empty() and !soTAs_SndReq.full()) {
1904  siTOE_Meta.read(tcpSessId);
1905  soTAs_SndReq.write(TcpAppSndReq(tcpSessId, tar_notification.tcpDatLen));
1906  tar_fsmState = CONSUME;
1907  }
1908  break;
1909  default:
1910  printFatal(myName, "Aborting testbench (The code should never end-up here).\n");
1911  break;
1912  } // End-of switch(testMode)
1913  break;
1914  case CONSUME: // Read all the remaining TCP data chunks
1915  switch (testMode) {
1916  case RX_MODE: // Dump incoming data to file
1917  if (!siTOE_Data.empty()) {
1918  siTOE_Data.read(currChunk);
1919  appTxBytCntr += writeAxisAppToFile(currChunk, ofTAIF_Data);
1920  // Consume incoming stream until LAST bit is set
1921  if (currChunk.getTLast() == 1)
1922  tar_fsmState = WAIT_NOTIF;
1923  }
1924  break;
1925  case ECHO_MODE: // Forward incoming data to the TcpAppSend process (TAs)
1926  if (!siTOE_Data.empty() and !soTAs_Data.full()) {
1927  siTOE_Data.read(currChunk);
1928  soTAs_Data.write(currChunk);
1929  appTxBytCntr += writeAxisAppToFile(currChunk, ofTAIF_Data);
1930  // Consume until LAST bit is set
1931  if (currChunk.getTLast() == 1) {
1932  tar_fsmState = WAIT_NOTIF;
1933  }
1934  }
1935  break;
1936  default:
1937  printFatal(myName, "Aborting testbench (The code should never end-up here).\n");
1938  break;
1939  } // End-of switch(testMode)
1940  break;
1941  }
1942 
1943 } // End of: pTAr
1944 
1945 
1968 void pTAIF_Send(
1969  int &nrError,
1970  char &testMode,
1971  bool &testTxPath,
1972  Ip4Address &toeIpAddress,
1973  ifstream &ifTAIF_Data,
1974  ofstream &ofIPTX_Gold2,
1975  int &apRxBytCntr,
1976  StsBit &piTOE_Ready,
1977  stream<TcpAppOpnReq> &soTOE_OpnReq,
1978  stream<TcpAppOpnRep> &siTOE_OpnRep,
1979  stream<TcpAppData> &soTOE_Data,
1980  stream<TcpAppSndReq> &soTOE_SndReq,
1981  stream<TcpAppSndRep> &siTOE_SndRep,
1982  stream<TcpAppClsReq> &soTOE_ClsReq,
1983  stream<TcpAppData> &siTAr_Data,
1984  stream<TcpAppSndReq> &siTAr_SndReq)
1985 {
1986  const char *myName = concat3(THIS_NAME, "/", "TAs");
1987 
1988  //-- STATIC VARIABLES ------------------------------------------------------
1989  static bool tas_globParseDone = false;
1990  static bool tas_appTxIdlingReq = false; // Request to idle (i.e., do not feed TOE's input stream)
1991  static unsigned int tas_appTxIdleCycReq = 0; // The requested number of idle cycles
1992  static unsigned int tas_appTxIdleCycCnt = 0; // The count of idle cycles
1993  static unsigned int tas_toeReadyDelay = 0; // The time it takes for TOE to be ready
1994  static vector<SessionId> tas_txSessIdVector; // A vector containing the Tx session IDs to be send from TAIF/Meta to TOE/Meta
1995  static map<SocketPair, SessionId> tas_openSessList; // Keeps track of the sessions opened by the TOE
1996  static bool tas_clearToSend = false;
1997  static SimAppData tas_simAppData;
1998 
1999  //-- DYNAMIC VARIABLES -----------------------------------------------------
2000  string rxStringBuffer;
2001  vector<string> stringVector;
2002  TcpAppOpnRep newConStatus;
2003  bool done;
2004  char *pEnd;
2005 
2006  //----------------------------------------
2007  //-- STEP-1 : RETURN IF TOE IS NOT READY
2008  //----------------------------------------
2009  if (piTOE_Ready == 0) {
2010  tas_toeReadyDelay++;
2011  return;
2012  }
2013 
2014  //------------------------------------------------------
2015  //-- STEP-1 : ARE WE ASKED TO OPEN A NEW CONNECTION
2016  //------------------------------------------------------
2017  SockAddr fpgaClientSocket(gFpgaIp4Addr, gFpgaSndPort);
2018  SockAddr hostServerSocket(gHostIp4Addr, gHostLsnPort);
2019  SocketPair currSocketPair(fpgaClientSocket, hostServerSocket);
2020  // Open current session if it does not yet exist
2021  if (tas_openSessList.find(currSocketPair) == tas_openSessList.end()) {
2022  // Let's open a new session
2023  done = pTcpAppConnect(
2024  nrError,
2025  currSocketPair,
2026  tas_openSessList,
2027  soTOE_OpnReq,
2028  siTOE_OpnRep);
2029  if (!done) {
2030  // The open session is not yet completed
2031  return;
2032  }
2033  }
2034 
2035  //-------------------------------------------------------------
2036  //-- STEP-2a : IMMEDIATELY QUIT IF TX TEST MODE IS NOT ENABLED
2037  //-------------------------------------------------------------
2038  if (not testTxPath)
2039  return;
2040 
2041  //-----------------------------------------------------
2042  //-- STEP-2b : ALSO RETURN IF IDLING IS REQUESTED
2043  //-----------------------------------------------------
2044  if (tas_appTxIdlingReq == true) {
2045  if (tas_appTxIdleCycCnt >= tas_appTxIdleCycReq) {
2046  tas_appTxIdleCycCnt = 0;
2047  tas_appTxIdlingReq = false;
2048  if (DEBUG_LEVEL & TRACE_TAs) {
2049  printInfo(myName, "End of APP Tx idling phase. \n");
2050  }
2051  }
2052  else {
2053  tas_appTxIdleCycCnt++;
2054  }
2055  return;
2056  }
2057 
2058  //----------------------------------------------------------------
2059  //-- STEP-3 : SHORT EXECUTION PATH WHEN TestingMode == ECHO_MODE
2060  //----------------------------------------------------------------
2061  if (testMode == ECHO_MODE) {
2062  pTcpAppEcho(
2063  nrError,
2064  ofIPTX_Gold2,
2065  apRxBytCntr,
2066  soTOE_Data,
2067  soTOE_SndReq,
2068  siTOE_SndRep,
2069  siTAr_Data,
2070  siTAr_SndReq);
2071  return;
2072  }
2073 
2074  //------------------------------------------------------
2075  //-- STEP-4 : HANDLE THE SEND REPLY INTERFACE
2076  //------------------------------------------------------
2077  if (!siTOE_SndRep.empty()) {
2078  TcpAppSndRep appSndRep = siTOE_SndRep.read();
2079  TcpAppSndErr rc = appSndRep.error;
2080  switch (rc) {
2081  case NO_ERROR:
2082  tas_clearToSend = true;
2083  break;
2084  case NO_CONNECTION: // [FIXME-Must handle this scenario]
2085  printFatal(myName, "Attempt to write data for session %d which is not established.\n", appSndRep.sessId.to_uint());
2086  nrError++;
2087  break;
2088  case NO_SPACE: // [FIXME-Must handle this scenario]
2089  printFatal(myName, "There is not enough TxBuf memory space available for session %d.\n",
2090  appSndRep.sessId.to_uint());
2091  nrError++;
2092  break;
2093  default:
2094  printFatal(myName, "Received unknown reply error (%d) from [TOE].\n", rc);
2095  nrError++;
2096  break;
2097  }
2098  }
2099 
2100  //------------------------------------------------------
2101  //-- STEP-5 : FEED DATA STREAM or BUILD A NEW ONE FROM FILE
2102  //------------------------------------------------------
2103  if (tas_simAppData.size() and tas_clearToSend) {
2104  if (!soTOE_Data.full()) {
2105  //-------------------------------------------------
2106  //-- Feed TOE with a new APP chunk
2107  //-------------------------------------------------
2108  AxisApp appChunk = tas_simAppData.pullChunk();
2109  soTOE_Data.write(appChunk);
2110  increaseSimTime(1);
2111  if (appChunk.getTLast()) {
2112  tas_clearToSend = false;
2113  }
2114  }
2115  }
2116  else if (tas_simAppData.size() == 0) {
2117  //------------------------------------------------------
2118  //-- Build a new DATA stream from FILE
2119  //------------------------------------------------------
2120  while (!ifTAIF_Data.eof()) {
2121  //-- Read a line from the test vector file -----------
2122  getline(ifTAIF_Data, rxStringBuffer);
2123  if (DEBUG_LEVEL & TRACE_TAs) { printf("%s ", rxStringBuffer.c_str()); fflush(stdout); }
2124  stringVector = myTokenizer(rxStringBuffer, ' ');
2125  if (stringVector[0] == "") {
2126  continue;
2127  }
2128  else if (stringVector[0].length() == 1) {
2129  //------------------------------------------------------
2130  //-- Process the command and comment lines
2131  //-- FYI: A command or a comment start with a single
2132  //-- character followed by a space character.
2133  //------------------------------------------------------
2134  if (stringVector[0] == "#") {
2135  // This is a comment line.
2136  continue;
2137  }
2138  else if (stringVector[0] == "G") {
2139  // This is a global parameter. It can be skipped because it was already parsed.
2140  continue;
2141  }
2142  else if (stringVector[0] == ">") {
2143  // The test vector is issuing a command.
2144  // FYI, don't forget to return at the end of command execution.
2145  if (stringVector[1] == "IDLE") {
2146  // Cmd = Request to idle for <NUM> cycles.
2147  tas_appTxIdleCycReq = strtol(stringVector[2].c_str(), &pEnd, 10);
2148  tas_appTxIdlingReq = true;
2149  if (DEBUG_LEVEL & TRACE_TAs) {
2150  printInfo(myName, "Request to idle for %d cycles. \n", tas_appTxIdleCycReq);
2151  }
2152  increaseSimTime(tas_appTxIdleCycReq);
2153  return;
2154  }
2155  if (stringVector[1] == "SET") {
2156  if (stringVector[2] == "HostIp4Addr") {
2157  // COMMAND = Set the active host IP address.
2158  char * ptr;
2159  // Retrieve the IPv4 address to set
2160  unsigned int ip4Addr;
2161  if (isDottedDecimal(stringVector[3]))
2162  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
2163  else if (isHexString(stringVector[3]))
2164  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 16);
2165  else
2166  ip4Addr = strtoul(stringVector[3].c_str(), &ptr, 10);
2167  gHostIp4Addr = ip4Addr;
2168  printInfo(myName, "Setting the current HOST IPv4 address to be: ");
2169  printIp4Addr(myName, gHostIp4Addr);
2170  return;
2171  }
2172  else if (stringVector[2] == "HostLsnPort") {
2173  // COMMAND = Set the active host listen port.
2174  char * ptr;
2175  // Retrieve the TCP-Port to set
2176  unsigned int tcpPort;
2177  if (isHexString(stringVector[3]))
2178  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 16);
2179  else
2180  tcpPort = strtoul(stringVector[3].c_str(), &ptr, 10);
2181  gHostLsnPort = tcpPort;
2182  printInfo(myName, "Setting the current HOST listen port to be: ");
2183  printTcpPort(myName, gHostLsnPort);
2184  return;
2185  }
2186  else if (stringVector[2] == "HostServerSocket") {
2187  // COMMAND = Set the active host server socket.
2188  // If socket does not exist, host must create, bind,
2189  // listen and accept new connections from the client.
2190  char *pEnd;
2191  // Retrieve the current foreign IPv4 address to set
2192  unsigned int ip4Addr;
2193  if (isDottedDecimal(stringVector[3]))
2194  ip4Addr = myDottedDecimalIpToUint32(stringVector[3]);
2195  else if (isHexString(stringVector[3]))
2196  ip4Addr = strtoul(stringVector[3].c_str(), &pEnd, 16);
2197  else
2198  ip4Addr = strtoul(stringVector[3].c_str(), &pEnd, 10);
2199  gHostIp4Addr = ip4Addr;
2200  // Retrieve the current foreign TCP-Port to set
2201  unsigned int tcpPort;
2202  if (isHexString(stringVector[4]))
2203  tcpPort = strtoul(stringVector[4].c_str(), &pEnd, 16);
2204  else
2205  tcpPort = strtoul(stringVector[4].c_str(), &pEnd, 10);
2206  gHostLsnPort = tcpPort;
2207 
2208  SockAddr newHostServerSocket(gHostIp4Addr, gHostLsnPort);
2209  printInfo(myName, "Setting current host server socket to be: \n");
2210  printSockAddr(myName, newHostServerSocket);
2211  return;
2212  }
2213  }
2214  }
2215  else {
2216  printFatal(myName, "Read unknown command \"%s\" from TAIF.\n", stringVector[0].c_str());
2217  }
2218  }
2219  else if (ifTAIF_Data.fail() == 1 || rxStringBuffer.empty()) {
2220  return;
2221  }
2222  else if (!tas_clearToSend) {
2223  //-- Build a new simAppData from file
2224  AxisApp appChunk;
2225  bool firstChunkFlag = true; // Axis chunk is first data chunk
2226  int writtenBytes = 0;
2227  do {
2228  if (firstChunkFlag == false) {
2229  getline(ifTAIF_Data, rxStringBuffer);
2230  stringVector = myTokenizer(rxStringBuffer, ' ');
2231  // Skip lines that might be commented out
2232  if (stringVector[0] == "#") {
2233  // This is a comment line.
2234  if (DEBUG_LEVEL & TRACE_TAs) { printf("%s ", rxStringBuffer.c_str()); fflush(stdout); }
2235  continue;
2236  }
2237  }
2238  firstChunkFlag = false;
2239  bool rc = readAxisRawFromLine(appChunk, rxStringBuffer);
2240  if (rc) {
2241  tas_simAppData.pushChunk(appChunk);
2242  }
2243  // Write current chunk to the gold file
2244  writtenBytes = writeAxisAppToFile(appChunk, ofIPTX_Gold2);
2245  apRxBytCntr += writtenBytes;
2246  if (appChunk.getTLast()) {
2247  // A send request must be sent by TAIF to TOE
2248  soTOE_SndReq.write(TcpAppSndReq(tas_openSessList[currSocketPair], tas_simAppData.length()));
2249  return;
2250  }
2251  } while (not appChunk.getTLast());
2252  } // End of: else
2253  } // End of: while
2254  } // End of: else
2255 } // End of: pTAs
2256 
2257 
2289 void pTAIF(
2290  bool &testTxPath,
2291  char &testMode,
2292  int &nrError,
2293  Ip4Address &toeIpAddress,
2294  ifstream &ifTAIF_Data,
2295  ofstream &ofTAIF_Data,
2296  ofstream &ofIPTX_Gold2,
2297  int &appRxBytCntr,
2298  int &appTxBytCntr,
2299  StsBit &piTOE_Ready,
2300  //-- Receive Interfaces
2301  stream<TcpAppLsnReq> &soTOE_LsnReq,
2302  stream<TcpAppLsnRep> &siTOE_LsnRep,
2303  stream<TcpAppNotif> &siTOE_Notif,
2304  stream<TcpAppRdReq> &soTOE_DReq,
2305  stream<TcpAppData> &siTOE_Data,
2306  stream<TcpAppMeta> &siTOE_Meta,
2307  //-- Transmit Interfaces
2308  stream<TcpAppOpnReq> &soTOE_OpnReq,
2309  stream<TcpAppOpnRep> &siTOE_OpnRep,
2310  stream<TcpAppData> &soTOE_Data,
2311  stream<TcpAppSndReq> &soTOE_SndReq,
2312  stream<TcpAppSndRep> &siTOE_SndRep,
2313  stream<TcpAppClsReq> &soTOE_ClsReq)
2314 {
2315 
2316  const char *myName = concat3(THIS_NAME, "/", "TAIF");
2317 
2318  //-- STATIC VARIABLES ------------------------------------------------------
2319  static bool taif_globParseDone = false;
2320  static unsigned int taif_toeReadyDelay = 0; // The time it takes for TOE to be ready
2321 
2322  //-------------------------------------------------------------------------
2323  //-- LOCAL STREAMS
2324  //-------------------------------------------------------------------------
2325  static stream<TcpAppData> ssTArToTAs_Data ("ssTArToTAs_Data");
2326  #pragma HLS STREAM variable=ssTArToTAs_Data depth=2048
2327  static stream<TcpAppSndReq> ssTArToTAs_SndReq ("ssTArToTAs_SndReq");
2328  #pragma HLS STREAM variable=ssTArToTAs_SndReq depth=64
2329 
2330  //---------------------------------------
2331  //-- STEP-0 : RETURN IF TOE IS NOT READY
2332  //---------------------------------------
2333  if (piTOE_Ready == 0) {
2334  taif_toeReadyDelay++;
2335  return;
2336  }
2337 
2338  //-------------------------------------------------------------------------
2339  //-- STEP-1: PARSE THE APP RX FILE.
2340  // THIS FIRST PASS WILL SPECIFICALLY SEARCH FOR GLOBAL PARAMETERS.
2341  //-------------------------------------------------------------------------
2342  if (!taif_globParseDone) {
2343  taif_globParseDone = setGlobalParameters(myName, taif_toeReadyDelay, ifTAIF_Data);
2344  if (taif_globParseDone == false) {
2345  printFatal(myName, "Aborting testbench (check for previous error).\n");
2346  }
2347  return;
2348  }
2349 
2350  pTAIF_Recv(
2351  nrError,
2352  testMode,
2353  ofTAIF_Data,
2354  appTxBytCntr,
2355  piTOE_Ready,
2356  soTOE_LsnReq,
2357  siTOE_LsnRep,
2358  siTOE_Notif,
2359  soTOE_DReq,
2360  siTOE_Data,
2361  siTOE_Meta,
2362  ssTArToTAs_Data,
2363  ssTArToTAs_SndReq);
2364 
2365  pTAIF_Send(
2366  nrError,
2367  testMode,
2368  testTxPath,
2369  toeIpAddress,
2370  ifTAIF_Data,
2371  ofIPTX_Gold2,
2372  appRxBytCntr,
2373  piTOE_Ready,
2374  soTOE_OpnReq,
2375  siTOE_OpnRep,
2376  soTOE_Data,
2377  soTOE_SndReq,
2378  siTOE_SndRep,
2379  soTOE_ClsReq,
2380  ssTArToTAs_Data,
2381  ssTArToTAs_SndReq);
2382 
2383 } // End of: pTAIF
2384 
2385 #if HLS_VERSION != 2017
2386 
2437  void toe_top_wrap(
2438  //-- MMIO Interfaces
2439  Ip4Addr piMMIO_IpAddr,
2440  stream<StsBit> &soMMIO_RxMemWrErr,
2441  stream<ap_uint<8> > &soMMIO_NotifDropCnt,
2442  stream<ap_uint<8> > &soMMIO_MetaDropCnt,
2443  stream<ap_uint<8> > &soMMIO_DataDropCnt,
2444  stream<ap_uint<8> > &soMMIO_CrcDropCnt,
2445  stream<ap_uint<8> > &soMMIO_SessDropCnt,
2446  stream<ap_uint<8> > &soMMIO_OooDropCnt,
2447  //-- NTS Interfaces
2448  StsBit &poNTS_Ready,
2449  //-- IPRX / IP Rx / Data Interface
2450  stream<AxisIp4> &siIPRX_Data,
2451  //-- IPTX / IP Tx / Data Interface
2452  stream<AxisIp4> &soIPTX_Data,
2453  //-- TAIF / Receive Data Interfaces
2454  stream<TcpAppNotif> &soTAIF_Notif,
2455  stream<TcpAppRdReq> &siTAIF_DReq,
2456  stream<TcpAppData> &soTAIF_Data,
2457  stream<TcpAppMeta> &soTAIF_Meta,
2458  //-- TAIF / Listen Interfaces
2459  stream<TcpAppLsnReq> &siTAIF_LsnReq,
2460  stream<TcpAppLsnRep> &soTAIF_LsnRep,
2461  //-- TAIF / Send Data Interfaces
2462  stream<TcpAppData> &siTAIF_Data,
2463  stream<TcpAppSndReq> &siTAIF_SndReq,
2464  stream<TcpAppSndRep> &soTAIF_SndRep,
2465  //-- TAIF / Open Connection Interfaces
2466  stream<TcpAppOpnReq> &siTAIF_OpnReq,
2467  stream<TcpAppOpnRep> &soTAIF_OpnRep,
2468  //-- TAIF / Close Interfaces
2469  stream<TcpAppClsReq> &siTAIF_ClsReq,
2470  //-- Not Used &soTAIF_ClsSts,
2471  //-- MEM / Rx PATH / S2MM Interface
2472  //-- Not Used &siMEM_RxP_RdSts,
2473  stream<DmCmd> &soMEM_RxP_RdCmd,
2474  stream<AxisApp> &siMEM_RxP_Data,
2475  stream<DmSts> &siMEM_RxP_WrSts,
2476  stream<DmCmd> &soMEM_RxP_WrCmd,
2477  stream<AxisApp> &soMEM_RxP_Data,
2478  //-- MEM / Tx PATH / S2MM Interface
2479  //-- Not Used &siMEM_TxP_RdSts,
2480  stream<DmCmd> &soMEM_TxP_RdCmd,
2481  stream<AxisApp> &siMEM_TxP_Data,
2482  stream<DmSts> &siMEM_TxP_WrSts,
2483  stream<DmCmd> &soMEM_TxP_WrCmd,
2484  stream<AxisApp> &soMEM_TxP_Data,
2485  //-- CAM / Session Lookup & Update Interfaces
2486  stream<CamSessionLookupRequest> &soCAM_SssLkpReq,
2487  stream<CamSessionLookupReply> &siCAM_SssLkpRep,
2488  stream<CamSessionUpdateRequest> &soCAM_SssUpdReq,
2489  stream<CamSessionUpdateReply> &siCAM_SssUpdRep,
2490  //-- DEBUG / Interfaces
2491  //-- DEBUG / Session Statistics Interfaces
2492  stream<ap_uint<16> > &soDBG_SssRelCnt,
2493  stream<ap_uint<16> > &soDBG_SssRegCnt,
2494  //-- DEBUG / Internal Counters Interfaces
2495  stream<RxBufPtr> &soDBG_RxFreeSpace,
2496  stream<ap_uint<32> > &soDBG_TcpIpRxByteCnt,
2497  stream<ap_uint< 8> > &soDBG_OooDebug
2499  //-- DEBUG / SimCycCounter
2500  ap_uint<32> &poSimCycCount
2501  #endif
2502  )
2503 {
2504  //-- LOCAL INPUT and OUTPUT STREAMS ----------------------------------------
2505  static stream<AxisRaw> ssiIPRX_Data ("ssiIPRX_Data");
2506  static stream<AxisRaw> ssoIPTX_Data ("ssoIPTX_Data");
2507 
2508  //-- INPUT STREAM CASTING -----------------------------
2509  pAxisRawCast(siIPRX_Data, ssiIPRX_Data);
2510 
2511  //-- MAIN TOE_TOP PROCESS -----------------------------
2512  toe_top(
2513  //-- MMIO Interfaces
2514  piMMIO_IpAddr,
2515  soMMIO_RxMemWrErr,
2516  soMMIO_NotifDropCnt,
2517  soMMIO_MetaDropCnt,
2518  soMMIO_DataDropCnt,
2519  soMMIO_CrcDropCnt,
2520  soMMIO_SessDropCnt,
2521  soMMIO_OooDropCnt,
2522  //-- NTS Interfaces
2523  poNTS_Ready,
2524  //-- IPv4 / Rx & Tx Data Interfaces
2525  ssiIPRX_Data,
2526  ssoIPTX_Data,
2527  //-- TAIF / Rx Data Interfaces
2528  soTAIF_Notif,
2529  siTAIF_DReq,
2530  soTAIF_Data,
2531  soTAIF_Meta,
2532  //-- TAIF / Listen Port Interfaces
2533  siTAIF_LsnReq,
2534  soTAIF_LsnRep,
2535  //-- TAIF / Tx Data Interfaces
2536  siTAIF_Data,
2537  siTAIF_SndReq,
2538  soTAIF_SndRep,
2539  //-- TAIF / Open Connection Interfaces
2540  siTAIF_OpnReq,
2541  soTAIF_OpnRep,
2542  //-- TAIF / Close Interfaces
2543  siTAIF_ClsReq,
2544  //-- [TODO] &soTAIF_ClsSts,
2545  //-- MEM / Rx PATH / S2MM Interface
2546  soMEM_RxP_RdCmd,
2547  siMEM_RxP_Data,
2548  siMEM_RxP_WrSts,
2549  soMEM_RxP_WrCmd,
2550  soMEM_RxP_Data,
2551  //-- MEM / Tx PATH / S2MM Interface
2552  soMEM_TxP_RdCmd,
2553  siMEM_TxP_Data,
2554  siMEM_TxP_WrSts,
2555  soMEM_TxP_WrCmd,
2556  soMEM_TxP_Data,
2557  //-- CAM / Session Lookup & Update Interfaces
2558  soCAM_SssLkpReq,
2559  siCAM_SssLkpRep,
2560  soCAM_SssUpdReq,
2561  siCAM_SssUpdRep,
2562  //-- DEBUG / Session Statistics Interfaces
2563  soDBG_SssRelCnt,
2564  soDBG_SssRegCnt,
2565  //-- DEBUG / Internal Counter Interfaces
2566  soDBG_RxFreeSpace,
2567  soDBG_TcpIpRxByteCnt,
2568  soDBG_OooDebug
2570  ,
2571  sTOE_TB_SimCycCnt
2572  #endif
2573  );
2574 
2575  //-- OUTPUT STREAM CASTING ----------------------------
2576  pAxisRawCast(ssoIPTX_Data, soIPTX_Data);
2577 }
2578 #endif
2579 
2580 
2600 int main(int argc, char *argv[]) {
2601 
2602  //------------------------------------------------------
2603  //-- TESTBENCH GLOBAL VARIABLES
2604  //------------------------------------------------------
2605  gSimCycCnt = 0; // Simulation cycle counter as a global variable
2606 
2607  //------------------------------------------------------
2608  //-- DUT SIGNAL INTERFACES
2609  //------------------------------------------------------
2610  StsBit sTOE_Ready;
2611 
2612  //------------------------------------------------------
2613  //-- DUT STREAM INTERFACES
2614  //------------------------------------------------------
2615 
2616  stream<AxisIp4> ssIPRX_TOE_Data ("ssIPRX_TOE_Data");
2617 
2618  stream<AxisIp4> ssTOE_IPTX_Data ("ssTOE_IPTX_Data");
2619 
2620  stream<TcpAppData> ssTAIF_TOE_Data ("ssTAIF_TOE_Data");
2621  stream<TcpAppSndReq> ssTAIF_TOE_SndReq ("ssTAIF_TOE_SndReq");
2622  stream<TcpAppSndRep> ssTOE_TAIF_SndRep ("ssTOE_TAIF_SndRep");
2623 
2624  stream<TcpAppRdReq> ssTAIF_TOE_DReq ("ssTAIF_TOE_DReq");
2625  stream<TcpAppData> ssTOE_TAIF_Data ("ssTOE_TAIF_Data");
2626  stream<TcpAppMeta> ssTOE_TAIF_Meta ("ssTOE_TAIF_Meta");
2627 
2628  stream<TcpAppLsnReq> ssTAIF_TOE_LsnReq ("ssTAIF_TOE_LsnReq");
2629  stream<TcpAppLsnRep> ssTOE_TAIF_LsnRep ("ssTOE_TAIF_LsnRep");
2630 
2631  stream<TcpAppOpnReq> ssTAIF_TOE_OpnReq ("ssTAIF_TOE_OpnReq");
2632  stream<TcpAppOpnRep> ssTOE_TAIF_OpnRep ("ssTOE_TAIF_OpnRep");
2633 
2634  stream<TcpAppNotif> ssTOE_TAIF_Notif ("ssTOE_TAIF_Notif");
2635 
2636  stream<TcpAppClsReq> ssTAIF_TOE_ClsReq ("ssTAIF_TOE_ClsReq");
2637 
2638  stream<DmCmd> ssTOE_MEM_RxP_RdCmd ("ssTOE_MEM_RxP_RdCmd");
2639  stream<AxisApp> ssMEM_TOE_RxP_Data ("ssMEM_TOE_RxP_Data");
2640  stream<DmSts> ssMEM_TOE_RxP_WrSts ("ssMEM_TOE_RxP_WrSts");
2641  stream<DmCmd> ssTOE_MEM_RxP_WrCmd ("ssTOE_MEM_RxP_WrCmd");
2642  stream<AxisApp> ssTOE_MEM_RxP_Data ("ssTOE_MEM_RxP_Data");
2643 
2644  stream<DmCmd> ssTOE_MEM_TxP_RdCmd ("ssTOE_MEM_TxP_RdCmd");
2645  stream<AxisApp> ssMEM_TOE_TxP_Data ("ssMEM_TOE_TxP_Data");
2646  stream<DmSts> ssMEM_TOE_TxP_WrSts ("ssMEM_TOE_TxP_WrSts");
2647  stream<DmCmd> ssTOE_MEM_TxP_WrCmd ("ssTOE_MEM_TxP_WrCmd");
2648  stream<AxisApp> ssTOE_MEM_TxP_Data ("ssTOE_MEM_TxP_Data");
2649 
2650  stream<CamSessionLookupRequest> ssTOE_CAM_SssLkpReq ("ssTOE_CAM_SssLkpReq");
2651  stream<CamSessionLookupReply> ssCAM_TOE_SssLkpRep ("ssCAM_TOE_SssLkpRep");
2652  stream<CamSessionUpdateRequest> ssTOE_CAM_SssUpdReq ("ssTOE_CAM_SssUpdReq");
2653  stream<CamSessionUpdateReply> ssCAM_TOE_SssUpdRep ("ssCAM_TOE_SssUpdRep");
2654 
2655  stream<StsBit> ssTOE_MMIO_RxMemWrErr ("ssTOE_MMIO_RxMemWrErr");
2656  stream<ap_uint<8> > ssTOE_MMIO_NotifDropCnt ("ssTOE_MMIO_NotifDropCnt");
2657  stream<ap_uint<8> > ssTOE_MMIO_MetaDropCnt ("ssTOE_MMIO_MetaDropCnt");
2658  stream<ap_uint<8> > ssTOE_MMIO_DataDropCnt ("ssTOE_MMIO_DataDropCnt");
2659  stream<ap_uint<8> > ssTOE_MMIO_CrcDropCnt ("ssTOE_MMIO_CrcDropCnt");
2660  stream<ap_uint<8> > ssTOE_MMIO_SessDropCnt ("ssTOE_MMIO_SessDropCnt");
2661  stream<ap_uint<8> > ssTOE_MMIO_OooDropCnt ("ssTOE_MMIO_OooDropCnt");
2662 
2663  stream<ap_uint<16> > ssTOE_OpnSessCount ("ssTOE_OpnSessCount");
2664  stream<ap_uint<16> > ssTOE_ClsSessCount ("ssTOE_ClsSessCount");
2665  stream<RxBufPtr> ssTOE_RxFreeSpace ("ssTOE_RxFreeSpace");
2666  stream<ap_uint<32> > ssTOE_TcpIprxByteCnt ("ssTOE_TcpIprxByteCnt");
2667  stream<ap_uint< 8> > ssTOE_OooDebugState ("ssTOE_OooDebugState");
2668  //------------------------------------------------------
2669  //-- TB SIGNALS
2670  //------------------------------------------------------
2671  StsBit sTOE_ReadyDly;
2672 
2673  //-----------------------------------------------------
2674  //-- TESTBENCH VARIABLES
2675  //-----------------------------------------------------
2676  #if TOE_FEATURE_USED_FOR_DEBUGGING
2677  ap_uint<32> sTOE_TB_SimCycCnt;
2678  #endif
2679 
2680  AxisIp4 ipRxData; // An IP4 chunk
2681  AxisApp tcpTxData; // A TCP chunk
2682 
2683  ap_uint<16> nrOpenedSessions;
2684  ap_uint<16> nrClosedSessions;
2685  ap_uint<32> nrTcpIprxBytes;
2686 
2687  DummyMemory rxMemory;
2688  DummyMemory txMemory;
2689 
2690  map<SocketPair, TcpAckNum> sessAckList; // [FIXME -Rename to Map]
2691  map<SocketPair, TcpSeqNum> sessSeqList; // [FIXME -Rename to Map]
2692 
2693  //-- Double-ended queue of packets --------------------
2694  deque<SimIp4Packet> ipRxPacketizer; // Packets intended for the IPRX interface of TOE
2695 
2696  //-----------------------------------------------------
2697  //-- TESTBENCH INPUT & OUTPUT FILE STREAMS
2698  //-----------------------------------------------------
2699  ifstream ifIPRX_Data; // IP4 packets from IPRX
2700  ifstream ifTAIF_Data; // APP data from TAIF
2701 
2702  ofstream ofTAIF_Data; // APP byte streams delivered to TAIF
2703  ofstream ofTAIF_Gold; // Gold reference file for 'ofTAIF_Data'
2704  ofstream ofIPTX_Data1; // Raw IP packets delivered to IPTX
2705  ofstream ofIPTX_Gold1; // Gold reference file for 'ofIPTX_Data1' (not used)
2706  ofstream ofIPTX_Data2; // Tcp payload of the IP packets delivered to IPTX
2707  ofstream ofIPTX_Gold2; // Gold reference file for 'ofIPTX_Data2'
2708 
2709  const char *ofTAIF_DataName = "../../../../test/simOutFiles/soTAIF.strm";
2710  const char *ofTAIF_GoldName = "../../../../test/simOutFiles/soTAIF.gold";
2711  const char *ofIPTX_Data1Name = "../../../../test/simOutFiles/soIPTX.dat";
2712  const char *ofIPTX_Gold1Name = "../../../../test/simOutFiles/soIPTX.gold";
2713  const char *ofIPTX_Data2Name = "../../../../test/simOutFiles/soIPTX_TcpData.strm";
2714  const char *ofIPTX_Gold2Name = "../../../../test/simOutFiles/soIPTX_TcpData.gold";
2715 
2716  string dataString, keepString;
2717 
2718  int nrErr = 0; // Total number of testbench errors
2719 
2720  int pktCounter_IPRX_TOE = 0; // Counts the # IP packets from IPRX-to-TOE (all kinds and from all sessions).
2721  int tcpBytCntr_IPRX_TOE = 0; // Counts the # TCP bytes from IPRX-to-TOE.
2722 
2723  int pktCounter_TOE_IPTX = 0; // Counts the # IP packets from TOE-to-IPTX (all kinds and from all sessions).
2724  int tcpBytCntr_TOE_IPTX = 0; // Counts the # TCP bytes from TOE-to-IPTX.
2725 
2726  int tcpBytCnt_APP_TOE = 0; // Counts the # TCP bytes from APP-to-TOE.
2727  int tcpBytCnt_TOE_APP = 0; // Counts the # TCP bytes from TOE-to-APP.
2728 
2729  bool testRxPath = false; // Indicates if the Rx path is to be tested.
2730  bool testTxPath = false; // Indicates if the Tx path is to be tested.
2731 
2732  int startUpDelay = TB_STARTUP_TIME;
2733 
2734  char mode = *argv[1];
2735  char cCurrPath[FILENAME_MAX];
2736 
2737  //------------------------------------------------------
2738  //-- REMOVE PREVIOUS OLD SIM FILES and OPEN NEW ONES
2739  //------------------------------------------------------
2740  remove(ofTAIF_DataName);
2741  ofTAIF_Data.open(ofTAIF_DataName);
2742  if (!ofTAIF_Data) {
2743  printError(THIS_NAME, "Cannot open the Application Tx file: \n\t %s \n", ofTAIF_DataName);
2744  return -1;
2745  }
2746  remove(ofTAIF_GoldName);
2747  ofTAIF_Gold.open(ofTAIF_GoldName);
2748  if (!ofTAIF_Gold) {
2749  printInfo(THIS_NAME, "Cannot open the Application Tx gold file: \n\t %s \n", ofTAIF_GoldName);
2750  return -1;
2751  }
2752  remove(ofIPTX_Data1Name);
2753  ofIPTX_Data1.open(ofIPTX_Data1Name);
2754  if (!ofIPTX_Data1) {
2755  printError(THIS_NAME, "Cannot open the IP Tx file: \n\t %s \n", ofIPTX_Data1Name);
2756  return -1;
2757  }
2758  remove(ofIPTX_Data2Name);
2759  ofIPTX_Data2.open(ofIPTX_Data2Name);
2760  if (!ofIPTX_Data2) {
2761  printError(THIS_NAME, "Cannot open the IP Tx file: \n\t %s \n", ofIPTX_Data2Name);
2762  return -1;
2763  }
2764  remove(ofIPTX_Gold2Name);
2765  ofIPTX_Gold1.open(ofIPTX_Gold1Name);
2766  if (!ofIPTX_Gold1) {
2767  printError(THIS_NAME, "Cannot open the IP Tx gold file: \n\t %s \n", ofIPTX_Gold1Name);
2768  return -1;
2769  }
2770  remove(ofIPTX_Gold2Name);
2771  ofIPTX_Gold2.open(ofIPTX_Gold2Name);
2772  if (!ofIPTX_Gold2) {
2773  printError(THIS_NAME, "Cannot open the IP Tx gold file: \n\t %s \n", ofIPTX_Gold2Name);
2774  return -1;
2775  }
2776 
2777  printInfo(THIS_NAME, "############################################################################\n");
2778  printInfo(THIS_NAME, "## TESTBENCH 'test_toe' STARTS HERE ##\n");
2779  printInfo(THIS_NAME, "############################################################################\n");
2780  printInfo(THIS_NAME, "This testbench will be executed with the following parameters: \n");
2781  for (int i=1; i<argc; i++) {
2782  printInfo(THIS_NAME, "\t==> Param[%d] = %s\n", (i-1), argv[i]);
2783  }
2784  printf("\n\n");
2785 
2786  sTOE_ReadyDly = 0;
2787 
2788  //------------------------------------------------------
2789  //-- PARSING TESBENCH ARGUMENTS
2790  //------------------------------------------------------
2791  if (argc < 3) {
2792  printError(THIS_NAME, "Expected a minimum of 2 or 3 parameters with one of the following synopsis:\n \t\t mode(0|3) siIPRX_<TestName>\n \t\t mode(1) siTAIF_<TestName>\n \t\t mode(2) siIPRX_<TestName> siTAIF_<TestName>\n");
2793  gFatalError = true;
2794  return 1;
2795  }
2796  printInfo(THIS_NAME, "This run executes in mode \'%c\'.\n", mode);
2797 
2798  if ((mode == RX_MODE) || (mode == BIDIR_MODE) || (mode == ECHO_MODE)) {
2799  testRxPath = true;
2800  //-------------------------------------------------
2801  //-- Files used for the test of the Rx side
2802  //-------------------------------------------------
2803  ifIPRX_Data.open(argv[2]);
2804  if (!ifIPRX_Data) {
2805  printError(THIS_NAME, "Cannot open the IP Rx file: \n\t %s \n", argv[2]);
2806  if (!getcwd(cCurrPath, sizeof(cCurrPath))) {
2807  return -1;
2808  }
2809  printInfo (THIS_NAME, "\t (FYI - The current working directory is: \n\t %s) \n", cCurrPath);
2810  return -1;
2811  }
2812  printInfo(THIS_NAME, "This run executes with IP Rx file : %s.\n", argv[2]);
2813  }
2814 
2815  if ((mode == TX_MODE) || (mode == BIDIR_MODE) || (mode == ECHO_MODE)) {
2816  testTxPath = true;
2817  //-------------------------------------------------
2818  //-- Files used for the test of the Tx side
2819  //-------------------------------------------------
2820  switch (mode) {
2821  case TX_MODE:
2822  ifTAIF_Data.open(argv[2]);
2823  if (!ifTAIF_Data) {
2824  printError(THIS_NAME, "Cannot open the APP Rx file: \n\t %s \n", argv[2]);
2825  if (!getcwd(cCurrPath, sizeof(cCurrPath))) {
2826  return -1;
2827  }
2828  printInfo (THIS_NAME, "\t (FYI - The current working directory is: \n\t %s) \n", cCurrPath);
2829  return -1;
2830  }
2831  printInfo(THIS_NAME, "This run executes with APP Rx file : %s.\n", argv[2]);
2832  break;
2833  case BIDIR_MODE:
2834  ifTAIF_Data.open(argv[3]);
2835  if (!ifTAIF_Data) {
2836  printError(THIS_NAME, "Cannot open the APP Rx file: \n\t %s \n", argv[3]);
2837  if (!getcwd(cCurrPath, sizeof(cCurrPath))) {
2838  return -1;
2839  }
2840  printf ("\t (FYI - The current working directory is: \n\t %s) \n", cCurrPath);
2841  return -1;
2842  }
2843  printInfo(THIS_NAME, "This run executes with APP Rx file : %s.\n", argv[3]);
2844  break;
2845  }
2846  }
2847 
2848  //-----------------------------------------------------
2849  //-- MAIN LOOP
2850  //-----------------------------------------------------
2851  do {
2852  //-------------------------------------------------
2853  //-- STEP-1 : Emulate the IPv4 Rx Path
2854  //-------------------------------------------------
2855  pIPRX(ifIPRX_Data, ofTAIF_Gold,
2856  testRxPath, pktCounter_IPRX_TOE, tcpBytCntr_IPRX_TOE,
2857  ipRxPacketizer, sessAckList,
2858  sTOE_ReadyDly, ssIPRX_TOE_Data);
2859 
2860  //-------------------------------------------------
2861  //-- STEP-2 : RUN DUT
2862  //-------------------------------------------------
2863  #if HLS_VERSION == 2017
2864  toe_top(
2865  #else
2866  toe_top_wrap(
2867  #endif
2868  //-- MMIO Interfaces
2869  gFpgaIp4Addr,
2870  ssTOE_MMIO_RxMemWrErr,
2871  ssTOE_MMIO_NotifDropCnt,
2872  ssTOE_MMIO_MetaDropCnt,
2873  ssTOE_MMIO_DataDropCnt,
2874  ssTOE_MMIO_CrcDropCnt,
2875  ssTOE_MMIO_SessDropCnt,
2876  ssTOE_MMIO_OooDropCnt,
2877  //-- NTS Interfaces
2878  sTOE_Ready,
2879  //-- IPv4 / Rx & Tx Data Interfaces
2880  ssIPRX_TOE_Data,
2881  ssTOE_IPTX_Data,
2882  //-- TAIF / Rx Data Interfaces
2883  ssTOE_TAIF_Notif,
2884  ssTAIF_TOE_DReq,
2885  ssTOE_TAIF_Data,
2886  ssTOE_TAIF_Meta,
2887  //-- TAIF / Listen Port Interfaces
2888  ssTAIF_TOE_LsnReq,
2889  ssTOE_TAIF_LsnRep,
2890  //-- TAIF / Tx Data Interfaces
2891  ssTAIF_TOE_Data,
2892  ssTAIF_TOE_SndReq,
2893  ssTOE_TAIF_SndRep,
2894  //-- TAIF / Open Connection Interfaces
2895  ssTAIF_TOE_OpnReq,
2896  ssTOE_TAIF_OpnRep,
2897  //-- TAIF / Close Interfaces
2898  ssTAIF_TOE_ClsReq,
2899  //-- [TODO] &soTAIF_ClsSts,
2900  //-- MEM / Rx PATH / S2MM Interface
2901  ssTOE_MEM_RxP_RdCmd,
2902  ssMEM_TOE_RxP_Data,
2903  ssMEM_TOE_RxP_WrSts,
2904  ssTOE_MEM_RxP_WrCmd,
2905  ssTOE_MEM_RxP_Data,
2906  //-- MEM / Tx PATH / S2MM Interface
2907  ssTOE_MEM_TxP_RdCmd,
2908  ssMEM_TOE_TxP_Data,
2909  ssMEM_TOE_TxP_WrSts,
2910  ssTOE_MEM_TxP_WrCmd,
2911  ssTOE_MEM_TxP_Data,
2912  //-- CAM / Session Lookup & Update Interfaces
2913  ssTOE_CAM_SssLkpReq,
2914  ssCAM_TOE_SssLkpRep,
2915  ssTOE_CAM_SssUpdReq,
2916  ssCAM_TOE_SssUpdRep,
2917  //-- DEBUG / Session Statistics Interfaces
2918  ssTOE_ClsSessCount,
2919  ssTOE_OpnSessCount,
2920  ssTOE_RxFreeSpace,
2921  ssTOE_TcpIprxByteCnt,
2922  ssTOE_OooDebugState
2924  ,
2925  sTOE_TB_SimCycCnt
2926  #endif
2927  );
2928 
2929  //------------------------------------------------------
2930  //-- STEP-2.1 : Drain TOE's Debug Streams
2931  //------------------------------------------------------
2932  if (!ssTOE_ClsSessCount.empty()) {
2933  nrClosedSessions = ssTOE_ClsSessCount.read();
2934  }
2935  if (!ssTOE_OpnSessCount.empty()) {
2936  nrOpenedSessions = ssTOE_OpnSessCount.read();
2937  }
2938  if (!ssTOE_RxFreeSpace.empty()) {
2939  nrOpenedSessions = ssTOE_RxFreeSpace.read();
2940  }
2941  if (!ssTOE_TcpIprxByteCnt.empty()) {
2942  nrTcpIprxBytes = ssTOE_TcpIprxByteCnt.read();
2943  }
2944  if (!ssTOE_OooDebugState.empty()) {
2945  ssTOE_OooDebugState.read();
2946  }
2947 
2948  //------------------------------------------------------
2949  //-- STEP-2.2 : GENERATE THE 'ReadyDly' SIGNAL
2950  //------------------------------------------------------
2951  if (sTOE_Ready == 1) {
2952  if (startUpDelay > 0) {
2953  startUpDelay--;
2954  if (DEBUG_LEVEL & TRACE_MAIN) {
2955  if (startUpDelay == 0) {
2956  printInfo(THIS_NAME, "TOE and TB are ready.\n");
2957  }
2958  }
2959  }
2960  else {
2961  sTOE_ReadyDly = sTOE_Ready;
2962  }
2963  }
2964 
2965  //-------------------------------------------------
2966  //-- STEP-3 : Emulate DRAM & CAM Interfaces
2967  //-------------------------------------------------
2968  if (sTOE_ReadyDly) {
2970  &rxMemory, nrErr,
2971  ssTOE_MEM_RxP_WrCmd, ssTOE_MEM_RxP_Data, ssMEM_TOE_RxP_WrSts,
2972  ssTOE_MEM_RxP_RdCmd, ssMEM_TOE_RxP_Data);
2973 
2975  &txMemory, nrErr,
2976  ssTOE_MEM_TxP_WrCmd, ssTOE_MEM_TxP_Data, ssMEM_TOE_TxP_WrSts,
2977  ssTOE_MEM_TxP_RdCmd, ssMEM_TOE_TxP_Data);
2978 
2979  pEmulateCam(
2980  ssTOE_CAM_SssLkpReq, ssCAM_TOE_SssLkpRep,
2981  ssTOE_CAM_SssUpdReq, ssCAM_TOE_SssUpdRep);
2982  }
2983 
2984  //------------------------------------------------------
2985  //-- STEP-4 : DRAIN DUT AND WRITE OUTPUT FILE STREAMS
2986  //------------------------------------------------------
2987 
2988  //-------------------------------------------------
2989  //-- STEP-4.0 : Emulate Layer-3 Multiplexer
2990  //-------------------------------------------------
2991  pIPTX(
2992  sTOE_ReadyDly,
2993  ssTOE_IPTX_Data,
2994  ofIPTX_Data1,
2995  ofIPTX_Data2,
2996  sessAckList,
2997  pktCounter_TOE_IPTX,
2998  tcpBytCntr_TOE_IPTX,
2999  ipRxPacketizer);
3000 
3001  //-------------------------------------------------
3002  //-- STEP-4.1 : Emulate TCP Application (TAIF)
3003  //-------------------------------------------------
3004  pTAIF(
3005  testTxPath,
3006  mode,
3007  nrErr,
3008  gFpgaIp4Addr,
3009  ifTAIF_Data,
3010  ofTAIF_Data,
3011  ofIPTX_Gold2,
3012  tcpBytCnt_APP_TOE,
3013  tcpBytCnt_TOE_APP,
3014  sTOE_ReadyDly,
3015  ssTAIF_TOE_LsnReq,
3016  ssTOE_TAIF_LsnRep,
3017  ssTOE_TAIF_Notif,
3018  ssTAIF_TOE_DReq,
3019  ssTOE_TAIF_Data,
3020  ssTOE_TAIF_Meta,
3021  ssTAIF_TOE_OpnReq,
3022  ssTOE_TAIF_OpnRep,
3023  ssTAIF_TOE_Data,
3024  ssTAIF_TOE_SndReq,
3025  ssTOE_TAIF_SndRep,
3026  ssTAIF_TOE_ClsReq);
3027 
3028 
3029  //------------------------------------------------------
3030  //-- STEP-7 : INCREMENT SIMULATION COUNTER
3031  //------------------------------------------------------
3032  #if TOE_FEATURE_USED_FOR_DEBUGGING
3033  // The sim-counter s generated by [TOE]
3034  gSimCycCnt = sTOE_TB_SimCycCnt.to_uint();
3035  if (gTraceEvent || ((gSimCycCnt % 1000) == 0)) {
3036  printf("-- [@%4.4d] -----------------------------\n", gSimCycCnt);
3037  gTraceEvent = false;
3038  }
3039  #else
3040  stepSim();
3041  #endif
3042 
3043  //------------------------------------------------------
3044  //-- EXIT UPON FATAL ERROR OR TOO MANY ERRORS
3045  //------------------------------------------------------
3046 
3047  } while ( (gSimCycCnt < gMaxSimCycles) and (not gFatalError) and (nrErr < 10) );
3048 
3049 
3050  printInfo(THIS_NAME, "############################################################################\n");
3051  printInfo(THIS_NAME, "## TESTBENCH 'test_toe' ENDS HERE ##\n");
3052  printInfo(THIS_NAME, "############################################################################\n");
3053  stepSim();
3054 
3055  //---------------------------------------------
3056  //-- DRAIN TOE-->MMIO DROP COUNTER STREAMS
3057  //---------------------------------------------
3058  int nrRxMemWrErr = drainMmioDropCounter(ssTOE_MMIO_RxMemWrErr, "drainMmioDropCounter");
3059  int nrNotifDrops = drainMmioDropCounter(ssTOE_MMIO_NotifDropCnt, "ssTOE_MMIO_NotifDropCnt");
3060  int nrMetaDrops = drainMmioDropCounter(ssTOE_MMIO_MetaDropCnt, "ssTOE_MMIO_MetaDropCnt");
3061  int nrDataDrops = drainMmioDropCounter(ssTOE_MMIO_DataDropCnt, "ssTOE_MMIO_DataDropCnt");
3062  int nrCrcDrops = drainMmioDropCounter(ssTOE_MMIO_CrcDropCnt, "ssTOE_MMIO_CrcDropCnt");
3063  int nrSessDrops = drainMmioDropCounter(ssTOE_MMIO_SessDropCnt, "ssTOE_MMIO_SessDropCnt");
3064  int nrOooDrops = drainMmioDropCounter(ssTOE_MMIO_OooDropCnt, "ssTOE_MMIO_OooDropCnt");
3065 
3066  //---------------------------------
3067  //-- CLOSING OPEN FILES
3068  //---------------------------------
3069  if ((mode == RX_MODE) || (mode == BIDIR_MODE) || (mode == ECHO_MODE)) {
3070  // Rx side testing only
3071  ifIPRX_Data.close();
3072  ofTAIF_Data.close();
3073  ofTAIF_Gold.close();
3074  }
3075 
3076  if ((mode == TX_MODE) || (mode == BIDIR_MODE) || (mode == ECHO_MODE)) {
3077  // Tx side testing only
3078  ifTAIF_Data.close();
3079  ofIPTX_Data1 << endl; ofIPTX_Data1.close();
3080  ofIPTX_Data2 << endl; ofIPTX_Data2.close();
3081  ofIPTX_Gold2 << endl; ofIPTX_Gold2.close();
3082  }
3083 
3084  //---------------------------------------------------------------
3085  //-- PRINT AN OVERALL TESTBENCH STATUS
3086  //---------------------------------------------------------------
3087  printInfo(THIS_NAME, "Number of sessions opened by TOE : %6d \n", nrOpenedSessions.to_uint());
3088  printInfo(THIS_NAME, "Number of sessions closed by TOE : %6d \n", nrClosedSessions.to_uint());
3089 
3090  printInfo(THIS_NAME, "Number of IP Packets from IPRX-to-TOE : %6d \n", pktCounter_IPRX_TOE);
3091  printInfo(THIS_NAME, "Number of IP Packets from TOE-to-IPTX : %6d \n", pktCounter_TOE_IPTX);
3092 
3093  printInfo(THIS_NAME, "Number of TCP Bytes from IPRX-to-TOE : %6d \n", tcpBytCntr_IPRX_TOE);
3094  printInfo(THIS_NAME, "Number of TCP Bytes from TOE-to-APP : %6d \n", tcpBytCnt_TOE_APP);
3095 
3096  printInfo(THIS_NAME, "Number of TCP Bytes from APP-to-TOE : %6d \n", tcpBytCnt_APP_TOE);
3097  printInfo(THIS_NAME, "Number of TCP Bytes from TOE-to-IPTX : %6d \n", tcpBytCntr_TOE_IPTX);
3098 
3099  printf("\n");
3100  //---------------------------------------------------------------
3101  //-- COMPARE TOE's EMBEDDED COUNTERS WITH TESTBENCH COUNTERS
3102  //---------------------------------------------------------------
3103  if (tcpBytCntr_IPRX_TOE != nrTcpIprxBytes.to_uint()) {
3104  printError(THIS_NAME, "The number of TCP bytes received by TOE on its IP interface (%d) does not match the internal TCP bytes counter of TOE (%d). \n", tcpBytCntr_IPRX_TOE, nrTcpIprxBytes.to_uint());
3105  nrErr++;
3106  }
3107 
3108  //---------------------------------------------------------------
3109  //-- COMPARE THE RESULTS FILES WITH GOLDEN FILES
3110  //---------------------------------------------------------------
3111  if ((mode == RX_MODE) or (mode == ECHO_MODE)) {
3112  if (mode != ECHO_MODE) {
3113  printInfo(THIS_NAME, "This testbench was executed in mode \'%c\' with siIPRX file = %s.\n", mode, argv[2]);
3114  }
3115  if (gSortTaifGold) {
3116  //-- Sort and merge the TAIF gold file before comparison
3117  string sortedTAIF_GoldName = std::string(ofTAIF_GoldName) + ".sorted";
3118  int rc = system(("sort " + std::string(ofTAIF_GoldName) + " > " +
3119  std::string(sortedTAIF_GoldName)).c_str());
3120  if (rc != 0) {
3121  printFatal(THIS_NAME, "Failed to sort output file \"%s\". \n", ofTAIF_GoldName);
3122  }
3123  string mergedTAIF_GoldName = std::string(sortedTAIF_GoldName) + ".merged";
3124  string mergedTAIF_StrmName = std::string(ofTAIF_DataName) + ".merged";
3125  int mergeCmd1 = system(("paste -sd \"\" "+ std::string(sortedTAIF_GoldName) + " > " + mergedTAIF_GoldName + " ").c_str());
3126  int mergeCmd2 = system(("paste -sd \"\" "+ std::string(ofTAIF_DataName) + " > " + mergedTAIF_StrmName + " ").c_str());
3127  int ipRx_TcpDataCompare = system(("diff --brief -w " + mergedTAIF_GoldName + " " + mergedTAIF_StrmName + " ").c_str());
3128  if (ipRx_TcpDataCompare != 0) {
3129  if (nrOooDrops == 0) {
3130  printError(THIS_NAME, "File \"%s\" differs from file \"%s\" \n", mergedTAIF_StrmName.c_str(), mergedTAIF_GoldName.c_str());
3131  nrErr++;
3132  }
3133  else {
3134  printWarn(THIS_NAME, "Skipping TCP data comparison on the IP Rx side.\n");
3135  }
3136  }
3137  }
3138  else {
3139  //-- Default checkers
3140  int appTxCompare = system(("diff --brief -w " + std::string(ofTAIF_DataName) + " "
3141  + std::string(ofTAIF_GoldName) + " ").c_str());
3142  if (appTxCompare != 0) {
3143  if (nrOooDrops == 0) {
3144  printError(THIS_NAME, "File \"%s\" differs from file \"%s\" \n", ofTAIF_DataName, ofTAIF_GoldName);
3145  nrErr++;
3146  }
3147  else {
3148  printWarn(THIS_NAME, "Skipping comparison between file \"%s\" and file \"%s\" \n", ofTAIF_DataName, ofTAIF_GoldName);
3149  }
3150  if (tcpBytCntr_IPRX_TOE != tcpBytCnt_TOE_APP) {
3151  if (nrOooDrops == 0) {
3152  printError(THIS_NAME, "The number of TCP bytes received by TOE on its IP interface (%d) does not match the number TCP bytes forwarded by TOE to the application over its TAIF interface (%d). \n", tcpBytCntr_IPRX_TOE, tcpBytCnt_TOE_APP);
3153  nrErr++;
3154  }
3155  else {
3156  printWarn(THIS_NAME, "Skipping TCP IpRx vs TCP App byte count comparison.\n");
3157  }
3158  }
3159  }
3160  }
3161  if ((nrOpenedSessions == 0) and (pktCounter_IPRX_TOE > 0)) {
3162  printWarn(THIS_NAME, "No session was opened by the TOE during this run. Please double check!!!\n");
3163  nrErr++;
3164  }
3165  }
3166 
3167  if ((mode == TX_MODE) or (mode == ECHO_MODE)) {
3168  printf("\n");
3169  printInfo(THIS_NAME, "This testbench was executed in mode \'%c\' with siTAIF file = %s.\n", mode, argv[2]);
3170  if (tcpBytCntr_TOE_IPTX != tcpBytCnt_APP_TOE) {
3171  printError(THIS_NAME, "The number of TCP bytes forwarded from TOE-to-IPTX (%d) does not match the number TCP bytes received from APP-to-TOE (%d). \n", tcpBytCntr_TOE_IPTX, tcpBytCnt_APP_TOE);
3172  nrErr++;
3173  }
3174  string mergedIPTX_Data2Name = std::string(ofIPTX_Data2Name) + ".merged";
3175  string mergedIPTX_Gold2Name = std::string(ofIPTX_Gold2Name) + ".merged";
3176  int mergeCmd1 = system(("paste -sd \"\" "+ std::string(ofIPTX_Data2Name) + " > " + mergedIPTX_Data2Name + " ").c_str());
3177  int mergeCmd2 = system(("paste -sd \"\" "+ std::string(ofIPTX_Gold2Name) + " > " + mergedIPTX_Gold2Name + " ").c_str());
3178  int ipTx_TcpDataCompare = system(("diff --brief -w " + mergedIPTX_Data2Name + " " + mergedIPTX_Gold2Name + " ").c_str());
3179  if (ipTx_TcpDataCompare != 0) {
3180  printError(THIS_NAME, "File \"%s\" differs from file \"%s\" \n", mergedIPTX_Data2Name.c_str(), mergedIPTX_Gold2Name.c_str());
3181  nrErr++;
3182  }
3183  }
3184 
3185  //---------------------------------------------------------------
3186  //-- PRINT TESTBENCH STATUS
3187  //---------------------------------------------------------------
3188  printf("\n\n");
3189  printInfo(THIS_NAME, "This testbench was executed with the following parameters: \n");
3190  printInfo(THIS_NAME, "\t==> TB Mode = %c\n", *argv[1]);
3191  for (int i=2; i<argc; i++) {
3192  printInfo(THIS_NAME, "\t==> Param[%d] = %s\n", (i-1), argv[i]);
3193  }
3194 
3195 
3196  if (nrErr) {
3197  printError(THIS_NAME, "###########################################################\n");
3198  printError(THIS_NAME, "#### TEST BENCH FAILED : TOTAL NUMBER OF ERROR(S) = %2d ####\n", nrErr);
3199  printError(THIS_NAME, "###########################################################\n\n");
3200 
3201  printInfo(THIS_NAME, "FYI - You may want to check for \'ERROR\' and/or \'WARNING\' alarms in the LOG file...\n\n");
3202  }
3203  else {
3204  printInfo(THIS_NAME, "#############################################################\n");
3205  printInfo(THIS_NAME, "#### SUCCESSFUL END OF TEST ####\n");
3206  printInfo(THIS_NAME, "#############################################################\n");
3207  }
3208 
3209  return nrErr;
3210 
3211 }
3212 
void setTLast(tLast last)
Definition: AxisRaw.hpp:246
tLast getTLast() const
Definition: AxisRaw.hpp:219
int getLen() const
Definition: AxisRaw.hpp:411
ap_uint< 40 > saddr
ap_uint< 23 > btt
Definition: mem.hpp:85
ap_uint< 1 > okay
Class App Data.
Definition: SimAppData.hpp:53
int length()
Definition: SimAppData.hpp:133
void pushChunk(AxisApp appChunk)
Definition: SimAppData.hpp:115
AxisApp pullChunk()
Definition: SimAppData.hpp:125
Class IPv4 Packet for simulation.
void writeTcpDataToDatFile(ofstream &outFile)
Dump the TCP payload of this IP packet into a file. Data is written as a string.
int sizeOfTcpData()
Return the size of the TCP data payload in octets.
TcpSeqNum getTcpSequenceNumber()
int getIpTotalLength()
bool isACK()
Returns true if packet is an ACK.
void setTcpSequenceNumber(TcpSeqNum num)
int tcpRecalculateChecksum()
Recalculate the checksum of a TCP segment after it was modified.
void setIpSourceAddress(int addr)
bool isWellFormed(const char *callerName, bool checkIp4TotLen=true, bool checkIp4HdrCsum=true, bool checkUdpLen=true, bool checkLy4Csum=true)
Checks if the IP header and embedded protocol fields are properly set.
TcpAckNum getTcpAcknowledgeNumber()
Ip4Addr getIpSourceAddress()
int getTcpDestinationPort()
int getTcpChecksum()
void pushChunk(AxisIp4 ip4Chunk)
void clone(SimIp4Packet &ipPkt)
Clone an IP packet.
bool isFIN()
Returns true if packet is a FIN.
void setTcpAcknowledgeNumber(TcpAckNum num)
void setTcpControlAck(int bit)
void setIpDestinationAddress(int addr)
Ip4Addr getIpDestinationAddress()
void printHdr(const char *callerName)
Print the header details of an IP packet.
void setTcpSourcePort(int port)
void printRaw(const char *callerName)
Raw print of an IP packet (.i.e, as AxisRaw chunks).
bool isSYN()
Returns true if packet is a SYN.
void setTcpChecksum(int csum)
int getTcpSourcePort()
void setTcpDestinationPort(int port)
AxisIp4 pullChunk()
Ip4Addr addr
Definition: nts_types.hpp:209
Ly4Port port
Definition: nts_types.hpp:210
SockAddr dst
Definition: nts_types.hpp:249
SockAddr src
Definition: nts_types.hpp:248
SessionId sessionID
Definition: nts.hpp:89
Ip4Addr ip4SrcAddr
Definition: nts.hpp:91
TcpPort tcpDstPort
Definition: nts.hpp:93
TcpDatLen tcpDatLen
Definition: nts.hpp:90
SessionId sessId
Definition: nts.hpp:167
TcpState tcpState
Definition: nts.hpp:168
TcpDatLen spaceLeft
Definition: nts.hpp:144
SessionId sessId
Definition: nts.hpp:142
TcpAppSndErr error
Definition: nts.hpp:145
TcpDatLen length
Definition: nts.hpp:143
int main()
Definition: tb_fmc.cpp:380
bool StsBool
Definition: nal.hpp:246
unsigned int gSimCycCnt
Definition: tb_nal.cpp:150
bool gTraceEvent
Definition: tb_nal.cpp:151
bool gFatalError
Definition: tb_nal.cpp:152
void stepSim()
Increment the simulation counter.
Definition: test_arp.cpp:54
#define CAM_LOOKUP_LATENCY
Definition: test_arp.hpp:56
unsigned int gMaxSimCycles
Definition: test_arp.hpp:69
#define CAM_UPDATE_LATENCY
Definition: test_arp.hpp:57
void pEmulateCam(stream< RtlMacLookupRequest > &siARS_MacLkpReq, stream< RtlMacLookupReply > &soARS_MacLkpRep, stream< RtlMacUpdateRequest > &siARS_MacUpdReq, stream< RtlMacUpdateReply > &soARS_MacUpdRep)
Emulate the behavior of the Content Addressable Memory (CAM).
Definition: test_arp.cpp:278
bool readAxisRawFromLine(AxisRaw &axisRaw, string stringBuffer)
Retrieve an AxisRaw chunk from a string.
vector< string > myTokenizer(string strBuff, char delimiter)
Brakes a string into tokens by using the 'delimiter' character.
bool writeAxisRawToFile(AxisRaw &axisRaw, ofstream &outFileStream)
Dump an Axis raw data chunk to a file.
bool isDottedDecimal(string ipStr)
Checks if a string contains an IP address represented in dot-decimal notation.
Definition: SimNtsUtils.cpp:72
int writeAxisAppToFile(AxisApp &axisApp, ofstream &outFile)
Dump a TCP or UDP application data chunk into a file. The data are stored as a stream of bytes which ...
bool isHexString(string str)
Checks if a string contains a hexadecimal number.
Definition: SimNtsUtils.cpp:90
ap_uint< 32 > myDottedDecimalIpToUint32(string ipStr)
Converts an IPv4 address represented with a dotted-decimal string into an UINT32.
bool gTest_RcvdIp4Packet
#define TRACE_CAM
Definition: test_toe.cpp:42
bool pTcpAppConnect(int &nrError, SocketPair &aSocketPair, map< SocketPair, SessionId > &openSessList, stream< SockAddr > &soTOE_OpnReq, stream< TcpAppOpnRep > &siTOE_OpnRep)
TCP Application Connect (Tac). Requests TOE to open a new connection to a HOST socket.
void pIPRX_FeedTOE(deque< SimIp4Packet > &ipRxPacketizer, int &ipRxPktCounter, stream< AxisIp4 > &soTOE_Data, map< SocketPair, TcpAckNum > &sessAckList)
Feed TOE with an IP packet.
#define TB_STARTUP_TIME
#define TRACE_TAr
Definition: test_toe.cpp:48
Ip4Addr gHostIp4Addr
void pIPRX(ifstream &ifIPRX_Data, ofstream &ofTAIF_Gold, bool &testRxPath, int &ipRxPktCounter, int &tcpBytCntr_IPRX_TOE, deque< SimIp4Packet > &ipRxPacketizer, map< SocketPair, TcpAckNum > &sessAckList, StsBit &piTOE_Ready, stream< AxisIp4 > &soTOE_Data)
Emulate the behavior of the IP Rx Path (IPRX).
int pIPRX_InjectAckNumber(SimIp4Packet &ipRxPacket, map< SocketPair, TcpAckNum > &sessAckList)
Take the ACK number of a session and inject it into the sequence number field of the current packet.
bool setGlobalParameters(const char *callerName, unsigned int startupDelay, ifstream &inputFile)
Parse the input test file and set the global parameters of the TB.
TcpPort gFpgaLsnPort
#define MEM_RD_STS_LATENCY
#define TRACE_Tal
Definition: test_toe.cpp:52
void pTAIF(bool &testTxPath, char &testMode, int &nrError, Ip4Address &toeIpAddress, ifstream &ifTAIF_Data, ofstream &ofTAIF_Data, ofstream &ofIPTX_Gold2, int &appRxBytCntr, int &appTxBytCntr, StsBit &piTOE_Ready, stream< TcpAppLsnReq > &soTOE_LsnReq, stream< TcpAppLsnRep > &siTOE_LsnRep, stream< TcpAppNotif > &siTOE_Notif, stream< TcpAppRdReq > &soTOE_DReq, stream< TcpAppData > &siTOE_Data, stream< TcpAppMeta > &siTOE_Meta, stream< TcpAppOpnReq > &soTOE_OpnReq, stream< TcpAppOpnRep > &siTOE_OpnRep, stream< TcpAppData > &soTOE_Data, stream< TcpAppSndReq > &soTOE_SndReq, stream< TcpAppSndRep > &siTOE_SndRep, stream< TcpAppClsReq > &soTOE_ClsReq)
Emulates the behavior of the TCP application interface (TAIF).
bool gTest_RcvdLy4Csum
TcpPort gFpgaSndPort
bool gTest_SentIp4TotLen
void pIPTX(StsBit &piTOE_Ready, stream< AxisIp4 > &siTOE_Data, ofstream &ofIPTX_Data1, ofstream &ofIPTX_Data2, map< SocketPair, TcpAckNum > &sessAckList, int &pktCounter_TOE_IPTX, int &tcpBytCntr_TOE_IPTX, deque< SimIp4Packet > &ipRxPacketizer)
Emulate the behavior of the IP Tx Handler (IPTX).
#define TRACE_Tac
Definition: test_toe.cpp:50
#define TRACE_IPTX
Definition: test_toe.cpp:44
void pTcpAppEcho(int &nrError, ofstream &ofIPTX_Gold2, int &apRxBytCntr, stream< TcpAppData > &soTOE_Data, stream< TcpAppSndReq > &soTOE_SndReq, stream< TcpAppSndRep > &siTOE_SndRep, stream< TcpAppData > &siTAr_Data, stream< TcpAppSndReq > &siTAr_SndReq)
TCP Application Echo (Tae). Performs an echo loopback between the receive and send parts of the TCP A...
#define TRACE_TXMEM
Definition: test_toe.cpp:53
#define MEM_RD_CMD_LATENCY
#define APP_RSP_LATENCY
void pTAIF_Send(int &nrError, char &testMode, bool &testTxPath, Ip4Address &toeIpAddress, ifstream &ifTAIF_Data, ofstream &ofIPTX_Gold2, int &apRxBytCntr, StsBit &piTOE_Ready, stream< TcpAppOpnReq > &soTOE_OpnReq, stream< TcpAppOpnRep > &siTOE_OpnRep, stream< TcpAppData > &soTOE_Data, stream< TcpAppSndReq > &soTOE_SndReq, stream< TcpAppSndRep > &siTOE_SndRep, stream< TcpAppClsReq > &soTOE_ClsReq, stream< TcpAppData > &siTAr_Data, stream< TcpAppSndReq > &siTAr_SndReq)
TCP Application Send (TAs). Emulates the Tx process of the TAIF.
bool gTest_SentIp4HdrCsum
#define TRACE_IPRX
Definition: test_toe.cpp:43
void cmdTestCommandParser(const char *callerName, vector< string > stringVector)
Parse and handle a 'COMMAND/TEST' request.
#define RTT_LINK
Ip4Addr gFpgaIp4Addr
#define TRACE_MAIN
Definition: test_toe.cpp:45
#define THIS_NAME
Definition: test_toe.cpp:39
bool pIPTX_Parse(SimIp4Packet &ipTxPacket, map< SocketPair, TcpAckNum > &sessAckList, deque< SimIp4Packet > &ipRxPacketizer)
Parse the TCP/IP packets generated by the TOE.
void increaseSimTime(unsigned int cycles)
Increase the simulation time of the testbench.
bool gTest_SentLy4Csum
bool pTcpAppListen(TcpPort lsnPortNum, set< TcpPort > &openedPorts, stream< TcpAppLsnReq > &soTOE_LsnReq, stream< TcpAppLsnRep > &siTOE_LsnRep)
TCP Application Listen (Tal). Requests TOE to listen on a new port.
#define MEM_WR_STS_LATENCY
#define TRACE_RXMEM
Definition: test_toe.cpp:46
bool gTest_RcvdIp4HdrCsum
const char * myCamAccessToString(int initiator)
Convert an access CAM initiator into a string.
#define TRACE_TAs
Definition: test_toe.cpp:49
#define DEBUG_LEVEL
Definition: test_toe.cpp:55
bool gTest_RcvdIp4TotLen
void pEmulateRxBufMem(DummyMemory *memory, int &nrError, stream< DmCmd > &siTOE_RxP_WrCmd, stream< AxisApp > &siTOE_RxP_Data, stream< DmSts > &soTOE_RxP_WrSts, stream< DmCmd > &siTOE_RxP_RdCmd, stream< AxisApp > &soTOE_RxP_Data)
Emulate the behavior of the Receive DDR4 Buffer Memory (RXMEM).
bool gSortTaifGold
void pEmulateTxBufMem(DummyMemory *memory, int &nrError, stream< DmCmd > &siTOE_TxP_WrCmd, stream< AxisApp > &siTOE_TxP_Data, stream< DmSts > &soTOE_TxP_WrSts, stream< DmCmd > &siTOE_TxP_RdCmd, stream< AxisApp > &soTOE_TxP_Data)
Emulate the behavior of the Transmit DDR4 Buffer Memory (TXMEM).
#define MEM_WR_CMD_LATENCY
void toe_top_wrap(Ip4Addr piMMIO_IpAddr, stream< StsBit > &soMMIO_RxMemWrErr, stream< ap_uint< 8 > > &soMMIO_NotifDropCnt, stream< ap_uint< 8 > > &soMMIO_MetaDropCnt, stream< ap_uint< 8 > > &soMMIO_DataDropCnt, stream< ap_uint< 8 > > &soMMIO_CrcDropCnt, stream< ap_uint< 8 > > &soMMIO_SessDropCnt, stream< ap_uint< 8 > > &soMMIO_OooDropCnt, StsBit &poNTS_Ready, stream< AxisIp4 > &siIPRX_Data, stream< AxisIp4 > &soIPTX_Data, stream< TcpAppNotif > &soTAIF_Notif, stream< TcpAppRdReq > &siTAIF_DReq, stream< TcpAppData > &soTAIF_Data, stream< TcpAppMeta > &soTAIF_Meta, stream< TcpAppLsnReq > &siTAIF_LsnReq, stream< TcpAppLsnRep > &soTAIF_LsnRep, stream< TcpAppData > &siTAIF_Data, stream< TcpAppSndReq > &siTAIF_SndReq, stream< TcpAppSndRep > &soTAIF_SndRep, stream< TcpAppOpnReq > &siTAIF_OpnReq, stream< TcpAppOpnRep > &soTAIF_OpnRep, stream< TcpAppClsReq > &siTAIF_ClsReq, stream< DmCmd > &soMEM_RxP_RdCmd, stream< AxisApp > &siMEM_RxP_Data, stream< DmSts > &siMEM_RxP_WrSts, stream< DmCmd > &soMEM_RxP_WrCmd, stream< AxisApp > &soMEM_RxP_Data, stream< DmCmd > &soMEM_TxP_RdCmd, stream< AxisApp > &siMEM_TxP_Data, stream< DmSts > &siMEM_TxP_WrSts, stream< DmCmd > &soMEM_TxP_WrCmd, stream< AxisApp > &soMEM_TxP_Data, stream< CamSessionLookupRequest > &soCAM_SssLkpReq, stream< CamSessionLookupReply > &siCAM_SssLkpRep, stream< CamSessionUpdateRequest > &soCAM_SssUpdReq, stream< CamSessionUpdateReply > &siCAM_SssUpdRep, stream< ap_uint< 16 > > &soDBG_SssRelCnt, stream< ap_uint< 16 > > &soDBG_SssRegCnt, stream< RxBufPtr > &soDBG_RxFreeSpace, stream< ap_uint< 32 > > &soDBG_TcpIpRxByteCnt, stream< ap_uint< 8 > > &soDBG_OooDebug)
A wrapper for the Toplevel of the TCP Offload Engine (TOE).
#define TRACE_TAIF
Definition: test_toe.cpp:47
void cmdSetCommandParser(const char *callerName, vector< string > stringVector)
Parse and handle a 'COMMAND/SET' request.
const char * camAccessorStrings[]
Definition: test_toe.cpp:81
void pTAIF_Recv(int &nrError, char &testMode, ofstream &ofTAIF_Data, int &appTxBytCntr, StsBit &piTOE_Ready, stream< TcpAppLsnReq > &soTOE_LsnReq, stream< TcpAppLsnRep > &siTOE_LsnRep, stream< TcpAppNotif > &siTOE_Notif, stream< TcpAppRdReq > &soTOE_DReq, stream< TcpAppData > &siTOE_Data, stream< TcpAppMeta > &siTOE_Meta, stream< TcpAppData > &soTAs_Data, stream< TcpAppSndReq > &soTAs_SndReq)
TCP Application Receive (TAr). Emulates the Rx process of the TAIF.
int drainMmioDropCounter(stream< T > &ss, string ssName)
Empty a DropCounter stream and throw it away.
bool gTest_RcvdUdpLen
TcpPort gHostLsnPort
#define FPGA_CLIENT_CONNECT_TIMEOUT
bool gTest_SentUdpLen
@ TX_MODE
@ BIDIR_MODE
@ ECHO_MODE
@ RX_MODE
void setReadCmd(DmCmd cmd)
void printFourTuple(const char *callerName, int src, FourTuple fourTuple)
Print a socket pair association from an internal FourTuple encoding.
Definition: toe_utils.cpp:73
void setWriteCmd(DmCmd cmd)
void readChunk(AxisApp &chunk)
#define TOE_FEATURE_USED_FOR_DEBUGGING
Definition: toe.hpp:103
void toe_top(Ip4Addr piMMIO_IpAddr, stream< StsBit > &soMMIO_RxMemWrErr, stream< ap_uint< 8 > > &soMMIO_NotifDropCnt, stream< ap_uint< 8 > > &soMMIO_MetaDropCnt, stream< ap_uint< 8 > > &soMMIO_DataDropCnt, stream< ap_uint< 8 > > &soMMIO_CrcDropCnt, stream< ap_uint< 8 > > &soMMIO_SessDropCnt, stream< ap_uint< 8 > > &soMMIO_OooDropCnt, StsBit &poNTS_Ready, stream< AxisRaw > &siIPRX_Data, stream< AxisRaw > &soIPTX_Data, stream< TcpAppNotif > &soTAIF_Notif, stream< TcpAppRdReq > &siTAIF_DReq, stream< TcpAppData > &soTAIF_Data, stream< TcpAppMeta > &soTAIF_Meta, stream< TcpAppLsnReq > &siTAIF_LsnReq, stream< TcpAppLsnRep > &soTAIF_LsnRep, stream< TcpAppData > &siTAIF_Data, stream< TcpAppSndReq > &siTAIF_SndReq, stream< TcpAppSndRep > &soTAIF_SndRep, stream< TcpAppOpnReq > &siTAIF_OpnReq, stream< TcpAppOpnRep > &soTAIF_OpnRep, stream< TcpAppClsReq > &siTAIF_ClsReq, stream< DmCmd > &soMEM_RxP_RdCmd, stream< AxisApp > &siMEM_RxP_Data, stream< DmSts > &siMEM_RxP_WrSts, stream< DmCmd > &soMEM_RxP_WrCmd, stream< AxisApp > &soMEM_RxP_Data, stream< DmCmd > &soMEM_TxP_RdCmd, stream< AxisApp > &siMEM_TxP_Data, stream< DmSts > &siMEM_TxP_WrSts, stream< DmCmd > &soMEM_TxP_WrCmd, stream< AxisApp > &soMEM_TxP_Data, stream< CamSessionLookupRequest > &soCAM_SssLkpReq, stream< CamSessionLookupReply > &siCAM_SssLkpRep, stream< CamSessionUpdateRequest > &soCAM_SssUpdReq, stream< CamSessionUpdateReply > &siCAM_SssUpdRep, stream< ap_uint< 16 > > &soDBG_SssRelCnt, stream< ap_uint< 16 > > &soDBG_SssRegCnt, stream< RxBufPtr > &soDBG_RxFreeSpace, stream< ap_uint< 32 > > &soDBG_TcpIpRxByteCnt, stream< ap_uint< 8 > > &soDBG_OooDebug)
Top of TCP Offload Engine (TOE)
Definition: toe.cpp:1056
#define TOE_FIRST_EPHEMERAL_PORT_NUM
Definition: toe.hpp:101
void writeChunk(AxisApp &chunk)
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
ap_uint< 1 > StsBit
Definition: nts_types.hpp:116
void printAxisRaw(const char *callerName, AxisRaw chunk)
Prints an Axis raw data chunk (used for debugging).
Definition: nts_utils.cpp:46
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
void pAxisRawCast(hls::stream< TypeIn > &si, hls::stream< TypeOut > &so)
AxisRaw cast - Casts an AxisRaw stream to/from an AxisRaw derived class.
Definition: AxisRaw.hpp:148
void printSockAddr(const char *callerName, SockAddr sockAddr)
Print a socket address.
Definition: nts_utils.cpp:174
#define IP4_PROT_TCP
Definition: nts_types.hpp:184
ap_uint< 16 > TcpPort
Definition: AxisTcp.hpp:105
TcpAppSndErr
Definition: nts_types.hpp:304
const char * getTcpStateName(TcpState tcpState)
Returns the name of an enum-based TCP-State as a user friendly string.
Definition: nts_utils.cpp:272
AxisRaw AxisApp
Definition: nts.hpp:51
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
void printIp4Addr(const char *callerName, const char *message, Ip4Addr ip4Addr)
Print an IPv4 address prepended with a message (used for debugging).
Definition: nts_utils.cpp:205
#define printWarn(callerName, format,...)
A macro to print a warning message.
Definition: nts_utils.hpp:182
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
ap_uint< 32 > Ip4Address
Definition: AxisIp4.hpp:168
void printTcpPort(const char *callerName, TcpPort tcpPort)
Print a TCP port.
Definition: nts_utils.cpp:257
void printSockPair(const char *callerName, SocketPair sockPair)
Print a socket pair association.
Definition: nts_utils.cpp:114
ap_uint< 32 > TcpAckNum
Definition: AxisTcp.hpp:107
#define printFatal(callerName, format,...)
A macro to print a fatal error message and exit.
Definition: nts_utils.hpp:208
#define STS_KO
Definition: nts_types.hpp:80
@ DELETE
Definition: nts_types.hpp:382
@ INSERT
Definition: nts_types.hpp:382
@ ESTABLISHED
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
: Testbench for the TCP Offload Engine (TOE)
ap_uint< 32 > byteSwap32(ap_uint< 32 > inputVector)
Definition: udp.cpp:78
ap_uint< 16 > byteSwap16(ap_uint< 16 > inputVector)
Definition: udp.cpp:82