Belle II Software  release-05-02-19
dummy_data_distrib.cc
1 #include <iostream>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <netinet/in.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/time.h>
8 #include <time.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <arpa/inet.h>
12 #include <limits.h>
13 #include <signal.h>
14 #include <poll.h>
15 
16 
18 // Parameter for data-contents
20 //#define REDUCED_DATA
21 //#define CRC_ON
22 #define LISTENQ 1
23 #define NUM_CLIENTS 5
24 #define MAX_EVENT 1000
25 
26 // Format (PCIe40)
27 #define NW_SEND_HEADER 6
28 #define NW_SEND_TRAILER 2
29 
30 #define NW_RAW_HEADER 8
31 #define NW_RAW_TRAILER 4
32 
33 #ifdef REDUCED_DATA
34 #define NW_B2L_HEADER 3
35 #define NW_B2L_TRAILER 2
36 #else
37 #define NW_B2L_HEADER 7
38 #define NW_B2L_TRAILER 3
39 #endif
40 
41 #define CTIME_VAL 0x12345601
42 
43 using namespace std;
44 
45 unsigned short CalcCRC16LittleEndian(unsigned short crc16, const int buf[], int nwords)
46 {
47 
48  if (nwords < 0) {
49  char err_buf[500];
50  sprintf(err_buf, "nwords value(%d) is invalid. Cannot calculate CRC16. Exiting...\n %s %s %d\n",
51  nwords, __FILE__, __PRETTY_FUNCTION__, __LINE__);
52  printf("%s", err_buf); fflush(stdout);
53  string err_str = err_buf;
54  throw (err_str);
55  }
56 
57  const unsigned short CRC16Table0x1021[ 256 ] = {
58  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
59  0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
60  0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
61  0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
62  0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
63  0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
64  0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
65  0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
66 
67  0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
68  0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
69  0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
70  0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
71  0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
72  0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
73  0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
74  0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
75 
76  0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
77  0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
78  0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
79  0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
80  0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
81  0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
82  0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
83  0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
84 
85  0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
86  0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
87  0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
88  0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
89  0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
90  0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
91  0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
92  0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
93  };
94 
95  int cnt = 0, nints = 0;
96  // printf("### %.8x %.4x\n", buf[ 0 ], crc16);
97  while (nwords != 0) {
98 
99  unsigned char temp_buf = *((unsigned char*)(buf + nints) + (-(cnt % 4) + 3));
100  crc16 = CRC16Table0x1021[(crc16 >> (16 - CHAR_BIT)) ^ temp_buf ] ^ (crc16 << CHAR_BIT);
101  // printf("%.2x %.4x\n", temp_buf, crc16);
102  if ((cnt % 4) == 3) {
103  nwords--;
104  nints++;
105  // printf("### %.8x\n", buf[ nints ] );
106  }
107 
108  cnt++;
109  }
110 
111 
112  return crc16;
113 
114 }
115 
116 
117 double getTimeSec()
118 {
119  struct timeval t;
120  gettimeofday(&t, NULL);
121  return (t.tv_sec + t.tv_usec * 1.e-6 - 1417570000.);
122 }
123 
124 int fillDataContents(int* buf, int nwords_per_fee, unsigned int node_id, int ncpr, int nhslb, int run)
125 {
126  int nwords = NW_SEND_HEADER + NW_SEND_TRAILER +
127  ncpr * (NW_RAW_HEADER +
128  (NW_B2L_HEADER + NW_B2L_TRAILER + nwords_per_fee) * nhslb
129  + NW_RAW_TRAILER);
130 
131  // Send Header
132  int offset = 0;
133  buf[ offset + 0 ] = nwords;
134  buf[ offset + 1 ] = 6;
135  buf[ offset + 2 ] = (1 << 16) | ncpr;
136  unsigned int exp_run = run << 8;
137  buf[ offset + 3 ] = exp_run;
138  buf[ offset + 5 ] = node_id;
139  offset += NW_SEND_HEADER;
140 
141  for (int k = 0; k < ncpr; k++) {
142  int top_pos = offset;
143  //
144  // RawHeader
145  //
146  int cpr_nwords = NW_RAW_HEADER +
147  (NW_B2L_HEADER + NW_B2L_TRAILER + nwords_per_fee) * nhslb
148  + NW_RAW_TRAILER;
149  int finesse_nwords = nwords_per_fee + NW_B2L_HEADER + NW_B2L_TRAILER;
150  unsigned int ctime = CTIME_VAL;
151  unsigned int utime = 0x98765432;
152 
153  buf[ offset + 0 ] = cpr_nwords;
154 #ifdef REDUCED_DATA
155  buf[ offset + 1 ] = 0x7f7f020c;
156 #else
157  buf[ offset + 1 ] = 0x7f7f820c;
158 #endif
159  buf[ offset + 2 ] = exp_run;
160  printf("run_no %d\n", exp_run); fflush(stdout);
161  buf[ offset + 4 ] = ctime;
162  buf[ offset + 5 ] = utime;
163  buf[ offset + 6 ] = node_id + k;
164  buf[ offset + 7 ] = 0x34567890;
165  offset += NW_RAW_HEADER;
166 
167  for (int i = 0; i < nhslb ; i++) {
168 #ifdef REDUCED_DATA
169  buf[ offset + 0 ] = nwords_per_fee + 3;
170  buf[ offset + 1 ] = 0xffaa0000;
171  buf[ offset + 2 ] = ctime;
172 #else
173  buf[ offset + 0 ] = nwords_per_fee + 7;
174  buf[ offset + 1 ] = 0xffaa0000;
175  buf[ offset + 3 ] = ctime;
176  buf[ offset + 4 ] = utime;
177  buf[ offset + 5 ] = exp_run;
178  buf[ offset + 6 ] = ctime;
179 #endif
180  offset += NW_B2L_HEADER;
181 
182  for (int j = offset; j < offset + nwords_per_fee; j++) {
183  buf[ j ] = rand();
184  }
185  offset += nwords_per_fee;
186 
187 #ifdef REDUCED_DATA
188  buf[ offset ] = 0;
189  buf[ offset + 1 ] = 0xff550000;
190 #else
191  buf[ offset ] = ctime;
192  buf[ offset + 1 ] = 0;
193  buf[ offset + 2 ] = 0xff550000;
194 #endif
195 
196  offset += NW_B2L_TRAILER;
197  }
198  buf[ offset ] = 0x0; // error bits
199  buf[ offset + 1 ] = 0x0; // error slots
200  buf[ offset + 2 ] = 0x0; // XOR checksum
201  buf[ offset + 3 ] = 0x7fff0006;
202  offset += NW_RAW_TRAILER;
203  }
204 
205  // Send trailer
206  buf[ offset ] = 0;
207  buf[ offset + 1 ] = 0x7fff0000;
208  offset += NW_SEND_TRAILER;
209  return offset;
210 }
211 
212 
213 
214 inline void addEvent(int* buf, int nwords_per_fee, unsigned int event, int ncpr, int nhslb)
215 //inline void addEvent(int* buf, int nwords, unsigned int event)
216 {
217  int offset = 0;
218  int prev_offset;
219  buf[ offset + 4 ] = event;
220  offset += NW_SEND_HEADER;
221 
222  for (int k = 0; k < ncpr; k++) {
223  int nwords = buf[ offset ];
224  int posback_xorchksum = 2;
225  int pos_xorchksum = offset + nwords - posback_xorchksum;
226  prev_offset = offset;
227  if (buf[ offset + 4 ] != CTIME_VAL) {
228  printf("[FATAL] data-production error 2 0x%.x", buf[ offset + 4 ]);
229  fflush(stdout);
230  exit(1);
231  }
232  // RawHeader
233  buf[ pos_xorchksum ] ^= buf[ offset + 3];
234  buf[ offset + 3] = event;
235  buf[ pos_xorchksum ] ^= buf[ offset + 3];
236 
237  // COPPER header
238  offset += NW_RAW_HEADER;
239  for (int i = 0; i < nhslb ; i++) {
240  if ((buf[ offset + 1 ] & 0xffff0000) != 0xffaa0000) {
241  printf("[FATAL] data-production error 3 : 0x%.x hslb %d cpr %d\n", buf[ offset ], i, k);
242  fflush(stdout);
243  exit(1);
244  }
245  buf[ offset + 1 ] = 0xffaa0000 + (event & 0xffff);
246  buf[ offset + 3 ] = event;
247 
248 #ifdef CRC_ON
249  int* crc_buf = buf + offset + 2; // 1 => size of HSLB B2L header
250  int crc_nwords = nwords_per_fee + 5; // 5 => size of FEE B2L header
251  unsigned short temp_crc16 = CalcCRC16LittleEndian(0xffff, crc_buf, crc_nwords);
252  buf[ offset + NW_B2L_HEADER + nwords_per_fee + 1 ] = ((event & 0x0000ffff) << 16) | temp_crc16;
253 #endif
254 
255 #ifdef REDUCED_DATA
256  offset += NW_B2L_HEADER + nwords_per_fee + NW_B2L_TRAILER;
257 #else
258  offset += NW_B2L_HEADER + nwords_per_fee + NW_B2L_TRAILER;
259 #endif
260  }
261  offset += NW_RAW_TRAILER;
262  unsigned int xor_chksum = 0;
263  unsigned int xor_chksum2 = 0;
264  }
265 
266 }
267 
268 
269 int main(int argc, char** argv)
270 {
271 
272  printf("###################################################\n");
273 #ifdef REDUCED_DATA
274  printf("# PCIe40 data after reduction (#define REDUCED_DATA) #\n");
275 #else
276  printf("# PCIe40 data before reduction (//#define REDUCED_DATA) #\n");
277 #endif
278  printf("###################################################\n");
279 
280  if (argc != 6) {
281  printf("Usage : %s <node ID> <run#> <nwords of det. buf per FEE> <# of CPR per COPPER> <# of HSLBs>\n", argv[ 0 ]);
282  exit(1);
283  }
284 
285  //
286  // network connection
287  //
288  int listenfd;
289  struct sockaddr_in servaddr;
290  struct pollfd client[NUM_CLIENTS + 1];
291 
292  //
293  // dummy data
294  //
295  unsigned int node_id = 0;
296  sscanf(argv[1], "0x%x", &node_id);
297 
298  int run_no = atoi(argv[2]);
299  int nwords_per_fee = atoi(argv[3]);
300  int ncpr = atoi(argv[4]);
301  int nhslb = atoi(argv[5]);
302 
303  int total_words = NW_SEND_HEADER + NW_SEND_TRAILER +
304  ncpr * (NW_RAW_HEADER + (NW_B2L_HEADER + NW_B2L_TRAILER + nwords_per_fee) * nhslb +
305  NW_RAW_TRAILER);
306  printf("TET %d %d %d %d %d\n ", NW_SEND_HEADER + NW_SEND_TRAILER, ncpr,
307  NW_RAW_HEADER, (NW_B2L_HEADER + NW_B2L_TRAILER + nwords_per_fee) * nhslb, NW_RAW_TRAILER);
308  int buff[total_words];
309 
310  //
311  // Prepare header
312  //
313  int temp_ret = fillDataContents(buff, nwords_per_fee, node_id, ncpr, nhslb, run_no);
314  if (temp_ret != total_words) {
315  printf("[FATAL] data-production error 1 %d %d\n", total_words, temp_ret);
316  fflush(stdout);
317  exit(1);
318  }
319 
320  listenfd = socket(AF_INET, SOCK_STREAM, 0);
321  memset(&servaddr, 0, sizeof(servaddr));
322  servaddr.sin_family = AF_INET;
323  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
324  servaddr.sin_port = htons(30000);
325 
326  int flags = 1;
327  int ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flags, (socklen_t)sizeof(flags));
328  if (ret < 0) {
329  perror("Failed to set REUSEADDR");
330  }
331 
332  bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
333 
334  listen(listenfd, LISTENQ);
335 
336  client[0].fd = listenfd;
337  client[0].events = POLLRDNORM;
338 
339  for (int i = 1; i <= NUM_CLIENTS; i++) {
340  client[i].fd = -1;
341  }
342 
343  int maxi = 0;
344  int id = 0;
345  int nconn = 0;
346 
347  while (1) {
348  int nready = poll(client, maxi + 1, -1);
349  if (client[0].revents & POLLRDNORM) {
350  printf("Accepting..."); fflush(stdout);
351  int connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
352  for (id = 1; id <= NUM_CLIENTS; id++) {
353  if (client[id].fd < 0) {
354  client[id].fd = connfd;
355  client[id].events = POLLRDNORM;
356  nconn++;
357  printf("Done. connections (%d/%d)", nconn, NUM_CLIENTS); fflush(stdout);
358  break;
359  }
360  }
361  if (id > NUM_CLIENTS) {
362  perror("[FATAL] too many clients.");
363  exit(1);
364  }
365  if (id > maxi) maxi = id;
366  if (nconn >= NUM_CLIENTS) break;
367  // if( -nready <= 0 ) continue;
368 
369  } else {
370  printf("No connection request. Still waiting..."); fflush(stdout);
371  }
372  }
373 
374  printf("All connections accepted\n"); fflush(stdout);
375 
376  double init_time = getTimeSec();
377  double prev_time = init_time;
378 
379  unsigned long long int cnt = 0;
380  unsigned long long int prev_cnt = 0;
381  unsigned long long int start_cnt = 300000;
382 
383 #ifdef MAX_EVENT
384  for (int j = 0; j < MAX_EVENT; j++) {
385 #else
386  for (;;) {
387 #endif
388  // addEvent(buff, total_words, cnt);
389  addEvent(buff, nwords_per_fee, cnt, ncpr, nhslb);
390  // printf("cnt %d bytes\n", cnt*total_words); fflush(stdout);
391  // sprintf( buff, "event %d dessa", cnt );
392 
393  // for(int i = 0 ; i < total_words ; i++){
394  // printf("%.8x ", buff[ i ]);
395  // if( i % 10 == 9 ) printf("\n");
396  // }
397 
398  for (int i = 1 ; i <= NUM_CLIENTS ; i++) {
399  int ret = 0;
400  if ((ret = write(client[i].fd, buff, total_words * sizeof(int))) <= 0) {
401  printf("[FATAL] Return value %d\n", ret);
402  fflush(stdout);
403  exit(1);
404  }
405  }
406 
407  cnt++;
408 
409  if (cnt == start_cnt) init_time = getTimeSec();
410  if (cnt % 10000 == 1) {
411  if (cnt > start_cnt) {
412  double cur_time = getTimeSec();
413  printf("run %d evt %lld time %.1lf dataflow %.1lf MB/s rate %.2lf kHz : so far dataflow %.1lf MB/s rate %.2lf kHz size %d\n",
414  run_no,
415  cnt,
416  cur_time - init_time,
417  NUM_CLIENTS * (cnt - prev_cnt)*total_words * sizeof(int) / 1000000. / (cur_time - prev_time),
418  (cnt - prev_cnt) / (cur_time - prev_time) / 1000. ,
419  NUM_CLIENTS * (cnt - start_cnt)*total_words * sizeof(int) / 1000000. / (cur_time - init_time),
420  (cnt - start_cnt) / (cur_time - init_time) / 1000. , total_words);
421 
422  fflush(stdout);
423  prev_time = cur_time;
424  prev_cnt = cnt;
425  } else {
426  // printf("Eve %lld\n", cnt);fflush(stdout);
427  }
428  }
429  }
430 
431 
432  for (int i = 1; i <= NUM_CLIENTS; i++) {
433  close(client[i].fd);
434  }
435 
436 
437 }
main
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:77