📄 fpa3x_dev.c
字号:
* reg2 uses data register 1 thru 29, and holds value 2; * reg3 uses data register 2 thru 30, and holds value 8; * reg4 uses data register 3 thru 31, and holds value 4. */pointer_cmdreg(){ register u_int r1, r2, r3, r4, data, dreg; u_int ms, ls, ms_exp, ls_exp; /* single precision command register test */ for (r1=0, r2=1, r3=2, r4=3; r4<FPA_NDATA_REGS; r1++, r2++, r3++, r4++) { /* clear all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) if (write_datareg(dreg,SZERO,SZERO)) return; /* load register value and execute instruction */ if (write_datareg(r2,STWO,SZERO)) return; if (write_datareg(r3,SEIGHT,SZERO)) return; if (write_datareg(r4,SFOUR,SZERO)) return; data = C_REG4(r4) | C_REG3(r3) | C_REG2(r2) | C_REG1(r1); if (write_fpa((u_int *)CSP_R1_R3aR2xR4,data,ON)) return; /* read to check all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) { if (read_datareg(dreg,&ms,&ls)) return; ms_exp = (dreg == r1) ? SSIXTEEN : (dreg == r2) ? STWO : (dreg == r3) ? SEIGHT : (dreg == r4) ? SFOUR : SZERO; ls_exp = SZERO; if (ms != ms_exp || ls != ls_exp) send_message(FPERR,ERROR,er_pointer,dreg,ms_exp,ls_exp,ms,ls); } } /* double precision command register */ for (r1=0, r2=1, r3=2, r4=3; r4<FPA_NDATA_REGS; r1++, r2++, r3++, r4++) { /* clear all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) if (write_datareg(dreg,DZERO_M,DZERO_L)) return; /* load register value and execute instruction */ if (write_datareg(r2,DTWO_M,DTWO_L)) return; if (write_datareg(r3,DEIGHT_M,DEIGHT_L)) return; if (write_datareg(r4,DFOUR_M,DFOUR_L)) return; data = C_REG4(r4) | C_REG3(r3) | C_REG2(r2) | C_REG1(r1); if (write_fpa((u_int *)CDP_R1_R3aR2xR4,data,ON)) return; /* read to check all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) { if (read_datareg(dreg,&ms,&ls)) return; ms_exp = (dreg == r1) ? DSIXTEEN_M : (dreg == r2) ? DTWO_M : (dreg == r3) ? DEIGHT_M : (dreg == r4) ? DFOUR_M : DZERO_M; ls_exp = DZERO_L; if (ms != ms_exp || ls != ls_exp) send_message(FPERR,ERROR,er_pointer,dreg,ms_exp,ls_exp,ms,ls); } }}/* * Function to test the pointers increment decrement using the command * register instructions. * For single precision, it uses the operation transpose 4x4 matrix. * Where reg1 starts from data register 0 thru 15. * Original Matrix ===> Transpose Matrix * 0 1 2 3 0 4 8 C * 4 5 6 7 1 5 9 D * 8 9 A B 2 6 A E * C D E F 3 7 B F * For double precision, it uses the operation: * reg1 = (reg2*reg3)+(reg2+1)*(reg3+1)+(reg2+2)*(reg3+2)+(reg2+3)*(reg3+3) * Where reg1 uses data register 0 thru 29, and should hold the result 40; * reg2 uses data register 1 thru 30, and holds value 1; * reg3 uses data register 2 thru 31, and holds value 2; * reg3+1 holds value 3; * reg3+2 holds value 4; * reg3+3 holds value 5; */pointer_incdec(){ register u_int r1, r2, r3, data, dreg; u_int ms, ls, ms_exp, ls_exp; /* single precision command register matrix 4x4 transpose test */ for (r1 = 0; r1 < FPA_NSHORT_REGS; r1++) { /* fill all data regs with 0xFF */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) if (write_datareg(dreg,0xFF,0xFF)) return; /* set up 4x4 matrix start at reg1 */ for (dreg = 0; dreg < 16; dreg++) if (write_datareg(dreg+r1,dreg,0xFF)) return; /* execute instruction */ data = C_REG1(r1); if (write_fpa((u_int *)CSP_TRANS4x4,data,ON)) return; /* read to check all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) { if (read_datareg(dreg,&ms,&ls)) return; ms_exp = ls_exp = 0xFF; if (r1 <= dreg && dreg <= (r1+15)) { ms_exp = dreg - r1; ms_exp = (ms_exp % 4) * 4 + (ms_exp / 4); } if (ms != ms_exp || ls != ls_exp) send_message(FPERR,ERROR,er_pointer,dreg,ms_exp,ls_exp,ms,ls); } } /* double precision command register dot product test */ for (r1=0, r2=1, r3=2; r3<(FPA_NDATA_REGS-3); r1++, r2++, r3++) { /* clear all data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) if (write_datareg(dreg,DZERO_M,DZERO_L)) return; /* load register value and execute instruction */ if (write_datareg(r2,DONE_M,DONE_L)) return; if (write_datareg(r3,DTWO_M,DTWO_L)) return; if (write_datareg(r3+1,DTHREE_M,DTHREE_L)) return; if (write_datareg(r3+2,DFOUR_M,DFOUR_L)) return; if (write_datareg(r3+3,DFIVE_M,DFIVE_L)) return; data = C_REG3(r3) | C_REG2(r2) | C_REG1(r1); if (write_fpa((u_int *)CDP_DOTPROD,data,ON)) return; /* read to check data registers */ for (dreg = 0; dreg < FPA_NDATA_REGS; dreg++) { if (read_datareg(dreg,&ms,&ls)) return; ms_exp = (dreg == r1) ? DFORTY_M : (dreg == r2) ? DONE_M : (dreg == r3) ? DTWO_M : (dreg == (r3+1)) ? DTHREE_M : (dreg == (r3+2)) ? DFOUR_M : (dreg == (r3+3)) ? DFIVE_M : DZERO_M; ls_exp = DZERO_L; if (ms != ms_exp || ls != ls_exp) send_message(FPERR,ERROR,er_pointer,dreg,ms_exp,ls_exp,ms,ls); } }}/* * Function to perform shadow register lock test in both active and * next stages. */lock_test(){ send_message(0,VERBOSE,tst_lock,"short"); lock_short(FALSE); send_message(0,VERBOSE,tst_lock,"extended"); lock_extend(FALSE); send_message(0,VERBOSE,tst_lock,"command register"); lock_cmdreg(FALSE); send_message(0,VERBOSE,tst_lock,"short, next"); lock_short(TRUE); send_message(0,VERBOSE,tst_lock,"extended, next"); lock_extend(TRUE); send_message(0,VERBOSE,tst_lock,"command register, next"); lock_cmdreg(TRUE);}/* * Function to perform lock test using single and double short instructions: * reg1 = reg1 / operand, where reg1 = 1 and operand = 3. * This operation will hang and lock the shadow register assign to reg1. */lock_short(next)register int next;{ register u_int r1, r1_next, inst; /* enable imask to hang operation */ if (write_fpa(&fpa->fp_imask,FPA_INEXACT,ON)) return; /* single precision short test */ for (r1 = 0; r1 < FPA_NSHAD_REGS; r1++) { if (write_datareg(r1,SONE,SZERO)) return; if (next) { r1_next = (r1 + 1) % FPA_NSHAD_REGS; if (write_datareg(r1_next,SONE,SZERO)) return; } inst = SP_DIVIDE | SP_REG1(r1); if (write_fpa((u_int *)inst,STHREE,ON)) return; if (next) { inst = SP_DIVIDE | SP_REG1(r1_next); if (write_fpa((u_int *)inst,STHREE,ON)) return; check_lock(2,r1,r1_next); } else check_lock(1,r1); } /* double precision short test */ for (r1 = 0; r1 < FPA_NSHAD_REGS; r1++) { if (write_datareg(r1,DONE_M,DONE_L)) return; if (next) { r1_next = (r1 + 1) % FPA_NSHAD_REGS; if (write_datareg(r1_next,DONE_M,DONE_L)) return; } inst = DP_DIVIDE | DP_REG1(r1); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; if (write_fpa((u_int *)DP_LSW,DTHREE_L,ON)) return; if (next) { inst = DP_DIVIDE | DP_REG1(r1_next); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; if (write_fpa((u_int *)DP_LSW,DTHREE_L,ON)) return; check_lock(2,r1,r1_next); } else check_lock(1,r1); }}/* * Function to perform lock test using single and double extended instruction: * reg1 = reg2 / operand, where reg2 = 1 and operand = 3. * This operation will hang and lock the shadow register assign to reg1. */lock_extend(next)register int next;{ register u_int r1, r2, r1_next, r2_next, inst; /* enable imask to hang operation */ if (write_fpa(&fpa->fp_imask,FPA_INEXACT,ON)) return; /* single precision extended test */ for (r1=0, r2=1; r2 < FPA_NSHAD_REGS; r1++, r2++) { if (write_datareg(r2,SONE,SZERO)) return; if (next) { r2_next = (r2 + 1) % FPA_NSHAD_REGS; r1_next = r1 + 1; if (write_datareg(r2_next,SONE,SZERO)) return; } inst = XSP_DIVIDE | X_REG2(r2); if (write_fpa((u_int *)inst,STHREE,ON)) return; inst = X_LSW | X_REG1(r1); if (write_fpa((u_int *)inst,SZERO,ON)) return; if (next) { inst = XSP_DIVIDE | X_REG2(r2_next); if (write_fpa((u_int *)inst,STHREE,ON)) return; inst = X_LSW | X_REG1(r1_next); if (write_fpa((u_int *)inst,SZERO,ON)) return; check_lock(2,r1,r1_next); } else check_lock(1,r1); } /* double precision extended test */ for (r1=0, r2=1; r2 < FPA_NSHAD_REGS; r1++, r2++) { if (write_datareg(r2,DONE_M,DONE_L)) return; if (next) { r2_next = (r2 + 1) % FPA_NSHAD_REGS; r1_next = r1 + 1; if (write_datareg(r2_next,DONE_M,DONE_L)) return; } inst = XDP_DIVIDE | X_REG2(r2); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; inst = X_LSW | X_REG1(r1); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; if (next) { inst = XDP_DIVIDE | X_REG2(r2_next); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; inst = X_LSW | X_REG1(r1_next); if (write_fpa((u_int *)inst,DTHREE_L,ON)) return; check_lock(2,r1,r1_next); } else check_lock(1,r1); }}/* * Function to perform lock test using Weitek command register instructions: * 1) reg1 = sine(reg2) and reg4 = cosine(reg2), where reg2 = 1. * 2) reg1 = reg2 / reg3, where reg2 = 1 and reg3 = 3. * The first operation will hang and lock all shadow registers. * The second operation will hang and lock the shadow register assign to reg1. */lock_cmdreg(next)register int next;{ register u_int r1, r2, r4, data; register u_int r1_next, r2_next, r3_next; /* enable imask to hang operation */ if (write_fpa(&fpa->fp_imask,FPA_INEXACT,ON)) return; /* single precision command register test */ for (r1=0, r2=1, r4=2; r4 < FPA_NSHAD_REGS; r1++, r2++, r4++) { if (write_datareg(r2,SONE,SZERO)) return; if (next) { r3_next = (r4 + 1) % FPA_NSHAD_REGS; r2_next = r2 + 1; r1_next = r1 + 1; if (write_datareg(r2_next,SONE,SZERO)) return; if (write_datareg(r3_next,STHREE,SZERO)) return; data = C_REG3(r3_next) | C_REG2(r2_next) | C_REG1(r1_next); if (write_fpa((u_int *)CWSP_DIVIDE,data,ON)) return; } data = C_REG4(r4) | C_REG2(r2) | C_REG1(r1); if (write_fpa((u_int *)CSP_SINCOS,data,ON)) return; check_lock(FPA_NSHAD_REGS,0,1,2,3,4,5,6,7); } /* double precision command register test */ for (r1=0, r2=1, r4=2; r4 < FPA_NSHAD_REGS; r1++, r2++, r4++) { if (write_datareg(r2,DONE_M,DONE_L)) return; if (next) { r3_next = (r4 + 1) % FPA_NSHAD_REGS; r2_next = r2 + 1; r1_next = r1 + 1; if (write_datareg(r2_next,DONE_M,DONE_L)) return; if (write_datareg(r3_next,DTHREE_M,DTHREE_L)) return; data = C_REG3(r3_next) | C_REG2(r2_next) | C_REG1(r1_next); if (write_fpa((u_int *)CWDP_DIVIDE,data,ON)) return; } data = C_REG4(r4) | C_REG2(r2) | C_REG1(r1); if (write_fpa((u_int *)CDP_SINCOS,data,ON)) return; check_lock(FPA_NSHAD_REGS,0,1,2,3,4,5,6,7); }}/* * Function to verify that all indicated shadow registers are locked, and * all others are not. * VARARGS. */check_lock(va_alist)va_dcl{ va_list ap; register int stat, reg, count, lock, n; u_int shadow[FPA_NSHAD_REGS], *addr, val, ierr_exp; /* get arguments for all shadow locks */ va_start(ap); count = va_arg(ap,int); for (lock = 0; lock < count; lock++) shadow[lock] = va_arg(ap,u_int); va_end(ap); /* verify that each indicated shadow register is locked */ for (reg = 0; reg < FPA_NSHAD_REGS; reg++) { /* see if this one is supposed to be locked */ for (lock = 0; lock < count; lock++) if (shadow[lock] == reg) break; /* check both most and least significant of register */ addr = (u_int *)&fpa->fp_shad[reg]; for (n = 0; n < 2; n++) { stat = read_fpa(addr+n,&val,OFF); if (lock < count) /* lock expected */ { ierr_exp = FPA_HUNG_PIPE; if (!stat) send_message(FPERR,ERROR,er_nolock,reg); } else /* no lock expected */ { ierr_exp = 0; if (stat) send_message(FPERR,ERROR,er_lock,reg); } if (read_fpa(&fpa->fp_ierr,&val,ON)) return; if ((val &= IERR_MASK) != ierr_exp) send_message(FPERR,ERROR,er_lockierr,ierr_exp,val); if (write_fpa(&fpa->fp_ierr,0,ON)) return; } } /* clear pipe to unlock */ if (write_fpa(&fpa->fp_clear_pipe,X,ON)) return;}/* * Function to perform jump condition test using command register instructions. */jumpcond_test(){ register u_int data, dreg; u_int ms, ls, ms_exp; send_message(0,VERBOSE,tst_jumpcond); /* assign value to data register 1 thru 7 */ for (dreg = 0; dreg < FPA_NSHAD_REGS; dreg++) if (write_datareg(dreg,jumpcond[dreg].data,SZERO)) return; /* execute instructions */ for (dreg = 0; dreg < FPA_NSHAD_REGS; dreg++) { data = C_REG2(dreg) | C_REG1(dreg); if (write_fpa((u_int *)jumpcond[dreg].inst,data,ON)) return; } /* read all data registers and check result */ for (dreg = 0; dreg < FPA_NSHAD_REGS; dreg++) { if (read_datareg(dreg,&ms,&ls)) return; ms_exp = jumpcond[dreg].result; if (ms != ms_exp || ls != SZERO) send_message(FPERR,ERROR,er_jumpcond,dreg,ms_exp,SZERO,ms,ls); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -