/* --------------------------------------------------------------------------- * Test functions for Timlet and Timrun * * Author : J.B.Lane UCL December 2000 timcode.c * --------------------------------------------------------------------------- */ #include "ask.h" #include "timlet.h" #include #include /* rand */ #include /* strcat strcpy */ #include /* ctime */ /* --------------------------------------------------------------------------- */ int check_clk (void) { int error = 0 ; int status ; status = (int)*reg_status ; if ((status & TIM_OK) == 0) { printf ("TIM_OK FAILURE: bit OFF, status %04X, delays %04X\n", status, *reg_delays) ; error = 1 ; } if ((status & SAclkON) == 0) { printf ("CLOCK FAILURE: Stand-alone clock OFF, status %04X, delays %04X\n", status, *reg_delays) ; error = 1 ; } return error ; } /* --------------------------------------------------------------------------- */ int check_TTCclk (void) { int error = 0 ; int status ; int enRun ; int TTCcmd ; status = (int)*reg_status ; enRun = (int)*reg_EnRun ; TTCcmd = (int)*reg_TTCcmd ; if ((status & TIM_OK) == 0) { printf ("TIM_OK FAILURE: bit OFF, status %04X, delays %04X\n", status, *reg_delays) ; error = 1 ; } /* if ((status & TTCclkON) == 0) { printf ("TTC clock is OFF, status %04X\n", status) ; error ++ ; } */ if (TTCcmd & TTCready) { printf("TTCrx Ready"); if (status & TTCclkON) { printf(", TTC Clock Detected, "); if (enRun & EnTTCClk) printf("and Enabled"); else printf("but not Enabled"); } printf(".\n"); } else { printf("Warning: TTCrx Not Ready. status %04x, enRun %04x, TTCcmd %04x.\n", status, enRun, TTCcmd); if ((enRun & EnTTCClk) == 1) printf("CLOCK FAILURE: TTC Clock Enabled, but OFF!\n"); error = 1; } return error ; } /* --------------------------------------------------------------------------- */ int checkBCID (const int outmask, const int next) { static int lastBCID = NONE ; int error = 0 ; int bcid ; bcid = *reg_BCid & 0xFFF ; if (lastBCID == NONE) lastBCID = 0 ; /* bcid ; ***/ if (outmask == 0) ; /***/ else if (outmask & L1A) { if (next != NONE) error += timCheck ("checkBCID: post L1A: (bcid, want)", bcid, next) ; else if (next == NONE && bcid == lastBCID) /* actually it's allowed */ { error = 0 ; printf ("Info: checkBCID: post L1A, BCIDs equal: bcid %04X\n", bcid) ; } } else error += timCheck ("checkBCID: post (bcid, want)", bcid, lastBCID) ; if (outmask != PresetNextL1ID) lastBCID = bcid ; return error ; } /* --------------------------------------------------------------------------- */ int checkID (const int outmask, const int next) { int error = 0 ; error += checkL1ID (outmask, next) ; error += checkBCID (outmask, next) ; return error ; } /* --------------------------------------------------------------------------- */ int checkL1ID (const int outmask, const int next) { static int lastL1ID = NONE ; static int nextL1ID = NONE ; /* value depends on when last reset */ int error = 0 ; int l1id ; l1id = timGetL1ID( *reg_L1lo, *reg_L1hi ) ; if (lastL1ID == NONE) /* Setup at first time called */ lastL1ID = l1id ; if (outmask == PresetNextL1ID) nextL1ID = next ; else if (outmask & ECR) { /* test if ECR resets L1ID */ /* from v9 still last trig, reset next trig... *** test this and ECR counter *** */ if (timVersion < 9) error += timCheck ("checkID: post ECR, L1ID non-zero: l1id=", l1id, 0) ; else error += timCheck ("checkID: post ECR, LIID value unexpected: (l1id, want)=", l1id, lastL1ID) ; nextL1ID = TIM_FIRST_L1ID ; } else if (outmask & L1A) { /* test if L1A increments L1ID */ error += timCheck ("checkID: post L1A, LIID value unexpected: (l1id, want)=", l1id, nextL1ID) ; nextL1ID = (l1id + 1) & 0xFFFFFF ; } else { error += timCheck ("checkID: post non-ECR/L1A, L1ID changed: (l1id, want)=", l1id, lastL1ID) ; } lastL1ID = l1id ; return error ; } /* --------------------------------------------------------------------------- */ void dump16 (char *string, volatile const unsigned short *array, const int words) { int i, n ; printf ("%s\n", string) ; n = words ; if (n > 16) n = 16 ; for (i = 0 ; i < n ; i++) printf ("%4X ", array[i]) ; printf ("\n") ; } /* --------------------------------------------------------------------------- */ void report_errors (char *name, int error_count) { printf ("%s test: ", name) ; if (error_count != 0) printf ("Fail -- 0x%0x (%d) errors\n", error_count, error_count) ; else printf ("Pass\n") ; } /* --------------------------------------------------------------------------- * Test a block of memory */ int test_block (volatile unsigned short *memory_ptr, unsigned int buffer[], const int nwords, const int loop, const int nmasks, const unsigned short masks[]) { static unsigned int seed = 0 ; unsigned int pattern ; unsigned int word_read ; int iword ; int imask ; int error_count = 0 ; int i ; srand (seed) ; /* Fill memory block with random pattern */ for (i = 0 ; i < nwords ; i++) { if (loop == 0) iword = i ; else iword = rand () % nwords ; imask = iword % nmasks ; pattern = rand () ; buffer [iword] = pattern ; memory_ptr[iword] = pattern & masks[imask] ; word_read = (int)memory_ptr[iword] & masks[imask] ; if (word_read != (pattern & masks[imask])) { error_count++ ; printf ("wrote %04X, read %04X, byte %x loop %d mask %04x\n", pattern, word_read, 2*iword, loop, masks[imask]) ; } } /* Regenerate same pattern and compare */ for (iword = 0 ; iword < nwords ; iword++) { imask = iword % nmasks ; pattern = buffer[iword] ; word_read = (int)memory_ptr[iword] & masks[imask] ; if (word_read != (pattern & masks[imask])) { error_count++ ; printf ("wrote %04X, read %04X, byte %x loop %d\n", pattern, word_read, 2*iword, loop) ; } } seed = pattern ; return (error_count) ; } /* --------------------------------------------------------------------------- */ int test_loop ( char* name, int (*test_func) (const int), int loops, int reset_level, int soak_loop ) { int error_count = 0 ; int jloop = loops * soak_loop ; int nloops = loops ; int r ; int i ; char string[99] ; if (reset_level > 1) { timReset(Quiet) ; } if (soak_loop < 0) { (void) strcpy(string, name) ; (void) strcat(string," test: Enter number of loops") ; r = ask_int(string, nloops, &nloops) ; jloop = 0 ; } for (i = 0 ; i < nloops ; i ++ ) { error_count += (*test_func) (i + jloop) ; } if (soak_loop < 0) { report_errors (name, error_count) ; } return error_count ; } /* --------------------------------------------------------------------------- */ int test_sink (unsigned int buffer[], const int RamWords, const int SeqWords) /* assumes buffer and RAM are ready */ { unsigned int output ; unsigned int pattern ; unsigned int word_read ; int i ; int error_count = 0 ; /* cmd LEDs flash during VME access if output enabled */ /* initial junk data could be set to 0 but it's not in RAM */ /* printf ("RamWords %04X SeqEnd %04X\n", RamWords, *reg_seq_end) ; dump16 ("RAM contents:", ram_ptr+0x3F00/2, 16) ; ram_ptr[SeqWords] = 0 ; buffer [SeqWords] = 0 ; printf ("RAM word %04X\n", ram_ptr[8]) ; */ output = 0 ; *reg_output = 0 ; /* reset */ timRunSeq (SeqWords) ; error_count += check_clk () ; timWait_seqBusys () ; /* wait for busy bits to clear */ for (i = 0 ; i < SeqWords ; i ++ ) { pattern = buffer[i] & 0xFF ; /* source */ buffer[i] = pattern + (pattern << 8) ; /* sink */ output = output | pattern ; } for (i = 0 ; i < RamWords ; i ++ ) { pattern = buffer[i] ; word_read = ram_ptr[i] ; if (word_read != (pattern & 0xffff)) { error_count++ ; printf ("test_sink: wrote %04X, read %04X, byte %x\n", pattern, word_read, 2*i) ; } } if (output != *reg_output) /* no &FF */ { error_count++ ; printf ("test_sink: reg_output %04X, want %04X, SeqWords %04X\n", *reg_output, output, SeqWords) ; } return error_count ; } /* --------------------------------------------------------------------------- */ int timCheck (const char *string, const int word1, const int word2) { int error = 0 ; if (word1 != word2) { printf("ERROR: %s diff (%06x, %06x, %6d)\n", string, word1, word2, word1-word2) ; error = 1 ; } return error ; } /* --------------------------------------------------------------------------- */ int timGetL1ID(const int lo, const int hi) { int l1id ; if (timVersion < 9) l1id = (lo & 0xFFF) + ((hi & 0xFFF) << 12) ; else l1id = (lo & 0xFFFF) + ((hi & 0xFF) << 16) ; return l1id ; } /* --------------------------------------------------------------------------- */ int timGetTIMid(void) { int timID, timSer, lo, hi ; time_t tp ; timID = *reg_TIMid ; timSer = timID & 0xFF ; timVersion = timID >> 8 ; printf ("\nTIM Serial No. %2X Version %2X\n", timSer, timVersion) ; if (timSer >= TIMID_FPGA) /* FPGA synthesis timestamps */ { timVersion += 0x300 ; lo = memory_ptr[ 0x14A / 2 ] ; /* timestamp lo */ hi = memory_ptr[ 0x14C / 2 ] ; /* timestamp hi */ tp = (lo & 0xFFFF) + ((hi & 0xFFFF) << 16) ; printf ("FPGA1 %s", ctime(&tp)) ; lo = memory_ptr[ 0x7C / 2 ] ; /* 37. timestamp lo */ hi = memory_ptr[ 0x7E / 2 ] ; /* 38. timestamp hi */ tp = (lo & 0xFFFF) + ((hi & 0xFFFF) << 16) ; printf ("FPGA2 %s", ctime(&tp)) ; } printf ("\n") ; if (timVersion < 9) TIM_FIRST_L1ID = 1 ; else TIM_FIRST_L1ID = 0 ; return timID ; } /* --------------------------------------------------------------------------- */ void timReset (const int noise) { /* Reset needs to wait longer ... * The TTCrx takes 50ms? to reset! */ static int foundTTCrx = 1; int timedout = 0; unsigned short reg; *reg_command = 0xFFFF; /* VReset */ reg = *reg_command; /* printf ("command reg %04X\n", reg); */ if (noise == Loud) printf("--- TIM VReset ---\n"); if (noise == Quiet) printf("VReset\n"); timedout = wait_state_timeout(reg_command, VMEreset, 0); if (timedout != 0) printf("timReset timeout on VMEreset\n"); if (foundTTCrx) { timedout = wait_state_timeout(reg_TTCcmd, TTCready, TTCready); if (timedout != 0) foundTTCrx = 0; if (noise >= Quiet) { if (timedout != 0) printf("timReset timeout on TTCReady\n"); } } (void) checkID (PresetNextL1ID, TIM_FIRST_L1ID); } /* --------------------------------------------------------------------------- */ void timRunSeq (const int Size) { *reg_enables = 0 ; /* ensure no other signals enabled */ *reg_command = 0 ; /* VME mode */ *reg_EnRun = 0 ; /* VME mode */ timSetupSeq (0x40FF, Size) ; /* Sink/SeqGO + all outputs enabled */ } /* --------------------------------------------------------------------------- */ void timSetupPtr (void) { /* pointer offsets are 16-bit words */ reg_srcAddr = memory_ptr + 0x74 / 2 ; reg_snkAddr = memory_ptr + 0x76 / 2 ; reg_enables = memory_ptr + 0 ; reg_command = memory_ptr + 1 ; reg_burst = memory_ptr + 2 ; reg_freqncy = memory_ptr + 3 ; reg_window = memory_ptr + 4 ; reg_delays = memory_ptr + 5 ; reg_status = memory_ptr + 6 ; reg_FIFO = memory_ptr + 7 ; reg_L1lo = memory_ptr + 8 ; reg_L1hi = memory_ptr + 9 ; reg_BCid = memory_ptr + 10 ; reg_TTid = memory_ptr + 11 ; reg_EnRun = memory_ptr + 12 ; reg_sequenc = memory_ptr + 13 ; reg_seq_end = memory_ptr + 14 ; reg_RODmask = memory_ptr + 15 ; reg_RODbusy = memory_ptr + 16 ; reg_RODheld = memory_ptr + 17 ; reg_RODmoni = memory_ptr + 18 ; reg_TTCdata = memory_ptr + 19 ; reg_TTCsel = memory_ptr + 20 ; reg_BCin = memory_ptr + 21 ; reg_TTCrx = memory_ptr + 22 ; reg_TTCcmd = memory_ptr + 23 ; reg_output = memory_ptr + 24 ; reg_TIMid = memory_ptr + 25 ; } /* --------------------------------------------------------------------------- */ void timSetupRun (void) { *reg_enables = 0 ; /* ensure no other signals en */ *reg_command = RunMode ; *reg_EnRun = 0x07FF ; /* enable TTC signals and eventID strobes */ } /* --------------------------------------------------------------------------- */ void timSetupSeq (const int Mask, const int Size) { *reg_seq_end = Size - 1 ; *reg_sequenc = 0x2200 ; /* seq reset. NEEDED. cures "write" errors? needed for new data errors! */ *reg_sequenc = 0 ; /* is this needed? */ *reg_sequenc = Mask ; } /* --------------------------------------------------------------------------- */ void timSetupVME (void) { *reg_enables = 0 ; /* ensure no other signals en */ *reg_command = 0 ; *reg_EnRun = (EnID | EnTType) ; /* enable eventID/TType strobes */ } /* --------------------------------------------------------------------------- */ void timWait_seqBusys (void) { int i ; for (i = 0 ; ((int)*reg_status & (SeqBUSY | SinkBUSY)) != 0 && i < 999 ; i ++) ; if (i >= 999) printf ("timWait_seqBusys: status %04X i %d\n", *reg_status, i) ; } /* --------------------------------------------------------------------------- */ void wait (void) { printf ("Press RETURN to continue :") ; (void) getchar() ; printf ("\n") ; } /* --------------------------------------------------------------------------- */ int wait_state_timeout (volatile unsigned short * reg, const int mask1, const int mask2) { int errors = 0; int timeout = 0x1FFFF; /* set timeout here, was 0xFFFF */ int time_remaining = timeout; int state; state = (int)*reg & mask1; while ((time_remaining > 0) && (state != mask2)) { state = (int)*reg & mask1; time_remaining--; } if (time_remaining < 1) { errors = 1; /* Error print out generated by caller... */ printf ("ERROR: Wait State TIMEOUT. reg %04X, timeout %d\n", *reg, timeout); } else if (debug_level < 0 && timeout - time_remaining > 1) printf("debug: wait_state_timeout: wait loops %5d, reg %04x.\n", (timeout - time_remaining), (*reg)); return errors; } /* --------------------------------------------------------------------------- void wait_state (volatile unsigned short * reg, const int mask1, const int mask2) { int i = 0 ; while (((int)*reg & mask1) != mask2) { i++ ; if ((i & 0x3FFFFF) == 0) printf ("wait_state: register %04X\n", *reg) ; } printf ("wait_state: wait loops %X\n", i) ; } */