Main testbench and user-application for Memtest on host. Client
61 if ((argc < 3) || (argc > 7)) {
62 cerr <<
"Usage: " << argv[0] <<
" <Server> <Server Port> <number of address to test> <testing times> <burst size> <optional list/interactive mode (type list or nothing)>\n";
74 string s_servAddress = argv[1];
75 char *s_servPort = argv[2];
79 string servAddress = s_servAddress;
80 unsigned short servPort;
81 if (net_type ==
udp) {
82 servPort = Socket::resolveService(s_servPort,
"udp");
84 else if (net_type ==
tcp) {
85 servPort = atoi(s_servPort);
88 cout <<
"ERROR: Invalid type of socket type provided: " << net_type <<
" Choosed one of (tcp=0 or udp=1)" << endl;
92 unsigned int recvMsgSize;
94 std::string input_string;
95 std::string strInput_memaddrUT;
96 std::string strInput_nmbrTest;
97 std::string strInput_burstSize;
99 std::string strInput_listMode;
101 unsigned long long int memory_addr_under_test=0;
102 unsigned int testingNumber = 1;
103 unsigned int burst_size = 1;
120 #ifndef TB_SIM_CFP_VITIS
121 UDPSocket udpsock(servPort);
128 TCPSocket tcpsock(servAddress, servPort);
136 input_string.assign(input_str);
138 strInput_memaddrUT.assign(argv[3]);
139 strInput_nmbrTest.assign(argv[4]);
140 strInput_burstSize.assign(argv[5]);
147 memory_addr_under_test = stoull(strInput_memaddrUT);
148 }
catch (
const std::exception& e) {
149 std::cerr << e.what() <<
'\n';
150 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
151 memory_addr_under_test = 64;
154 cout <<
"WARNING the address inserted is not allowed, hence default use" << endl;
155 memory_addr_under_test = 64;
156 strInput_memaddrUT.assign(to_string(memory_addr_under_test));
160 testingNumber = stoul(strInput_nmbrTest);
161 }
catch (
const std::exception& e) {
162 std::cerr << e.what() <<
'\n';
163 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
166 if(testingNumber > max_testingNumber || testingNumber<=0){
167 cout <<
"WARNING the repetition inserted is not allowed, hence default use" << endl;
169 strInput_nmbrTest.assign(to_string(testingNumber));
172 burst_size = stoul(strInput_burstSize);
173 }
catch (
const std::exception& e) {
174 std::cerr << e.what() <<
'\n';
175 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
179 cout <<
"WARNING the burst size inserted is not allowed, hence default use" << endl;
181 strInput_burstSize.assign(to_string(burst_size));
190 unsigned int burst_size_opposite = min_burst_size;
193 strInput_listMode.assign(argv[6]);
195 strInput_listMode.assign(
"");
197 bool use_the_list_mode=
false;
198 if(strInput_listMode.compare(
"list")==0){
199 use_the_list_mode=
true;
200 std::cout <<
"Employing the List mode with max of " << max_size_mem_size << std::endl;
206 string user_choice =
"r";
209 if(use_the_list_mode){
210 testingNumber=desired_repetitions;
211 memory_addr_under_test=min_size_mem_size;
212 burst_size=max_burst_size;
215 while (user_choice.compare(
"q") != 0 )
218 unsigned int test_pack = 1;
219 size_t charOutputSizeRoughBytes=8*1+((8 * (2 + 1 + 1 + 1)) * testingNumber);
221 size_t charOutputSize =
PACK_SIZE*(test_pack);
222 string initial_input_string(input_string);
224 cout <<
" Creating mem test commands with " << memory_addr_under_test <<
" " << testingNumber <<
" " << burst_size <<
" as addr, iters, brst" << endl;
226 size_t charInputSize = 8*2;
228 if (input_string.length() == 0) {
229 cerr <<
"Empty string provided. Aborting...\n\n" << endl;
233 clock_t start_cycle_main =
clock();
234 cout <<
" ___________________________________________________________________ " << endl;
235 cout <<
"/ \\" << endl;
236 cout <<
"INFO: Batch # " << ++
num_frame << endl;
242 unsigned int total_out_pack = 1 + (input_string.length() - 1) /
PACK_SIZE;
243 unsigned int total_out_bytes = charInputSize;
244 unsigned int bytes_out_last_pack = input_string.length() - (total_out_pack-1) *
PACK_SIZE;
247 unsigned int total_in_pack = test_pack;
248 unsigned int total_in_bytes = total_in_pack *
PACK_SIZE;
249 unsigned int bytes_in_last_pack_in = charOutputSizeRoughBytes - (total_in_pack - 1) *
PACK_SIZE;
251 cout <<
"INFO: Network socket : " << ((net_type ==
tcp) ?
"TCP" :
"UDP") << endl;
252 cout <<
"INFO: Total packets to send = " << total_out_pack << endl;
253 cout <<
"INFO: Total packets to receive = " << total_in_pack << endl;
254 cout <<
"INFO: Total bytes to send = " << total_out_bytes << endl;
255 cout <<
"INFO: Total bytes to receive = " << total_in_bytes << endl;
256 cout <<
"INFO: Total bytes rx " << total_in_bytes <<
" packets = " << total_in_pack << endl;
257 cout <<
"INFO: Bytes in last packet tx = " << bytes_out_last_pack << endl;
258 cout <<
"INFO: Bytes in last packet rx = " << bytes_in_last_pack_in << endl;
259 cout <<
"INFO: Packet size (custom MTU) = " <<
PACK_SIZE << endl;
264 clock_t start_cycle_memtest_hw =
clock();
269 clock_t last_cycle_tx =
clock();
271 for (
unsigned int i = 0; i < total_out_pack; i++) {
272 if ( i == total_out_pack - 1 ) {
273 sending_now = bytes_out_last_pack;
278 udpsock.sendTo( & input_string[i *
PACK_SIZE], sending_now, servAddress, servPort);
280 tcpsock.send( & input_string[i *
PACK_SIZE], sending_now);
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 SPS TX:" << (1 / duration_tx) <<
" \tkbps:" << (
PACK_SIZE *
287 total_out_pack / duration_tx / 1024 * 8) << endl;
288 last_cycle_tx = next_cycle_tx;
294 clock_t last_cycle_rx =
clock();
295 unsigned int bytes_received = 0;
297 cout <<
"INFO: Expecting length of packs:" << total_in_pack << endl;
298 char * longbuf =
new char[
PACK_SIZE * total_in_pack+1];
299 for (
unsigned int i = 0; i < total_in_pack; ) {
300 if ( i == total_in_pack - 1 ) {
301 receiving_now = bytes_in_last_pack_in;
304 recvMsgSize = udpsock.recvFrom(buffer,
BUF_LEN, servAddress, servPort);
306 recvMsgSize = tcpsock.recv(buffer,
BUF_LEN);
308 if (recvMsgSize != receiving_now) {
309 cerr <<
"WARNING: Received unexpected size pack:" << recvMsgSize <<
". Expected: " <<
310 receiving_now << endl;
312 memcpy( longbuf+(i*bytes_received), buffer, recvMsgSize);
313 cout <<
"DEBUG: recvMsgSize=" << recvMsgSize << endl;
314 bytes_received += recvMsgSize;
318 cout <<
"INFO: Received packet from " << servAddress <<
":" << servPort << endl;
321 char *output_string = output_str;
323 char *output_string =
new char [(
PACK_SIZE * total_in_pack*
sizeof(char))];
325 memcpy( output_string, longbuf, bytes_received*
sizeof(
char));
326 output_string[
PACK_SIZE * total_in_pack]=
'\0';
327 cout <<
"INFO: Received string : " << output_string << endl;
330 clock_t next_cycle_rx =
clock();
331 double duration_rx = (next_cycle_rx - last_cycle_rx) / (
double) CLOCKS_PER_SEC;
332 cout <<
"INFO: Effective SPS RX:" << (1 / duration_rx) <<
" \tkbps:" << (
PACK_SIZE *
333 total_in_pack / duration_rx / 1024 * 8) << endl;
334 last_cycle_rx = next_cycle_rx;
336 clock_t end_cycle_memtest_hw = next_cycle_rx;
338 double duration_memtest_hw = (end_cycle_memtest_hw - start_cycle_memtest_hw) /
339 (
double) CLOCKS_PER_SEC;
340 cout <<
"INFO: HW exec. time:" << duration_memtest_hw <<
" seconds" << endl;
341 cout <<
"INFO: Effective SPS HW:" << (1 / duration_memtest_hw) <<
" \tkbps:" <<
342 (
PACK_SIZE * total_in_pack / duration_memtest_hw / 1024 * 8) << endl;
344 double duration_main = (
clock() - start_cycle_main) / (
double) CLOCKS_PER_SEC;
345 cout <<
"INFO: Effective SPS E2E:" << (1 / duration_main) << endl;
346 cout <<
"\\___________________________________________________________________/" << endl
357 cout <<
" ___________________________________________________________________ " << endl;
358 cout <<
"/ \\" << endl;
359 cout <<
"INFO: Entering in the output parsing section "<< endl;
360 std::vector<MemoryTestResult> testResults_vector;
361 string output_to_parse_string;
362 output_to_parse_string.append(output_string,charOutputSizeRoughBytes);
363 int rawdatalines = charOutputSizeRoughBytes / 8;;
364 testResults_vector=
parseMemoryTestOutput(output_to_parse_string,charOutputSizeRoughBytes,rawdatalines);
366 cout <<
"INFO: Test Results appearing" << endl;
367 cout <<
" The Memory test run for " << testResults_vector.size() <<
" iterations " << endl;
368 unsigned int mem_word_size = 512;
369 unsigned int mem_word_byte_size = mem_word_size/8;
370 double rd_bndwdth=0.0;
371 double wr_bndwdth=0.0;
372 double avg_rd_bndwdth=0.0;
373 double avg_wr_bndwdth=0.0;
374 int avg_fault_cnt = 0;
376 unsigned long long int written_words=0;
377 for(
auto it = std::begin(testResults_vector); it != std::end(testResults_vector); ++it) {
378 cout <<
" Test number " << it - testResults_vector.begin() <<
" stress " << it->target_address <<
" addresses " << endl;
379 cout <<
" it presented " << it->fault_cntr <<
" faults " << endl;
380 cout <<
" and the first faulty address (if any) was " << it->first_fault_address << endl;
381 written_words = ((it->target_address) %mem_word_byte_size) == 0 ? ((it->target_address)/mem_word_byte_size) : (((it->target_address)/mem_word_byte_size) + 1);
382 rd_bndwdth = ( (double)written_words*(
double)mem_word_size / ( (double)it->clock_cycles_read * 6.4 ) );
383 wr_bndwdth = ( (double)written_words*(
double)mem_word_size / ( (double)it->clock_cycles_write * 6.4 ) );
384 cout <<
" RD BW " << rd_bndwdth <<
"[GBit/s], with " << it->clock_cycles_read <<
" ccs" << endl;
385 cout <<
" WR BW " << wr_bndwdth <<
"[GBit/s], with " << it->clock_cycles_write <<
" ccs" << endl;
386 cout << endl << endl;
387 avg_rd_bndwdth += rd_bndwdth;
388 avg_wr_bndwdth += wr_bndwdth;
389 avg_fault_cnt += it->fault_cntr;
392 logTheSingleResult(iterations, it->target_address, burst_size, written_words, rd_bndwdth, wr_bndwdth, it->fault_cntr, it->first_fault_address);
394 avg_rd_bndwdth = avg_rd_bndwdth / iterations;
395 avg_wr_bndwdth = avg_wr_bndwdth / iterations;
396 avg_fault_cnt = avg_fault_cnt / iterations;
397 cout <<
"Based on " << iterations <<
" iterations, AVG WR " << avg_wr_bndwdth <<
" AVG RD " << avg_rd_bndwdth <<
" AVG faults " << avg_fault_cnt << endl;
399 logTheAvgResult(iterations, memory_addr_under_test, burst_size, written_words, avg_rd_bndwdth, avg_wr_bndwdth, avg_fault_cnt);
402 delete [] output_string;
403 testResults_vector.clear();
404 output_to_parse_string.clear();
405 input_string.clear();
406 initial_input_string.clear();
407 strInput_memaddrUT.clear();
408 strInput_nmbrTest.clear();
419 if (user_choice.compare(
"rq")==0)
421 cout <<
"INFO: going to close the application and send a stop command as the user requested." << endl;
424 char stop_char_buff [8];
425 memcpy(stop_char_buff, cmd_string.data(), 8);
429 udpsock.sendTo(stop_char_buff, sending_now, servAddress, servPort);
431 tcpsock.send(stop_char_buff, sending_now);
435 recvMsgSize = udpsock.recvFrom(buffer,
BUF_LEN, servAddress, servPort);
437 recvMsgSize = tcpsock.recv(buffer,
BUF_LEN);
440 char output_stop [8];
441 memcpy(output_stop,buffer,8);
442 if(strcmp(output_stop,stop_char_buff)==0){
443 cout <<
"INFO: Accelerator answered ok" << endl;
445 cout <<
"INFO: Bad answer received, take care "<< endl;
448 cout <<
"INFO: IBM ZRL Memtest is closing." << endl<<
"Goodbye :D" << endl;
453 string confirmation=
"";
455 cout <<
"That is all from this application." << endl;
457 if(use_the_list_mode){
458 user_choice.assign(
"r");
459 testingNumber=desired_repetitions;
460 burst_size=burst_size/2;
461 burst_size_opposite=burst_size_opposite*2;
462 cout <<
" burst size " << burst_size <<
" burst oppostit " << burst_size_opposite << endl;
463 if(burst_size_opposite>max_burst_size){
465 burst_size=max_burst_size;
466 burst_size_opposite=min_burst_size;
467 memory_addr_under_test=memory_addr_under_test*2;
468 memory_addr_under_test=memory_addr_under_test==max_size_mem_size ? memory_addr_under_test-64 : memory_addr_under_test;
469 if(memory_addr_under_test>max_size_mem_size){
470 user_choice.assign(
"q");
478 while (user_choice.empty() || (confirmation.compare(
"y")!=0) || ( (confirmation.compare(
"y")==0) && (user_choice.compare(
"r")!=0 && user_choice.compare(
"q")!=0) && user_choice.compare(
"rq")!=0) )
480 cout <<
"What do you want to do now?" << endl;
481 cout <<
" <r>: run a new test, <q>: quit, <rq>: run a new test and quit "<<endl;
482 cout <<
"Please type your choice "<<endl;
484 cout <<
"Your choice is " << user_choice <<
", is it ok? (y/n) " << endl;
487 if (user_choice.compare(
"q")!=0)
489 confirmation.clear();
491 while ( strInput_memaddrUT.empty() || strInput_nmbrTest.empty() || strInput_burstSize.empty() || (confirmation.compare(
"y")!=0))
493 cout <<
"Please type in the maximum address to test (no more than "<< to_string(max_testable_address) <<
")"<< endl;
494 cin >> strInput_memaddrUT;
496 memory_addr_under_test = stoull(strInput_memaddrUT);
497 }
catch (
const std::exception& e) {
498 std::cerr << e.what() <<
'\n';
499 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
500 memory_addr_under_test = 64;
503 cout <<
"WARNING the address inserted is not allowed, hence default use" << endl;
504 memory_addr_under_test = 64;
505 strInput_memaddrUT.assign(to_string(memory_addr_under_test));
508 cout <<
"Please type in the repetition of the test (no more than " << to_string(max_testingNumber) <<
")"<< endl;
509 cin >> strInput_nmbrTest;
511 testingNumber = stoul(strInput_nmbrTest);
512 }
catch (
const std::exception& e) {
513 std::cerr << e.what() <<
'\n';
514 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
517 if(testingNumber > max_testingNumber || testingNumber<=0){
518 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
520 strInput_nmbrTest.assign(to_string(testingNumber));
522 cout <<
"Please type in the desired burst size (no more than "<< to_string(
MAX_BURST_SIZE) <<
")"<< endl;
523 cin >> strInput_burstSize;
525 burst_size = stoul(strInput_burstSize);
526 }
catch (
const std::exception& e) {
527 std::cerr << e.what() <<
'\n';
528 cout <<
"WARNING something bad happened in the insertion, hence default used" << endl;
532 cout <<
"WARNING the burst size inserted is not allowed, hence default use" << endl;
534 strInput_burstSize.assign(to_string(burst_size));
536 cout <<
"Your choice is to test " << testingNumber <<
" times up to address " << memory_addr_under_test <<
" burst size " << burst_size <<
", is it ok? (y/n) " << endl;
541 if (user_choice.compare(
"q")==0)
543 cout <<
"INFO: IBM ZRL Memtest is closing." << endl<<
"Goodbye :D" << endl;
546 char stop_char_buff [8];
547 memcpy(stop_char_buff, cmd_string.data(), 8);
551 udpsock.sendTo(stop_char_buff, sending_now, servAddress, servPort);
553 tcpsock.send(stop_char_buff, sending_now);
557 recvMsgSize = udpsock.recvFrom(buffer,
BUF_LEN, servAddress, servPort);
559 recvMsgSize = tcpsock.recv(buffer,
BUF_LEN);
562 char output_stop [8];
563 memcpy(output_stop,buffer,8);
564 if(strcmp(output_stop,stop_char_buff)==0){
565 cout <<
"INFO: Accelerator answered ok" << endl;
567 cout <<
"INFO: Bad answer received, take care "<< endl;
570 cout <<
"INFO: IBM ZRL Memtest is closing." << endl<<
"Goodbye :D" << endl;
583 }
catch (SocketException & e) {
584 cerr << e.what() << endl;
585 cout <<
"INFO: there was a SocketException, now aborting" << endl;
cat GET request dos socat stdio tcp
std::vector< MemoryTestResult > parseMemoryTestOutput(const string longbuf, size_t charOutputSize, int rawdatalines)
Parse the memory test output contained in astring with a given size.
#define MAX_TESTABLE_ADDRESS
#define MAX_BURST_SIZE_BENCHMARKING
#define MIN_MEM_SIZE_BENCHMARKING_POWER_OF_TWO
string createMemTestCommands(unsigned long long int mem_address, unsigned int testingNumber, unsigned int burst_size)
Create the commands for a memory test with start/max address to test-nop to execute-stop.
#define REPETITIONS_BENCHMARKING
#define MAX_MEM_SIZE_BENCHMARKING_POWER_OF_TWO
string createMemTestStopCommand()
void logTheAvgResult(unsigned int iters, unsigned long long int trgt_address, unsigned int brst_size, unsigned int wr_words, double rd_bw, double wr_bw, unsigned int faults)
void delay(unsigned int mseconds)
void logTheSingleResult(unsigned int iters, unsigned long long int trgt_address, unsigned int brst_size, unsigned int wr_words, double rd_bw, double wr_bw, unsigned int faults, unsigned long long int first_faulty_address)
void print_cFpMemtest(void)
#define MIN_BURST_SIZE_BENCHMARKING
#define MAX_TEST_REPETITION_BITWIDTH