cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
uppercase_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 "PracticalSockets.h"
42 #include "../include/config.h"
43 
44 using namespace std;
45 
46 // This defines the maximum number of packets, each of size PACK_SIZE, that we enable this fwd_tb to
47 // process.
48 #define MAX_PACKETS_FOR_TB 10
49 
50 static inline ssize_t
51 __file_size(const char *fname)
52 {
53  int rc;
54  struct stat s;
55 
56  rc = lstat(fname, &s);
57  if (rc != 0) {
58  fprintf(stderr, "err: Cannot find %s!\n", fname);
59  return rc;
60  }
61  return s.st_size;
62 }
63 
64 static inline ssize_t
65 __file_read(const char *fname, char *buff, size_t len)
66 {
67  int rc;
68  FILE *fp;
69 
70  if ((fname == NULL) || (buff == NULL) || (len == 0))
71  return -EINVAL;
72 
73  fp = fopen(fname, "r");
74  if (!fp) {
75  fprintf(stderr, "err: Cannot open file %s: %s\n",
76  fname, strerror(errno));
77  return -ENODEV;
78  }
79  rc = fread(buff, len, 1, fp);
80  if (rc == -1) {
81  fprintf(stderr, "err: Cannot read from %s: %s\n",
82  fname, strerror(errno));
83  fclose(fp);
84  return -EIO;
85  }
86  fclose(fp);
87  return rc;
88 }
89 
90 
91 bool findCharNullPos (char * str) {
92  unsigned int len = strlen(str);
93  bool f = false;
94  for(unsigned int i=0; i<=len; i++) {
95  if(str[i]=='\0') {
96  printf("DEBUG: null character position: %d\n",i+1);
97  f = true;
98  }
99  }
100  if(f == false) {
101  printf("DEBUG: null character not found\n");
102  }
103  return f;
104 }
105 
106 
111 int main(int argc, char * argv[]) {
112 
113  if ((argc < 2) || (argc > 4)) { // Test for correct number of parameters
114  cerr << "Usage: " << argv[0] << " <Server Port> <optional simulation mode> <optional >" << endl;
115  cerr << "<optional simulation mode> : 0 - fcsim, 2 - csim, 3 - csynth + cosim, 4 - memchecksim, 5 - kcachegrind" << endl;
116  cerr << "<optional loop> : 0 - executed once, 1 - executed continuously" << endl;
117  exit(1);
118  }
119 
120  unsigned short servPort = atoi(argv[1]); // First arg: local port
121  unsigned int num_batch = 0;
122  string clean_cmd, synth_cmd;;
123  unsigned int run_loop = 0;
124 
125  if (argc == 4) {
126  run_loop = atoi(argv[3]);
127  if (run_loop > 1) {
128  cerr << "ERROR: Not valid loop option provided: " << argv[3] << " . Choose either 0 or 1. Aborting..." << endl;
129  exit(EXIT_FAILURE);
130  }
131  }
132 
133  try {
134  #if NET_TYPE == udp
135  UDPSocket sock(servPort);
136  #else
137  TCPServerSocket servSock(servPort); // Server Socket object
138  TCPSocket *servsock = servSock.accept(); // Wait for a client to connect
139  #endif
140  char buffer[BUF_LEN]; // Buffer for echo string
141  unsigned int recvMsgSize; // Size of received message
142  string sourceAddress; // Address of datagram source
143  unsigned short sourcePort; // Port of datagram source
144 
145  #if NET_TYPE == tcp
146  // TCP client handling
147  cout << "Handling client ";
148  try {
149  cout << servsock->getForeignAddress() << ":";
150  } catch (SocketException e) {
151  cerr << "Unable to get foreign address" << endl;
152  }
153  try {
154  cout << servsock->getForeignPort();
155  } catch (SocketException e) {
156  cerr << "Unable to get foreign port" << endl;
157  }
158  cout << endl;
159  #endif
160 
161  // Loop over a number of tb proxy times (to allow host sw to test several times)
162  do {
163  // RX Step
164  clock_t last_cycle_rx = clock();
165 
166  // Block until receive message from a client
167 
168  int input_string_total_len = 0;
169  //int receiving_now = PACK_SIZE;
170  int total_pack = 0;
171  int bytes_in_last_pack;
172  bool msg_received = false;
173  cout << " ___________________________________________________________________ " << endl;
174  cout << "/ \\" << endl;
175  cout << "INFO: Proxy tb batch # " << ++num_batch << endl;
176  //char * longbuf = new char[PACK_SIZE * total_pack];
177  char * longbuf = (char *) malloc (PACK_SIZE * MAX_PACKETS_FOR_TB * sizeof(char));
178 
179  // RX Loop
180  for (int i = 0; msg_received != true; i++, total_pack++) {
181  #if NET_TYPE == udp
182  recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
183  #else
184  recvMsgSize = servsock->recv(buffer, receiving_now);
185  #endif
186  input_string_total_len += recvMsgSize;
187  bytes_in_last_pack = recvMsgSize;
188  bool nullcharfound = findCharNullPos(buffer);
189  //printf("DEBUG: i=%d recvMsgSize=%u strlen(buffer)=%u nullcharfound=%u\n", i, recvMsgSize, strlen(buffer), nullcharfound);
190  memcpy( & longbuf[i * PACK_SIZE], buffer, recvMsgSize);
191  if (nullcharfound != true) {
192  cout << "INFO: The string is not entirely fit in packet " << total_pack << endl;
193  }
194  else {
195  msg_received = true;
196  }
197  }
198 
199  cout << "INFO: Received packet from " << sourceAddress << ":" << sourcePort << endl;
200  //cout << "DEBUG: longbuf=" << longbuf << endl;
201  string input_string = longbuf;
202  if (input_string.length() == 0) {
203  cerr << "ERROR: received an empty string! Aborting..." << endl;
204  return -1;
205  }
206 
207  // Select simulation mode, default fcsim
208  synth_cmd = " ";
209  string exec_cmd = "make fcsim -j 4";
210  string ouf_file = "../../../../../../ROLE/custom/hls/uppercase/uppercase_prj/solution1/fcsim/build/hls_out.txt";
211  if (argc >= 3) {
212  if (atoi(argv[2]) == 2) {
213  exec_cmd = "make csim";
214  ouf_file = "../../../../../../ROLE/custom/hls/uppercase/uppercase_prj/solution1/csim/build/hls_out.txt";
215  }
216  else if (atoi(argv[2]) == 3) {
217  synth_cmd = "make csynth && ";
218  exec_cmd = "make cosim";
219  ouf_file = "../../../../../../ROLE/custom/hls/uppercase/uppercase_prj/solution1/sim/wrapc_pc/build/hls_out.txt";
220  }
221  else if (atoi(argv[2]) == 4) {
222  exec_cmd = "make memchecksim";
223  ouf_file = "../../../../../../ROLE/custom/hls/uppercase/uppercase_prj/solution1/fcsim/build/hls_out.txt";
224  }
225  else if (atoi(argv[2]) == 5) {
226  exec_cmd = "make kcachegrind";
227  ouf_file = "../../../../../../ROLE/custom/hls/uppercase/uppercase_prj/solution1/fcsim/build/hls_out.txt";
228  }
229  } // Calling the actual TB over its typical makefile procedure, but passing the save file
230  // Skip the rebuilding phase on the 2nd run. However ensure that it's a clean recompile
231  // the first time.
232  clean_cmd = " ";
233  if (num_batch == 1) {
234  clean_cmd = "make clean && ";
235  }
236 
237  string str_command = "cd ../../../../../../ROLE/custom/hls/uppercase/ && " + clean_cmd + synth_cmd + "\
238  INPUT_STRING=" + input_string + " " + exec_cmd + " && \
239  cd ../../../../HOST/custom/uppercase/languages/cplusplus/build/ ";
240  const char *command = str_command.c_str();
241  cout << "Calling TB with command:" << command << endl;
242  system(command);
243 
244  ssize_t size = __file_size(ouf_file.c_str());
245  int rc = __file_read(ouf_file.c_str(), longbuf, size);
246  if (rc < 0) {
247  cerr << "ERROR: Cannot read file " << ouf_file << " . Aborting..."<< endl;
248  return -1;
249  }
250 
251  clock_t next_cycle_rx = clock();
252  double duration_rx = (next_cycle_rx - last_cycle_rx) / (double) CLOCKS_PER_SEC;
253  cout << "INFO: Effective FPS RX:" << (1 / duration_rx) << " \tkbps:" << (PACK_SIZE *
254  total_pack / duration_rx / 1024 * 8) << endl;
255  last_cycle_rx = next_cycle_rx;
256 
257 
258  // TX step
259  string out_string = longbuf;
260  if (out_string.length() == 0) {
261  cerr << "ERROR: Received empty string!" << endl;
262  return -1;
263  }
264  else {
265  cout << "INFO: Succesfully received string from TB : " << out_string << endl;
266  cout << "INFO: Will forward it back to host app ... total_pack=" << endl;
267  }
268 
269 
270  // TX Loop
271  unsigned int sending_now = PACK_SIZE;
272  clock_t last_cycle_tx = clock();
273  for (int i = 0; i < total_pack; i++) {
274  if ( i == total_pack - 1 ) {
275  sending_now = bytes_in_last_pack;
276  }
277  #if NET_TYPE == udp
278  sock.sendTo( & longbuf[i * PACK_SIZE], sending_now, sourceAddress, sourcePort);
279  #else
280  servsock->send( & longbuf[i * PACK_SIZE], sending_now);
281  #endif
282  }
283 
284  clock_t next_cycle_tx = clock();
285  double duration_tx = (next_cycle_tx - last_cycle_tx) / (double) CLOCKS_PER_SEC;
286  cout << "INFO: Effective FPS TX:" << (1 / duration_tx) << " \tkbps:" << (PACK_SIZE *
287  total_pack / duration_tx / 1024 * 8) << endl;
288  last_cycle_tx = next_cycle_tx;
289  free(longbuf);
290  cout << "\\___________________________________________________________________/" << endl;
291 
292  } while (run_loop == 1);
293 
294  #if NET_TYPE == tcp
295  delete servsock;
296  #endif
297  } catch (SocketException & e) {
298  cerr << e.what() << endl;
299  exit(1);
300  }
301  return 0;
302 }
303 
304 
#define BUF_LEN
Definition: config.h:54
#define PACK_SIZE
Definition: config.h:51
int main(int argc, char *argv[])
#define MAX_PACKETS_FOR_TB
bool findCharNullPos(char *str)
def clock()
Definition: common.py:174
ap_uint< 32 > size