cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
simu_udp_app_flash_env.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 
44 
45 using namespace hls;
46 using namespace std;
47 
48 
51 extern unsigned int gSimCycCnt;
52 extern bool gTraceEvent;
53 extern bool gFatalError;
54 extern unsigned int gMaxSimCycles; // = MAX_SIM_CYCLES + TB_GRACE_TIME;
55 
56 
60 #define THIS_NAME "SIM"
61 
62 #define TRACE_OFF 0x0000
63 #define TRACE_USIF 1 << 1
64 #define TRACE_UAF 1 << 2
65 #define TRACE_CGTF 1 << 3
66 #define TRACE_DUMTF 1 << 4
67 #define TRACE_ALL 0xFFFF
68 #define DEBUG_LEVEL (TRACE_OFF)
69 
70 
73 void stepSim() {
74  gSimCycCnt++;
75  if (gTraceEvent || ((gSimCycCnt % 1000) == 0)) {
76  printInfo(THIS_NAME, "-- [@%4.4d] -----------------------------\n", gSimCycCnt);
77  gTraceEvent = false;
78  }
79  else if (0) {
80  printInfo(THIS_NAME, "------------------- [@%d] ------------\n", gSimCycCnt);
81  }
82 }
83 
84 
89 void increaseSimTime(unsigned int cycles) {
90  gMaxSimCycles += cycles;
91 }
92 
93 
107 bool readDatagramFromFile(const char *myName, SimUdpDatagram &appDatagram,
108  ifstream &ifsData, SocketPair &sockPair,
109  queue<UdpAppMeta> &udpMetaQueue,
110  queue<UdpAppDLen> &udpDLenQueue, int &inpChunks,
111  int &inpDgrms, int &inpBytes) {
112 
113  string stringBuffer;
114  vector<string> stringVector;
115  UdpAppData udpAppData;
116  UdpAppDLen udpAppDLen=0;
117  bool endOfDgm=false;
118  bool rc;
119 
120  do {
121  //-- Read one line at a time from the input test DAT file
122  getline(ifsData, stringBuffer);
123  stringVector = myTokenizer(stringBuffer, ' ');
124  //-- Read the Host Socket Address from line (if present)
125  rc = readHostSocketFromLine(sockPair.src, stringBuffer);
126  if (rc) {
127  if (DEBUG_LEVEL & TRACE_CGTF) {
128  printInfo(myName, "Read a new HOST socket address from DAT file:\n");
129  printSockAddr(myName, sockPair.src);
130  }
131  }
132  //-- Read the Fpga Socket Address from line (if present)
133  rc = readFpgaSocketFromLine(sockPair.dst, stringBuffer);
134  if (rc) {
135  if (DEBUG_LEVEL & TRACE_CGTF) {
136  printInfo(myName, "Read a new FPGA socket address from DAT file:\n");
137  printSockAddr(myName, sockPair.dst);
138  }
139  }
140  //-- Read an AxiWord from line
141  rc = readAxisRawFromLine(udpAppData, stringBuffer);
142  if (rc) {
143  appDatagram.pushChunk(AxisUdp(udpAppData.getLE_TData(),
144  udpAppData.getLE_TKeep(),
145  udpAppData.getLE_TLast()));
146  inpChunks++;
147  inpBytes += udpAppData.getLen();
148  udpAppDLen += udpAppData.getLen();
149  if (udpAppData.getLE_TLast() == 1) {
150  inpDgrms++;
151  udpMetaQueue.push(UdpAppMeta(sockPair.src.addr, sockPair.src.port,
152  sockPair.dst.addr, sockPair.dst.port));
153  udpDLenQueue.push(udpAppDLen);
154  endOfDgm = true;
155  }
156  }
157  } while ((ifsData.peek() != EOF) && (!endOfDgm));
158 
159  return endOfDgm;
160 }
161 
162 
178  EchoCtrl tbCtrlMode,
179  string inpData_FileName,
180  queue<UdpAppMeta> &udpMetaQueue,
181  queue<UdpAppDLen> &udpDLenQueue,
182  string outData_GoldName,
183  string outMeta_GoldName,
184  string outDLen_GoldName)
185 {
186  const char *myName = concat3(THIS_NAME, "/", "CGTF");
187 
188  const Ip4Addr hostDefaultIp4Address = 0x0A0CC832; // 10.012.200.50
189  const Ip4Addr fpgaDefaultIp4Address = 0x0A0CC807; // 10.012.200.7
190  const UdpPort fpgaDefaultUdpLsnPort = ECHO_PATH_THRU_PORT;
191  const UdpPort hostDefaultUdpLsnPort = fpgaDefaultUdpLsnPort;
192  const UdpPort hostDefaultUdpSndPort = 32768+ECHO_PATH_THRU_PORT; // 41571
193  const UdpPort fpgaDefaultUdpSndPort = hostDefaultUdpSndPort;
194 
195  ifstream ifsData;
196  ofstream ofsDataGold;
197  ofstream ofsMetaGold;
198  ofstream ofsDLenGold;
199 
200  char currPath[FILENAME_MAX];
201  int ret=NTS_OK;
202  int inpChunks=0, outChunks=0;
203  int inpDgrms=0, outDgrms=0;
204  int inpBytes=0, outBytes=0;
205 
206  //-- STEP-1 : OPEN INPUT TEST FILE ----------------------------------------
207  if (not isDatFile(inpData_FileName)) {
208  printError(myName, "Cannot create golden files from input file \'%s\' because file is not of type \'.dat\'.\n",
209  inpData_FileName.c_str());
210  return(NTS_KO);
211  }
212  else {
213  ifsData.open(inpData_FileName.c_str());
214  if (!ifsData) {
215  getcwd(currPath, sizeof(currPath));
216  printError(myName, "Cannot open the file: %s \n\t (FYI - The current working directory is: %s) \n",
217  inpData_FileName.c_str(), currPath);
218  return(NTS_KO);
219  }
220  }
221 
222  //-- STEP-2 : OPEN THE OUTPUT GOLD FILES ----------------------------------
223  remove(outData_GoldName.c_str());
224  remove(outMeta_GoldName.c_str());
225  remove(outDLen_GoldName.c_str());
226  if (!ofsDataGold.is_open()) {
227  ofsDataGold.open (outData_GoldName.c_str(), ofstream::out);
228  if (!ofsDataGold) {
229  printFatal(THIS_NAME, "Could not open the output gold file \'%s\'. \n",
230  outData_GoldName.c_str());
231  }
232  }
233  if (!ofsMetaGold.is_open()) {
234  ofsMetaGold.open (outMeta_GoldName.c_str(), ofstream::out);
235  if (!ofsMetaGold) {
236  printFatal(THIS_NAME, "Could not open the output gold file \'%s\'. \n",
237  outMeta_GoldName.c_str());
238  }
239  }
240  if (!ofsDLenGold.is_open()) {
241  ofsDLenGold.open (outDLen_GoldName.c_str(), ofstream::out);
242  if (!ofsDLenGold) {
243  printFatal(THIS_NAME, "Could not open the output gold file \'%s\'. \n",
244  outDLen_GoldName.c_str());
245  }
246  }
247 
248  //-- STEP-3 : READ AND PARSE THE INPUT TEST FILE --------------------------
249  SockAddr hostSock = SockAddr(hostDefaultIp4Address, hostDefaultUdpSndPort);
250  SockAddr fpgaSock = SockAddr(fpgaDefaultIp4Address, fpgaDefaultUdpLsnPort);
251  int dgmCnt = 0;
252  do {
253  SimUdpDatagram appDatagram(8);
254  SocketPair currSockPair(hostSock, fpgaSock);
255  UdpAppDLen udpAppDLen = 0;
256  bool endOfDgm=false;
257  //-- Retrieve one APP datagram from input DAT file (can be up to 2^16-1 bytes)
258  endOfDgm = readDatagramFromFile(myName, appDatagram, ifsData,
259  currSockPair, udpMetaQueue, udpDLenQueue,
260  inpChunks, inpDgrms, inpBytes);
261  if (endOfDgm) {
262  //-- Swap the IP_SA/IP_DA but keep UDP_SP/UDP/DP as is
263  SocketPair goldSockPair(SockAddr(currSockPair.dst.addr, currSockPair.src.port),
264  SockAddr(currSockPair.src.addr, currSockPair.dst.port));
265  // Dump the socket pair to file
266  if (tbCtrlMode == ECHO_CTRL_DISABLED) {
267  writeSocketPairToFile(goldSockPair, ofsMetaGold);
268  if (DEBUG_LEVEL & TRACE_CGTF) {
269  printInfo(myName, "Writing new socket-pair to gold file:\n");
270  printSockPair(myName, goldSockPair);
271  }
272  }
273 
274  // Dump the data len to file
275  if (tbCtrlMode == ECHO_CTRL_DISABLED) {
276  UdpAppDLen appDLen;
277  if (currSockPair.dst.port == ECHO_PATH_THRU_PORT) {
278  //-- The traffic will be forwarded in 'ECHO-CUT-THRU' mode
279  // [TODO] if (dgmCnt % 2) {
280  // [TODO] //-- Datagram counter is an ODD value
281  // [TODO] //-- Enable the 'STREAMING-MODE' by setting 'DLen' to zero.
282  // [TODO] appDLen = 0;
283  // [TODO] }
284  // [TODO] else {
285  appDLen = appDatagram.length() - UDP_HEADER_LEN;
286  // [TODO] }
287  }
288  else {
289  appDLen = appDatagram.length() - UDP_HEADER_LEN;
290  }
291 
299  writeApUintToFile(appDLen, ofsDLenGold);
300  if (DEBUG_LEVEL & TRACE_CGTF) {
301  printInfo(myName, "Writing new datagram len (%d) to gold file:\n", appDLen.to_int());
302  }
303  }
304 
305  // Dump UDP datagram payload to gold file
306  if (tbCtrlMode == ECHO_CTRL_DISABLED) {
307  if (appDatagram.writePayloadToDatFile(ofsDataGold) == false) {
308  printError(myName, "Failed to write UDP payload to GOLD file.\n");
309  ret = NTS_KO;
310  }
311  else {
312  outDgrms += 1;
313  outChunks += appDatagram.size();
314  outBytes += appDatagram.length();
315  }
316  }
317  dgmCnt++;
318  } // End-of:if (endOfDgm) {
319 
320  } while(ifsData.peek() != EOF);
321 
322  //-- STEP-4: CLOSE FILES
323  ifsData.close();
324  ofsDataGold.close();
325  ofsMetaGold.close();
326  ofsDLenGold.close();
327 
328  //-- STEP-5: PRINT RESULTS
329  printInfo(myName, "Done with the creation of the golden file.\n");
330  printInfo(myName, "\tProcessed %5d chunks in %4d datagrams, for a total of %6d bytes.\n",
331  inpChunks, inpDgrms, inpBytes);
332  printInfo(myName, "\tGenerated %5d chunks in %4d datagrams, for a total of %6d bytes.\n",
333  outChunks, outDgrms, outBytes);
334  return NTS_OK;
335 }
336 
337 
354  stream<AxisApp> &ssData, const string ssDataName,
355  stream<UdpAppMeta> &ssMeta, const string ssMetaName,
356  stream<UdpAppDLen> &ssDLen, const string ssMDLenName,
357  string datFile,
358  queue<UdpAppMeta> &metaQueue,
359  queue<UdpAppDLen> &dlenQueue,
360  int &nrFeededChunks)
361 {
362 
363  int nrUSIF_UAF_MetaChunks = 0;
364  int nrUSIF_UAF_MetaGrams = 0;
365  int nrUSIF_UAF_MetaBytes = 0;
366 
367  //-- STEP-1: FEED AXIS DATA STREAM FROM DAT FILE --------------------------
368  int nrDataChunks=0, nrDataGrams=0, nrDataBytes=0;
369  if (feedAxisFromFile(ssData, ssDataName, datFile,
370  nrDataChunks, nrDataGrams, nrDataBytes)) {
371  printInfo(THIS_NAME, "Done with the creation of UDP-Data traffic as a stream:\n");
372  printInfo(THIS_NAME, "\tGenerated %d chunks in %d datagrams, for a total of %d bytes.\n\n",
373  nrDataChunks, nrDataGrams, nrDataBytes);
374  nrFeededChunks = nrDataChunks;
375  }
376  else {
377  printError(THIS_NAME, "Failed to create UDP-Data traffic as input stream. \n");
378  return NTS_KO;
379  }
380 
381  //-- STEP-2: FEED METADATA STREAM FROM QUEUE ------------------------------
382  while (!metaQueue.empty()) {
383  ssMeta.write(metaQueue.front());
384  metaQueue.pop();
385  }
386 
387  //-- STEP-3: FEED DATA LEN STREAM ROM QUEUE -------------------------------
388  while (!dlenQueue.empty()) {
389  ssDLen.write(dlenQueue.front());
390  dlenQueue.pop();
391  }
392 
393  return NTS_OK;
394 
395 } // End-of: createUdpRxTraffic()
396 
397 
409 bool drainUdpMetaStreamToFile(stream<UdpAppMeta> &ss, string ssName,
410  string datFile, int &nrChunks, int &nrFrames, int &nrBytes) {
411  ofstream outFileStream;
412  char currPath[FILENAME_MAX];
413  UdpAppMeta udpMeta;
414 
415  const char *myName = concat3(THIS_NAME, "/", "DUMTF");
416 
417  //-- REMOVE PREVIOUS FILE
418  remove(ssName.c_str());
419 
420  //-- OPEN FILE
421  if (!outFileStream.is_open()) {
422  outFileStream.open(datFile.c_str(), ofstream::out);
423  if (!outFileStream) {
424  printError(THIS_NAME, "Cannot open the file: \'%s\'.\n", datFile.c_str());
425  return(NTS_KO);
426  }
427  }
428 
429  // Assess that file has ".dat" extension
430  if ( datFile.find_last_of ( '.' ) != string::npos ) {
431  string extension ( datFile.substr( datFile.find_last_of ( '.' ) + 1 ) );
432  if (extension != "dat") {
433  printError(THIS_NAME, "Cannot dump SocketPair stream to file \'%s\' because file is not of type \'DAT\'.\n", datFile.c_str());
434  outFileStream.close();
435  return(NTS_KO);
436  }
437  }
438 
439  //-- READ FROM STREAM AND WRITE TO FILE
440  while (!(ss.empty())) {
441  ss.read(udpMeta);
442  SocketPair socketPair(SockAddr(udpMeta.ip4SrcAddr, udpMeta.udpSrcPort),
443  SockAddr(udpMeta.ip4DstAddr, udpMeta.udpDstPort));
444  writeSocketPairToFile(socketPair, outFileStream);
445  nrChunks++;
446  nrBytes += 12;
447  nrFrames++;
448  if (DEBUG_LEVEL & TRACE_DUMTF) {
449  printInfo(myName, "Writing new socket-pair to file:\n");
450  printSockPair(myName, socketPair);
451  }
452  }
453 
454  //-- CLOSE FILE
455  outFileStream.close();
456 
457  return(NTS_OK);
458 }
459 
460 
472 bool drainUdpDLenStreamToFile(stream<UdpAppDLen> &ss, string ssName,
473  string datFile, int &nrChunks, int &nrFrames, int &nrBytes) {
474  ofstream outFileStream;
475  char currPath[FILENAME_MAX];
476  UdpAppDLen udpDLen;
477 
478  const char *myName = concat3(THIS_NAME, "/", "DUDTF");
479 
480  //-- REMOVE PREVIOUS FILE
481  remove(ssName.c_str());
482 
483  //-- OPEN FILE
484  if (!outFileStream.is_open()) {
485  outFileStream.open(datFile.c_str(), ofstream::out);
486  if (!outFileStream) {
487  printError(THIS_NAME, "Cannot open the file: \'%s\'.\n", datFile.c_str());
488  return(NTS_KO);
489  }
490  }
491 
492  // Assess that file has ".dat" extension
493  if ( datFile.find_last_of ( '.' ) != string::npos ) {
494  string extension ( datFile.substr( datFile.find_last_of ( '.' ) + 1 ) );
495  if (extension != "dat") {
496  printError(THIS_NAME, "Cannot dump SocketPair stream to file \'%s\' because file is not of type \'DAT\'.\n", datFile.c_str());
497  outFileStream.close();
498  return(NTS_KO);
499  }
500  }
501 
502  //-- READ FROM STREAM AND WRITE TO FILE
503  while (!(ss.empty())) {
504  ss.read(udpDLen);
505  writeApUintToFile(udpDLen, outFileStream);
506  nrChunks++;
507  nrBytes += 2;
508  nrFrames++;
509  if (DEBUG_LEVEL & TRACE_DUMTF) {
510  printInfo(myName, "Writing new datagram length file. Len=%d.\n", udpDLen.to_int());
511  }
512  }
513 
514  //-- CLOSE FILE
515  outFileStream.close();
516 
517  return(NTS_OK);
518 }
519 
LE_tKeep getLE_TKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:264
LE_tData getLE_TData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:260
int getLen() const
Definition: AxisRaw.hpp:411
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
Class UDP Datagram.
void pushChunk(AxisUdp udpChunk)
bool writePayloadToDatFile(ofstream &outFileStream)
Dump the payload of this datagram as AxisUdp chunks into a file.
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
Ly4Port udpDstPort
Definition: nts.hpp:229
Ly4Port udpSrcPort
Definition: nts.hpp:227
Ip4Addr ip4SrcAddr
Definition: nts.hpp:226
Ip4Addr ip4DstAddr
Definition: nts.hpp:228
EchoCtrl
Definition: memtest.hpp:49
UdpLen UdpAppDLen
Definition: nal.hpp:255
ap_uint< 16 > UdpPort
Definition: nal.hpp:249
bool readHostSocketFromLine(SockAddr &hostSock, string stringBuffer)
Retrieve a Host socket from a string.
bool readFpgaSocketFromLine(SockAddr &fpgaSock, string stringBuffer)
Retrieve an Fpga socket from a string.
bool readAxisRawFromLine(AxisRaw &axisRaw, string stringBuffer)
Retrieve an AxisRaw chunk from a string.
bool writeApUintToFile(ap_uint< D > &data, ofstream &outFileStream)
Dump an AP_UINT to a file.
vector< string > myTokenizer(string strBuff, char delimiter)
Brakes a string into tokens by using the 'delimiter' character.
bool isDatFile(string fileName)
Checks if a file has a ".dat" extension.
Definition: SimNtsUtils.cpp:52
bool feedAxisFromFile(stream< AXIS_T > &ss, const string ssName, string datFile, int &nrChunks, int &nrFrames, int &nrBytes)
Initialize an Axi4-Stream (Axis) from a DAT file.
bool writeSocketPairToFile(SocketPair &socketPair, ofstream &outFileStream)
Dump a SocketPair to a file.
#define NTS_KO
Definition: nts_types.hpp:56
#define printError(callerName, format,...)
A macro to print an error message.
Definition: nts_utils.hpp:195
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
void printSockAddr(const char *callerName, SockAddr sockAddr)
Print a socket address.
Definition: nts_utils.cpp:174
#define NTS_OK
Definition: nts_types.hpp:55
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
#define UDP_HEADER_LEN
Definition: AxisUdp.hpp:81
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
void printSockPair(const char *callerName, SocketPair sockPair)
Print a socket pair association.
Definition: nts_utils.cpp:114
#define printFatal(callerName, format,...)
A macro to print a fatal error message and exit.
Definition: nts_utils.hpp:208
#define ECHO_PATH_THRU_PORT
bool drainUdpDLenStreamToFile(stream< UdpAppDLen > &ss, string ssName, string datFile, int &nrChunks, int &nrFrames, int &nrBytes)
Empty a UdpDLen stream to a DAT file.
void stepSim()
Increment the simulation counter.
bool readDatagramFromFile(const char *myName, SimUdpDatagram &appDatagram, ifstream &ifsData, SocketPair &sockPair, queue< UdpAppMeta > &udpMetaQueue, queue< UdpAppDLen > &udpDLenQueue, int &inpChunks, int &inpDgrms, int &inpBytes)
Read a datagram from a DAT file.
unsigned int gMaxSimCycles
Definition: test_arp.hpp:69
int createUdpRxTraffic(stream< AxisApp > &ssData, const string ssDataName, stream< UdpAppMeta > &ssMeta, const string ssMetaName, stream< UdpAppDLen > &ssDLen, const string ssMDLenName, string datFile, queue< UdpAppMeta > &metaQueue, queue< UdpAppDLen > &dlenQueue, int &nrFeededChunks)
Create the UDP Rx traffic as streams from an input test file.
unsigned int gSimCycCnt
Definition: tb_nal.cpp:150
#define TRACE_CGTF
bool gTraceEvent
Definition: tb_nal.cpp:151
#define THIS_NAME
void increaseSimTime(unsigned int cycles)
Increase the simulation time of the testbench.
bool drainUdpMetaStreamToFile(stream< UdpAppMeta > &ss, string ssName, string datFile, int &nrChunks, int &nrFrames, int &nrBytes)
Empty an UdpMeta stream to a DAT file.
bool gFatalError
Definition: tb_nal.cpp:152
#define TRACE_DUMTF
#define DEBUG_LEVEL
int createGoldenTxFiles(EchoCtrl tbCtrlMode, string inpData_FileName, queue< UdpAppMeta > &udpMetaQueue, queue< UdpAppDLen > &udpDLenQueue, string outData_GoldName, string outMeta_GoldName, string outDLen_GoldName)
Create the golden UDP Tx files from an input test file.
@ ECHO_CTRL_DISABLED
out
Definition: test.py:12