cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
memtest_host_fwd_tb.cpp
Go to the documentation of this file.
1 
17 
32 #include <cstdlib> // For atoi()
33 #include <iostream> // For cout and cerr
34 #include <cstdio>
35 #include <memory>
36 #include <stdexcept>
37 #include <string>
38 #include <string.h>
39 #include <array>
40 #include <sys/stat.h>
41 #include <sstream>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include "../../../../../PracticalSockets/src/PracticalSockets.h"
45 #include "../include/config.h"
46 #include<algorithm>
47 #include <fstream>
48 #include "../include/common.hpp"
49 
54 int main(int argc, char * argv[]) {
55 
56  if ((argc < 2) || (argc > 3)) { // Test for correct number of parameters
57  cerr << "Usage: " << argv[0] << " <Server Port> <optional simulation mode>" << endl;
58  exit(1);
59  }
60 
61  unsigned short servPort = atoi(argv[1]); // First arg: local port
62  unsigned int num_batch = 0;
63  string clean_cmd, synth_cmd;
64  unsigned int testingNumber=3;
65  string strInput_nmbrTest="";
66 
67 
68 //Infinite Loop Logic
69 bool endOfLooping=false;
70 while(!endOfLooping){
71 
72  //------------------------------------------------------
73  //-- Setup the RX
74  //------------------------------------------------------
75  try {
76  #if NET_TYPE == udp
77  UDPSocket sock(servPort);
78  #else
79  TCPServerSocket servSock(servPort); // Server Socket object
80  TCPSocket *servsock = servSock.accept(); // Wait for a client to connect
81  #endif
82  char buffer[BUF_LEN]; // Buffer for echo string
83  unsigned int recvMsgSize; // Size of received message
84  string sourceAddress; // Address of datagram source
85  unsigned short sourcePort; // Port of datagram source
86 
87  #if NET_TYPE == tcp
88  // TCP client handling
89  cout << "Handling client ";
90  try {
91  cout << servsock->getForeignAddress() << ":";
92  } catch (SocketException e) {
93  cerr << "Unable to get foreign address" << endl;
94  }
95  try {
96  cout << servsock->getForeignPort();
97  } catch (SocketException e) {
98  cerr << "Unable to get foreign port" << endl;
99  }
100  cout << endl;
101  #endif
102 
103  //------------------------------------------------------
104  //-- RX Step
105  //------------------------------------------------------
106  clock_t last_cycle_rx = clock();
107  // Block until receive message from a client
108  int input_string_total_len = 0;
109  //int receiving_now = PACK_SIZE;
110  int total_pack = 1;
111  int bytes_in_last_pack;
112  size_t total_size =0;
113  bool msg_received = false;
114  cout << " ___________________________________________________________________ " << endl;
115  cout << "/ \\" << endl;
116  cout << "INFO: Proxy tb batch # " << ++num_batch << endl;
117  char * longbuf = new char[PACK_SIZE * (total_pack+1)];
118  // RX Loop
119  for (int i = 0; msg_received != true; i++, total_pack++) {
120  #if NET_TYPE == udp
121  recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
122  #else
123  recvMsgSize = servsock->recv(buffer, receiving_now);
124  #endif
125  input_string_total_len += recvMsgSize;
126  bytes_in_last_pack = recvMsgSize;
127  bool nullcharfound = findCharNullPos(buffer);
128  memcpy(longbuf+(i*PACK_SIZE), buffer, recvMsgSize);
129  total_size += recvMsgSize;
130  longbuf[total_size+1]='\0';
131 
132  if (nullcharfound != true) {
133  cout << "INFO: The string is not entirely fit in packet " << total_pack << endl;
134  }
135  else {
136  msg_received = true;
137  }
138  }
139 
140  cout << "INFO: Received packet from " << sourceAddress << ":" << sourcePort << endl;
141 
142  string input_string;
143  input_string.append(longbuf,total_size);
144  if (input_string.length() == 0) {
145  cerr << "ERROR: received an empty string! Aborting..." << endl;
146  return -1;
147  }
148  //------------------------------------------------------
149  //-- DECODING LOGIC for output size determination and end of looping
150  //------------------------------------------------------
151  unsigned long long int memory_addr_under_test = 0;
152  testingNumber = 0;
153  unsigned int burst_size = 0;
154 
155  cout << "Begin the decoding step" << endl;
156  //printStringHex(input_string,input_string.length());
157  //printBits(input_string.length(),input_string.c_str());
158 
159  // revert the input string and extract substring
160  reverse(input_string.begin(), input_string.end());
161 
162  //------------------------------------------------------
163  //-- DECODING LOGIC check which command was
164  //------------------------------------------------------
165  string substr_tmp, to_translate_String;
166  substr_tmp = input_string.substr(7,1);
167  ascii2hexWithSize(substr_tmp,to_translate_String,1);
169  if(to_translate_String.compare("2")==0){
170  endOfLooping=true;
171  string cmd_string = createMemTestStopCommand();
172  char cmd_stop [8];
173  strncpy(cmd_stop,cmd_string.c_str(),8);
174  unsigned int sending_bytes=8;
175  #if NET_TYPE == udp
176  sock.sendTo( cmd_stop, sending_bytes, sourceAddress, sourcePort);
177  #else
178  servsock->send(cmd_stop, sending_bytes);
179  #endif
180  cout << "A stop received, going to sleep the EMU :)" << endl;
181  cout << "\\___________________________________________________________________/" << endl;
182  #if NET_TYPE == tcp
183  delete servsock;
184  #endif
185  continue;
186  }
187  reverse(input_string.begin(), input_string.end());
188  //printStringHex(input_string,input_string.length());
189  //printBits(input_string.length(),input_string.c_str());
190 
191  //------------------------------------------------------
192  //-- DECODING LOGIC for output and TB setup
193  //------------------------------------------------------
194  char myTmpOutBuff[8];
195  //how many test to perform
196  substr_tmp = input_string.substr(1,2);
197  for(int i=0; i < 8; i++){myTmpOutBuff[i]=(char)0;}
198  strncpy(myTmpOutBuff,substr_tmp.c_str(),2);
199  testingNumber = *reinterpret_cast<unsigned long long*>(myTmpOutBuff);
200  substr_tmp.clear();
201 
202  //the maximum address to test
203  for(int i=0; i < 8; i++){myTmpOutBuff[i]=(char)0;}
204  substr_tmp=input_string.substr(3,5);
205  memcpy(myTmpOutBuff,substr_tmp.c_str(),5);
206  memory_addr_under_test = *reinterpret_cast<unsigned long long*>(myTmpOutBuff);
207  substr_tmp.clear();
208 
209  //the selected burst size
210  substr_tmp = input_string.substr(9,2);
211  printBits(2,substr_tmp.c_str());
212  for(int i=0; i < 8; i++){myTmpOutBuff[i]=(char)0;}
213  memcpy(myTmpOutBuff,substr_tmp.c_str(),2);
214  burst_size = *reinterpret_cast<unsigned long long*>(myTmpOutBuff);
215  substr_tmp.clear();
216  for(int i=0; i < 8; i++){myTmpOutBuff[i]=(char)0;}
217 
218 
219  reverse(input_string.begin(), input_string.end());
220  cout << input_string << endl;
221  //------------------------------------------------------
222  //-- EMULATION preparing the emulation mode, default is fcsim
223  //------------------------------------------------------
224  synth_cmd = " ";
225  string exec_cmd = "make fcsim ";
226  string ouf_file = "../../../../../../ROLE/custom/hls/memtest/memtest_prj/solution1/fcsim/build/hls_out.txt";
227  if (argc >= 3) {
228  if (atoi(argv[2]) == 2) {
229  exec_cmd = "make csim";
230  ouf_file = "../../../../../../ROLE/custom/hls/memtest/memtest_prj/solution1/csim/build/hls_out.txt";
231  }
232  else if (atoi(argv[2]) == 3) {
233  synth_cmd = "make csynth && ";
234  exec_cmd = "make cosim";
235  ouf_file = "../../../../../../ROLE/custom/hls/memtest/memtest_prj/solution1/sim/wrapc_pc/build/hls_out.txt";
236  }
237  else if (atoi(argv[2]) == 4) {
238  exec_cmd = "make kcachegrind";
239  ouf_file = "../../../../../../ROLE/custom/hls/memtest/memtest_prj/solution1/fcsim/build/hls_out.txt";
240  }
241  }
242  // Calling the actual TB over its typical makefile procedure, but passing the save file
243  // Skip the rebuilding phase on the 2nd run. However ensure that it's a clean recompile
244  // the first time.
245  clean_cmd = " ";
246  if (num_batch == 1) {
247  clean_cmd = "make clean && ";
248  }
249  string str_command = "cd ../../../../../../ROLE/custom/hls/memtest/ && ";
250  str_command = str_command.append(clean_cmd + synth_cmd+ exec_cmd);
251  size_t str_command_size = str_command.length();
252  string final_cmd = " TEST_NUMBER=" + std::to_string(testingNumber) + " INPUT_STRING=" + std::to_string(memory_addr_under_test) + " BURST_SIZE=" + std::to_string(burst_size) + " && cd ../../../../HOST/custom/memtest/languages/cplusplus/build/ ";
253  str_command = str_command.append(final_cmd);
254  str_command_size+=final_cmd.length();
255 
256  char *command =(char*)malloc((str_command_size+1)* sizeof(char));
257  for(int i=0; i < (str_command_size+1); i++){
258  command[i]=str_command[i];
259  }
260  cout << "Calling TB with command:" << command << endl;
261  system(command);
262 
263  //clean dynamic memory
264  input_string.clear();
265  str_command.clear();
266  final_cmd.clear();
267  free(command);
268 
269  //------------------------------------------------------
270  //-- TB output parsing
271  //------------------------------------------------------
272  ssize_t size = __file_size(ouf_file.c_str());
273  size_t charOutputSize = 8*1+((8 * (2 + 1+ 1 + 1)) * testingNumber); //stop, 4 for each test, potential stop?
274 
275  int rawdatalines=0;
276  int rc = 0;
277  string out_string;
278  delete [] longbuf;
279 
280  longbuf = new char[charOutputSize+1];
281  out_string.reserve(charOutputSize);
282  out_string = dumpFileToStringRawDataString(ouf_file.c_str(), &rawdatalines, charOutputSize);
283  memcpy(longbuf,out_string.data(),charOutputSize);
284 
285  if (rc < 0) {
286  cerr << "ERROR: Cannot read file " << ouf_file << " . Aborting..."<< endl;
287  return -1;
288  }
289 
290  clock_t next_cycle_rx = clock();
291  double duration_rx = (next_cycle_rx - last_cycle_rx) / (double) CLOCKS_PER_SEC;
292  cout << "INFO: Effective FPS RX:" << (1 / duration_rx) << " \tkbps:" << (PACK_SIZE *
293  total_pack / duration_rx / 1024 * 8) << endl;
294  last_cycle_rx = next_cycle_rx;
295 
296 
297  //------------------------------------------------------
298  //-- TX step
299  //------------------------------------------------------
300 
301  unsigned int total_retx_pack = 1;
302  total_retx_pack = charOutputSize%PACK_SIZE==0 ? charOutputSize/PACK_SIZE : charOutputSize/PACK_SIZE + 1;
303  if (out_string.length() == 0) {
304  cerr << "ERROR: Received empty string!" << endl;
305  return -1;
306  }
307  else {
308  cout << "INFO: Succesfully received string from TB : " << out_string << endl;
309  //printStringHex(out_string, charOutputSize);
310  cout << "INFO: Will forward it back to host app ... total_pack=" << total_retx_pack << endl;
311  }
312 
313  // TX Loop
314  unsigned int sending_now = PACK_SIZE;
315  clock_t last_cycle_tx = clock();
316  unsigned int bytes_in_last_pack_in = charOutputSize - (total_retx_pack - 1) * PACK_SIZE;
317  for (int i = 0; i < total_retx_pack; i++) {
318  if ( i == total_retx_pack - 1 ) {
319  sending_now = bytes_in_last_pack_in;
320  }
321  #if NET_TYPE == udp
322  sock.sendTo( longbuf+(i * PACK_SIZE), sending_now, sourceAddress, sourcePort);
323  #else
324  servsock->send( & longbuf[i * PACK_SIZE], sending_now);
325  #endif
326  }
327  clock_t next_cycle_tx = clock();
328  double duration_tx = (next_cycle_tx - last_cycle_tx) / (double) CLOCKS_PER_SEC;
329  cout << "INFO: Effective FPS TX:" << (1 / duration_tx) << " \tkbps:" << (PACK_SIZE *
330  total_retx_pack / duration_tx / 1024 * 8) << endl;
331  last_cycle_tx = next_cycle_tx;
332  delete [] longbuf;
333  cout << "\\___________________________________________________________________/" << endl;
334  #if NET_TYPE == tcp
335  delete servsock;
336  #endif
337  out_string.clear();
338  } catch (SocketException & e) {
339  cerr << e.what() << endl;
340  exit(1);
341  }
342 
343  //------------------------------------------------------
344  //-- Now loop until stop or crash :D
345  //------------------------------------------------------
346  }//while
347  return 0;
348 }
349 
350 
int main(int argc, char *argv[])
string dumpFileToStringRawDataString(const string inpFileName, int *rawdatalines, size_t outputSize)
Initialize an input data stream from a file with only data.
Definition: common.hpp:279
void printBits(size_t const size, void const *const ptr)
print the binary representation of a target pointer buffer of a given size. Assumes little endian.
Definition: common.hpp:98
void ascii2hexWithSize(const string &in, string &out, size_t bytesize)
Convert a ascii string to a hexadecimal string.
Definition: common.hpp:331
#define BUF_LEN
Definition: config.h:54
string createMemTestStopCommand()
Definition: common.hpp:168
#define PACK_SIZE
Definition: config.h:51
bool findCharNullPos(char *str)
Definition: common.hpp:340
def clock()
Definition: common.py:174
ap_uint< 32 > size