Skip to content
Snippets Groups Projects
main_pcie40_ul.cpp 16 KiB
Newer Older
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include "altera_dma_regs.h"
qzhou's avatar
qzhou committed
#include "pcie40_ecs.h"
#include <sys/time.h>
#define OLD_RUN 1
#define OLD_EVENT 2
#define NO_TRAILER 3
#define PRESCALE 1000
const int CRC16_XMODEM_TABLE[] = {
  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
} ;

double getTimeSec()
{
  struct timeval t;
  gettimeofday(&t, NULL);
  return (t.tv_sec + t.tv_usec * 1.e-6);
}
int crc_calc( int * crc, unsigned int * data ){ 
  int byte1, byte2, byte3, byte4 ;
  byte1 = (*data) & 0xFF;
  byte2 = ( (*data) & 0xFF00 ) >> 8;
  byte3 = ( (*data) & 0xFF0000 ) >> 16;
  byte4 = ( (*data) & 0xFF000000 ) >> 24;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte4] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte3] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte2] ;
  *crc = ((((*crc))<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((((*crc))>>8)&0xff)^byte1] ;
int crc_calc_event( unsigned int* data, int start_pos, int *crc_good, int *crc_bad ){
  int i = 0;
  int cur_pos = start_pos;
  int first_crc ;
  int crc = 0xffff ;
  int size = data[ cur_pos % DMASIZE ];
  int good_flag = 0;
  int hdr_start = 2;
  if( size > 0xffff || size <= 0 ){
    printf("Invalid total event size %.8x\n", size);
    return -1;
  /* printf( "TRL %.8x %.8x %.8x\n",  */
  /* 	  data[ ( cur_pos + size - 1 + DMASIZE ) % DMASIZE ],  */
  /* 	  data[ ( cur_pos + 1 + size ) % DMASIZE ],  */
  /* 	  data[ ( cur_pos + 2 + size ) % DMASIZE ] );  */
  cur_pos = start_pos + 4;
  unsigned int ctime = data[ cur_pos % DMASIZE ];
  cur_pos = start_pos + 3;
  unsigned int evenum = data[ cur_pos % DMASIZE ];
  cur_pos = start_pos + 5;
  unsigned int utime = data[ cur_pos % DMASIZE ];
  cur_pos = start_pos + 2;
  unsigned int exp_run = data[ cur_pos % DMASIZE ] ;
  crc_calc( &crc, &ctime );
  crc_calc( &crc, &evenum );
  crc_calc( &crc, &utime );
  crc_calc( &crc, &exp_run );
  first_crc = crc ;
  int offset = 8; // size of ROB header [words]
  int link_num = 0;

#ifdef DEBUG
  printf("Start\n");
  for( i = start_pos ; i < start_pos + size ; i++){
    printf("%.8x\n", data[ i % DMASIZE ] );
  }
  printf("End\n");
#endif
  int bad = 0;
  while( offset + 4 < size ){ // 4 = ROB trailer size
    cur_pos = start_pos + offset;
    int size_link = data[ cur_pos % DMASIZE ] & 0x000ffff ;
    if ( 0 >= size_link || size_link > 10000000 ){
      printf("[ERROR] Invalid size per link (%.8x words): link num %d\n", 
	     size_link, link_num);
      return -1 ; // it could be that the memory was read
    } 

    //
    // Calculation of CRC
    //
    crc = first_crc ;
#ifdef DEBUG
    printf("%.8x %.8x crc %.8x\n", data[ ( start_pos + offset ) % DMASIZE ], 
	   data[ ( start_pos + offset + 1 ) % DMASIZE ], crc );
    for( cur_pos = start_pos + offset + hdr_start ; 
	 cur_pos < start_pos + offset + size_link -2; ++cur_pos ){
      crc_calc( &crc, &data[ cur_pos % DMASIZE ] );
#ifdef DEBUG
      printf("crc %.8x data %.8x\n", crc, data[ cur_pos % DMASIZE ] );
#endif
    printf("%.8x %.8x\n", data[ ( cur_pos ) % DMASIZE ], 
	   data[ ( cur_pos + 1 ) % DMASIZE ]);
#endif
    //    cur_pos = start_pos +  8 + size_link -2;
    cur_pos = ( start_pos + offset + size_link - 2 + DMASIZE) % DMASIZE;
#ifdef DEBUG
    printf("calcd %.4x data %.4x\n", crc, data[ cur_pos % DMASIZE ] & 0xffff );
#endif

    //
    // Check of CRC
    //
    if( ( crc & 0xffff ) != ( data[ cur_pos % DMASIZE ] & 0xffff ) ){
        printf("%.2d Bad  ! calcd %.8x data %.4x offset %.4x size %.4x szlnk %.4x trl %.8x\n", 
         	     link_num, crc, data[ cur_pos % DMASIZE ], offset, 
         	     size, size_link, data[ (cur_pos+1) % DMASIZE ] );
      good_flag = 1;
       // printf("%.2d Good ! calcd %.4x data %.8x offset %.4x size %.4x szlnk %.4x trl %.8x\n",  
       // 	      link_num, crc, data[ cur_pos % DMASIZE ], offset, 
       // 	      size, size_link, data[ (cur_pos+1) % DMASIZE ] ); 
    link_num++;
    offset += size_link;
  }

  if( bad ){
       for( i = 0 ; i < size ; i++){
         printf("%.8x ", data[ ( start_pos  + i ) % DMASIZE ] );
         if( i % 8 == 7 ) printf("\n %.8x  ", ( start_pos  + i ) % DMASIZE );
       }
       printf("\n");
       good_flag = -2;
  }
  return good_flag;
int print_line(unsigned int *data, int cur_pos ){

  printf("pos %.8x : ", cur_pos );
  for( int i = 0; i < 8 ; i++ ){
    printf("%.8x ", data[ ( cur_pos + i - ( cur_pos % 8 ) ) % DMASIZE ]);
  }
  printf("\n");

  return 0;
}

int check_hdr_trl( unsigned int *data, int cur_pos, int *event_flag, 
		   unsigned int cur_exp_run, unsigned int cur_eve, 
		   unsigned int *next_exp_run, unsigned int *next_eve ){

  unsigned int trailer = 0;
  int size = data[ cur_pos ] ;
  *next_exp_run = 0;
  *event_flag = 0;
  *next_eve = 0;

  if ( ( ( data[ ( cur_pos + 1 ) % DMASIZE ] & 0xffff0000 ) == 0x7f7f0000 ) ){
    *next_exp_run =  data[ ( cur_pos + 2 ) % DMASIZE ] ;
    *next_eve = data[ ( cur_pos + 3 ) % DMASIZE ];
    trailer = data[ ( cur_pos + size + DMASIZE - 1 ) % DMASIZE ];
    if( *next_exp_run < cur_exp_run && cur_exp_run != 0 ){
      // printf( "OLD-run's event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
      //  	      *next_exp_run , *next_eve, cur_exp_run, cur_eve, cur_pos, size );
      *event_flag = OLD_RUN;
    }else if( ( *next_eve <= cur_eve && cur_exp_run != 0 ) && *next_exp_run <= cur_exp_run){
      //         printf( "OLD or same event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", *next_exp_run , *next_eve, cur_exp_run, cur_eve, cur_pos, size );
      //                  print_line( data, ( cur_pos + 1 ) % DMASIZE );
      *event_flag = OLD_EVENT;
      //    }else if( trailer != 0x7fff0008 ){
    }else if( ( trailer & 0xffff0000 ) != 0x7fbf0000 && ( trailer & 0xffff0000 ) != 0x7fcf0000 ){
       // printf( ".No trailer [%.8x] : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
       //  	      trailer, *next_exp_run , *next_eve, cur_exp_run, cur_eve, cur_pos, size );
       //  print_line( data, ( cur_pos + size + DMASIZE - 1 ) % DMASIZE );
      *event_flag = NO_TRAILER;
    }else{
      // printf( "New event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
      // 	      *next_exp_run , *next_eve, cur_exp_run, cur_eve, cur_pos, size );

    //    print_line( data, cur_pos );
// if( dma_cnt % 1000 == 0 ){
//   printf( "7f7f is found. TRAILER %.8x eve %.8x exprun %.8x pos 0x%x dmacnt %d\n", 
// 	      data[ ( cur_pos + data[ ( cur_pos + j + DMASIZE ) % DMASIZE ] - 1 + DMASIZE ) % DMASIZE ], 
// 	      next_eve, next_exp_run, ( cur_pos + j + 1 ) % DMASIZE, dma_cnt );
// }


int main (int argc ,char** argv) {
  printf("DMASIZE %.8x\n", DMASIZE );fflush(stdout);
  int res = ecs_open( 0 , 0 ) ;
  if ( -1 == res ) printf("ERROR: Could not open device (BAR 0)\n") ;
  else printf("SUCCESS: Device opened for DMA\n");
  res = ecs_open( 0 , 2 ) ;
  // ecs_write( 0 , 2 ,  0x000501A0 , 0x0 ) ;
  ecs_write( 0 , 2 ,  0x000501A0 , 0x1 ) ;
  pcie40_b2dmabufferreset( 0 ) ; 

  double start_time = 0., time_diff = 0.;
  start_time = getTimeSec();
  int run  = 0 ; 
  FILE* fp; 
  char * ptr ;
  char * tmp ;
  char buf[1000] ;
  char exp[] = "exp" ; 

  unsigned int * data ; 
  double time_spent ;
  int retry ;
  int bad ;
  int evn ;
  evn = 0  ;
  bad = 0 ;
  retry = 0 ;
  int pctime, putime ; 
  pctime = 0 ;
  putime = 0 ;

  int i ;
  int size, size_256, currentEventIndex, crc, nErr, nEvt, nRetry, nMissed ;
  currentEventIndex = 0 ;
  nErr = 0 ;
  nEvt = 0 ;
  nRetry = 0 ;
  nMissed = 0 ;

  clock_t begin = clock() ;
  int size_zero_cnt = 0;

  int start_flag = 1;

  int magic; 
  int size_link;

  int offset; 
  unsigned int next_exp_run, cur_exp_run = 0, evenum, ctime, utime, first_eve = 0; 
  int start_pos = 0;
  int cnt = 0, dma_cnt = 0;
  int crc_good = 0, crc_bad = 0;
  int eve_cnt = 0, first_event_flag = 0, crc_err_eve_cnt = 0;
  int cur_pos = 0;
  int ret = 0, event_flag = 0;
  unsigned int cur_eve = 0, next_eve = 0;
  int mod_pos = 0;
  
  int old_run_cnt = 0, old_eve_cnt = 0, no_trl_cnt = 0;
  unsigned int total_err_cnt = 0;
  //    if ( ( nEvt % 1000 == 1 ) && ( size != 0 ) ) printf( "Event number %d\n", nEvt ) ;

  //
  // Read the 1st data
  //
  res = pcie40_b2dmapointerread( 0 , &data ) ;
  dma_cnt++;
  if ( start_flag == 1 ){
    ecs_write( 0 , 2 ,  0x000501A0 , 0x0 ) ;
    start_flag = 0;
  }
  //
  // Main loop
  //
  while( 1 ){
    // Search 7f7f header magic word.
    while( 1 ){ 
      ret = check_hdr_trl( data, cur_pos, &event_flag, cur_exp_run, cur_eve, &next_exp_run, &next_eve );
      if( ret == 1 && event_flag == 0){
	break;
      }else{
	if( event_flag == OLD_RUN ){
	  total_err_cnt++;
	  old_run_cnt++;
	}else if( event_flag == OLD_EVENT ){ 
	  total_err_cnt++;
	  old_eve_cnt++;
	}else if( event_flag == NO_TRAILER ){ 
	  total_err_cnt++;
	  no_trl_cnt++;
	}

	if(total_err_cnt % PRESCALE == 1 && event_flag != 0 ){
	  printf("total %d oldrun %d old/same event %d no_trl %d goodlink %d badlink %d\n", 
		 total_err_cnt, old_run_cnt, old_eve_cnt, no_trl_cnt, crc_good, crc_bad );
	  size = data[cur_pos];
	  // if( event_flag == OLD_RUN ){
	  //   printf( "OLD-run's event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
	  // 	    next_exp_run , next_eve, cur_exp_run, cur_eve, cur_pos, size );
	  //   print_line( data,cur_pos % DMASIZE );
	  // }else if( event_flag == OLD_EVENT ){ 
	  //   printf( "OLD or same event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
	  // 	    next_exp_run , next_eve, cur_exp_run, cur_eve, cur_pos, size );
	  //   print_line( data,cur_pos % DMASIZE );
	  // }else if( event_flag == NO_TRAILER ){ 
	  //   printf( "No trailer [%.8x] : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
	  // 	    next_exp_run, next_eve, cur_exp_run, cur_eve, cur_pos, size );
	  //   print_line( data, ( cur_pos + size + DMASIZE - 1 ) % DMASIZE );
	  // }
      }
      usleep(1000); // to avoid BUSY loop
	
      //
      // Refresh DMA memory
      //
      res = pcie40_b2dmapointerread( 0 , &data ) ;
      int wait_flag = 0;

      //
      // Scan to find x"7f7f...."
      //
      if( cnt > 100 ){
	cnt = 0;
	int j = 0 ; 
	for ( j = 0 ; j < DMASIZE ; ++j ) { 
	  ret = check_hdr_trl( data, cur_pos + j, &event_flag, cur_exp_run, cur_eve, &next_exp_run, &next_eve );
	  if( ret == 1 && event_flag == 0 ){
	    cur_pos = ( cur_pos + j ) % DMASIZE;
	    if( event_flag == OLD_RUN ){
	      old_run_cnt++;
	    }else if( event_flag == OLD_EVENT ){ 
	      old_eve_cnt++;
	    }else if( event_flag == NO_TRAILER ){ 
	    if(total_err_cnt % PRESCALE == 1 && event_flag != 0 ){
	      printf("total %d oldrun %d old/same event %d no_trl %d goodlink %d badlink %d\n", 
		     total_err_cnt, old_run_cnt, old_eve_cnt, no_trl_cnt, crc_good, crc_bad );
	      size = data[cur_pos] & 0xffffff;
	      if( event_flag == OLD_RUN ){
		printf( "OLD-run's event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
			next_exp_run , next_eve, cur_exp_run, cur_eve, cur_pos, size );
		print_line( data,cur_pos % DMASIZE );
	      }else if( event_flag == OLD_EVENT ){ 
		printf( "OLD or same event : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
			next_exp_run , next_eve, cur_exp_run, cur_eve, cur_pos, size );
		print_line( data,cur_pos % DMASIZE );
	      }else if( event_flag == NO_TRAILER ){ 
		printf( "No trailer : run %.8x eve %.8x ( cur run %.8x eve %.8x) : pos %.8x size %d\n", 
			next_exp_run, next_eve, cur_exp_run, cur_eve, cur_pos, size );
		print_line( data, ( cur_pos + size + DMASIZE - 1 ) % DMASIZE );
	      }
    // Check event-data

#ifdef FULL_CHECK
    if( ( data[ ( cur_pos +  data[ cur_pos  % DMASIZE ] - 2 + DMASIZE ) % DMASIZE ] != 0x00000000 ) ||
	( data[ ( cur_pos +  data[ cur_pos  % DMASIZE ] - 3 + DMASIZE ) % DMASIZE ] != 0x7faf0000 ) ){
      printf("Full ! %.8x %.8x\n", 
	     data[ ( cur_pos +  data[ cur_pos  % DMASIZE ] - 3 + DMASIZE ) % DMASIZE ],
	     data[ ( cur_pos +  data[ cur_pos  % DMASIZE ] - 2 + DMASIZE ) % DMASIZE ] );
    }
    size = data[cur_pos] & 0xffffff;
    next_eve = data[ ( cur_pos + 3 ) % DMASIZE ];
    next_exp_run = data[ ( cur_pos + 2 ) % DMASIZE ];

    if( first_event_flag == 0 || cur_exp_run != next_exp_run ){
      first_event_flag = 1;
      first_eve = next_eve;
      // crc_err_eve_cnt = 0;
      // eve_cnt = 0;
    }
    eve_cnt++;
    ret = crc_calc_event( data, cur_pos, &crc_good, &crc_bad );
    //      printf("crc ret %d cnt %d\n", eve_cnt);
    if( ret != 1 ){
      crc_err_eve_cnt++;
    }
    if(ret != 1 || eve_cnt % PRESCALE == 0 ){
      printf( "Event number prev %.8x new %.8x pos %.8x size %.8x\n" , cur_eve , next_eve, cur_pos, size );
    }
    cur_eve = next_eve;
    cur_exp_run = next_exp_run;
    if( eve_cnt % PRESCALE == 0 ){
      //    if( ret != 1 ){
      //    if(ret != 1 ||  eve_cnt % 100 == 0 ){
      time_diff = getTimeSec() - start_time;
      printf("STATUS : tot eve %d read eve %d err_eve %d run %.8x crcgood %d crcbad %d time %.1lf\n", next_eve - first_eve, eve_cnt, crc_err_eve_cnt, cur_exp_run, crc_good, crc_bad, time_diff); fflush(stdout);
    mod_pos = ( cur_pos + size ) % 8;
    if( mod_pos != 0 ){
      cur_pos = ( cur_pos + size + DMASIZE + ( 8 - mod_pos) ) % DMASIZE ;
    }else{
      cur_pos = ( cur_pos + size + DMASIZE ) % DMASIZE ;
    }

  }
  clock_t end = clock();
  time_spent += (double)(end - begin) / CLOCKS_PER_SEC;
  ecs_close( 0 , 0 ) ;
  printf( "Timing = %f s\n" , time_spent ) ;
  printf( "Number of events = %d \n", nEvt ) ;  
  printf( "Number of errors = %d \n", nErr ) ; 
  printf( "Number of retries = %d \n", nRetry ) ;
  printf( "Number of missed = %d \n", nMissed ) ;
  return 0 ;
}