/************************************************************* /* /* evg /* /* E. Pasqualucci 11-6-1996 /* This program implements an event /* generator for the data acquisition test stand. /* Needs to be linked with utilib functions and Vme package. /* E. Pasqualucci 11-6-1996 /* /* Modified to implement trigger number sharing. The first /* trigger generated is written into a location on Vme /* mirrored memory, the trigger location is written before /* the generated lengths. /* E. Pasqualucci 19-9-1996 /* /* Modified to implement the effect of the edge of Vic memory. /* The trigger number is now generated as the maximum trigger /* number seen by the collectors. /* E. Pasqualucci 26-9-1996 /* /* Options modified to allow to write on a fifo at a given address. /* E. Pasqualucci 26-9-1996 /* /* Writing on fifo enabled. /* Parameter names modified (EVG_ prefix inserted). /* Help updated. /* E. Pasqualucci 4-10-1996 /* /* Program debug. Minor bugs fixed and generated length /* aligned to 256 bytes when the events are written on VIC. /* E. Pasqualucci 16-10-1996 /* /* Options regarding the event structure included. /* E. Pasqualucci 22-10-1996 /* /* Bug regarding timeouts corrected. /* E. Pasqualucci 24-10-1996 /* /* v1 released. /* E. Pasqualucci 24-10-1996 /* /*************************************************************/ #define debug #define program /* standard include files */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> #include <signal.h> #include <limits.h> /* for compatibility with LynxOS */ #ifndef RAND_MAX #define RAND_MAX INT_MAX #endif /* Vme package include file */ #include "Vme.h" /* specific include files */ #include "evg.h" /* prototype files */ #include "evg_protos.h" #include "utilib_protos.h" /* global variables */ int cid; int fcid; int mcid; int rand_max = RAND_MAX; int seed = EVG_DEF_SEED; int tot_len = 0; int n_chain = EVG_DEF_N_CHAIN; int n_mm_events = EVG_DEF_N_MM_EVENTS; int min_datalen = EVG_DEF_MIN_DATALEN; /* (in 32 bit words) */ int ave_datalen = EVG_DEF_AVE_DATALEN; int ave_htrigger_time = EVG_DEF_AVE_HTRIG_TIME; /* (in microseconds) */ int retry_htrigger_time = EVG_DEF_RETRY_HTRIG_TIME; int ave_kloe_rate = EVG_DEF_AVE_KLOE_RATE; int vic_address = EVG_DEF_VIC_ADDRESS; int vic_size = EVG_DEF_VIC_SIZE; /* (in bytes) */ int vic_am = EVG_DEF_VIC_AM; int vic_offset = EVG_DEF_VIC_OFFSET; int first_event_offset = 0; int trigger_loc_offset = EVG_DEF_TRIGGER_LOC_OFFSET; int fifo_loc = (int) NULL; int fifo_mark = (int) 0; int fifo_len = 0; int fifo_am = EVG_DEF_VIC_AM; int struct_flag = EVG_DEF_EVENT_STRUCT; unsigned int final_mask = 0; unsigned int initial_mask = 0; unsigned int trigger_number = 0; unsigned int *nv; unsigned int *ntrg; unsigned int *evptr; unsigned int *lenbuf; unsigned int *chain_ptr; unsigned int *chain_tnum; struct evlen *mm_evlen; void evg_help (void) { printf (" Usage:\n\t evg [options]\n\n Options:\n\n"); printf ("[-h]\t\tHelp\n"); printf ("[-c] nchain\tNumber of Vme chains (default = %d)\n", EVG_DEF_N_CHAIN); printf ("[-f] loc len\t%s", "Fifo location and length (in bytes - hex format)\n"); printf ("[-s] seed\tRandom seed (default = %d)\n", EVG_DEF_SEED); printf ("[-e] nev\tNumber of events in the VIC memory or fifo\n", EVG_DEF_N_MM_EVENTS); printf ("[-t] time\t%s%d%s", "Average time between generations (default = ", EVG_DEF_AVE_HTRIG_TIME, " usec)\n"); printf ("[-r] time\t%s%d%s", "Time between two write attempts on VIC (default = ", EVG_DEF_RETRY_HTRIG_TIME, " usec)\n"); printf ("[-k] time\t%s%d%s", "Average time between two triggers (default = ", EVG_DEF_AVE_KLOE_RATE, " usec)\n"); printf ("[-d] average\t%s%d%s", "Average data length (in 32 bit words, default = ", EVG_DEF_AVE_DATALEN, ")\n"); printf ("[-w] flag\t%s%s%s", "Event structure flag (w = word num. /e = event num.,", " default = e", ")\n"); printf ("[-dm] min\t%s%d%s", "Minimum data length (in 32 bit words, default = ", EVG_DEF_MIN_DATALEN, ")\n"); printf ("\n VIC options (hex format):\n\n"); printf ("[-va] add\tVIC address to map (default = 0x%x)\n", EVG_DEF_VIC_ADDRESS); printf ("[-vs] space\tVIC space to map (default = 0x%x bytes)\n", EVG_DEF_VIC_SIZE); printf ("[-vo] offs\tVIC offset from base (default = 0x%x bytes)\n", EVG_DEF_VIC_OFFSET); printf ("[-vm] mode\tVIC address modifier (default = ox%x)\n", EVG_DEF_VIC_AM); } void evg_opt (int argc, char **argv) { register int i; register int arg; int idummy; char sdummy[80]; for (arg = 1; arg < argc; arg++) if (argv[arg][0] == '-') switch (argv[arg][1]) { case 'd': if (argv[arg][2] == 'm') min_datalen = atoi (argv[++arg]); else ave_datalen = atoi (argv[++arg]); break; case 'v': switch (argv[arg][2]) { case 'a': sscanf (argv[++arg], "%x", &vic_address); break; case 's': sscanf (argv[++arg], "%x", &vic_size); break; case 'o': sscanf (argv[++arg], "%x", &vic_offset); break; case 'm': sscanf (argv[++arg], "%x", &vic_am); break; default: printf (" please select a VIC option:\n"); printf ("\t -va -vs -vo -vm\n"); exit (0); break; } break; case 'w': switch (argv[++arg][0]) { case 'e': struct_flag = EVG_EVN_EVENT_STRUCT; break; case 'w': struct_flag = EVG_WDN_EVENT_STRUCT; break; default: printf (" invalid event structure\n"); printf (" please specify :\t e/w\n"); exit (0); break; } break; case 'c': n_chain = atoi (argv[++arg]); break; case 's': seed = atoi (argv[++arg]); break; case 'e': n_mm_events = atoi (argv[++arg]); break; case 't': ave_htrigger_time = atoi (argv[++arg]); break; case 'f': sscanf (argv[++arg], "%x", &fifo_loc); sscanf (argv[++arg], "%x", &fifo_len); fifo_mark = fifo_loc + EVG_DEF_MARK_OFFS; break; case 'r': retry_htrigger_time = atoi (argv[++arg]); break; case 'k': ave_kloe_rate = atoi (argv[++arg]); break; case 'h': evg_help (); exit (0); case 'n': ++arg; break; default: printf ("invalid option: -%c\n", argv[arg][1]); break; } } void evg_delay (int us) { struct timeval tv; int status; tv.tv_sec = 0; tv.tv_usec = us; status = select( 1, 0, 0, 0, &tv ); } unsigned int evg_find_trg (unsigned int ptr) { register unsigned int i; for (i=0; i < n_mm_events ; ++i) if (evptr[i] > ptr) return i; } unsigned int evg_trigger_number (void) { register unsigned int i; register unsigned int imax = ntrg[0]; for (i=1 ; i < n_chain ; ++i) if (ntrg[i] > imax) imax = ntrg[i]; return imax; } void evg_main_loop () { register int i; int offs; int len = (int) sizeof (struct evlen); int retry; int status; int lenmod; int prev = 0; int modint = EVG_EVOFF_MOD/sizeof(int); int time_left; float factor; struct timeval t0, t1; unsigned int mask; int nev_htrigger = ave_htrigger_time/ave_kloe_rate; int n_max_retry = ave_htrigger_time/retry_htrigger_time; factor = 2.*(float)(ave_datalen - min_datalen) * (float) nev_htrigger / (float) rand_max; for (i=0 ; i < n_chain ; ++i) { lenbuf[i] = (min_datalen + EVG_NHT) * nev_htrigger + (int) (factor * (float) rand()); /* If we are not reading from fifo we have to align */ /* the lengths. */ if (!fifo_loc) { lenmod = lenbuf[i] % modint; lenbuf[i] -= lenmod; lenbuf[i] += lenmod > modint/2 ? modint : 0; } if ((int) chain_ptr[i] + lenbuf[i] < tot_len) { chain_ptr[i] += (unsigned int) lenbuf[i]; ntrg[i] = nv[i] * (unsigned int) n_mm_events + evg_find_trg (chain_ptr[i]); } else { ++nv[i]; chain_ptr[i] = 0; ntrg[i] = nv[i] * (unsigned int) n_mm_events; lenbuf[i] = tot_len - (int) chain_ptr[i]; } mm_evlen[i].fifolen = lenbuf[i]; mm_evlen[i].flag = 1; offs = vic_offset + (int) ((char *) (mm_evlen+i) - (char *) mm_evlen); VmeWrite (cid, offs, (char *) (mm_evlen+i), len); } trigger_number = evg_trigger_number (); VmeWrite (cid, trigger_loc_offset, (char *) &trigger_number, sizeof (unsigned int)); while (TRUE) { gettimeofday (&t0, (struct timezone *) 0); t1.tv_usec = t0.tv_usec + ave_htrigger_time % SEC_OVER_USEC; t1.tv_sec = t0.tv_sec + ave_htrigger_time/SEC_OVER_USEC; mask = initial_mask; retry = 0; time_left = ave_htrigger_time; for (i=0 ; i < n_chain ; ++i) { lenbuf[i] = (min_datalen + EVG_NHT) * nev_htrigger + (int) (factor * (float) rand()); /* If we are not reading from fifo we have to align */ /* the lengths. */ if (!fifo_loc) { lenmod = lenbuf[i] % modint; lenbuf[i] -= lenmod; lenbuf[i] += lenmod > modint/2 ? modint : 0; } if ((int) chain_ptr[i] + lenbuf[i] < tot_len) { chain_ptr[i] += (unsigned int) lenbuf[i]; ntrg[i] = nv[i] * (unsigned int) n_mm_events + evg_find_trg (chain_ptr[i]); } else { ++nv[i]; ntrg[i] = nv[i] * (unsigned int) n_mm_events; lenbuf[i] = tot_len - (int) chain_ptr[i]; chain_ptr[i] = 0; } } while (retry < n_max_retry && timercmp (&t1, &t0, >)) { time_left -= retry_htrigger_time; evg_delay (retry_htrigger_time); for (i=0 ; i < n_chain ; ++i) if (mask & (1 << i)) { offs = vic_offset + (int) ((char *) &(mm_evlen[i].flag) - (char *) mm_evlen); VmeRead (cid, offs, (char *) &(mm_evlen[i].flag), sizeof (int)); if (!mm_evlen[i].flag) { mm_evlen[i].fifolen = lenbuf[i]; mm_evlen[i].flag = 1; offs = vic_offset + (int) ((char *) (mm_evlen+i) - (char *) mm_evlen); VmeWrite (cid, offs, (char *) (mm_evlen+i), len); mask = mask & ~(1 << i); } } if (mask == final_mask) break; else ++retry; gettimeofday (&t0, (struct timezone *) 0); } if (mask != final_mask) { fprintf (stderr, " error : chain delay \n"); for (i=0 ; i < n_chain ; ++i) if (mask & (1 << i)) fprintf (stderr, " chain n. %d\n", i); evg_close (); exit (0); } trigger_number = evg_trigger_number(); VmeWrite (cid, trigger_loc_offset, (char *) &trigger_number, sizeof (unsigned int)); #ifdef debug if (trigger_number-(trigger_number%EVG_DEF_DEB_PRINT_INTERVAL) > prev) { printf ("trigger generated : %d\n", trigger_number); prev = trigger_number-(trigger_number%EVG_DEF_DEB_PRINT_INTERVAL); } #endif gettimeofday (&t0, (struct timezone *) 0); time_left = (t0.tv_sec - t1.tv_sec) * SEC_OVER_USEC + (t0.tv_usec - t1.tv_usec); evg_delay (time_left); } } void evg_init () { int j; int len, lenby, ierr; int count; int buf; int lastadd, size; register int i; float factor; int *vic_ptr; int *fifo_ptr; int *mark_ptr; int *len_table; /* data length for the events (in int) - to be generated */ unsigned int *ip; unsigned int *local_mm_evlen; unsigned int *pointer; unsigned int *local_mm_events; vic_offset += (trigger_loc_offset + sizeof (int)); factor = 2.*(float)(ave_datalen-min_datalen)/(float)rand_max; nv = (unsigned int *) calloc ((size_t) n_chain, sizeof (int)); ntrg = (unsigned int *) calloc ((size_t) n_chain, sizeof (int)); lenbuf = (unsigned int *) calloc ((size_t) n_chain, sizeof (int)); chain_ptr = (unsigned int *) calloc ((size_t) n_chain, sizeof (int)); chain_tnum = (unsigned int *) calloc ((size_t) n_chain, sizeof (int)); uti_vzero ((char *) nv, n_chain * (int) sizeof (unsigned int)); uti_vzero ((char *) ntrg, n_chain * (int) sizeof (unsigned int)); uti_vzero ((char *) chain_ptr, n_chain * (int) sizeof (unsigned int)); uti_vzero ((char *) chain_tnum, n_chain * (int) sizeof (unsigned int)); for (i=0 ; i < n_chain ; ++i) initial_mask = initial_mask | (1 << i); /* VME initialization */ if ((cid = VmeOpenChannel ("EventGeneratorVIC","pio")) < 0) { fprintf (stderr, " error in opening VIC vme channel\n"); exit (0); } if (fifo_loc) { if ((fcid = VmeOpenChannel ("EventGeneratorFifo","pio")) < 0) { fprintf (stderr, " error in opening fifo vme channel\n"); VmeCloseChannel (cid); exit (0); } if ((mcid = VmeOpenChannel ("EventGeneratorMark","pio")) < 0) { fprintf (stderr, " error in opening fifo mark channel\n"); VmeCloseChannel (cid); VmeCloseChannel (fcid); exit (0); } } if ((vic_ptr = (int *) VmeMapAddress (cid, vic_address, vic_size, vic_am)) == (int *) NULL) { fprintf (stderr, " error in mapping VIC\n"); evg_close (); exit (0); } if (VmeSetProperty (cid, Vme_SET_COPY_AM, vic_am) < 0) { fprintf (stderr, " error in setting access mode\n"); evg_close (); exit (0); } if (fifo_loc) { if ((fifo_ptr = (int *) VmeMapAddress (fcid, fifo_loc, fifo_len, fifo_am)) == (int *) NULL) { fprintf (stderr, " error in mapping fifo\n"); evg_close (); exit (0); } if ((mark_ptr = (int *) VmeMapAddress (mcid, fifo_mark, (int) sizeof (int), fifo_am)) == (int *) NULL) { fprintf (stderr, " error in mapping fifo mark\n"); evg_close (); exit (0); } } /* Header initialization */ len = n_chain * (int) sizeof (struct evlen) / (int) sizeof (unsigned int); lenby = n_chain * (int) sizeof (struct evlen); local_mm_evlen = (unsigned int *) calloc ((size_t) n_chain, (size_t) len); mm_evlen = (struct evlen *) local_mm_evlen; uti_vzero ((char *) local_mm_evlen, len * (int) sizeof (unsigned int)); count = VmeWrite (cid, vic_offset, (char *) local_mm_evlen, lenby); #ifdef debug fprintf (stderr, "VmeWrite: count = %d\n", count); count = VmeRead (cid, vic_offset, (char *) local_mm_evlen, lenby); fprintf (stderr, "VmeRead: count = %d\n", count); fprintf (stderr, "%d %d %d %d\n", local_mm_evlen[0], local_mm_evlen[1], local_mm_evlen[2], local_mm_evlen[3]); #endif /* Generation of event lengths */ evptr = (unsigned int *) calloc ((size_t) n_mm_events, sizeof (int)); len_table = (int *) calloc ((size_t) n_mm_events, sizeof (int)); srand (seed); first_event_offset = (vic_offset + lenby) / EVG_EVOFF_MOD; first_event_offset += EVG_EVOFF_MOD; size = fifo_loc ? fifo_len : vic_size; lastadd = fifo_loc ? 0 : first_event_offset; for (i=0 ; i < n_mm_events ; ++i) { len_table[i] = min_datalen + (int) (factor * (float) rand()); if (size > lastadd + ((len_table[i] + EVG_NHT) * sizeof (int))) { evptr[i] = tot_len; tot_len += (len_table[i] + EVG_NHT); lastadd += (len_table[i] + EVG_NHT) * sizeof (int); } else { evptr[i] = tot_len; lastadd = size; tot_len = (size - (fifo_loc ? 0 : first_event_offset)) / sizeof(int); len_table[i] = tot_len - evptr[i] - EVG_NHT; n_mm_events = ++i; fprintf (stderr, " Warning: only %d events generated by evg\n", i); break; } } /* Generation of events */ pointer = local_mm_events = (unsigned int *) calloc ((size_t) tot_len, sizeof (unsigned int)); for (j=0 ; j < n_mm_events ; ++j , ++pointer) { *pointer = 0 | (j << EVG_TRIGGER_BIT_SHIFT); if (struct_flag == EVG_EVN_EVENT_STRUCT) for (i=0 ; i < len_table[j] ; ++i) *(++pointer) = 0 | (j << EVG_DATA_BIT_SHIFT); else if (struct_flag == EVG_WDN_EVENT_STRUCT) for (i=0 ; i < len_table[j] ; ++i) *(++pointer) = 0 | (i << EVG_DATA_BIT_SHIFT); if (EVG_NHT == 3) { *(++pointer) = 0 | (len_table[j] << EVG_DATA_BIT_SHIFT); *(++pointer) = 1 << EVG_EOB_BIT_SHIFT; } else *(++pointer) = 1 << EVG_EOB_BIT_SHIFT | (len_table[j] << EVG_DATA_BIT_SHIFT); } #ifdef debug fprintf (stderr, " Events generated :\n"); for (i=0 ; i < len_table[0] + EVG_NHT ; ++i) fprintf (stderr, "%x\n", local_mm_events[i]); #endif /* Now the events have to be copied to the mirrored memory or the fifo */ if (fifo_loc) { for (i=0, ip = local_mm_events ; i < tot_len ; ++i, ++ip) count = VmeWrite (fcid, 0, (char *) ip, sizeof (int)); count = VmeRead (mcid, 0, (char *) &buf, sizeof (int)); } else { count = VmeWrite (cid, first_event_offset, (char *) local_mm_events, tot_len * sizeof(int)); } /* Init the trigger number */ count = VmeWrite (cid, trigger_loc_offset, (char *) &trigger_number, sizeof (unsigned int)); #ifdef debug count = VmeRead (cid, first_event_offset, (char *) local_mm_events, tot_len * sizeof(int)); fprintf (stderr, " VmeRead : count = %d\n", count); fprintf (stderr, " Events read from VIC :\n"); for (i=0 ; i < len_table[0]+EVG_NHT ; ++i) fprintf (stderr, "%x\n", local_mm_events[i]); count = VmeRead (cid, trigger_loc_offset, (char *) &trigger_number, sizeof(unsigned int)); fprintf (stderr, " VmeRead : count = %d\n", count); fprintf (stderr, " trigger offset = %d\n", trigger_loc_offset); fprintf (stderr, " trigger number = %d\n", trigger_number); #endif fprintf (stderr, " VIC filled up\n\t from offset %d\n\t to offset %d\n", trigger_loc_offset, fifo_loc ? vic_offset + lenby : first_event_offset + tot_len * sizeof(int)); } void evg_close () { VmeCloseChannel (cid); if (fifo_loc) { VmeCloseChannel (fcid); VmeCloseChannel (mcid); } } #ifdef program main (int argc, char **argv) { evg_opt(argc,argv); evg_init(); evg_main_loop(); evg_close(); } #endif