; #inc ; program to pack/unpack/check the configuration in the TRAP chip ; ; by V.Angelov ; ; $Id$: ; ; The format for single conf. reg. ; Bit 31 is 1 ; Bits 30..17 - address ; Bits 16..0 - data ; The format of a block is ; Bits 31 ; Block 0 start_address(30..15) words(14..7) widthM1(6..2) se(1) astep(0) ; - start_address is 16-bit, but all configuration registers are ; below 0x3FFF ; - words (8 bit) is the number of configuration words, not the number ; of 32-bit data words that follow ; words=0 means end of the data => our end marker is just 0 ! ;- widthM1 (5 bit) 0..31, for 1 to 32 bits ; from 1 to 8 bits: 8 bits ; from 9 to 16 bits: 16 bits ; more than 16 bits : 32 bits ; the more precise number of bits can be used later for extensions ;- se 0|1 is sign extension of the data, only in case of width 8 and 16 ; the sign extension should be used carefully! ; e.g. 5 bit signed, if the configuration register is 5 bit, we can consider the ; register as unsigned and this is safer. ;- astep 0|1 is the increment of the TRAP IO address, normally we need 1 or 2: 0|1 ; This program is better executed by cpu0..2, not 3, because cpu3 can not access DMEM in GIO. ; unpack ; input: in c11 the start address in GIO ; output: in c11 is the number of errors, if cnf_compare is defined #def mask_1F = r8 ; 5 bit mask #def mask_FF = r9 ; 8 bit mask #def mask_1FFFF = r10 ; 17 bit mask #def mask_FFFF = r11 ; 16 bit mask #def cnst_sa = c8 ; the start address in GIO #def cmp_errors_un = 0xF0F0 ; number of differences #def cpu_clocks_un = 0xF0F1 ; number of clocks for unpacking #def cpu_clocks_crc = 0xF0F2 ; number of clocks for unpacking+crc32 ;#def cnf_compare = 1 ; enable compare & counting errors ;#def debug = 1 ; enable debugging in DMEM ;#def debugT = 1 ; enable timer conf_man_un: #ifdef debugT mov 0x640, r0 spio r0, CTPCTRL mov 0, r0 spio r0, CTPDINI #endif ; initialization mov 0 , r15 ; the DMEM pointer mov cnst_sa, r14 ; the GIO access register with autoincrement mov cnst_sa, r13 ; copy of the start address mov 0x1F, mask_1F ; prepare the masks needed later mov 0xFF, mask_FF iext 0x1FFFF mov 0x1FFFF, mask_1FFFF iext 0xFFFF mov 0xFFFF, mask_FFFF #ifdef cnf_compare mov 0, r6 ; error counter #endif ; start loop - next block/single conf_man_un_next: jmpr cc_busy, 0 #ifdef debug sra+ r14 ; debugging #endif lgio+ 0 ; read the next block/single jmpr cc_busy, 0 lpio GBUSR0, r0 #ifdef debug sra+ r0 ; debugging #endif shl -7, r0, r1 ; shift the number of words shl 1, r0, r2 ; check the 31th bit jmp cc_carry conf_man_un_sng ; jump to single and mask_FF, r1, r1 ; number of words in r1 jmp cc_zero, conf_man_un_exit ; exit if 0 shl -2, r0, r2 ; shift the width-1 to the right and mask_1F, r2, r2 ; width-1 in r2 and r0, c1, r3 ; step-1 add r3, c1, r3 ; step in r3 shl -15, r0, r0 ; address, not necessary to mask cmp r2, 16 jmp cc_geu, conf_man_un_32 ; 32 bit case cmp r2, 8 jmp cc_geu, conf_man_un_16 ; 16 bit case ; 8 bit case conf_man_un_8: ; step in r3 ; address in r0 ; number of words in r1 jmpr cc_busy, 0 lgio+ 0 ; read the 4 bytes jmpr cc_busy, 0 lpio GBUSR0, r2 ; data to write ; byte 0 and r2, mask_FF, r4 ; mask the upper 24 bits #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FF, r5 ; mask the upper 24 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the lower byte #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_zero, conf_man_un_next ; next block/single ; byte 1 shl -8, r2, r2 ; shift the next 8 bits to the right and r2, mask_FF, r4 ; mask the upper 24 bits jmpr cc_busy, 0 #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FF, r5 ; mask the upper 24 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the byte #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_zero, conf_man_un_next ; next block/single ; byte 2 shl -8, r2, r2 ; shift the next 8 bits to the right and r2, mask_FF, r4 ; mask the upper 24 bits jmpr cc_busy, 0 #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FF, r5 ; mask the upper 24 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the byte #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_zero, conf_man_un_next ; next block/single ; byte 3 shl -8, r2, r4 ; shift the next 8 bits to the right jmpr cc_busy, 0 #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FF, r5 ; mask the upper 24 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the byte #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_nzero, conf_man_un_8 ; next 4 bytes jmp cc_uncond, conf_man_un_next ; next block/single ; 16 bit case conf_man_un_16: ; step in r3 ; address in r0 ; number of words in r1 jmpr cc_busy, 0 lgio+ 0 ; read the 2 x 16 bit words jmpr cc_busy, 0 lpio GBUSR0, r2 ; data to write and r2, mask_FFFF, r4 ; mask the upper 16 bits #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FFFF, r5 ; mask the upper 16 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the lower 16 bits #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_zero, conf_man_un_next ; next block/single shl -16, r2, r4 ; shift the upper 16 bits to the right jmpr cc_busy, 0 #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_FFFF, r5 ; mask the upper 16 bits cmp r5, r4 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r4, r0 ; store to GIO the upper 16 bits #ifdef debug sra+ r0 ; debugging nop sra+ r4 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_nzero, conf_man_un_16 ; next 2 x 16 bit words jmp cc_uncond, conf_man_un_next ; 32 bit case conf_man_un_32: ; step in r3 ; address in r0 ; number of words in r1 jmpr cc_busy, 0 lgio+ 0 ; read the 32 bit word jmpr cc_busy, 0 lpio GBUSR0, r2 ; data to write #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data cmp r5, r2 ; compare jmpr cc_eq, +3 ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r2, r0 ; store to GIO #ifdef debug sra+ r0 ; debugging nop sra+ r2 #endif add r0, r3, r0 ; increment the write address sub r1, c1, r1 ; decrement the number of words jmp cc_nzero, conf_man_un_32 ; next 32 bit word jmp cc_uncond, conf_man_un_next ; next block/single ; single case conf_man_un_sng: and r0, mask_1FFFF, r1 ; data in r1 shl -11, r2, r0 ; r2[31..18] contains the address shl -7, r0, r0 ; address in r0 #ifdef cnf_compare lgio 1, r0 jmpr cc_busy, 0 lpio GBUSR1, r5 ; read data and r5, mask_1FFFF, r5 ; data in r1 cmp r5, r1 ; compare jmp cc_eq, conf_man_un_next ; skip the error inc and the SGIO! add r6, c1, r6 ; count up the errors #endif sgio r1, r0 #ifdef debug sra+ r0 ; debugging nop sra+ r1 #endif jmp cc_uncond, conf_man_un_next conf_man_un_exit: #ifdef debugT #ifdef cnf_compare iext cmp_errors_un sgio r6, cmp_errors_un ; c11 of CPU0 in GIO #endif lpio CTPDOUT, r6 ; the number of CPU clocks jmpr cc_busy, 0 iext cpu_clocks_un sgio r6, cpu_clocks_un #endif jmp cc_uncond, crc32 ; calculate crc32 conf_man_un_lp: #ifdef debugT lpio CTPDOUT, r6 ; the number of CPU clocks after CRC32 jmpr cc_busy, 0 iext cpu_clocks_crc sgio r6, cpu_clocks_crc #endif ; low power shl 4, c12, r0 ; event counter << 2 or r0, c3, r0 ; (event counter << 2) | 3 iext LP_REP mov LP_REP, r1 add r1, c5, r1 ; + CPU# jmpr cc_busy, 0 sgio r0, r1 mov cmd_lp, r0 jmpr cc_busy, 0 sgio r0, SMCMD ; go to low power, will be changed later jmpr cc_busy, 0 jmpr cc_uncond, 0 nop crc32: mov r14, r2 ; r14 last value points to the CRC32 word mov r13, r14 ; the GIO access register with autoincrement mov c7, r1 ; the CRC32 register is r1, now initilised with FFF..FF lgio+ 0 ; request the first word from DBANK iext 0x04C11DB7 mov 0x04C11DB7, r3 ; the generator Poly jmpr cc_busy, 0 crc32_next_word: lpio GBUSR0, r0 ; hold the data, requested before lgio+ 0 ; request the next word mov 32, r5 ; init the bit counter crc32_next_bit: shl -1, r0, r0 ; shift right r0, carry=LSB adc r1, r1, r1 ; shift left r1 and add the carry jmpr cc_ncarry, +2 ; skip the xor if now carry-out xor r1, r3, r1 ; xor with the generator Poly sub r5, c1, r5 ; dec the bit counter jmp cc_nzero, crc32_next_bit ; end of the bit loop cmp r14, r2 ; compare with the end address jmp cc_leu, crc32_next_word ; end of the loop xor r1, c7, r1 ; xor with FF..FF at the end lpio GBUSR0, r0 cmp r1, r0 ; compare the appended and the calculated crc32 sgio+ r1 ; store the calculated crc32 jmp cc_uncond, conf_man_un_lp nop