cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
memtest_pattern_library.hpp
Go to the documentation of this file.
1 
26 #ifndef _ROLE_MEMTEST_PATTERN_LIBRARY_HPP_
27 #define _ROLE_MEMTEST_PATTERN_LIBRARY_HPP_
28 
29 #include <stdio.h>
30 #include <iostream>
31 #include <hls_stream.h>
32 #include "ap_int.h"
33 #include <stdint.h>
34 #include "../../../../../HOST/custom/memtest/languages/cplusplus/include/config.h"//debug level define
35 
36 #include "network.hpp"
37 
38 using namespace hls;
39 
40 
41 #define LOCAL_MEM_WORD_SIZE 512
42 #define LOCAL_MEM_ADDR_SIZE 40
43 
44 typedef ap_uint<LOCAL_MEM_WORD_SIZE> local_mem_word_t;
45 typedef ap_uint<LOCAL_MEM_ADDR_SIZE> local_mem_addr_t;
46 #define LOCAL_MEM_ADDR_SIZE_NON_BYTE_ADDRESSABLE 40 // TODO: to parametrize better
47 typedef ap_uint<LOCAL_MEM_ADDR_SIZE_NON_BYTE_ADDRESSABLE> local_mem_addr_non_byteaddressable_t;
48 #define LOCAL_MEM_ADDR_OFFSET (LOCAL_MEM_WORD_SIZE/8) //byte addres offset
49 #define LOCAL_MEM_WORD_BYTE_SIZE (LOCAL_MEM_WORD_SIZE/8) //byte size of a local mem word
50 
54 
55 
58 template<typename Tin, typename Tout>
59 Tout genNextFibonacciNumber(Tin curr, Tin prev){
60 #pragma HLS INLINE
61  return static_cast<Tout>(curr + prev);
62 }
63 
64 template<typename ADDR_T, unsigned int sequenceDim, typename BIGWORD_T, typename SMALLWORD_T, unsigned int smallWordDim>
65 void genFibonacciNumbers(ADDR_T curr, BIGWORD_T * outBigWord){
66 //#pragma HLS INLINE off
67 
68 // REQUIREMENT: must be a multiple
69  //assert( (BIGWORD_T%SMALLWORD_T)==0);
70 
71  SMALLWORD_T currentFibonacciNumber = static_cast<SMALLWORD_T>(curr);
72  SMALLWORD_T prevFibonacciNumber = currentFibonacciNumber + 1;
73  SMALLWORD_T nextFibonacciNumber = genNextFibonacciNumber<ADDR_T,SMALLWORD_T>(currentFibonacciNumber,prevFibonacciNumber);
74 
75  gen_sequence_loop: for (unsigned int i = 0; i < sequenceDim; i++)
76  {
77 #pragma HLS PIPELINE
78  (*outBigWord).range(smallWordDim*(i+1)-1,smallWordDim*i)=nextFibonacciNumber;
79  prevFibonacciNumber=currentFibonacciNumber;
80  currentFibonacciNumber=nextFibonacciNumber;
81  nextFibonacciNumber=genNextFibonacciNumber<ADDR_T,SMALLWORD_T>(currentFibonacciNumber,prevFibonacciNumber);
82  }
83 
84 
85 }
86 
87 
88 template<typename ADDR_T, unsigned int sequenceDim, typename BIGWORD_T, typename SMALLWORD_T, unsigned int smallWordDim>
89 void genXoredSequentialNumbers(ADDR_T curr, BIGWORD_T * outBigWord){
90 #pragma HLS INLINE off
91 
92 // REQUIREMENT: must be a multiple
93  //assert( (BIGWORD_T%SMALLWORD_T)==0);
94 
95  SMALLWORD_T currentNumber = static_cast<SMALLWORD_T>(curr);
96  SMALLWORD_T nextNumber = (currentNumber+1) xor 1;
97  SMALLWORD_T prevNumber = currentNumber;
98 
99  gen_sequence_loop: for (unsigned int i = 0; i < sequenceDim; i++)
100  {
101 #pragma HLS PIPELINE
102  (*outBigWord).range(smallWordDim*(i+1)-1,smallWordDim*i)=nextNumber;
103  prevNumber = currentNumber;
104  currentNumber = nextNumber;
105  nextNumber = (nextNumber + 1 ) xor i;
106  }
107 }
108 
109 
110 template<typename ADDR_T, unsigned int sequenceDim, typename BIGWORD_T, typename SMALLWORD_T, unsigned int smallWordDim>
111 void genXoredSequentialNumbersSecondVersion(ADDR_T curr, BIGWORD_T * outBigWord){
112 #pragma HLS INLINE
113 // REQUIREMENT: must be a multiple
114  //assert( (BIGWORD_T%SMALLWORD_T)==0);
115  SMALLWORD_T currentNumber = static_cast<SMALLWORD_T>(curr);
116  SMALLWORD_T nextNumber = (currentNumber+1) xor 1;
117  SMALLWORD_T prevNumber = currentNumber;
118 
119  gen_sequence_loop: for (unsigned int i = 0; i < sequenceDim; i++)
120  {
121 #pragma HLS UNROLL
122  (*outBigWord).range(smallWordDim*(i+1)-1,smallWordDim*i)=nextNumber;
123  prevNumber = currentNumber;
124  currentNumber = nextNumber;
125  nextNumber = (nextNumber + 1 ) xor i;
126  }
127 }
128 
129 template<typename ADDR_T, typename BIGWORD_T>
130 void genXoredNumbersSingleWord(ADDR_T curr, BIGWORD_T * outBigWord){
131 #pragma HLS INLINE
132  BIGWORD_T currentNumber = static_cast<BIGWORD_T>(curr);
133  BIGWORD_T nextNumber = (currentNumber+1) xor 1;
134  *outBigWord=nextNumber;
135 }
136 
137 
138 template<typename ADDR_T, typename BIGWORD_T>
139 void genSequentialNumbers(ADDR_T curr, BIGWORD_T * outBigWord){
140 #pragma HLS INLINE
141  *outBigWord = curr+1;
142 }
143 
147 
151 
152 
163 template<const unsigned int max_iterations=4000000, const unsigned int buff_dim = 16>
165  hls::stream<local_mem_word_t>& sOutGeneratedData,
166  ap_uint<32> * testCounter,
167  local_mem_addr_t max_addr_ut)
168 {
169 #pragma HLS INLINE off
170  static local_mem_word_t tmp_out [buff_dim];
171 #pragma HLS array_partition variable=tmp_out cyclic factor=2 dim=1
172 
173  static local_mem_addr_t curr_address_ut=0;
174  generate_loop:
175  for (; curr_address_ut < max_addr_ut; )
176  {
177 #pragma HLS PIPELINE II=1
178 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
179 //if free to generate or need backpressure
180  if (!sOutGeneratedData.full())
181  {
182  //Step 1) Generated the data according to a function
183 
184  // genXoredSequentialNumbersSecondVersion
185  // <local_mem_addr_non_byteaddressable_t, LOCAL_MEM_WORD_SIZE/32, local_mem_word_t,
186  // ap_uint<32>,32>(maddr_non_byte,
187  // tmp_out+(maddr_non_byte));
188  //genSequentialNumbers<local_mem_addr_non_byteaddressable_t,local_mem_word_t>(curr_address_ut*64, tmp_out+(maddr_non_byte));
190  local_mem_word_t>(curr_address_ut, tmp_out+(curr_address_ut%buff_dim));
191 
192 //Step 2) Optional fault injection
193  local_mem_word_t tmp_out_scalar;
194  #ifdef FAULT_INJECTION
195  //TODO: place for control fault injection with a function?
196  if(*testCounter >= 2 && curr_address_ut > 0){
197  tmp_out_scalar = tmp_out[curr_address_ut%buff_dim] & static_cast<local_mem_word_t>(0);
198  }else{
199  tmp_out_scalar = tmp_out[curr_address_ut%buff_dim];
200  }
201  #else // FAULT_INJECTION
202  tmp_out_scalar = tmp_out[curr_address_ut%buff_dim];
203  #endif // FAULT_INJECTION
204  //Step 3) write out to the next macrostep and going to the next element
205  sOutGeneratedData.write(tmp_out_scalar);
206  curr_address_ut++;
207  }
208  //else account for a newer cycle to write
209  }
210  curr_address_ut=0;
211 
212 
213 }
214 
215 
226 template <typename Tcntr, const unsigned int max_iterations=4000000,
227 const unsigned int buff_dim=64*2>
229  hls::stream<Tcntr>& sOutCmd,
230 hls::stream<local_mem_word_t>& sInGeneratedData,
231 membus_t * lcl_mem,
232 local_mem_addr_t max_addr_ut,
233 unsigned int burst_size)
234 {
235 #pragma HLS INLINE off
236  local_mem_addr_t curr_address_ut;
237  local_mem_addr_t curr_writing_addr;
238  static local_mem_word_t tmp_out[buff_dim];
239  static unsigned int end_distance=0;
240  static bool last_iteration = false;
241  static bool activated_cntr = false;
242 #pragma HLS array_partition variable=tmp_out block factor=2 dim=1
243 
244  int idx, written_i;
245  int ptrs_difference=0;
246  unsigned int last_words=max_addr_ut;
247  unsigned int maximum_usable_fifo_words=buff_dim-buff_dim%burst_size;
248  read_and_write:
249  for (curr_address_ut = 0, idx=0, curr_writing_addr=0, written_i=0; curr_address_ut < max_addr_ut; curr_address_ut++)
250  {
251 #pragma HLS PIPELINE II=1
252 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
253  if (!sInGeneratedData.empty())
254  {
255  tmp_out[idx] = sInGeneratedData.read();
256  #if DEBUG_LEVEL == TRACE_ALL
257  #ifndef __SYNTHESIS__
258  std::cout << tmp_out[idx] << std::endl;
259  #endif//synth
260  #endif//debug lvl
261  //if stored enough data to begin the bursting OR this is last iteration
262  end_distance = max_addr_ut-curr_address_ut;
263  last_iteration = 1>=end_distance;
264  #if DEBUG_LEVEL == TRACE_ALL
265  #ifndef __SYNTHESIS__
266  std::cout << "test addr " << idx << " current address " << curr_address_ut << " max addr " << max_addr_ut << std::endl;
267  std::cout << "ptrs_difference " << ptrs_difference << " last_iteration " << last_iteration <<std::endl;
268  #endif
269  #endif
270 //accumulated a burst or last iteration
271  if ((ptrs_difference>0 && ptrs_difference>=burst_size-1) || (last_iteration))
272  {
273  #if DEBUG_LEVEL == TRACE_ALL
274  #ifndef __SYNTHESIS__
275  std::cout << "Burst filled or last iteration, end distance will be= " << end_distance << std::endl;
276  #endif
277  #endif
278  if (!last_iteration)
279  {
280  #if DEBUG_LEVEL == TRACE_ALL
281  #ifndef __SYNTHESIS__
282  std::cout << "BURST transferring " << burst_size << " words at " << curr_writing_addr << " address, from " << written_i << std::endl;
283  #endif
284  #endif
285  if(!activated_cntr){
286  sOutCmd.write(0);
287  activated_cntr = true;
288  }else{
289  sOutCmd.write(1);
290  }
291  memcpy(lcl_mem+curr_writing_addr, tmp_out+written_i, sizeof(local_mem_word_t)*burst_size);
292  sOutCmd.write(1);
293  curr_writing_addr+=burst_size;
294  written_i= (written_i+burst_size)%maximum_usable_fifo_words;
295  ptrs_difference-=burst_size;
296  last_words=end_distance;
297  }else{
298  #if DEBUG_LEVEL == TRACE_ALL
299  //#ifndef __SYNTHESIS__
300  std::cout << "LAST transferring " << last_words << " words at " << curr_writing_addr << " address, from " << written_i << std::endl;
301  //#endif
302  #endif
303  if(!activated_cntr){
304  sOutCmd.write(0);
305  activated_cntr = true;
306  }else{
307  sOutCmd.write(1);
308  }
309  memcpy(lcl_mem+curr_writing_addr, tmp_out+written_i, sizeof(local_mem_word_t)*(last_words));
310  sOutCmd.write(1);
311  curr_writing_addr+=(last_words);
312  written_i=(written_i+last_words)%maximum_usable_fifo_words;
313  ptrs_difference-=last_words;
314  }
315  }
316  if(idx==maximum_usable_fifo_words-1){
317  idx=0;
318  }else{
319  idx++;
320  }
321  ptrs_difference++;
322  }else{
323  curr_address_ut--;
324  }
325  }
326  sOutCmd.write(0);//quit everything
327  end_distance=0;
328  last_iteration = false;
329 }
330 
331 
342 template <typename Tcntr, const unsigned int max_iterations=4000000,const unsigned int buff_dim=64*2>
344 hls::stream<Tcntr>& sOutCmd,
345 membus_t * lcl_mem,
346 local_mem_addr_t max_addr_ut,
347 unsigned int burst_size)
348 {
349 //Step 1) start counting
350  sOutCmd.write(0);
351  local_mem_addr_t curr_address_ut;
352 //Step 2) write a simple pattern
353  for (curr_address_ut = 0; curr_address_ut < max_addr_ut; curr_address_ut++)
354  {
355 #pragma HLS PIPELINE II=1
356 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
357  #if DEBUG_LEVEL == TRACE_ALL
358  #ifndef __SYNTHESIS__
359  printf("Writing address %s with max %s\n",curr_address_ut.to_string().c_str(), max_addr_ut.to_string().c_str());
360  #endif
361  #endif
362  lcl_mem[curr_address_ut]=curr_address_ut+1;
363  }
364 //Step 3) stop counting
365  sOutCmd.write(0);
366 }
367 
371 
375 
376 
389 template <typename Tcntr, const unsigned int max_iterations=4000000,const unsigned int buff_dim=64*2>
391 hls::stream<Tcntr>& sOutCmd,
392 membus_t * lcl_mem,
393 local_mem_addr_t max_addr_ut,
394 unsigned int burst_size ,
395 ap_uint<32> * faulty_addresses_cntr,
396 local_mem_addr_t * first_faulty_address)
397 {
398  local_mem_addr_t curr_address_ut;
399  int faults = 0;
400 //Step 1) start counting
401  sOutCmd.write(0);
402  for (curr_address_ut = 0; curr_address_ut < max_addr_ut; curr_address_ut++){
403 #pragma HLS PIPELINE II=1
404 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
405  #if DEBUG_LEVEL == TRACE_ALL
406  #ifndef __SYNTHESIS__
407  printf("Tst=%s vs gld=%s\n",lcl_mem[curr_address_ut].to_string().c_str(),(curr_address_ut+1).to_string().c_str());
408  #endif
409  #endif
410 //Step 2) read a simple pattern and fault checks
411  faults += (lcl_mem[curr_address_ut]!=(curr_address_ut+1)) ? 1 : 0;
412  }
413 //Step 3) stop counting
414  sOutCmd.write(0);
415  *faulty_addresses_cntr = faults;
416  *first_faulty_address = 0;
417 }
418 
419 
420 
432 template <typename Tcntr, const unsigned int max_iterations=4000000,
433 const unsigned int buff_dim=64*2>
435  hls::stream<Tcntr>& sOutCmd,
436  hls::stream<local_mem_word_t>& sOutReadData,
437  membus_t * lcl_mem,
438  local_mem_addr_t max_addr_ut,
439  unsigned int burst_size)
440 {
441 #pragma HLS INLINE off
442 #pragma HLS interface ap_ctrl_none port=return
443 
444  local_mem_addr_t curr_address_ut;
445  static local_mem_word_t tmp_out[buff_dim];
446 #pragma HLS array_partition variable=tmp_out cyclic factor=2 dim=1
448  static local_mem_addr_t curr_reading_addr;
449  static unsigned int end_distance=0;
450  static bool transfer_less_than_burst = false;
451  static bool activated_cntr = false;
452  static bool can_read_data = false;
453 
454  read_data_from_main_mem:
455  int reading_mm_i = 0;//how much filled the buff
456  int consumed_fifo_i = 0;//how much already outputed
457  int missing_words=0;
458  for (curr_address_ut = 0, curr_reading_addr=0; curr_address_ut < max_addr_ut; )
459  {
460 #pragma HLS PIPELINE II=1
461 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
462  if (!sOutReadData.full())
463  {
464  end_distance = max_addr_ut-curr_reading_addr;
465  transfer_less_than_burst = burst_size>end_distance;
466  //i have data to crunch, and eithre the fifo can read a burst or consumed enough to tx less than a burst)
467  can_read_data=(end_distance > 0) ;
468  #if DEBUG_LEVEL == TRACE_ALL
469  #ifndef __SYNTHESIS__
470  std::cout << "Max " << max_addr_ut << " reading at " << curr_reading_addr << " reading fifo at " << reading_mm_i << " consumed at " << consumed_fifo_i << std::endl;
471  std::cout << "End dst " << end_distance << " is last? " << transfer_less_than_burst << std::endl;
472  std::cout << "curr_address_ut " << curr_address_ut << std::endl;
473  #endif
474  #endif
475  //if more than a burst size to available or the last iteration
476  if(can_read_data){
477  if (!transfer_less_than_burst)
478  {
479  //read a burst
480  if(!activated_cntr){
481  activated_cntr = true;
483  local_mem_word_t,64>(lcl_mem+curr_reading_addr,
484  sOutReadData, burst_size, sOutCmd);
485  }else{
487  local_mem_word_t,64>(lcl_mem+curr_reading_addr,
488  sOutReadData, burst_size, sOutCmd);
489  }
490  #if DEBUG_LEVEL == TRACE_ALL
491  #ifndef __SYNTHESIS__
492  std::cout << "BURST reading " << burst_size << " words from " << curr_reading_addr << " address, to " << reading_mm_i << std::endl;
493  #endif
494  #endif
495  curr_reading_addr+=burst_size;
496  reading_mm_i=(reading_mm_i+burst_size)%buff_dim;
497  }else{
498  //read the missing words
499  missing_words= end_distance%burst_size;
500  if(!activated_cntr){
501  activated_cntr = true;
503  local_mem_word_t,64>(lcl_mem+curr_reading_addr,
504  sOutReadData, missing_words, sOutCmd);
505  }else{
507  local_mem_word_t,64>(lcl_mem+curr_reading_addr,
508  sOutReadData, missing_words, sOutCmd);
509  }
510  #if DEBUG_LEVEL == TRACE_ALL
511  #ifndef __SYNTHESIS__
512  std::cout << "LAST reading " << missing_words << " words from " << curr_reading_addr << " address, to " << reading_mm_i << std::endl;
513  #endif
514  #endif
515  curr_reading_addr+=missing_words;
516  reading_mm_i=(reading_mm_i+missing_words)%buff_dim;
517  }
518  }
519 
522  //if() still data to read and to consume
523  curr_address_ut++;
524  //else{
525  // curr_address_ut=max_addr_ut;
526  //}
527  #if DEBUG_LEVEL == TRACE_ALL
528  #ifndef __SYNTHESIS__
529  std::cout <<std::endl;
530  #endif
531  #endif
532  }
533  }
534  sOutCmd.write(0);
535  //reset
536  end_distance=0;
537  transfer_less_than_burst = false;
538  activated_cntr=false;
539  can_read_data=false;
540 }
541 
542 
543 
553 template<const unsigned int max_iterations=4000000>
555  hls::stream<local_mem_word_t>& sInReadData,
556  local_mem_addr_t max_addr_ut,
557  hls::stream<local_mem_word_t>& sOutReadData,
558  hls::stream<local_mem_word_t>& sOutGoldData)
559 {
560 #pragma HLS interface ap_ctrl_none port=return
561  static local_mem_addr_t curr_address_ut= 0;
562  local_mem_word_t testingVector;
563  local_mem_word_t goldenVector;
564 
565  generate_loop:
566  for (; curr_address_ut < max_addr_ut; )
567  {
568 #pragma HLS PIPELINE II=1
569 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
570  if (!sInReadData.empty() && !sOutReadData.full() && !sOutGoldData.full())
571  {
572  testingVector = sInReadData.read();
573 
574  // genXoredSequentialNumbersSecondVersion<local_mem_addr_non_byteaddressable_t, LOCAL_MEM_WORD_SIZE/32,
575  // local_mem_word_t, ap_uint<32>,32>(local_mem_addr_non_byteaddressable, &goldenVector);
577  local_mem_word_t>(curr_address_ut, &goldenVector);
578  //genSequentialNumbers<local_mem_addr_non_byteaddressable_t,local_mem_word_t>(curr_address_ut*64, &goldenVector);
579 
580  sOutReadData.write(testingVector);
581  sOutGoldData.write(goldenVector);
582  curr_address_ut++;
583  }
584  }
585  curr_address_ut = 0;
586 }
587 
588 
589 
600 template<const unsigned int max_iterations=4000000, const unsigned int buff_dim=16>
602  local_mem_addr_t max_addr_ut,
603  hls::stream<local_mem_word_t>& sInReadData,
604  hls::stream<local_mem_word_t>& sInGoldData,
605  ap_uint<32> * faulty_addresses_cntr,
606  local_mem_addr_t * first_faulty_address)
607 {
608 #pragma HLS INLINE off
609 #pragma HLS interface ap_ctrl_none port=return
610  local_mem_addr_t curr_address_ut;
611  static local_mem_word_t testingVector[buff_dim];
612  static local_mem_word_t goldenVector[buff_dim];
613  local_mem_addr_non_byteaddressable_t maddr_non_byte=0;
614  static bool cmp_ok [buff_dim];
615  static ap_uint<32> faulty_addresses_cntr_support_array [buff_dim];
616 
617  static bool first_fault_found = false;
618  static ap_uint<32> faulty_addresses_cntr_local;
619 
620  reading_loop:
621  for (curr_address_ut = 0, faulty_addresses_cntr_local=0; curr_address_ut < max_addr_ut; curr_address_ut++)
622  {
623 #pragma HLS PIPELINE
624 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
625 #pragma HLS dependence variable=faulty_addresses_cntr_support_array inter RAW distance=buff_dim true
626 
627  if (!sInReadData.empty() && !sInGoldData.empty())
628  {
629  testingVector[maddr_non_byte%buff_dim] = sInReadData.read();
630  goldenVector[maddr_non_byte%buff_dim] = sInGoldData.read();
631 
632  int idx=maddr_non_byte%buff_dim;
633  #if DEBUG_LEVEL == TRACE_ALL
634  #ifndef __SYNTHESIS__
635  std::cout << maddr_non_byte << " tst=" << testingVector[idx] << " vs gld=" << goldenVector[idx] << std::endl;
636  #endif
637  #endif
638  bool cmp_results = testingVector[idx] == goldenVector[idx];
639  cmp_ok[idx]=cmp_results;
640  if(!cmp_results ){
641  faulty_addresses_cntr_support_array[idx]++;
642  if (!first_fault_found)
643  {
644  *first_faulty_address=curr_address_ut*64;
645  first_fault_found = true;
646  }else{
647  first_fault_found = first_fault_found;
648  }
649  }
650 
651  maddr_non_byte++;
652  }else{
653  curr_address_ut--;
654  }
655  }
656  // std::cout << std::endl;
657 
658  for (int i = 0; i < buff_dim; i++)
659  {
660 #pragma HLS PIPELINE
661  faulty_addresses_cntr_local += faulty_addresses_cntr_support_array[i];
662  faulty_addresses_cntr_support_array[i]=0;
663  }
664 
665  first_fault_found=false;
666 *faulty_addresses_cntr=faulty_addresses_cntr_local;
667 
668 }
669 
673 
686 template<const unsigned int max_iterations=4000000, const unsigned int unrolling_factor= LOCAL_MEM_ADDR_OFFSET, //inability of using define in pragmas solved in 2021.1
687  const unsigned int buff_dim=16>
689  local_mem_addr_t max_addr_ut,
690  hls::stream<local_mem_word_t>& sInReadData,
691  hls::stream<local_mem_word_t>& sInGoldData,
692  ap_uint<32> * faulty_addresses_cntr,
693  local_mem_addr_t * first_faulty_address)
694 {
695 //#pragma HLS INLINE off
696  const unsigned int dble_wrd_dim = LOCAL_MEM_ADDR_OFFSET * 2;
697  const unsigned int support_dim = LOCAL_MEM_ADDR_OFFSET * 2;
698 
699 
700  local_mem_addr_t curr_address_ut;
701  static local_mem_word_t testingVector[buff_dim];
702  static local_mem_word_t goldenVector[buff_dim];
703  local_mem_addr_non_byteaddressable_t maddr_non_byte=0;
704 
705 
706  static ap_uint<8> testingVector_bytes [support_dim];
707  static ap_uint<8> goldenVector_bytes [support_dim];
708  static bool cmp_ok [support_dim];
709  static ap_uint<32> faulty_addresses_cntr_support_array [support_dim];
710 
711 #pragma HLS array_partition variable=faulty_addresses_cntr_support_array cyclic factor=2 dim=1
712 #pragma HLS array_partition variable=testingVector_bytes cyclic factor=2 dim=1
713 #pragma HLS array_partition variable=goldenVector_bytes cyclic factor=2 dim=1
714 #pragma HLS array_partition variable=cmp_ok cyclic factor=2 dim=1
715 
716  static bool first_fault_found = false;
717  static ap_uint<32> faulty_addresses_cntr_local;
718 
719  ap_uint<1> k;
720  reading_loop:
721  for (curr_address_ut = 0, k=0, faulty_addresses_cntr_local=0; curr_address_ut < max_addr_ut; k++, curr_address_ut++)
722  {
723 #pragma HLS PIPELINE
724 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
725  if (!sInReadData.empty() && !sInGoldData.empty())
726  {
727  testingVector[maddr_non_byte%buff_dim] = sInReadData.read();
728  goldenVector[maddr_non_byte%buff_dim] = sInGoldData.read();
729  golden_comparison: for (int i = 0; i < LOCAL_MEM_ADDR_OFFSET; i++)
730  {
731  //#pragma HLS UNROLL factor=unrolling_factor skip_exit_check
732  int idx = (i + k*LOCAL_MEM_ADDR_OFFSET);
733  testingVector_bytes[idx]=testingVector[maddr_non_byte%buff_dim].range((i+1)*8-1,i*8);
734  goldenVector_bytes[idx]=goldenVector[maddr_non_byte%buff_dim].range((i+1)*8-1,i*8);
735  #if DEBUG_LEVEL == TRACE_ALL
736  #ifndef __SYNTHESIS__
737  std::cout << " tst=" << testingVector_bytes[idx] << " vs gld=" << goldenVector_bytes[idx] ;
738  #endif
739  #endif
740 
741  cmp_ok[idx] = testingVector_bytes[idx] == goldenVector_bytes[idx];
742  if(!cmp_ok[idx] ){
743  faulty_addresses_cntr_support_array[i+k]++;
744  if (!first_fault_found)
745  {
746  *first_faulty_address=i+curr_address_ut*64;
747  first_fault_found = true;
748  }else{
749  first_fault_found = first_fault_found;
750  }
751  }
752  }
753  #if DEBUG_LEVEL == TRACE_ALL
754  #ifndef __SYNTHESIS__
755  std::cout << std::endl;
756  #endif
757  #endif
758  //sInCmpRes.write(tmpOut);
759  maddr_non_byte++;
760  }else{
761  k--;
762  curr_address_ut--;
763  }
764  }
765 
766  flt_cntr_loop: for (int i = 0; i < support_dim; i++)
767  {
768 #pragma HLS PIPELINE
769  faulty_addresses_cntr_local += faulty_addresses_cntr_support_array[i];
770  faulty_addresses_cntr_support_array[i]=0;
771  }
772 
773  first_fault_found=false;
774 *faulty_addresses_cntr=faulty_addresses_cntr_local;
775 
776 }
777 
778 
779 
793 template <typename Tcntr, const unsigned int max_iterations=4000000,
794 const unsigned int buff_dim=64*2>
796  hls::stream<Tcntr>& sOutCmd,
797  hls::stream<local_mem_word_t>& sOutreadData,
798  membus_t * lcl_mem,
799  local_mem_addr_t max_addr_ut,
800  unsigned int burst_size)
801 {
802 #pragma HLS INLINE off
803 
804  local_mem_addr_t curr_address_ut;
805  static local_mem_addr_t curr_reading_addr;
806  static local_mem_word_t tmp_out[buff_dim];
807 #pragma HLS array_partition variable=tmp_out cyclic factor=2 dim=1
808 
809  sOutCmd.write(0);
810  int i, reading_i;
811  read_data_from_main_mem:
812  for (i = 0, curr_address_ut = 0, curr_reading_addr=0, reading_i=0; curr_address_ut < max_addr_ut; )
813  {
814 #pragma HLS PIPELINE II=1
815 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
816  if (!sOutreadData.full())
817  {
818 
819  memcpy(tmp_out+reading_i, lcl_mem+curr_address_ut, sizeof(local_mem_word_t));
820  if(reading_i > curr_reading_addr+1){
821  sOutreadData.write(tmp_out[curr_reading_addr]);
822  #if DEBUG_LEVEL == TRACE_ALL
823  #ifndef __SYNTHESIS__
824  std::cout << " writing a memory word " << curr_reading_addr << " I have to reach " << i << std::endl;
825  #endif
826  #endif
827  curr_reading_addr++;
828 
829  }
830  #if DEBUG_LEVEL == TRACE_ALL
831  #ifndef __SYNTHESIS__
832  std::cout << "read the " << reading_i << " memory word, outputreading at " << curr_reading_addr << " i at " << i << std::endl;
833  #endif
834  #endif
835 
836  if(reading_i==buff_dim-1){
837  reading_i=0;
838  }else{
839  reading_i++;
840  }
841  curr_address_ut++;
842  i++;
843  }
844  }
845 
846  sOutCmd.write(0);
847  i--;
848  reading_i=i%buff_dim;
849  sent_out_remaining_buff:
850  for (int j = 0; j < buff_dim; j++)
851  {
852 #pragma HLS LOOP_TRIPCOUNT min = 1 max = buff_dim
853 #pragma HLS PIPELINE II=1
854  if (!sOutreadData.full())
855  {
856  if(j==curr_reading_addr && i >= curr_reading_addr){
857  #if DEBUG_LEVEL == TRACE_ALL
858  #ifndef __SYNTHESIS__
859  std::cout << " writing a memory word " << curr_reading_addr << " I have to reach " << i << std::endl;
860  #endif
861  #endif
862  sOutreadData.write(tmp_out[curr_reading_addr]);
863  curr_reading_addr++;
864  tmp_out[j]=0;
865  }else{
866  tmp_out[j]=0;
867  }
868  }else{
869  j--;
870  }
871  }
872  curr_reading_addr=0;
873 
874 }
875 
876 
890 template <typename Tcntr, const unsigned int max_iterations=4000000,
891 const unsigned int buff_dim=64*2>
893  hls::stream<Tcntr>& sOutCmd,
894  hls::stream<local_mem_word_t>& sOutreadData,
895  membus_t * lcl_mem,
896  local_mem_addr_t max_addr_ut,
897  unsigned int burst_size)
898 {
899 #pragma HLS INLINE off
900 
901  local_mem_addr_t curr_address_ut;
902  static local_mem_word_t tmp_out[buff_dim];
903 #pragma HLS array_partition variable=tmp_out cyclic factor=2 dim=1
905  static local_mem_addr_t curr_reading_addr;
906  static unsigned int end_distance=0;
907  static int ptrs_distance=0;
908  static int ptrs_distance_opposite=0;
909  static bool transfer_less_than_burst = false;
910  static bool activated_cntr = false;
911  static bool can_read_data = false;
912 
913  read_data_from_main_mem:
914  int reading_mm_i = 0;//how much filled the buff
915  int consumed_fifo_i = 0;//how much already outputed
916  int missing_words=0;
917  unsigned int total_consumed_words=0;
918  unsigned int total_readfrom_mm_words=0;
919  bool fifo_is_not_full=false;
920  for (curr_address_ut = 0, curr_reading_addr=0; curr_address_ut < max_addr_ut; )
921  {
922 #pragma HLS PIPELINE II=1
923 #pragma HLS LOOP_TRIPCOUNT min = 1 max = max_iterations
924  if (!sOutreadData.full())
925  {
926 
927  end_distance = max_addr_ut-curr_reading_addr;
928  ptrs_distance = total_readfrom_mm_words - total_consumed_words;
929  ptrs_distance_opposite = total_consumed_words - total_readfrom_mm_words;
930  transfer_less_than_burst = burst_size>end_distance;
931  fifo_is_not_full = ptrs_distance <= burst_size;
932  //i have data to crunch, and eithre the fifo can read a burst or consumed enough to tx less than a burst)
933  can_read_data=(end_distance > 0) && (fifo_is_not_full || (ptrs_distance<=end_distance && transfer_less_than_burst));
934  #if DEBUG_LEVEL == TRACE_ALL
935  #ifndef __SYNTHESIS__
936  std::cout << "Max " << max_addr_ut << " reading at " << curr_reading_addr << " reading fifo at " << reading_mm_i << " consumed at " << consumed_fifo_i << std::endl;
937  std::cout << "End dst " << end_distance << " ptrs dst " << ptrs_distance << " is last? " << transfer_less_than_burst << std::endl;
938  std::cout << "curr_address_ut " << curr_address_ut << std::endl;
939  #endif
940  #endif
941  //if more than a burst size to available or the last iteration
942  if(can_read_data){
943  if (!transfer_less_than_burst)
944  {
945  //read a burst
946  if(!activated_cntr){
947  sOutCmd.write(0);
948  activated_cntr = true;
949  }else{
950  sOutCmd.write(1);
951  }
952  #if DEBUG_LEVEL == TRACE_ALL
953  #ifndef __SYNTHESIS__
954  std::cout << "BURST reading " << burst_size << " words from " << curr_reading_addr << " address, to " << reading_mm_i << std::endl;
955  #endif
956  #endif
957  memcpy(tmp_out+reading_mm_i, lcl_mem+curr_reading_addr, sizeof(local_mem_word_t)*burst_size);
958  sOutCmd.write(1);
959  std::cout << "before " << curr_reading_addr;
960  curr_reading_addr+=burst_size;
961  std::cout << " afterwards " << curr_reading_addr << std::endl;
962  total_readfrom_mm_words+=burst_size;
963  reading_mm_i=(reading_mm_i+burst_size)%buff_dim;
964  }else{
965  //read the missing words
966  missing_words= end_distance%burst_size;
967  std::cout << "before of before 1" << curr_reading_addr << std::endl;
968  if(!activated_cntr){
969  sOutCmd.write(0);
970  activated_cntr = true;
971  }else{
972  sOutCmd.write(1);
973  }
974  #if DEBUG_LEVEL == TRACE_ALL
975  #ifndef __SYNTHESIS__
976  std::cout << "LAST reading " << missing_words << " words from " << curr_reading_addr << " address, to " << reading_mm_i << std::endl;
977  #endif
978  #endif
979  total_readfrom_mm_words+=missing_words;
980  std::cout << "before of before 3" << curr_reading_addr << std::endl;
981  memcpy(tmp_out+reading_mm_i, lcl_mem+curr_reading_addr, sizeof(local_mem_word_t)*(end_distance%burst_size));
982  sOutCmd.write(1);
983 
984  std::cout << "before " << curr_reading_addr;
985  curr_reading_addr+=missing_words;
986  std::cout << " afterwards " << curr_reading_addr << std::endl;
987  reading_mm_i=(reading_mm_i+missing_words)%buff_dim;
988  }
989  }
990 
991  if(ptrs_distance > 0 || can_read_data){
992  sOutreadData.write(tmp_out[consumed_fifo_i]);
993  #if DEBUG_LEVEL == TRACE_ALL
994  #ifndef __SYNTHESIS__
995  std::cout << " consumin a read memory word " << consumed_fifo_i << " I have to reach " << reading_mm_i << std::endl;
996  std::cout << " The readmemoryword is " << tmp_out[consumed_fifo_i] << std::endl;
997  #endif
998  #endif
999 
1000  if(consumed_fifo_i==buff_dim-1){
1001  consumed_fifo_i=0;
1002  }else{
1003  consumed_fifo_i++;
1004  }
1005  total_consumed_words++;
1006  }
1009  //if() still data to read and to consume
1010  curr_address_ut++;
1011  //else{
1012  // curr_address_ut=max_addr_ut;
1013  //}
1014  #if DEBUG_LEVEL == TRACE_ALL
1015  #ifndef __SYNTHESIS__
1016  std::cout <<std::endl;
1017  #endif
1018  #endif
1019  }
1020  }
1021  sOutCmd.write(0);
1022  //reset
1023  end_distance=0;
1024  transfer_less_than_burst = false;
1025  activated_cntr=false;
1026  can_read_data=false;
1027  ptrs_distance=0;
1028 }
1029 
1030 
1034 
1035 #endif //_ROLE_MEMTEST_PATTERN_LIBRARY_HPP_
void genFibonacciNumbers(ADDR_T curr, BIGWORD_T *outBigWord)
ap_uint< 40 > local_mem_addr_t
void pRDMainMemoryRead2StreamData(hls::stream< Tcntr > &sOutCmd, hls::stream< local_mem_word_t > &sOutreadData, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size)
Read a single word of data and output on a stream and count the cc needed just 4 transfer NOT USED.
void genXoredSequentialNumbersSecondVersion(ADDR_T curr, BIGWORD_T *outBigWord)
ap_uint< 40 > local_mem_addr_non_byteaddressable_t
void genXoredSequentialNumbers(ADDR_T curr, BIGWORD_T *outBigWord)
void pReadSimplerTestMemTest(hls::stream< Tcntr > &sOutCmd, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size, ap_uint< 32 > *faulty_addresses_cntr, local_mem_addr_t *first_faulty_address)
Simple version of a read memtest that read up to a given maximum address No control on the burst size...
void pWRStream2WriteMainMemory(hls::stream< Tcntr > &sOutCmd, hls::stream< local_mem_word_t > &sInGeneratedData, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size)
A function that read a stream of data and write them in a run-time variable burst-size.
membus_512_t membus_t
Definition: memtest.hpp:92
void pRDRead2StreamDataVariableBurstNoMemCpy(hls::stream< Tcntr > &sOutCmd, hls::stream< local_mem_word_t > &sOutReadData, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size)
Read a variable burst_size amount of data and output on a stream and count the cc needed just 4 trans...
void pReadAxiMemMapped2HlsStreamCountFirst(Tin *main_mem, hls::stream< Tout > &sOut, unsigned int elems, hls::stream< Tcntr > &cmd)
Copy a run-time variable amount of data to an hls stream with a given max it assumes also the initial...
#define LOCAL_MEM_ADDR_OFFSET
void genSequentialNumbers(ADDR_T curr, BIGWORD_T *outBigWord)
void pRDRead2StreamDataVariableBurst(hls::stream< Tcntr > &sOutCmd, hls::stream< local_mem_word_t > &sOutreadData, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size)
Read a variable burst_size amount of data and output on a stream and count the cc needed just 4 trans...
Tout genNextFibonacciNumber(Tin curr, Tin prev)
void pRDReadDataStreamAndProduceGold(hls::stream< local_mem_word_t > &sInReadData, local_mem_addr_t max_addr_ut, hls::stream< local_mem_word_t > &sOutReadData, hls::stream< local_mem_word_t > &sOutGoldData)
Read a data stream and produce the gold expected value.
void pReadAxiMemMapped2HlsStreamCountActivated(Tin *main_mem, hls::stream< Tout > &sOut, unsigned int elems, hls::stream< Tcntr > &cmd)
Copy a run-time variable amount of data to an hls stream with a given max it assumes "perfCounterMult...
void pWRGenerateData2WriteOnStream(hls::stream< local_mem_word_t > &sOutGeneratedData, ap_uint< 32 > *testCounter, local_mem_addr_t max_addr_ut)
A function that generate a streams of data according to function and writes them on a stream CHECK: F...
void pWriteSimplerTestMemTest(hls::stream< Tcntr > &sOutCmd, membus_t *lcl_mem, local_mem_addr_t max_addr_ut, unsigned int burst_size)
Simple version of a write memtest that write up to a given maximum address No control on the burst si...
void pRDCmpStreamsCntWordAligned(local_mem_addr_t max_addr_ut, hls::stream< local_mem_word_t > &sInReadData, hls::stream< local_mem_word_t > &sInGoldData, ap_uint< 32 > *faulty_addresses_cntr, local_mem_addr_t *first_faulty_address)
Read two streams, compare them and output the number of faults and the first faulty address.
void genXoredNumbersSingleWord(ADDR_T curr, BIGWORD_T *outBigWord)
ap_uint< 512 > local_mem_word_t
void pRDCompareDataStreamsCount(local_mem_addr_t max_addr_ut, hls::stream< local_mem_word_t > &sInReadData, hls::stream< local_mem_word_t > &sInGoldData, ap_uint< 32 > *faulty_addresses_cntr, local_mem_addr_t *first_faulty_address)
Read two streams, compare them and output the number of faults and the first faulty address,...