/************************************************************************* * MHB TEST RANDOM * * checks HB functions sending random data * * with random maps. Extensive slow check * * Uses two mergers to send hits and roads * * Allow some limited tests of Meger 0 at the same time * * * **************************************************************************/ /* *** REVISION HISTORY * 13 Nov 99: S.Belforte. Original creation from hb_generate_test_events * and other scripts and programs.. * 3 Apr 00: S.Belforte: bring in modificatins from TS: add switch for * one/two HB's and for protections agains merger * output bug and add some cabling instructions * 4 Apr 00: S.Belforte: do not reset Spy Pointers, handle wraparound * 6 Apr 00: S.Belforte: remove usleep, add check for data flow end in * check_data * 6 Apr 00: S.Belforte: print hardware configuration at begining with * complete cabling description. Comment out * Spy Control calls. * 14 Apr 00: S.Belforte: for merger test: * do not reset merger spy pointer, allow wrap and * allow software switch of merger input A-B-C-D * 24 May 00: S.Belforte: read crates/slots from console and save to file * 29 May 00: S.Belforte: fix memory leak: add missing fclose(SSsize_file) * 30 may 00: S.Belforte: fix init error for lmip1, must be 0 not 1. * add pointers file to dump_data, rationalise pointers * updating/passing/handling * **************************************************************************/ #include #include #include #include #include #include #include #include #include "vmesvt_realvme_ppc.h" /* GLOBAL DEFINITIONS AND VARIABLES */ const unsigned long EEflag = 0x400000; /* bit 22 */ const unsigned long EPflag = 0x200000; /* bit 21 */ const unsigned long IOVFflag = 0x2000; /* bit 13 */ /**** execution switches ***/ const int protect_against_merger_output_bug = 0; /***************************/ /**************************************************************************/ /*** if following constans change, code has to change !!!!!!!!!!! *********/ const int Max_Iter = 2; /* number of iterations for full systematic check */ const int MaxEv = 200; /* maximum number of events for random generation */ const int MaxExtraWords = 1; /* maximum extra words for hit, i.e. 2 total */ const int MaxNoisy = 4; /* maximum number of noisy hits per layer */ const int MaxRoadsInEvent = 20; /* maximum number of roads in one event */ const int MaxLayer = 7; /* Maximum Layer Number as set on HB dip-switch */ const int SS_Update_Interval = 2000; /* change SS size each xx iterations*/ const int Maps_Update_Interval = 500; /* change HB maps each xx iter */ const int Spy_Check_Interval = 5; /* check all HB Spy Buffers each xx it */ /**************************************************************************/ int two_hbs; int input_channel; int change_slots; VISION_SLAVE sc1; VISION_SLAVE hb0; VISION_SLAVE hb1; VISION_SLAVE mrg0; VISION_SLAVE mrg1; char sc_cpu[20]; char hb0_cpu[20]; char hb1_cpu[20]; char mrg0_cpu[20]; char mrg1_cpu[20]; int scadd; int hb0add; int hb1add; int mrg0add; int mrg1add; hbsim_t *simhb; unsigned long * ss_map; unsigned long * am_map; int N_SS, SSsize; unsigned int seed; unsigned long * HitData; unsigned long * RoadData; unsigned long * OutData; unsigned long * DataPtr; unsigned long * Mrg0In; unsigned long * Mrg1In; unsigned long * Hb0Hit; unsigned long * Hb0Road; unsigned long * Hb0Out; unsigned long * Hb1Hit; unsigned long * Hb1Road; unsigned long * Hb1Out; unsigned long * OutPtr; unsigned long * RefPtr; int new_maps; int nhits, nroads, nouts, nrefs; int nMrg0In, nMrg1In; int nHb0Hit, nHb0Road, nHb0Out; int nHb1Hit, nHb1Road, nHb1Out; unsigned long curHp0, curRp0, curOp0; /* current HB0 hit/road/out spy ptrs */ unsigned long curHp1, curRp1, curOp1; /* current HB1 hit/road/out spy ptrs */ unsigned long curMip0; /* current MRG0 input spy pointer */ unsigned long curMip1; /* current MRG1 input spy pointer */ unsigned long lstHp0, lstRp0, lstOp0; /* last HB0 hit/road/out spy pointer */ unsigned long lstHp1, lstRp1, lstOp1; /* last HB1 hit/road/out spy pointer */ unsigned long lstMip0; /* last MRG0 input spy pointer */ unsigned long lstMip1; /* last MRG1 input spy pointer */ unsigned long NlstHp0, NlstRp0, NlstOp0; /* next-to-last HB0 spy ptrs */ unsigned long NlstHp1, NlstRp1, NlstOp1; /* next-to-last HB1 spy ptrs */ unsigned long NlstMip0; /* next-to-last MRG0 input spy pointer */ unsigned long NlstMip1; /* next-to-last MRG1 input spy pointer */ hbsim_t *simhb; time_t lt; struct tm * timeptr; char mytime[26]; int b8=0; FILE * logfile; void parse_arguments(int argc, char* argv[]); void get_hardware_configuration(); void print_hardware_configuration(); void change_hardware_configuration(); void save_hardware_configuration(); void get_local_time(); void init_log(); void update_log(int niter); void log_message(char * message); void get_random_seed(); void save_random_seed(); void read_SS_size(); void pick_SS_size(); void read_hb_maps(); void download_hb_maps(); void generate_hb_maps(); void create_data_structures(); void generate_hb_test_events(); void reset_boards(); void init_boards(); void reset_merger_spys(); void update_pointers(); int merger_inspy_pointer(VISION_SLAVE mrg); void send_data(); void wait_for_processing(); void read_merger_inspy(VISION_SLAVE mrg, unsigned long *Data, int nw, unsigned long offset); int check_data(); int check_spys(); int check_hb_spy_buffers(VISION_SLAVE hb, unsigned long HitPtr, unsigned long RoadPtr, unsigned long OutPtr, unsigned long LastHitPtr, unsigned long LastRoadPtr, unsigned long LastOutPtr, int *nHit, int *nRoad, int *nOut, unsigned long *Hit, unsigned long *Road, unsigned long *Out); unsigned int delta_pointers(unsigned int Ptr, unsigned int LastPtr); void dump_data(); void dump_hb_spy_buffers(VISION_SLAVE hb, int hbid); void clean_up(); void Vtry(int status, char action[]); void freeze(); void unfreeze(); void wait_a_bit(); int Parity(unsigned long w, unsigned long n); int iran (int imin, int imax); int rnpoissn (float mean); int compare(int nref, unsigned long * RefData, int ntest, unsigned long * TestData); void caos(); /*************************************************************************/ int main(int argc, char * argv[]) { int iter; int result; char message[80]; parse_arguments(argc, argv); get_hardware_configuration(); if (change_slots==1) { change_hardware_configuration(); save_hardware_configuration(); } print_hardware_configuration(); init_log(); create_data_structures(); get_random_seed(); if(new_maps != 0) { read_SS_size(); generate_hb_maps(); download_hb_maps(); } else { read_SS_size(); read_hb_maps(); } iter = 0; result = 0; init_boards(); while (result == 0) { save_random_seed(); get_local_time(); generate_hb_test_events(); reset_boards(); send_data(); wait_for_processing(); /*This is now done in check_data */ update_pointers(); result = check_data(); update_log(iter++); if ( ((iter%Spy_Check_Interval) == 0) || (result != 0) ) { result |= check_spys(); log_message("!"); } if ( result !=0 ) { sprintf(message,"\n ** ERROR. check result is %d. **\n", result); log_message(message); dump_data(); } if ( ((iter%SS_Update_Interval) == 0) & (result == 0) ) { pick_SS_size(); } if ( (((iter%Maps_Update_Interval) == 0) | ((iter%SS_Update_Interval ) == 0) ) & (result == 0) ) { generate_hb_maps(); download_hb_maps(); } seed = rand(); } clean_up(); exit(result); } /* end of main */ /*------------------------------------------------------------------*/ /*==================================================================*/ /*------------------------------------------------------------------*/ void parse_arguments(int argc, char* argv[]) { if (argc<=4) { printf("Program to test 2 HB's with random events\n"); printf("Needs 2 mergers, one SpyC and one/two HB's\n"); printf("Merger 0 sends Hits, Merger 1 sends Roads. \n"); printf("Merger 0 receives data from HB 0.Merger 1 from HB 1. \n"); printf("Syntax:\n\n"); printf("%s \n\n",argv[0]); printf(" new_maps : 0 ==> start with AM/SS maps as on disk \n"); printf(" assume they are already loaded on HB\n"); printf(" 1 ==> generate new maps before starting \n"); printf(" two_hbs : 0 ==> test only one HB \n"); printf(" 1 ==> test 2 HB's at the same time \n"); printf(" Merg inp# : 1/2/3/4 ==> use merger input A/B/C/D \n"); printf(" change_slots : 0 ==> use previous crate/slot config. \n"); printf(" change_slots : 1 ==> change crate/slot configuration \n"); printf("\n"); printf("\n"); exit(0); } sscanf(argv[1], "%d", &new_maps); sscanf(argv[2], "%d", &two_hbs); sscanf(argv[3], "%d", &input_channel); sscanf(argv[4], "%d", &change_slots); } /*------------------------------------------------------------------*/ void init_log() { logfile = fopen("log_hb_test_random.txt","w"); get_local_time(); printf("%s START\n",mytime); fprintf(logfile, "%s START\n",mytime); return; } /*------------------------------------------------------------------*/ void get_hardware_configuration() { FILE * conf_file; conf_file = fopen("MHB_CONFIGURATION","r"); if (conf_file != NULL ) { fscanf(conf_file,"%s",sc_cpu); fscanf(conf_file,"%d",&scadd); fscanf(conf_file,"%s",hb0_cpu); fscanf(conf_file,"%d",&hb0add); fscanf(conf_file,"%s",hb1_cpu); fscanf(conf_file,"%d",&hb1add); fscanf(conf_file,"%s",mrg0_cpu); fscanf(conf_file,"%d",&mrg0add); fscanf(conf_file,"%s",mrg1_cpu); fscanf(conf_file,"%d",&mrg1add); } else { sscanf("vmesvt1.ts.infn.it","%s",sc_cpu); sscanf("vmesvt1.ts.infn.it","%s",hb0_cpu); sscanf("vmesvt1.ts.infn.it","%s",hb1_cpu); sscanf("vmesvt2.ts.infn.it","%s",mrg0_cpu); sscanf("vmesvt2.ts.infn.it","%s",mrg1_cpu); scadd = 3; hb0add = 16; hb1add = 18; mrg0add = 10; mrg1add = 18; } return; } /*------------------------------------------------------------------*/ void print_hardware_configuration() { printf("Will use following board location, *CHECK IT* !!\n"); printf(" SPY CONTROL: crate %s slot %2d (unused at present)\n", sc_cpu, scadd); printf(" MERGER 0: crate %s slot %2d sends HITS\n", mrg0_cpu, mrg0add); printf(" MERGER 1: crate %s slot %2d sends ROADS\n", mrg1_cpu, mrg1add); printf(" HIT BUFFER 0: crate %s slot %2d sends OUT to MERGER 0\n", hb0_cpu, hb0add); printf(" HIT BUFFER 1: crate %s slot %2d sends OUT to MERGER 1\n", hb1_cpu, hb1add); printf("\n"); printf(" (if need to change, must run with 4th argument = 1 )\n"); printf("\n"); return; } /*------------------------------------------------------------------*/ void change_hardware_configuration() { printf("\nEnter cpu/slot configuration. Ctrl-D to accept default\n"); printf("Spy_Control (unused at present)"); printf("\n crate [%s]:" ,sc_cpu); scanf("%s",sc_cpu); printf("\n slot [%d]: ",scadd); scanf("%d", &scadd); printf("\nHB 0"); printf("\n crate [%s]:",hb0_cpu); scanf("%s",hb0_cpu); printf("\n slot [%d]: ",hb0add); scanf("%d", &hb0add); if (two_hbs==1) { printf("\nHB 1"); printf("\n crate [%s]:",hb1_cpu); scanf("%s",hb1_cpu); printf("\n slot [%d]: ",hb1add); scanf("%d", &hb1add); } printf("\nMerger 0 : sends HITS, receives HB 0 out"); printf("\n crate [%s]:",mrg0_cpu); scanf("%s",mrg0_cpu); printf("\n slot [%d]: ",mrg0add); scanf("%d", &mrg0add); printf("\nMerger 1 : sends ROADS, receives HB 1 out"); printf("\n crate [%s]:",mrg1_cpu); scanf("%s",mrg1_cpu); printf("\n slot [%d]: ",mrg1add); scanf("%d", &mrg1add); return; } /*------------------------------------------------------------------*/ void save_hardware_configuration() { FILE *conf_file; assert (conf_file = fopen("MHB_CONFIGURATION","w")); fprintf (conf_file, "%s\n", sc_cpu); fprintf (conf_file, "%d\n", scadd); fprintf (conf_file, "%s\n", hb0_cpu); fprintf (conf_file, "%d\n", hb0add); fprintf (conf_file, "%s\n", hb1_cpu); fprintf (conf_file, "%d\n", hb1add); fprintf (conf_file, "%s\n", mrg0_cpu); fprintf (conf_file, "%d\n", mrg0add); fprintf (conf_file, "%s\n", mrg1_cpu); fprintf (conf_file, "%d\n", mrg1add); fclose (conf_file); return; } /*------------------------------------------------------------------*/ void update_log(int n) { if ((n%100)==0) fprintf(logfile,"\n%s It %6d\n",mytime+1,n); else if ((n%50)==0) fprintf(logfile,"\n"); fprintf (logfile,"."); /* if ((n%100)==0) printf("\n%s It %6d\n",mytime+1,n); else if ((n%50)==0) printf("\n"); */ if ((n%50)==0) printf("\n"); printf ("."); fflush(NULL); return; } /*------------------------------------------------------------------*/ void log_message(char * message) { printf("%s",message); fprintf(logfile,"%s",message); fflush(NULL); return; } /*------------------------------------------------------------------*/ void pick_SS_size() { /* pick a random value for the SuperStrip size. The same value will * be used for all SS in the SS/AM map. Try to sample possible sizes * somehow proportionally to the relative frequency in real life by * making SS=2 twice as frequent as SS=4 and 4 times as frequent as S=8 */ FILE * SSsize_file; int i; char message[80]; i = iran(1,7); switch (i) { case 1: SSsize=2; break; case 2: SSsize=2; break; case 3: SSsize=2; break; case 4: SSsize=2; break; case 5: SSsize=4; break; case 6: SSsize=4; break; case 7: SSsize=8; break; } if (SSsize==2) N_SS = 4*1024; /* 4k SS for each of 8 layers */ else if (SSsize==4) N_SS = 2*1024; /* 2k SS for each of 8 layers */ else if (SSsize==8) N_SS = 1024; /* 1k SS for each of 8 layers */ else {printf(" Illegal SSsize specification %d. Abort\n", SSsize); exit(0);} SSsize_file = fopen("SS_size", "w"); fprintf(SSsize_file,"%d\n", SSsize); fclose(SSsize_file); sprintf(message,"\nNew SSsize = %d chosen and saved\n", SSsize); log_message(message); return ; } /*------------------------------------------------------------------*/ void read_SS_size() { FILE* SSsize_file; if ( (SSsize_file = fopen("SS_size", "r")) == NULL) { printf("cannot open file SS_size \n"); exit(0); } else { fscanf(SSsize_file,"%d", &SSsize); printf("file read, SSsize : %d \n", SSsize); fclose(SSsize_file); } if (SSsize==2) N_SS = 4*1024; /* 4k SS for each of 8 layers */ else if (SSsize==4) N_SS = 2*1024; /* 2k SS for each of 8 layers */ else if (SSsize==8) N_SS = 1024; /* 1k SS for each of 8 layers */ else {printf(" Illegal SSsize specification %d. Abort\n", SSsize); exit(0);} return ; } /*------------------------------------------------------------------*/ void read_hb_maps() { int result; FILE * am_map_file; FILE * ss_map_file; /* read HB_AM_MAP */ /* try binary first */ printf("reading HB_AM_MAP_BIN file .... "); fflush(NULL); am_map_file = fopen("HB_AM_MAP_BIN","r"); result = fread(am_map, sizeof(unsigned long), HIT_BUFFER_AMMAP_LENGHT, am_map_file); fclose(am_map_file); printf(" DONE\n"); if (result != HIT_BUFFER_AMMAP_LENGHT) { /* if not found, read ascii version */ printf("reading HB_AM_MAP file .... "); fflush(NULL); result=load_struct_hex("HB_AM_MAP",am_map); printf(" DONE\n"); } /* read HB_SS_MAP */ /* try binary first */ printf("reading HB_SS_MAP_BIN file .... "); fflush(NULL); ss_map_file = fopen("HB_SS_MAP_BIN","r"); result = fread(ss_map, sizeof(unsigned long), HIT_BUFFER_SSMAP_LENGHT, ss_map_file); fclose(ss_map_file); printf(" DONE\n"); if (result != HIT_BUFFER_SSMAP_LENGHT) { /* if not found, read ascii version */ printf("reading HB_SS_MAP file .... "); fflush(NULL); result=load_struct_hex("HB_SS_MAP",ss_map); printf(" DONE\n"); } /* pass HB maps to simulation */ hbsim_loadAMmap(simhb, am_map); hbsim_loadSSmap(simhb, ss_map); } /*------------------------------------------------------------------*/ void generate_hb_maps() { /***************************************************** * generate_hb_maps.c * * C Program to creat SS and AM maps fo HB for extensive * tests. These maps should allow easy access to all HLM * location in all combination of SSsizes. * * In HB SS map output the last bits are used to define SS size (2,4,8): * reporting form the HB document: * SS bits SSsize in Hit List Memory * <15...2> <1> <0> * SS ss 0 2 * SS 0 1 4 * SS 1 1 8 * * here ss indicates that bit1 i part of the SS number for size2 * SuperStrips. * Given the 64K location in the HB Hit List Memory (HLM) there * can be up to 32k size2 SS, 16k size4 and 8K size8. * With 8 layers, in each layer we can have at most 4k, 2k and 1k SS's. * * We keep thing simple by making SS map as diagonal as possible, * rember that the 4 lsbits of each hit are dropped and only * the next 17 bits are used as SS address. * In output we need at most 32k word, so 16 bits, so we just take * 15 bits from the input: * SuperStrip: SS MAP will use LSSS as 16-bit address (msb=0 !) and * map LSSSn --> LSSS. Note that actually L=llls, i.e. * the 3 msbits are the 3 layer bits, and the next one is * part of a 13-bit SuperStrip id inside a layer, so * allowing to allocate up to 4k SS per layer as needed. * The MAP then adds the needed lsbits as indicated in the * previous table to correctly specify the size, so: * size=2 ==> add 0 at right * size=4 ==> shift 1 place left and add 01 at right * size=8 ==> shift 2 places left and add 011 at right * right and thus only 14/13 bits are needed!). * More explicitely, here is how each hit word will be interpreted: * * bit 2 1 * field 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * SIZE=2 E P l l l x s s s s s s s s s s s s s x x x x * SIZE=4 E P l l l x x s s s s s s s s s s s s x x x x * SIZE=8 E P l l l x x x s s s s s s s s s s s x x x x * * and the output is: * l l l s s s s s s s s s s s s s * * here: E = EndEvent bit 22 * P = EndPacket bit 21 * l = bit used as layer bit (3 total, bits 18-20) * s = bit used as SuperStrip id * x = bit ignored in the mappint hit-->SuperStrip id * * * ROADS: AM MAP is very simple in this version, * thre are as many road as SupeStrips in each layer * (2K for SSsize=2 or 4, 1K for SSsize=8) and * each road has the same SS in all 8 layers, with * SS = Road #., * each road has the same SuperStrip in all layer, with * SuperStrip number equal to the Road number ! * From N_SS on all roads are invalid (AM_MAP=FFFF) * * S.Belforte 16 Oct, 1999. * * revision history: * *****************************************************/ unsigned long layer, SS, road; unsigned long i, data; int result; FILE * am_bin_map_file; FILE * ss_bin_map_file; log_message("\nGenerate new HB SS+AM maps and save as BIN files\n"); for (i=0; i<128*1024; i++){ layer = (i & 0x1C000) >> 14; if (SSsize == 2) { SS = (i & 0x1FFF); data = (layer<<13) | (SS<<1) | 0x0 ; } if (SSsize == 4) { SS = (i & 0xFFF); data = (layer<<13) | (SS<<2) | 0x1 ; } if (SSsize == 8) { SS = (i & 0x7FF); data = (layer<<13) | (SS<<3) | 0x3 ; } ss_map[i] = data; } /* AM_MAP, loop on all possible addresses and inteprete them as L-Road */ for (i=0; i<1024*1024; i++) /* AM_MAP address = 20 bits = 1 Mega-bit */ { layer = (i & 0xE0000) >> 17; road = (i & 0x1FFFF) ; if (road < N_SS) /* for the first N_SS roads, things are simple */ SS = road; /* for each layer/road the SSid is the road # */ else /* for the rest of the roads */ SS = iran(0, N_SS-1 ); /* just pick the SS at random */ /* the SSadd is built as for the SS map */ if (SSsize == 2) data = (layer<<13) | (SS<<1) | 0x0 ; if (SSsize == 4) data = (layer<<13) | (SS<<2) | 0x1 ; if (SSsize == 8) data = (layer<<13) | (SS<<3) | 0x3 ; am_map[i] = data; } /* Save binary image on file for fast read */ printf("writing HB_SS_MAP_BIN file .... "); fflush(NULL); ss_bin_map_file = fopen("HB_SS_MAP_BIN","w"); result = fwrite(ss_map, 4, HIT_BUFFER_SSMAP_LENGHT, ss_bin_map_file); fclose(ss_bin_map_file); printf(" DONE\n"); printf("writing HB_AM_MAP_BIN file .... "); fflush(NULL); am_bin_map_file = fopen("HB_AM_MAP_BIN","w"); result = fwrite(am_map, 4, HIT_BUFFER_AMMAP_LENGHT, am_bin_map_file); fclose(am_bin_map_file); printf(" DONE\n"); return; } /*------------------------------------------------------------------*/ void download_hb_maps() { unsigned long * test_map; int i,nw; /* download maps Into HB's. Also read back and check*/ /* HB 0 */ Vtry(hit_buffer_TmodeEnable(hb0),"Set HB 0 in Test Mode"); def_struct(HIT_BUFFER_SSMAP_LENGHT, &test_map); log_message("Downloading SS map to HB 0.."); nw=hit_buffer_SSmapWrite(hb0,ss_map,NULL,0); log_message("Reading it back.."); nw=hit_buffer_SSmapRead(hb0,test_map,NULL,0); log_message("Checking.."); for (i=0;i0) read_merger_inspy(mrg0,Mrg0In,nw,lstMip0); else if (nw==0) {printf("Merger0 Input Spy Pointer is 0. Nothing read.\n"); error0=1;} else { nw = 128*1024 - lstMip0; nMrg0In = nw + curMip0; read_merger_inspy(mrg0,Mrg0In, nw, lstMip0); read_merger_inspy(mrg0,Mrg0In+nw,curMip0,0); } for(i=0;i0) read_merger_inspy(mrg1,Mrg1In,nw,lstMip1); else if (nw==0) {printf("Merger1 Input Spy Pointer is 0. Nothing read.\n"); error1=1;} else { nw = 128*1024 - lstMip1; nMrg1In = nw + curMip1; read_merger_inspy(mrg1,Mrg1In, nw, lstMip1); read_merger_inspy(mrg1,Mrg1In+nw,curMip1,0); } for(i=0;i0) { Vtry(hit_buffer_HitSpyBufferReadOffset(hb,Hit,nw,LastHitPtr), "read HB HSpy"); for(i=0;i0) { Vtry(hit_buffer_RoadSpyBufferReadOffset(hb,Road,nw,LastRoadPtr), "read HB RSpy"); for(i=0;i0) { Vtry(hit_buffer_OutputSpyBufferReadOffset(hb,Out,nw,LastOutPtr), "read HB OSpy"); for(i=0;i0) { Vtry(hit_buffer_HitSpyBufferReadOffset(hb,DataPtr,nw,0), "read HB HSpy"); for(i=0;i0) { Vtry(hit_buffer_RoadSpyBufferReadOffset(hb,DataPtr,nw,0), "read HB RSpy"); for(i=0;i0) { Vtry(hit_buffer_OutputSpyBufferReadOffset(hb,DataPtr,nw,0), "read HB OSpy"); for(i=0;iSS correspondance is the same. * This is done to avoid a lenghty inversion of the SS_MAP * This program needs to know the SuperStrip size, * to decide if InternalOverlfow is generated and to figure out * the maximum number of SuperStrips per layer, so it reads it * form the same SS_size file as generate_hb_maps.c does. * * S.Belforte 16 Oct, 1999. * * revision history: * 18 Oct 99: VERSION 2: change arguments to: * RANDOM (0=false, 1=true) * Niter =1,2 only used for RANDOM=false to * divide systematic test in smaller files * Multiplicity = only used for RANMDON=false to * set the #of hits for each SS, * which is always the same * Version 2 frozen on 19 Oct 1999. No major mileston, but most * of random stuff is there and hopefully without having * messed up the simpler systematics checks. * It is frozen to allow more free work to complete * and debug random code for Version 3. * *****************************************************/ int pick_number_of_events(); int pick_number_of_roads(); unsigned long find_SS (unsigned long road, unsigned long layer); int find_hits (unsigned long SS, unsigned long layer, unsigned long * hits, int* n2out, unsigned long* IOVF); int extra_word(); int pick_noise(int layer); int kill_hit (); /**************** CODE *********************/ int MaxHitsInLayer; int evmin, evmax; int Nev, ev; int Nroad, roads_in_this_event; int i, nr, nhit,nout,nroad; unsigned long noutsim; int MaxHitWords, MaxRoadWords, MaxOutWords; int hitparity, roadparity, outparity; int words, bytes; unsigned long road, layer, SSid, SS, hit, out; int hit_words; int n2out; int result; unsigned long * hits_in_SS; unsigned long bunch_id; unsigned long L2buff; unsigned long L1bits; unsigned long IOVF, intoverflow; unsigned long data; unsigned long * Hits; unsigned long * Roads; unsigned long * Outs; unsigned long * Outsim; FILE* ss_map; FILE* am_map; FILE* HITfile; FILE* ROADfile; FILE* OUTfile; FILE* OUTSfile; nhits = 0; nroads = 0; nouts = 0; nrefs = 0; Nroad = 128 * 1024; /* 128k roads exists in AM Map */ Nev = pick_number_of_events(); evmin = 0; evmax = Nev; /* allocate memory, just use fixed arrays over and over */ bytes = sizeof(unsigned long); MaxHitsInLayer = (SSsize + 1)*(1+MaxExtraWords) + MaxNoisy; words = MaxRoadsInEvent + 1; /* words = 10000; */ Roads = malloc (words*bytes); if (Roads == NULL) {printf("No memory for %d roads\n",words);exit(8);} MaxRoadWords = words; words=MaxHitsInLayer; hits_in_SS = malloc(words*bytes); if (hits_in_SS == NULL) {printf("No memory for %d hits\n",words);exit(8);} words = MaxRoadsInEvent*8*MaxHitsInLayer + 1; /* words = 10000; */ Hits = malloc (words*bytes); if (Hits == NULL) {printf("No memory for %d hits\n",words);exit(8);} MaxHitWords = words; words = MaxRoadsInEvent*(8*MaxHitsInLayer+1) + 1; /* words = 10000; */ Outs = malloc (words*bytes); if (Outs == NULL) {printf("No memory for %d outs\n",words);exit(8);} Outsim = malloc (words*bytes); if (Outsim == NULL) {printf("No memory for %d outs\n",words);exit(8);} MaxOutWords = words; /* printf("Sim %3d evts",Nev); fflush(NULL); */ /* open output files */ /* if ( (HITfile = fopen("HIT_DATA", "w")) == NULL) { printf("cannot open file HIT_DATA for writing \n"); exit(0); } if ( (ROADfile = fopen("ROAD_DATA", "w")) == NULL) { printf("cannot open file ROAD_DATA for writing \n"); exit(0); } if ( (OUTfile = fopen("OUT_DATA", "w")) == NULL) { printf("cannot open file OUT_DATA for writing \n"); exit(0); } if ( (OUTSfile = fopen("OUTS_DATA", "w")) == NULL) { printf("cannot open file OUTS_DATA for writing \n"); exit(0); } */ /************* main loop *********************/ for (ev=evmin; ev1 words)*/ hit_words = find_hits(SS, layer, hits_in_SS, &n2out, &IOVF); intoverflow |= IOVF; /* add hit to hit event record and the output record*/ for (i=0;i>10 ) <<19; L1bits = ( (ev&0x300) >>8 ) <<17; bunch_id = ev & 0xFF; Hits[nhit++] = EEflag | EPflag | L2buff| L1bits | hitparity <<8 | bunch_id; Roads[nroad++]= EEflag | EPflag | L2buff| L1bits | roadparity<<8 | bunch_id; Outs[nout++] = EEflag | EPflag | L2buff| L1bits | outparity <<8 | bunch_id; if (intoverflow) Outs[nout-1] |= IOVFflag ; /* compute HB output using simulation */ hbsim_resetCounter(simhb); hbsim_inputHits (simhb, Hits, nhit); hbsim_inputRoads(simhb, Roads, nroad); hbsim_procEvent(simhb); noutsim=hbsim_getOutput(simhb, Outsim, (unsigned long)MaxOutWords); /* load data on output */ for (i=0;iMaxEv)) ; */ /*nev = 1; */ /* change to flat in 2 - Max */ nev=iran(2,MaxEv); return nev; } /*------------------------------------------------------------------*/ int pick_number_of_roads() { /* select a random numer of roads for this event. At present Poisson distribution with average 2.5 This gives a peak at nroad=2 and about as many 1 as 3. Also cut at MaxRoadsInEvent to be safe, less then 0.1% of the Poisson is above 10 anyhow */ int nroad; do nroad = rnpoissn(2.5); while (nroad>MaxRoadsInEvent) ; return nroad; } /*------------------------------------------------------------------*/ unsigned long find_SS (unsigned long road, unsigned long layer) { /* */ unsigned long SSid; unsigned long SS; int am_map_add; am_map_add = road + (layer<<17); SSid = am_map[am_map_add] & 0x1FFF; /* pick leftmost 13bits */ if ((SSid&0x1)==0) /* SSsize = 2 */ SS = SSid >> 1; else if ((SSid&0x3)==0x1) /* SSsize = 4 */ SS = SSid >> 2; else if ((SSid&0x3)==0x3) /* SSsize = 8 */ SS = SSid >> 3; else { printf("Illegal SSid %x at AM_MAP add %x, wrong SSsize bits.", SSid,road+layer<<13); printf("Abort\n"); exit(0); } return SS; } /*------------------------------------------------------------------*/ int find_hits (unsigned long SS, unsigned long layer, unsigned long * hits, int* n2out, unsigned long* IOVF) { /* assume simple algorithm used in generate_hb_maps.c * So just left shit and pad with random numbers the * rightmost 4 bits that are dropped before addressing SS map * Note that layer has a different shift... * Also remember that each hit is a packet. */ float hit_average; unsigned long right_byte; unsigned long SSdata; unsigned long SSid; unsigned long hit; int nwords, nhit, i; int noisy_hits; /* sometimes there are additional hits in the same SS just use Poisson with average cut in (0,SSsize+1] using average such to keep IOVF from occuring in each event */ switch(SSsize) { case 2: hit_average=0.5; break; case 4: hit_average=2.0; break; case 8: hit_average=5.0; break; } do nhit=rnpoissn(hit_average); while ((nhit==0)|(nhit>(SSsize+1))) ; /* find from SS Map one hit that belongs to this SS */ /* for the time being do this as for non-random making assumptions on how SS Map has been filled */ SSdata = SS & 0x1FFF; /* create hits */ nwords = 0; *IOVF = 0; for (i=0;iSSsize) *n2out=SSsize; /* tell caller if Internal Overflow will be generated */ if (nwords>SSsize) *IOVF = 1; /* sometimes there are noisy hits in other SS of the same layer */ noisy_hits = pick_noise(layer); for (i=0;i> 4; /* SS this hit will point to */ } while (SSid == SS); /* make sure noise is on other SS's */ hit |= ( EPflag | (layer<<18) ) ; /* add layer and EP */ hits[nwords++] = hit; } return nwords; } /*------------------------------------------------------------------*/ int kill_hit () { /* 10% of the hits are killed at present */ int test, kill; kill=0; test=iran(1,10); if (test==1) kill=1; return kill; } /*------------------------------------------------------------------*/ int extra_word () { /* 10% of hits have one extra word at present */ int test, extra; extra =0; test=iran(1,100); if (test<=10) extra = 1; return extra; } /*------------------------------------------------------------------*/ int pick_noise (int layer) { /* decide how many extra hits on this layer, to be realistic this should be pretty large, to avoid being overflowed with irrelevant make a peak at 0 with a long flat tail. At present noise is the same on all layers */ int nnoisy, test; test=iran(1,2); if(test==1) { /* very little noise */ do nnoisy=rnpoissn(0.2); while ( nnoisy>MaxNoisy ) ; } else { /* long tail */ nnoisy=iran(0,MaxNoisy); } return nnoisy; } /*------------------------------------------------------------------*/ void get_random_seed() { FILE* seedfile; if ( (seedfile = fopen("lastseed","r")) != NULL) { fscanf(seedfile,"%i",&seed); fclose(seedfile); } else seed = rand(); srand(seed); return; } /*------------------------------------------------------------------*/ void save_random_seed() { FILE* seedfile; seedfile = fopen("lastseed","w"); fprintf(seedfile,"%i\n",seed); fclose(seedfile); srand(seed); return; } /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/ int Parity(unsigned long w, unsigned long n) /* * Returns parity of the n LSb's of the word w. (Must be n>1). The * result is stored in the LSb of the return value. All other bits * are randomly set and should not be used from G. Punzi Parity.c */ { unsigned long out = w; while (--n) out ^= w >>= 1; out &= 0x1; return out; } /*------------------------------------------------------------------*/ float ranf(void) /* random in [0,1), 0 included, 1 excluded */ { float r; r = (float)rand() / ((float)(RAND_MAX)+1.); return r; } /*------------------------------------------------------------------*/ int iran (int imin, int imax) /* * Returns an integer random number * uniformly distributed in [imin,imax] * both imin and imax are a possible return value. */ { float r; /* random in [0,1) */ r = ranf(); return imin+(int)(r*(float)(imax-imin+1)); } /*------------------------------------------------------------------*/ int ulran (unsigned long ulmin, unsigned long ulmax) { float r; /* random in [0,1), 0 included, 1 excluded */ r=1.; while (r==1.) r = ranf(); return ulmin+(unsigned long)(r*(float)(ulmax-ulmin+1)); } /*------------------------------------------------------------------*/ float fran() { float fmin=0.; float fmax=1.; float r; r=1.; while (r==1.) r=(float)(drand48()/1.); return (fmin+(r*(fmax-fmin))); } /*------------------------------------------------------------------*/ int rnpoissn(float mean) /* * Returns interger distributed as Poisson with given mean * Translated from poiprb.F in CDF r_n area * by Bill AShmanskas on Oct 19 1999. */ { const float plim = 16; /* cut-off to switch to gaussian */ const float TWOPI = 2. * 3.141592653; /* just 2-pi */ float a, p, r, rr, s, phi, x; int n; a = mean; n = 0; if (a>0) { if (a<=plim) { r = ranf(); p = exp(-a); s = p; if (r>s) do { n++; p *= a/n; s += p; } while (s1.0e-30); } else { rr = sqrt(-2*log(ranf())); phi = TWOPI*ranf(); x = rr*cos(phi); n = a + x*sqrt(a) + 0.5; if (n<0) n = 0; } } return n; }