;############################################################################## ;# ;# Rudimentary Readout Program for TRAP3 chip ;# ;# Marcus Gutfleisch ;# Universitaet Heidelberg, Kirchhoff-Institut fuer Physik ;# ;# -- last modified: 17:01 / 31-Jan-2006 / V.Angelov ;# ;############################################################################## #inc ;############################################################################## ;# ;# defines ;# ;############################################################################## ; for I2C and JTAG #def srv_command = 0xF0E0 #def srv_indata = 0xF0E1 #def srv_outdata = 0xF0F0 #def endsig_tr = g14 ; end signature for tracklet readout #def endsig_rr = g15 ; end signature for raw data readout #def nsamples = c13 ; number of ADC samples per pad #def ChipPOS = c14 ; Chip Position for Header #def CHIP_ID_EXT = c14 ; Chip Position for Header (NEW PROGRAM) #def EventHeader = c9 ; Readout Board Header (CPU0) #def EHchip = 44 ; Event Header sending chip #def EventCounter = c12 ; event counter #def EvtCtrGIOAdr = 0xC04 ; Address of Event Counter in GIO #def NI_tmsn_delay = c11 ; programmable network interface readout delay, cpu3 only! #def ReadoutFlag = c15 ; bit1: NI readout enable ; bit0: SCSN readout enable #def rstack = r8 ; program counter stack (depth=1) #def rio = r14 ; local I/O auto incrementer register #ifdef cpu0 #def clk_onoff = CPU0SS ; own clock #def clk_onoff_next = CPU2SS ; for delayed start of partner CPU #def LSBdata = 0x03 ; LSBs for data transfer words #def AddrSCdata = 0xF000 ; Address in GIO to store the ADC data for SCSN readout #endif #ifdef cpu1 #def clk_onoff = CPU1SS ; own clock #def clk_onoff_next = CPU3SS ; for delayed start of partner CPU #def LSBdata = 0x02 ; LSBs for data transfer words #def AddrSCdata = 0xF040 ; Address in GIO to store the ADC data for SCSN readout #endif #ifdef cpu2 #def clk_onoff = CPU2SS ; own clock #def LSBdata = 0x03 ; LSBs for data transfer words #def AddrSCdata = 0xF080 ; Address in GIO to store the ADC data for SCSN readout #endif #ifdef cpu3 #def clk_onoff = CPU3SS ; own clock #def LSBdata = 0x02 ; LSBs for data transfer words #def AddrSCdata = 0xF0C0 ; Address in GIO to store the ADC data for SCSN readout #endif ;############################################################################## ;# ;# 0x000: Infinite Loop at Instruction Memory Reset Address ;# ;############################################################################## ORG 0x0; lpw: nop nop nop ; low power mov 0, r0 sgio r0, clk_onoff jmpr cc_uncond, 0 nop ;############################################################################## ;# ;# 0x100: Interrupt Clear Jump Address ;# ;############################################################################## ORG 0x100; clr: mov 0, r12 mov 4, r13 #ifdef cpu0 iext b1111_0101_0000_0000_0010_0000; mov b1111_0101_0000_0000_0010_0000, r1 jmpr cc_busy, 0 sgio r1, SMOFFON ; switch off all NI LVDS cells, clk_prepr, clk_ni (VA), clk_fil ON nop nop nop nop #endif #ifdef cpu1 ; copy the end signature words NES into GRF lgio 0, NES iext 0xFFFF mov 0xFFFF, r1 jmpr cc_busy, 0 lpio 0x300, r2 and r1, r2, endsig_tr swp r2, r2 and r1, r2, endsig_rr #endif #ifdef cpu2 nop nop nop nop nop nop nop nop #endif #ifdef cpu3 ; exit from clear state nop nop nop nop lgio 0, NES jmpr cc_busy, 0; here just to be sure cpu3 waits enough mov cmd_ext_clr, r0 sgio r0, SMCMD ; clear ready (VA) #endif jmpr cc_uncond, 0 nop ;############################################################################## ;# ;# 0x200: Interrupt Tracklet Processing Jump Address ;# ;############################################################################## ORG 0x200; acq: #ifdef cpu0 mov b0000_0010_0000, r1 jmpr cc_busy, 0 sgio r1, SMOFF ; switch off clk_fil, can be moved after division below mov 1, g0 ; should be moved to clear procedure #else nop ; could be omitted later nop nop nop #endif ;############################################################## ;# ;# check for tracklets: CHANNEL !=31 ;# ;############################################################## shl 10, f8, r8 ; ( CHANNEL + 1 ) * 256 * 4 ; to guarantee OFFSET >0 below jmp cc_zero, acq_no_tr ; if CHANNEL + 1 == 0 then exit ;############################################################## ;# ;# fit parameter calculation ;# ;# SLOPE = ( N * XY - X * Y ) / ( N * XX - X * X ) ;# OFFSET = ( XX * Y - X * XY ) / ( N * XX - X * X ) ;# ;############################################################## add f1, f9, r15 ; N = N0 + N1 add f3, f11, r1 ; X = X0 + X1 mul32 r1, r1, r3 ; X * X add f4, f12, r2 ; XX = XX0 + XX1 mul32 r15, r2, r4 ; N * XX add f2, f10, r7 ; Q = Q0 + Q1 sub r4, r3, r3 ; N * XX - X * X ; r12 = 0 in clear procedure ; r13 = 4 in clear procedure div r12, r3 ; 2**34 / DENOMINATOR after 19 clocks shl 8, f9, r5 ; 256 * N1 ( 1) add f13, r5, r5 ; Y1 + 256 * N1 ( 2) add f5, r5, r5 ; Y = Y0 + Y1 + 256 * N1 ( 3) shl 8, f11, r6 ; 256 * X1 ( 4) add f14, r6, r6 ; XY1 + 256 * X1 ( 5) add f6, r6, r6 ; XY = XY0 + XY1 + 256 * X1 ( 6) mus32 r1, r5, r3 ; X * Y ( 7) mus32 r1, r6, r4 ; X * XY ( 8) mus32 r2, r5, r1 ; XX * Y ( 9) mus32 r15, r6, r2 ; N * XY (10) sub r1, r4, r1 ; OF = XX * Y - X * XY (11) sub r2, r3, r2 ; SL = N * XY - X * Y (12) shl 2, r15, r15 ; byte adressing in DMEM (13) ; QA = low word of Q, ignored shl -16, r7, r4 ; QB = high word of Q (14) lra rr_dword, r0 ; 2**27 / N (15) lra rr_dword, r0 ; 2**27 / N (16) mul r0, r4, r0 ; QB * 2**27 / N (17) mov 0x1F, r6 ; do something useful here !!! (18) and r13, r6, r6 ; QB * 2**(-5) / N (19) ; QB / N >= 2**10 not catched shl 7, r6, r6 ; E.PROBABILITY & 0[7] (20) or r6, CHIP_ID_EXT, r6 ; E.PROBABILITY & CHIP ID (21) die r7 ; get 2**34 / DENOMINATOR mus r7, r1, r1 ; lower 32 bit word of OFFSET mus r7, r2, r2 ; lower 32 bit word of SLOPE add r8, r13, r1 ; OFFSET [15] ( * 256 * 4 ) shl 11, r13, r2 ; SLOPE [11] ( * 256 * 4 ) & 0[11] ;############################################################## ;# ;# tracklet synthesis and transmission ;# ;# SLOPE [9] *1024 - 0.25 < . < + 0.25 ;# & OFFSET [11] *64 + 0.00 < . < + 20.0 ;# & E.PROBABILITY [5] /32 + 0.00 < . < + 1.0 ;# & CHIP ID [7] ;# ;############################################################## shl -4, r1, r1 ; OFFSET [11] ( * 64 ) or r1, r2, r5 ; SLOPE & OFFSET shl 12, r5, r5 ; SLOPE & OFFSET & 0[12] or r5, r6, r5 ; SLOPE & OFFSET & E.PROB. & CHIP ID mov 16, r1 ; delay transmission acq_tr_del: sub r1, c1, r1 jmp cc_nzero, acq_tr_del spio r5, NODP jmpr cc_uncond, 0 nop ;############################################################## ;# ;# send end signature if there is no tracklet ;# ;# do any power management here (to be implemented !!!) ;# ;############################################################## acq_no_tr: mov 32, r1 ; delay transmission acq_nt_del: sub r1, c1, r1 jmp cc_nzero, acq_nt_del mov endsig_tr, r5 spio r5, NODP jmpr cc_uncond, 0 nop ;############################################################################## ;# ;# 0x400: Interrupt Raw Data Transmission Jump Address ;# ;############################################################################## ORG 0x400 raw: #ifdef cpu0 mov cmd_CPU_done r0 ; CPU0 indicates upcoming data transmission jmpr cc_busy, 0 sgio r0 SMCMD; jmp cc_uncond, raw_continue ; CPU0 fills FIFO immediately #endif #ifdef cpu1 nop nop nop jmp cc_uncond, raw_continue ; CPU1 fills FIFO immediately as well #endif #ifdef cpu2 nop nop nop nop #endif #ifdef cpu3 nop nop nop nop #endif mov 0, r0 ; switch off own clock because jmpr cc_busy, 0 sgio r0, clk_onoff ; CPU2 and CPU3 are filling their FIFOs delayed. jmpr cc_busy, 0 ; They will be started by CPU0 and CPU 1 later. nop nop nop nop raw_continue: ;############################################## ;# Store Start addresses for SCSN transfer via Databank ;############################################## iext AddrSCdata mov AddrSCdata, rio ;############################################## ;# NI transfer event header (CPU0 only) ;############################################## #ifdef cpu0 mov EHchip, r0 ; chip EHchip starts readout tree sequence cmp r0, ChipPOS ; and sends event header jmp cc_nzero, raw_no_event_header shl 2, EventHeader, r0 ; combine event header or r0, c1, r0 ; SOE+"01"+SOE+"01" shl 15, r0, r1 ; where SOE is the 14 bit Start of Event Marker shl 1, r1, r1 or r0, r1, r0 spio r0 NODP ; NI transfer event header jmpr cc_busy, 0 ; SCSN transfer chip header sgio+ r0 #else nop nop nop nop nop nop nop nop nop nop nop #endif raw_no_event_header: swp rio, rio ; swap DBANK address to high word of rio mov ReadoutFlag, r2 ; load NI&SCSN readout flag cmp r2, 0 jmp cc_zero, raw_del_end ; check for transmission flags #ifdef cpu0 shl 15, ChipPOS, r0 ; combine chip header shl 5, r0, r0 ; ChipPOS(8)+EventCounter(20)+"1100" or r0, EventCounter, r0 shl 2, r0, r0 or r0, c3, r0 shl 2, r0, r0 spio r0 NODP ; NI transfer chip header swp rio, rio jmpr cc_busy, 0 ; SCSN transfer chip header sgio+ r0 ; no busy flag check due to large delay swp rio, rio ; till next access #else nop nop nop nop nop nop nop nop nop nop nop #endif mov LSBdata, r7 ; pass the two LSBs for data transmission iext 0xFFFF0000 ; high word mask for Channel switching mov 0xFFFF0000, r15 ; Note: this works because of the sign extension! mov g0, r0 cmp r0, 0 jmp cc_eq, raw_del_end mov nsamples, r1 ; initially load number of samples cmp r1, 0 jmp cc_nzero, raw_run_tmsn ; check for transmission flags raw_del_end: mov 0x002, r2 ; wait a while to make sure that GSM and raw_no_tmsn_del: ; NI are ready for transmission and state sub r2, c1, r2 ; transition. jmp cc_nzero, raw_no_tmsn_del nop jmp cc_uncond, raw_complete_ni_tmsn nop raw_run_tmsn: ;############################################## ;# NI&SCSN transfer 1st channel ;############################################## mov EBR0, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio ; mov nsamples,r1 ; number of samples to read (done above) mvpcr +2, rstack jmp cc_uncond, raw_ChTML; ;############################################## ;# NI&SCSN transfer 2nd channel ;############################################## and r15, rio, rio mov EBR1, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio mov nsamples,r1 ; number of samples to read mvpcr +2, rstack jmp cc_uncond, raw_ChTML; ;############################################## ;# NI&SCSN transfer 3rd channel ;############################################## and r15, rio, rio mov EBR2, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio mov nsamples,r1 ; number of samples to read mvpcr +2, rstack jmp cc_uncond, raw_ChTML; ;############################################## ;# NI&SCSN transfer 4th channel ;############################################## and r15, rio, rio mov EBR3, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio mov nsamples,r1 ; number of samples to read mvpcr +2, rstack jmp cc_uncond, raw_ChTML; ;############################################## ;# NI&SCSN transfer 5th channel ;############################################## and r15, rio, rio mov EBR4, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio mov nsamples,r1 ; number of samples to read mvpcr +2, rstack jmp cc_uncond, raw_ChTML; ;############################################## ;# NI&SCSN transfer 6th channel (CPU3 only) ;############################################## #ifdef cpu3 and r15, rio, rio mov EBR5, r0 ; address in LIO of the event buffer or r0, rio, rio ; to low word of rio mov nsamples,r1 ; number of samples to read mvpcr +2, rstack jmp cc_uncond, raw_ChTML; #else nop nop nop nop nop nop #endif; ;############################################## ;# Slow down NI transmission if NI_tmsn_delay != 0 ;############################################## raw_complete_ni_tmsn: nop #ifdef cpu3 mov NI_tmsn_delay, r1 ; mov doesn't set the flags! andt r1, r1 jmp cc_zero, raw_end_ni_tmsn cli lgio 0, IRQHW3 jmpr cc_busy, 0 lpio 0x300, r8 ; mov 0x015, r8 ; the present IRQ mask mov 0x415, r0 ; the new IRQ mask, IRQ NI fifo empty enabled sgio r0, IRQHW3 ; modify the IVT jmpr cc_busy, 0 sgio r0, IRQHL3 jmpr cc_busy, 0 jmp cc_uncond, raw_coff #else nop nop nop nop nop nop nop nop nop nop nop nop nop nop #endif ;############################################## ;# CPU0, CPU1: start CPU2 and CPU3 for delayed transfer ;############################################## raw_end_ni_tmsn: mov 1, r1 #ifdef cpu0 jmpr cc_busy, 0 sgio r1 clk_onoff_next #endif #ifdef cpu1 jmpr cc_busy, 0 sgio r1 clk_onoff_next #endif #ifdef cpu2 nop nop #endif #ifdef cpu3 nop nop #endif ;############################################## ;# CPU3: Increment Event Counter ;############################################## #ifdef cpu3 mov EventCounter, r0 add r0, c1, r0 iext 0x1FFFFF mov 0x1FFFFF, r1 and r1, r0, r0 jmp cc_nzero, raw_EvtCtrOK mov 10, r0 raw_EvtCtrOK: jmpr cc_busy, 0 sgio r0 EvtCtrGIOAdr #else nop nop nop nop nop nop nop nop nop #endif ;############################################## ;# NI&SCSN transfer end marker ;############################################## mov endsig_rr r0 spio r0 NODP swp rio, rio jmpr cc_busy, 0 sgio+ r0 swp rio, rio ;############################################## ;# automatically go to clear state if ReadoutFlag=0 ;############################################## ; mov ReadoutFlag, r2 ; load NI&SCSN readout flag ; cmp r2, 0 ; jmp cc_nzero, coff ; check for transmission flags ; ; #ifdef cpu3 ; mov CMD_CLEAR, r0 ; CPU0 indicates upcoming data transmission ; jmpr cc_busy, 0 ; sgio r0 SMCMD; ; #else ; nop ; nop ; nop ; #endif ;############################################## ;# switch off own clock after transfer ;############################################## raw_coff: mov 0, r0 jmpr cc_busy, 0 sgio r0 clk_onoff jmpr cc_busy, 0 nop nop nop nop nop nop nop #ifdef cpu3 jmpr cc_uncond, 0 #else jmp cc_uncond, raw_coff #endif nop ;############################################################################## ;# ;# NI transmission of one channel ;# ;############################################################################## ;# ;# Interface: ;# ;# Input: r14 start address of event buffer in LIO ;# r1 number of time bins to read (>0, multiple of three) ;# r7 OR mask for the 32 bit word ;# r2 Readout Flags ;# ;# Output: sends data to the NI output port ;# Modifies: r3, r4, r5, r14, r1 (0) ;# ;############################################################################## ;############################################## ;# BEGIN data transfer loop raw_ChTML: ;############################################## lpio+ r3 ; initial read has to be done twice due to lpio+ r3 ; memory delay (synchronous read) lpio+ r4 lpio rio, r5 shl 10, r5, r5 ; combine three 10 bit data words or r5, r4, r5 ; to one (32=10+10+10+2) bit data word shl 10, r5, r5 or r5, r3, r5 shl 2, r5, r5 or r5, r7, r5 ; set the two LSBs and r2, c2, r2 ; check NI readout flag jmp cc_zero, raw_scsn_readout spio r5, NODP ; write to NI raw_scsn_readout: swp rio, rio ; switch to SCSN storage address sgio+ r5 ; write to DBANK for SCSN reading swp rio, rio ; switch back to event buffer read address sub r1, c3, r1 ; decrease number of words to read jmp cc_gtu, raw_ChTML ; loop xor r7, c1, r7 jmp cc_uncond, rstack ; return from subroutine ;############################################## ;# END data transfer loop ;############################################## nop ;############################################################################## ;# ;# 0x500: Interrupt NI FIFO empty, irq10 ;# ;############################################################################## ORG 0x500 nififoe: sgio r8, IRQHL3 jmpr cc_busy, 0 sgio r8, IRQHW3 jmpr cc_busy, 0 ; program the delay mov NI_tmsn_delay, r1 spio r1, 0x200 mov b1010_0101_1111, r1 ; counter, down, irq spio r1, 0x201 ; enable IRQ local timer mov b0101_0101, r1 sgio r1, IRQHL3 jmpr cc_busy, 0 sgio r1, IRQHW3 jmpr cc_busy, 0 jmp cc_uncond, raw_coff ;############################################################################## ;# ;# 0x600: Interrupt Local Counter/Timer ;# ;############################################################################## ORG 0x600 localtm: ; restore the interrupt mask ; mov 0x015, r1 sgio r8, IRQHL3 jmpr cc_busy, 0 sgio r8, IRQHW3 jmpr cc_busy, 0 ; send end signature jmp cc_uncond, raw_end_ni_tmsn nop ORG 0x700 ; Style recommendations ; ; 1) use include for the different parts of the CPU program ; ; 2) use prefix in the labels, e.g. ; ; -- start of the acq subroutine ; acq: ... ; ... ; acq_store: ; ... ; acq_delay: ; ... ; -- end of the acq subroutine ; ADDITIONAL PROGRAMS ; ; GENERAL RULES ; ; 1) The programs do not use any programmable constants ; 2) CPU3 is never used ; 3) The programs use for data exchange a small region in the DBANK ; or DMEM or IMEM3, accessible through GIO. The start addresses ; must be defined in the main program as follows: ; ; srv_command - command from the SCSN master, code of the service operation ; srv_indata - input data, stored by the SCSN master ; srv_outdata - output data, stored by the TRAP CPU ; ; 4) The programs may modify all registers (privat and global) ; ; 5) The programs end with command low power to the global state machine. ; This can be changed later - may be is reasonable to have the option for normal ; IRT (interrupt return) or just jump to some address. ; ; 6) By default the configuration of the main program enables interrupt TST for CPU0,1,2 ; but sets the start address to a small assembler code to switch the power off ; ; 7) When the SCSN master wants to start some service program, it must send the ; TRAP to the low power state, then modify the IVT (interrupt vector table) ; - store the correct start address of the service program. Then the SCSN master ; stores its request at srv_command and activates IRQ TST. The SCSN master checks ; the state of the TRAP and sends it to low power state if a timeout occurs. ; After finishing the service operation (which can consist of many service requests), ; the SCSN master restores the IVT to the original. ; J2C #ifdef cpu0 #inc "j2c.asm" #endif #ifdef cpu1 #inc "I2C.asm" #endif #ifdef cpu2 ;#inc "jtag.asm" tst: nop #endif