/* --------------------------------------------------------------------------- * Soak test program for TIM standalone * * Author : J.B.Lane UCL September 2000 timlet.c * --------------------------------------------------------------------------- */ /* ox9 PLD firmware is CVS v1.30 14Oct02 */ #include "ask.h" #include "timlet.h" #define TIM_CMD_SIZE 100 /* 37 too small, 50 too small by 1 */ #define REGISTER_WORDS 26 static int reset_level = 0 ; static int timID ; const static unsigned short RAM_mask[1] = {0xFFFF} ; /* NB some regs < 16 bits */ /* Not const as reg_rst_vals can change depending whether TTCrx * is present. In particular: 0c(stat) and 2e(ttc) * Maybe document that TTC functions take AGES to reset (50us?) * Changed 00 to 0000 (no EnIntClk), 0c --> 0b80 (rodbusy in SAmode) */ static unsigned short reg_rst_vals[REGISTER_WORDS] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2A80, 0x4040, 0xFFFF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000} ; /* 0:0 2:1 4:2 6:3 8:4 a:5 c:6 e:7 * 10:8 12:9 14:10 16:11 18:12 1a:13 1c:14 1e:15 * 20:16 22:17 24:18 26:19 28:20 2a:21 2c:22 2e:23 */ const static unsigned short reg_rd_masks[REGISTER_WORDS] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xD9FE, 0xFFFF, 0x0000} ; static unsigned short reg_wr_masks[REGISTER_WORDS] = /* * need to turn off all sources of ECR & L1A for L1ID ... *** * {0xFFFF, 0x6FFF, ... ... 0xFFFF, 0xFFFF, ... */ {0xFF00, 0x6F00, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0x00FF, 0xF000, 0x03FF, 0x7FE0, 0xFFF0, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x0000, 0x7FFF, 0x0000, 0x0000, 0x0000} ; /* 0 1 2 3 4 5 6 7 * 8 9 10 11 12 13 14 15 * 16 17 18 19 20 21 22 23 */ unsigned int buffer[TIM_RAM_SIZE] ; void timlet (void) ; int test_bcid (const int) ; int test_brst (const int) ; int test_clk (const int) ; int test_cmd (const int) ; int test_l1id (const int) ; int test_ram (const int) ; int test_reg (const int) ; int test_rst (const int) ; int test_seq (const int) ; int test_ser (const int) ; int test_veto (const int) ; int test_burst (const int, const int, const int, const int) ; int test_cmdbit (const int, const int) ; int test_cmdsink (const int, const int) ; void test_seqalls (void) ; int test_seqbits (void) ; int test_seqcmd (const int) ; int test_seqcmds (void) ; void test_set (void) ; int main (void) { memory_ptr = ask_vme (0x10000) ; ram_ptr = memory_ptr + TIM_RAM_SIZE ; /* offset is 16-bit words */ if (memory_ptr != NULL) timlet () ; else printf ("Error opening VME window\n") ; vme_end () ; return (0) ; } /* --------------------------------------------------------------------------- */ void timlet (void) { int error_count = 0 ; int errors = 0 ; int nloops, loop, i ; (void) ask_int("ALL test: Enter number of loops", 1, &nloops) ; test_set() ; check_clk() ; check_TTCclk() ; for (i = 0 ; i < nloops ; i ++ ) { errors = 0 ; loop = i ; if (nloops == 1) loop = -1 ; if (reset_level > 0) timReset(Quiet) ; errors += test_loop( "RST", test_rst, 3, reset_level, loop ) ; errors += test_loop( "CLK", test_clk, 1, reset_level, loop ) ; errors += test_loop( "REG", test_reg, 3, reset_level, loop ) ; errors += test_loop( "RAM", test_ram, 2, reset_level, loop ) ; errors += test_loop( "SEQ", test_seq, 2, reset_level, loop ) ; /* after ram */ errors += test_loop( "L1ID", test_l1id, 3, reset_level, loop ) ; errors += test_loop( "BCID", test_bcid, 3, reset_level, loop ) ; errors += test_loop( "SER", test_ser, 3, reset_level, loop ) ; errors += test_loop( "CMD", test_cmd, 3, reset_level, loop ) ; errors += test_loop( "BRST", test_brst, 3, reset_level, loop ) ; if (timID >= TIMID_FPGA) { errors += test_loop( "VETO", test_veto, 1, reset_level, loop ) ; } if (errors > 0) { printf ("ERRORS in loop %d ", loop) ; report_errors ("ALL", errors) ; } error_count += errors ; } test_seqalls () ; report_errors ("ALL", error_count) ; } /* --------------------------------------------------------------------------- */ int test_bcid (const int loop) { int error_count = 0 ; int ioff ; for (ioff = 0 ; ioff < 16 ; ioff ++ ) { *reg_BCid = ioff << 12 ; error_count += test_seqcmd (L1A) ; } return error_count ; } /* --------------------------------------------------------------------------- */ int test_brst (const int loop) { int burst_count = 7 ; int error_count = 0 ; timSetupVME() ; /* set reg_freqncy and reg_delays */ *reg_freqncy = 0 ; /* clear random value */ *reg_delays = loop % 0x90 ; /* max delay is 8F */ if (loop == 3) *reg_delays = 0x8F ; error_count += test_burst (burst_count, 2, 0, 0) ; /* int trigger burst */ error_count += test_burst (burst_count, 0, VCAL, CAL) ; /* CAL burst */ return error_count ; } /* --------------------------------------------------------------------------- */ int test_burst (const int burst_count, const int enables, const int cmdmask, const int outmask) { int error_count = 0 ; *reg_enables = enables ; /* input signals */ *reg_burst = burst_count ; /* set number of triggers in burst */ *reg_command = 0x0200 ; /* set vBurstMode bit */ *reg_L1lo = 0xFFFF ; /* extra F for new 16-bit register */ *reg_L1hi = 0x00FF ; /* reset L1ID */ timWait_seqBusys () ; /* why is this needed !!! ? ***/ /*** try longer timeout */ timSetupSeq (0x8000, TIM_RAM_SIZE) ; *reg_output = 0 ; *reg_command = 0x0600 ; /* set vBurstGo (leaving vBurstMode set) */ *reg_command = 0x0600 | cmdmask ; /* maybe generate a CAL: set vCAL bit */ /* Poll the BurstBUSY Status bit until the burst is done */ if (wait_state_timeout(reg_status, 0x0010, 0x0000) == 1) { printf("BRST: cmd %04x BurstBusy TIMEOUT: reg_status %04x, mask %04x delay %04x.\n", cmdmask, *reg_status, 0x0010, *reg_delays) ; error_count ++ ; } timWait_seqBusys () ; /* avoid events in sink from last time */ *reg_sequenc = 0x0000 ; *reg_enables = 0x0000 ; /* disable all input signals */ if (debug_level > 0) printf ("L1ID %06X, BCid %03X\n", timGetL1ID(*reg_L1lo, *reg_L1hi), *reg_BCid) ; *reg_command = 0x0000 ; /* clear vBurstMode and vBurstGo */ (void) checkID (PresetNextL1ID, burst_count-1) ; /* reset */ error_count += checkID (TRG | outmask, NONE) ; error_count += timCheck ("BRST: reg_output want", *reg_output, TRG | outmask) ; if (debug_level > 0) timDump (TIM_RAM_SIZE, 1) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_clk (const int loop) { int error_count = 0 ; int i ; for (i = 0 ; i < 0x40 ; i ++) { *reg_delays = i << 8 ; error_count += check_clk () ; } return error_count ; } /* --------------------------------------------------------------------------- */ int test_cmd (const int loop) { int error_count = 0 ; timSetupVME() ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VECR, ECR) ; /* ECR resets L1ID */ error_count += test_cmdbit (VBCR, BCR) ; error_count += test_cmdbit (VFER, FER) ; error_count += test_cmdbit (VSPA, SPA) ; error_count += test_cmdbit (VCAL, CAL | TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; error_count += test_cmdbit (VTRG, TRG) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_cmdbit (const int cmdmask, const int outmask) { int error = 0 ; *reg_output = 0 ; /* reset */ *reg_command = 0 ; /* clear for repeated edge command */ *reg_command = cmdmask ; if (wait_state_timeout(reg_status, IntBusy, 0x0000) == 1) { printf("CMD: IntBusy TIMEOUT: reg_output %02x, want %02x.\n", *reg_output, outmask) ; error = 1 ; } else /* wait for command to complete, especially CAL */ { if (wait_state_timeout(reg_output, outmask, outmask) == 1) printf("CMD: output TIMEOUT: reg_output %02x, want %02x.\n", *reg_output, outmask) ; error = checkID (outmask, NONE) ; error += timCheck ("CMD : reg_output want", *reg_output, outmask) ; } if (debug_level > 2) printf ("test_cmdbit: cmdmask %02x, outmask %02X, L1ID %06X, BCid %03X\n", cmdmask, outmask, timGetL1ID(*reg_L1lo, *reg_L1hi), *reg_BCid) ; return error ; } /* --------------------------------------------------------------------------- */ int test_cmdsink (const int cmdmask, const int outmask) { int delay, error = 0 ; int indexL1A ; int size ; delay = (*reg_delays & 0xFF) + 4 ; /* max delay is 8F */ size = TIM_CMD_SIZE + delay ; if (cmdmask == VCAL) size = TIM_RAM_SIZE ; timSetupSeq (0x8000, size) ; if (debug_level > 0 && timID >= TIMID_FPGA) { printf ("test_cmdsink: src addr %04X, snk addr %04X\n", *reg_srcAddr, *reg_snkAddr) ; } /* how do we tell if seq didn't run ***/ if (cmdmask == VCAL && timID < TIMID_FPGA) { error += test_cmdbit (VTRG, TRG) ; } error += test_cmdbit (cmdmask, outmask) ; if (debug_level > 0 && timID >= TIMID_FPGA) { printf ("test_cmdsink: src addr %04X, snk addr %04X\n", *reg_srcAddr, *reg_snkAddr) ; } if (error == 0) { error += checkSink (size, NONE, &indexL1A) ; if (cmdmask == VTRG) error += timCheck ("SINK:(scan,delay)", indexL1A, delay) ; if (error != 0) printf ("test_cmdsink scan errors: cmdmask %02x, outmask %02X, delays %04X\n", cmdmask, outmask, *reg_delays) ; } if (debug_level > 0) { printf ("test_cmdsink: src addr %04X, snk addr %04X\n", *reg_srcAddr, *reg_snkAddr) ; timDump (size, 1) ; } return error ; } /* --------------------------------------------------------------------------- */ int test_l1id (const int loop) { int error_count = 0 ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VECR, ECR) ; /* ECR resets L1ID */ error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; if (debug_level > 2) printf("\nDEBUG: Run A - mid roll over\n") ; (void) checkID (PresetNextL1ID, 0x000FFE) ; /* reset */ *reg_L1lo = 0x0FFD ; /* order affected result! */ *reg_L1hi = 0 ; if (debug_level > 2) printf("DEBUG: Starting at l1id %06x.\n", timGetL1ID(*reg_L1lo, *reg_L1hi)) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; if (debug_level > 2) printf("\nRun 2 - full roll over\n") ; (void) checkID (PresetNextL1ID, 0xFFFFFE) ; /* reset */ *reg_L1hi = 0x0FFF ; /* order affected result! */ *reg_L1lo = 0xFFFD ; /* extra F for new 16-bit register */ if (debug_level > 2) printf("Starting at l1id %06x.\n", timGetL1ID(*reg_L1lo, *reg_L1hi)) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; error_count += test_cmdbit (VTRG, L1A) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_ram (const int loop) { unsigned int error_count ; int i ; if (debug_level > 1) dump16 ("RAM contents:", ram_ptr, 16) ; *reg_sequenc = 0x2200 ; /* reset - otherwise sink can overwrite - new here */ for (i = 0 ; i < TIM_RAM_SIZE ; i++) buffer[i] = ram_ptr[i] ; /* RAM values have changed */ error_count = test_block (ram_ptr, buffer, TIM_RAM_SIZE, loop, 1, RAM_mask) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_reg (const int loop) { unsigned int error_count ; int i ; /* address and size of RAM block to test */ if (debug_level > 0) { printf ("Testing %dd registers\n", REGISTER_WORDS) ; dump16 ("Register mask contents:", reg_wr_masks, REGISTER_WORDS) ; dump16 ("Register contents:", memory_ptr, REGISTER_WORDS) ; } *reg_command = 0 ; /* cmd reg esp runmode */ *reg_sequenc = 0x2200 ; /* reset - otherwise sink can overwrite */ for (i = 0 ; i < REGISTER_WORDS ; i++) buffer[i] = memory_ptr[i] ; /* register values have changed */ error_count = test_block (memory_ptr, buffer, REGISTER_WORDS, loop, REGISTER_WORDS, reg_wr_masks) ; timReset(Silent) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_rst (const int loop) { /* Change masks for reg c:0A00->0B00, 2e: 0000->4000 * These are c:TTCClkOn bit, 2e:TTCready bit * * BCR from TTC */ int error_count = 0 ; unsigned short word_read ; int i ; if (timVersion < 9) { reg_wr_masks[ 8] = 0x0FFF; reg_rst_vals[ 8] = 0x0000; reg_rst_vals[ 9] = 0x0000; } if (*reg_TTCcmd & TTCready) { reg_rst_vals[23] |= TTCready; } else { reg_rst_vals[22] |= *reg_TTCrx & 0x8000; } /* else if (timVersion > 7) { reg_rst_vals[21] = 0x0FFF; reg_rst_vals[23] = 0x3FFF; } */ if (*reg_status & TTCclkON) { reg_rst_vals[ 6] |= TTCclkON; } timReset(Silent); for (i = 0 ; i < REGISTER_WORDS ; i ++) { word_read = memory_ptr[i] ; if ((word_read & reg_rd_masks[i]) != (reg_rst_vals[i] & reg_rd_masks[i])) { printf ("read %04X, mask %04X, want %04X, byte %x, loop %d\n", word_read, reg_rd_masks[i], reg_rst_vals[i], 2*i, loop) ; error_count ++ ; } } return error_count ; } /* --------------------------------------------------------------------------- */ int test_seq (const int loop) { unsigned int error_count = 0 ; timSetupVME() ; /* ensure sequencer is off - is it needed? */ if (debug_level > 1) dump16 ("RAM contents:", ram_ptr, 16) ; /* ram_ptr[0] = 0x00ff ; buffer [0] = 0x00ff ; timReset(Quiet) ; */ error_count += test_sink (buffer, TIM_RAM_SIZE, TIM_RAM_SIZE / 2) ; error_count += test_seqbits () ; error_count += test_seqcmds () ; /* moved out of loop for byte zero testing */ return error_count ; } /* --------------------------------------------------------------------------- */ void test_seqalls (void) { int rods, slot, i ; int error_count = 0 ; for (i = 0 ; i < TIM_CMD_SIZE ; i ++ ) { buffer [i] = 0 ; ram_ptr[i] = 0 ; } buffer [1] = 0xFF ; ram_ptr[1] = 0xFF ; /* 0 now gives sink error */ buffer [2] = 0x80 ; ram_ptr[2] = 0x80 ; error_count += test_sink (buffer, TIM_CMD_SIZE + 1, TIM_CMD_SIZE) ; report_errors ("SEQall", error_count) ; /* leave all seq cmds running */ *reg_RODheld = 0 ; /* reset */ *reg_sequenc = 0 ; /* is this needed? YES it is! */ *reg_sequenc = 0x4cFF ; /* cycling gives errors beyond end */ rods = *reg_RODheld ; if (rods == 0) printf ("No ROD BUSY found\n") ; else { for (i = 0 ; i < 16 ; i ++ ) { if (rods & 01) { slot = i + 5 ; if (slot > 12) slot ++ ; printf ("ROD BUSY found at bit %2d, slot %2d\n", i, slot) ; } rods >>= 1 ; } } } /* --------------------------------------------------------------------------- */ int test_seqbits (void) { /* Fill memory with pattern */ int ibit ; int i ; int error_count = 0 ; for (ibit = 0 ; ibit < 8 ; ibit++) { for (i = 0 ; i < TIM_CMD_SIZE ; i ++ ) { buffer [i] = 0 ; ram_ptr[i] = 0 ; } buffer [TIM_CMD_SIZE] = 1 << ibit ; ram_ptr[TIM_CMD_SIZE] = 1 << ibit ; error_count += test_sink (buffer, TIM_CMD_SIZE + 1, TIM_CMD_SIZE) ; } *reg_command = 0 ; /* clear for repeated edge command */ *reg_command = VECR ; (void) checkID (PresetNextL1ID, 0) ; /* reset */ return error_count ; } /* --------------------------------------------------------------------------- */ int test_seqcmd (const int mask) { int i, ioff, bcid ; int jump, jBCR, jCMD ; int error_count ; jump = 18 ; /* bigger than BCID offset avoids negative BCIDs */ jBCR = 1 ; /* 0 now gives sink error */ jCMD = jump + jBCR ; *reg_sequenc = 0 ; /* write generates commands if enabled */ if (debug_level > 2) printf ("test_seqcmd: mask %02X, L1lo %03X.\n", mask, *reg_L1lo) ; for (i = 0 ; i < TIM_CMD_SIZE + jCMD ; i ++ ) { buffer [i] = 0 ; ram_ptr[i] = 0 ; } buffer [jBCR] = BCR ; ram_ptr[jBCR] = BCR ; buffer [jCMD] = mask ; ram_ptr[jCMD] = mask ; if (debug_level > 2) printf ("test_seqcmd: mask %02X, L1lo %03X.\n", mask, *reg_L1lo) ; error_count = test_sink (buffer, TIM_CMD_SIZE + 1, TIM_CMD_SIZE) ; /*** when does bcid fail? relationship with neg value? delayed BCR must be after L1A */ ioff = *reg_BCid >> 12 ; bcid = (jump - ioff + 0x1000) % 0x1000 ; if (timID < TIMID_FPGA) bcid -- ; /* -1 for PLD ox9 */ error_count += checkID (mask, bcid) ; if (debug_level > 2) printf ("test_seqcmd: mask %02X, L1lo %03X, BCid %03X.\n", mask, *reg_L1lo, *reg_BCid) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_seqcmds (void) { int error_count = 0 ; error_count += test_seqcmd (L1A) ; error_count += test_seqcmd (L1A) ; error_count += test_seqcmd (ECR) ; error_count += test_seqcmd (L1A) ; error_count += test_seqcmd (L1A) ; if (debug_level > 2) timDump (TIM_CMD_SIZE, 1) ; return error_count ; } /* --------------------------------------------------------------------------- */ int test_ser (const int loop) { int error_count = 0 ; timSetupVME() ; *reg_TTid = loop ; *reg_delays = loop % 0x90 ; /* max delay is 8F */ if (loop == 1) *reg_delays = 0x10 ; if (loop == 2) *reg_delays = 0x8F ; error_count += test_cmdsink (VTRG, TRG) ; error_count += test_cmdsink (VCAL, CAL | TRG) ; *reg_delays = 0 ; return error_count ; } /* --------------------------------------------------------------------------- */ void test_set (void) { debug_level = 0 ; (void) ask_int ("Enter debug level", debug_level, &debug_level) ; (void) ask_int ("Enter reset level", reset_level, &reset_level) ; #ifdef __alpha printf ("long %ld int %ld short %ld char %ld bytes\n", #else printf ("long %d int %d short %d char %d bytes\n", #endif sizeof(long), sizeof(int), sizeof(short), sizeof(char)) ; timSetupPtr () ; timReset(Loud) ; timID = timGetTIMid() & 0xFF ; } /* --------------------------------------------------------------------------- */ int test_veto (const int loop) { int burst_count = 100 ; int errors = 0 ; int status, veto_count, busy_count ; timSetupVME() ; *reg_freqncy = 1 ; /* 60kHz */ *reg_delays = loop % 0x90 ; /* max delay is 8F */ memory_ptr[ 0x40 / 2 ] = 1 ; /* Enable Veto */ errors += test_burst (burst_count, 0x02, 0, 0) ; /* fixed */ status = memory_ptr[ 0x44 / 2 ] ; /* Status */ veto_count = memory_ptr[ 0x54 / 2 ] ; /* Veto count lo */ busy_count = memory_ptr[ 0x6C / 2 ] ; /* Busy count lo */ printf ("fixed : status %04X, veto_count %d, busy_count %d\n", status, veto_count, busy_count) ; errors += test_burst (burst_count, 0x12, 0, 0) ; /* random */ status = memory_ptr[ 0x44 / 2 ] ; /* Status */ veto_count = memory_ptr[ 0x54 / 2 ] ; /* Veto count lo */ busy_count = memory_ptr[ 0x6C / 2 ] ; /* Busy count lo */ printf ("random: status %04X, veto_count %d, busy_count %d\n", status, veto_count, busy_count) ; return errors ; }