From 18f10c316a8db771a2dd420a55b716f748d483fd Mon Sep 17 00:00:00 2001 From: Patrick Robbe <robbe@lal.in2p3.fr> Date: Tue, 21 Jul 2020 03:29:16 +0900 Subject: [PATCH] Improve CRC checking in DMA test software --- Pcie40Applications/Makefile | 4 +- .../main_pcie40_dmahighrate.cpp | 149 ++++++++++++------ Pcie40Applications/rules.mk | 2 +- 3 files changed, 107 insertions(+), 48 deletions(-) diff --git a/Pcie40Applications/Makefile b/Pcie40Applications/Makefile index 441dade..13aef4a 100644 --- a/Pcie40Applications/Makefile +++ b/Pcie40Applications/Makefile @@ -41,13 +41,13 @@ PCIE40_B2LRESET_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLib PCIE40_DMA :=pcie40_dma PCIE40_DMA_OBJS =main_pcie40_dma.o -PCIE40_DMA_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Driver -I$(TOP)/../Pcie40Libraries +PCIE40_DMA_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Driver -I$(TOP)/../Pcie40Libraries PCIE40_DMA_INSTALL =$(PREFIX)/bin PCIE40_DMA_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs PCIE40_DMAHIGHRATE :=pcie40_dmahighrate PCIE40_DMAHIGHRATE_OBJS =main_pcie40_dmahighrate.o -PCIE40_DMAHIGHRATE_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Driver -I$(TOP)/../Pcie40Libraries +PCIE40_DMAHIGHRATE_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Driver -I$(TOP)/../Pcie40Libraries -I/home/usr/yamadas/basf2/externals/v01-09-00/include PCIE40_DMAHIGHRATE_INSTALL =$(PREFIX)/bin PCIE40_DMAHIGHRATE_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs diff --git a/Pcie40Applications/main_pcie40_dmahighrate.cpp b/Pcie40Applications/main_pcie40_dmahighrate.cpp index 7180c0a..d483a92 100644 --- a/Pcie40Applications/main_pcie40_dmahighrate.cpp +++ b/Pcie40Applications/main_pcie40_dmahighrate.cpp @@ -1,7 +1,9 @@ bool exit_on_error = false ; -int nTot = 1000000 ; +int nTot = 100000 ; int max_number_of_messages = 10 ; +#define NUMBER_OF_PROCESSES 7 + #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -13,6 +15,13 @@ int max_number_of_messages = 10 ; #include <set> #include <map> #include <cstring> +#include <omp.h> +#include <thread> +#include <mqueue.h> +#include<sys/wait.h> +#include<sys/ipc.h> +#include<sys/shm.h> +#include<sys/types.h> std::map< int , int > n_messages = { { 0 , 0 } , // no data @@ -34,11 +43,18 @@ std::map< int , int > n_messages = { { 16 , 0 } // missing links }; - extern "C" int ecs_open(int dev, int bar); extern "C" void ecs_close(int dev, int bar); extern "C" unsigned ecs_read(int dev, int bar, unsigned add) ; +struct shm_crc { + int cnt ; + int complete ; + int first_crc ; + int crc_data ; + unsigned int data[ 10000 ] ; +}; + const int CRC16_XMODEM_TABLE[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, @@ -86,9 +102,9 @@ void crc_calc( unsigned int & crc, const unsigned int & data ){ crc = (((crc)<<8)&0xff00) ^ CRC16_XMODEM_TABLE[(((crc)>>8)&0xff)^byte1] ; } -unsigned int get_crc( const std::vector< unsigned int > &data , unsigned int initial_value ) { +unsigned int get_crc( unsigned int * data , int length , unsigned int initial_value ) { unsigned int result = initial_value ; - for( auto it = data.begin() ; it != data.end() ; ++it ) crc_calc( result , (*it) ) ; + for ( int i = 0 ; i < length ; ++i ) crc_calc( result , data[ i ] ) ; return result ; } @@ -203,7 +219,8 @@ int analyzeHeader( unsigned int * & data , unsigned int & size , double & dsize } int analyzeEventData( unsigned int * data , int i , unsigned int size , unsigned int &exprun , unsigned int &runnumber , unsigned int &evtnum , - std::set< int > vlinks ) { + std::set< int > vlinks , struct shm_crc * shmp[ NUMBER_OF_PROCESSES ] ) { + int expected_number_of_links = vlinks.size() ; // TO CHECK LATER unsigned int event_size = data[ 8 ] ; if ( ( data[ 1 ] & 0xFFFF0000 ) != 0x7F7F0000 ) { n_messages[ 7 ] = n_messages[ 7 ] + 1 ; @@ -242,17 +259,9 @@ int analyzeEventData( unsigned int * data , int i , unsigned int size , unsigned unsigned int exp_run = data[ 2 ] ; unsigned int crc_init = 0xFFFF ; - std::vector< unsigned int > f_crc ; - f_crc.push_back( ctime ) ; - f_crc.push_back( myevtnum ) ; - f_crc.push_back( utime ) ; - f_crc.push_back( exp_run ) ; - unsigned int first_crc = get_crc( f_crc , crc_init ) ; - - std::vector< unsigned int > all_crc_data ; - all_crc_data.reserve( 48 ) ; - std::vector< std::vector< unsigned int > > data_all_crc ; - + unsigned int f_crc[ 4 ] = { ctime , myevtnum , utime , exp_run } ; + unsigned int first_crc = get_crc( f_crc , 4 , crc_init ) ; + // find number of links unsigned int numLinks = 0 ; unsigned int linksize = data[ 8 ] & 0xFFFFFFFF ; // to be checked with Yamada-san if OK @@ -285,17 +294,17 @@ int analyzeEventData( unsigned int * data , int i , unsigned int size , unsigned printf( "Bad size of data %X\n" , data[ current_event_start + linksize -1 ] ) ; return 1 ; } - std::vector< unsigned int > data_crc( data + current_event_start + 2 , data + current_event_start + linksize - 2 ) ; - data_all_crc.push_back( data_crc ) ; - unsigned int crc_calc = get_crc( data_crc , first_crc ) ; + // std::vector< unsigned int > data_crc( data + current_event_start + 2 , data + current_event_start + linksize - 2 ) ; unsigned int crc_data = data[ current_event_start + linksize - 2 ] & 0xFFFF ; - all_crc_data.push_back( crc_data ) ; - if ( crc_calc != crc_data ) { - n_messages[ 15 ] = n_messages[ 15 ] + 1 ; - if ( n_messages[ 15 ] < max_number_of_messages ) - printf( "CRC Error %X %X\n" , crc_calc , crc_data ) ; - return 1 ; - } + int sh_index = ( i*expected_number_of_links + numLinks ) % NUMBER_OF_PROCESSES ; + while ( shmp[ sh_index ] -> complete == 0 ) { sleep( 0 ) ; } ; + memcpy( &(shmp[ sh_index ]->data), data+current_event_start+2 , ( linksize - 4 ) * 4 ) ; + shmp[ sh_index ]->cnt = linksize-4 ; + shmp[ sh_index ]->first_crc = first_crc ; + shmp[ sh_index ]-> crc_data = crc_data ; + shmp[ sh_index ]-> complete = 0 ; + // unsigned int crc_calc = get_crc( data_crc , first_crc ) ; + numLinks++ ; if ( ( ( data[ current_event_start + linksize ] & 0xFFFF0000 ) == 0x7FFF0000 ) ) break ; current_event_start = current_event_start + linksize ; @@ -309,18 +318,6 @@ int analyzeEventData( unsigned int * data , int i , unsigned int size , unsigned return 1 ; } - int index = 0 ; - for( auto it = data_all_crc.begin() ; it != data_all_crc.end() ; ++it ) { - // printf( "CRC Error %X %X for link %d\n" , get_crc( (*it) , first_crc ) , all_crc_data[ index ] , index ) ; - if ( get_crc( (*it) , first_crc ) != all_crc_data[ index ] ) { - n_messages[ 15 ] = n_messages[ 15 ] + 1 ; - if ( n_messages[ 15 ] < max_number_of_messages ) - printf( "CRC Error %X %X for link %d\n" , get_crc( (*it) , first_crc ) , all_crc_data[ index ] , index ) ; - return 1 ; - } - index++ ; - } - return 0 ; } @@ -375,10 +372,6 @@ void analyzeEventGenerator( unsigned int * data , int i , unsigned int size ) { // 0 = data, 1 = generator int main (int argc ,char** argv) { - double triggerRate = 400 ; // kHz - double data_size = 0. ; - - int size = 0x1F ; bool isData = true ; printf( "Program to read events by DMA\n" ) ; if ( argc != 2) { @@ -393,6 +386,51 @@ int main (int argc ,char** argv) { printf( "Data mode\n" ) ; } + int shmid[ NUMBER_OF_PROCESSES ] ; + // shared memory + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++p ) { + shmid[ p ] = shmget( 0x1234+p , sizeof( struct shm_crc ) , 0644|IPC_CREAT ) ; + if ( shmid[ p ] == -1 ) perror( "Create shared memory" ) ; + } + + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++p ) { + if ( 0 == fork() ) { + unsigned int data_for_crc[ 10000 ] ; + + int crc_processed = 0 ; + int crc_errors = 0 ; + struct shm_crc * shmp = ( struct shm_crc * ) shmat(shmid[ p ], NULL, 0); + if (shmp == (void *) -1) perror("Shared memory attach"); + printf( "Process %d\n" , p ) ; + while( true ) { + // int status = mq_receive(mqfd, (char *)&value, 8 , 0); + // if ( status == -1 ) perror("Erreur:") ; + while( shmp->complete == 1 ) { sleep( 0 ) ;} ; + crc_processed++ ; + if ( -1 == shmp -> complete ) { + printf( "End of CRC thread\n" ) ; + printf( "Number of CRC processed = %d\n" , crc_processed-1 ) ; + printf( "Number of CRC errors = %d\n" , crc_errors ) ; + exit( 0 ) ; + } + memcpy( &data_for_crc[0] , &shmp->data[0] , shmp->cnt*4 ); + int size = shmp->cnt ; + unsigned int first_crc = shmp->first_crc ; + shmp->complete = 1 ; + unsigned int value = shmp->crc_data ; + if ( get_crc( data_for_crc , size , first_crc ) != value ) { + // printf( "CRC Error %X %X\n" , get_crc( data_for_crc , size , first_crc ) , value ) ; + crc_errors++ ; + } + } + } + } + + double triggerRate = 400 ; // kHz + double data_size = 0. ; + + int size = 0x1F ; + int res = ecs_open( 0 , 0 ) ; if ( -1 == res ) printf("ERROR: Could not open device (BAR 0)\n") ; else printf("SUCCESS: Device opened for ECS 0\n"); @@ -464,6 +502,14 @@ int main (int argc ,char** argv) { int previous_index = 0 ; unsigned int frag_size = 0 ; auto t1 = std::chrono::high_resolution_clock::now(); + + struct shm_crc * shmp[ NUMBER_OF_PROCESSES ] ; + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++p ) { + shmp[p] = ( struct shm_crc *) shmat(shmid[p], NULL, 0); + if ( shmp[p] == (void *) -1 ) perror( "Attach shared memory" ) ; + shmp[p] -> complete = 1 ; + } + while ( k < nTot ) { // start DMA and wait for one or more super pages of data rv = pcie40_dmaStart( 0 ) ; @@ -473,7 +519,7 @@ int main (int argc ,char** argv) { // data = pcie40_getSuperPagePointer( 0 , ( i / S_PAGE_SLOT_NMB ) % S_PAGES , i % S_PAGE_SLOT_NMB ) ; data = pcie40_getSuperPageCopy( 0 , ( i / S_PAGE_SLOT_NMB ) % S_PAGES , i % S_PAGE_SLOT_NMB ) ; if ( ( i == 0 ) && ( j == 0 ) ) t1 = std::chrono::high_resolution_clock::now() ; - + // printf( "Event number %d\n" , getEventNumber( data ) ) ; if ( ! isData ) analyzeEventGenerator( data , i , size ) ; else { @@ -499,7 +545,7 @@ int main (int argc ,char** argv) { } } else esize = frag_size ; - if ( 0 != analyzeEventData( data , k , esize , exprun , runnumber , evtnum , valid_links ) ) { + if ( 0 != analyzeEventData( data , k , esize , exprun , runnumber , evtnum , valid_links , shmp ) ) { if ( exit_on_error ) exit( 0 ) ; errors++ ; } @@ -509,10 +555,21 @@ int main (int argc ,char** argv) { // if ( i != getEventNumber( data ) ) printf( "Mismatch event number %d %d\n" , i , getEventNumber( data ) ) ; ++i ; ++k ; - if ( ( k % 1000 ) == 0 ) printf( "Event number %d\n" , k ) ; + if ( ( k % 1000 ) == 0 ) { + printf( "Event number %d\n" , k ) ; + } if ( ( i > 0 ) && ( ( i % S_PAGE_SLOT_NMB ) == 0 ) ) pcie40_freeSuperPage( 0 , 1 ) ; } } + // unsigned int message = -1 ; + //mq_send( mqfd , (char * ) &message , 8 , 0 ) ; + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++p ) { + shmp[ p ] -> complete = -1 ; + } + printf( "Event number %d\n" , k ) ; + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++ p ) + wait( 0 ) ; + auto t2 = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count(); double rate = 0. ; @@ -524,6 +581,8 @@ int main (int argc ,char** argv) { printf( "Errors = %d (%.2f percent)\n" , errors , 100.*( ( (double) errors ) / ( (double) nTot ) ) ) ; // // + for ( int p = 0 ; p < NUMBER_OF_PROCESSES ; ++p ) + if ( shmctl( shmid[ p ] , IPC_RMID , 0 ) == -1 ) perror( "Delete shared memory" ) ; ecs_close( 0 , 0 ) ; ecs_close( 0 , 2 ) ; dma_close( 0 ) ; diff --git a/Pcie40Applications/rules.mk b/Pcie40Applications/rules.mk index f885ee2..f80e295 100644 --- a/Pcie40Applications/rules.mk +++ b/Pcie40Applications/rules.mk @@ -2,7 +2,7 @@ BUILD_PREFIX ?= LIBDIR_SUFFIX ?=64 FLEX ?=flex LFLAGS ?= -CFLAGS +=-Wall -g -O3 +CFLAGS +=-Wall -g -O3 -fopenmp CXXFLAGS +=-Wall -g -O3 -fopenmp DOCRA ?=docra ASCIIDOCTOR ?=asciidoctor -- GitLab