📄 fpa3x_dev.c
字号:
/* * This function performs write/read test to the MODE register bits 3-0. * The MODE register can be written only via micro-instruction. */mode_test(){ register u_int w; u_int r; send_message(0,VERBOSE,tst_reg,"MODE"); for (w = 0; w <= NIBBLE_MAX; w++) { if (write_fpa(&fpa->fp_restore_mode3_0,w,ON)) return; if (read_fpa(&fpa->fp_mode3_0_clear,&r,ON)) return; r &= MODE_MASK; if (w != r) send_message(FPERR,ERROR,er_reg,"MODE",w,r); }}/* * This function tests the WSTATUS register by write to bits 11-8, then * read back and verified. Bits 11-8 will decode value for bits 15 and 4-0. * For this test, the inexact error bit in IMASK register will be masked. * This test will be done twice, once with inexact error bit mask, once * without. The WSTATUS register can be written only via micro-instruction. */wstatus_test(){ register u_int w, exp, imask, k; u_int r; send_message(0,VERBOSE,tst_reg,"WSTATUS"); for (imask = 0; imask <= 1; imask++) { if (write_fpa(&fpa->fp_imask,imask,ON)) return; for (k = 0; k <= NIBBLE_MAX; k++) { w = k << WSTATUS_SHIFT; if (write_fpa(&fpa->fp_restore_wstatus,w,ON)) return; if (read_fpa(&fpa->fp_wstatus_clear,&r,ON)) return; r &= WSTATUS_MASK; exp = wstatexp[k]; if (!imask && (w == WS_COND)) exp |= WS_ERROR; if (r != exp) send_message(FPERR,ERROR,er_wstatus,w,exp,r); } }}/* * This function tests all registers of current context in register file by * write/read using address pattern. */datareg_test(){ register u_int reg; u_int ms, ls; send_message(0,VERBOSE,tst_datareg); /* Write address pattern to all data registers */ for (reg = 0; reg < FPA_NDATA_REGS; reg++) if (write_datareg(reg,reg,~reg)) return; /* Read back to verify all data registers */ for (reg = 0; reg < FPA_NDATA_REGS; reg++) { if (read_datareg(reg,&ms,&ls)) return; if (ms != reg || ls != ~reg) send_message(FPERR,ERROR,er_datareg,reg,reg,~reg,ms,ls); }}/* * Function to write to register file in current context. * Function returns 0 if successful, else nonzero. */write_datareg(reg,ms,ls)u_int reg, ms, ls;{ register u_int *addr; addr = (u_int *)&fpa->fp_data[reg]; if (reg < FPA_NDATA_REGS) { if (write_fpa(addr,ms,ON)) return(TRUE); if (write_fpa(addr+1,ls,ON)) return(TRUE); } return(FALSE);}/* * Function to read register file in current context. * Function returns 0 if successful, else nonzero. */read_datareg(reg,ms,ls)u_int reg, *ms, *ls;{ register u_int *addr; addr = (u_int *)&fpa->fp_data[reg]; if (reg < FPA_NDATA_REGS) { if (read_fpa(addr,ms,ON)) return(TRUE); if (read_fpa(addr+1,ls,ON)) return(TRUE); } return(FALSE);}/* * This function tests shadow RAM by write to the register file and read * back from the shadow RAM register. */shadow_test(){ register u_int reg; u_int ms, ls; send_message(0,VERBOSE,tst_shadow); /* Write inverse address pattern to all data registers */ for (reg = 0; reg < FPA_NDATA_REGS; reg++) if (write_datareg(reg,~reg,reg)) return; /* Read back to verify Shadow RAM registers */ for (reg = 0; reg < FPA_NSHAD_REGS; reg++) { read_shadow(reg,&ms,&ls); if (ms != ~reg || ls != reg) send_message(FPERR,ERROR,er_shadow,reg,~reg,reg,ms,ls); }}/* * Function to read a shadow register in current context. */read_shadow(reg,ms,ls)u_int reg, *ms, *ls;{ register u_int *addr; addr = (u_int *)&fpa->fp_shad[reg]; if (reg < FPA_NSHAD_REGS) { if (read_fpa(addr,ms,ON)) return; if (read_fpa(addr+1,ls,ON)) return; }}/* * This function generates error conditions then verifies negative * acknowledegement status from the FPA board. */nack_test(){ register int nack, addr, k; u_int val; send_message(0,VERBOSE,tst_nack); /* non 32-bit access */ addr = (u_int) &fpa->fp_imask; for (k = 1; k < 4; k++) { addr += k; nack = read_fpa((u_int *)addr,&val,OFF); check_nack(nack,FPA_NON32_ACCESS); } /* write to supervisor space in user mode (hard clear pipe) */ nack = write_fpa(&fpa->fp_hard_clear_pipe,X,OFF); check_nack(nack,FPA_PROTECTION); /* write to supervisor space in user mode (state) */ nack = write_fpa(&fpa->fp_state,X,OFF); check_nack(nack,FPA_PROTECTION); /* write to Register File while it is disabled */ if (read_fpa(&fpa->fp_state,&val,ON)) return; if (!(val & FPA_ACCESS_BIT)) { if (write_fpa(&fpa->fp_load_ptr,X,ON)) return; nack = write_fpa((u_int *)INS_LOADRF_M,X,OFF); check_nack(nack,FPA_PROTECTION); } /* write to Microstore RAM while it is disabled */ if (read_fpa(&fpa->fp_state,&val,ON)) return; if (!(val & FPA_LOAD_BIT)) { if (write_fpa(&fpa->fp_load_ptr,0,ON)) return; nack = write_fpa(&fpa->fp_ld_ram,X,OFF); check_nack(nack,FPA_PROTECTION); } /* access illegal address */ nack = read_fpa((u_int *)FPA3X_ILLADDR,&val,OFF); check_nack(nack,FPA_PROTECTION); /* access illegal diagnostic only address */ nack = read_fpa((u_int *)FPA3X_ILLDIAG,&val,OFF); check_nack(nack,FPA_PROTECTION); /* read FPA-3X write-only address */ nack = read_fpa(&fpa->fp_clear_pipe,&val,OFF); check_nack(nack,FPA_ILLEGAL_ACCESS); /* write FPA-3X read-only address */ nack = write_fpa(&fpa->fp_pipe_status,X,OFF); check_nack(nack,FPA_ILLEGAL_ACCESS); /* illegal access sequence */ if (write_fpa((u_int *)DP_NOP,X,ON)) return; nack = write_fpa((u_int *)X_LSW,X,OFF); check_nack(nack,FPA_ILLEGAL_SEQ); /* access pipe while pipe hung */ if (write_fpa(&fpa->fp_unimplemented,X,ON)) return; nack = read_fpa((u_int *)&fpa->fp_data[0],&val,OFF); check_nack(nack,FPA_HUNG_PIPE); /* access control while pipe hung */ if (write_fpa(&fpa->fp_unimplemented,X,ON)) return; nack = read_fpa(&fpa->fp_mode3_0_clear,&val,OFF); check_nack(nack,FPA_HUNG_PIPE); /* access shadow RAM while pipe hung */ if (write_fpa(&fpa->fp_unimplemented,X,ON)) return; nack = read_fpa((u_int *)&fpa->fp_shad[0],&val,OFF); check_nack(nack,FPA_HUNG_PIPE); /* access illegal control register */ nack = read_fpa((u_int *)FPA3X_ILLCTRL,&val,OFF); check_nack(nack,FPA_ILLE_CTL_ADDR);}/* * This function verifies that nack occurs and checks the IERR status. * The IERR register will be cleared afterwards, and clear pipe is issued. */check_nack(nack,ierr_exp)register int nack;register int ierr_exp;{ u_int ierr_obs; if (!nack) send_message(FPERR,ERROR,er_nonack,ierr_exp); else { if (read_fpa(&fpa->fp_ierr,&ierr_obs,ON)) return; ierr_obs &= IERR_MASK; if (ierr_obs != ierr_exp) send_message(FPERR,ERROR,er_nack,ierr_exp,ierr_obs); if (write_fpa(&fpa->fp_ierr,0,ON)) return; } if (write_fpa(&fpa->fp_clear_pipe,X,ON)) return;}/* * Function to issue simple instructions and check pipe status. */simpleins_test(){ register u_int inst, k; u_int pipestat; send_message(0,VERBOSE,tst_simpleins); for (k = 0; inst = simple[k].inst; k++) { if (write_fpa((u_int *)inst,X,ON)) return; if (read_fpa(&fpa->fp_pipe_status,&pipestat,ON)) return; pipestat &= PIPESTAT_MASK; if (pipestat != simple[k].stat) send_message(FPERR,ERROR,er_simpleins,inst,simple[k].stat,pipestat); }}/* * Function to test the pointers 1 thru 4 using single and double precision * short, extended, and command register instructions. */pointer_test(){ send_message(0,VERBOSE,tst_pointer,"short"); pointer_short(); send_message(0,VERBOSE,tst_pointer,"extended"); pointer_extend(); send_message(0,VERBOSE,tst_pointer,"command register"); pointer_cmdreg(); send_message(0,VERBOSE,tst_pointer,"increment/decrement"); pointer_incdec();}/* * Function to test pointer 2 using single and double precision short * instructions. This function uses the operation: reg1 = reg1 + operand. * Where reg1 uses data register 0 thru 15, and holds value 2, and the * operand holds value 6. Result of reg1 should be 8. */pointer_short(){ register u_int dreg, r1, inst; u_int ms, ls, ms_exp, ls_exp; /* single precision short test */ for (r1 = 0; r1 < FPA_NSHORT_REGS; r1++) { /* 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(r1,STWO,SZERO)) return; inst = SP_ADD | SP_REG1(r1); if (write_fpa((u_int *)inst,SSIX,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) ? SEIGHT : 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 short test */ for (r1 = 0; r1 < FPA_NSHORT_REGS; r1++) { /* 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(r1,DTWO_M,DTWO_L)) return; inst = DP_ADD | DP_REG1(r1); if (write_fpa((u_int *)inst,DSIX_M,ON)) return; if (write_fpa((u_int *)DP_LSW,DSIX_L,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) ? DEIGHT_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 pointer 1 thru 3 using the extended instructions. * For single precision, it uses the operation: reg1 = op2 + (reg2 * op1). * Where reg1 uses data register 0 thru 14, and should hold result 9; * reg2 uses data register 1 thru 15, and holds value 4; * operand1 holds value 2, and operand2 holds value 1. * For double precision, it uses the operation: reg1 = reg3 + (reg2 * op1). * Where reg1 uses data register 0 thru 13, and should hold result 10; * reg2 uses data register 1 thru 14, and holds value 2; * reg3 uses data register 2 thru 15, and holds value 4; * operand1 holds value 3. */pointer_extend(){ register u_int dreg, r1, r2, r3, inst; u_int ms, ls, ms_exp, ls_exp; /* extended single precision test */ for (r1=0, r2=1; r2 < FPA_NSHORT_REGS; r1++, r2++) { /* 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,SFOUR,SZERO)) return; inst = XSP_R1_O2aR2xO | X_REG2(r2); if (write_fpa((u_int *)inst,STWO,ON)) return; inst = X_LSW | X_REG1(r1); if (write_fpa((u_int *)inst,SONE,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) ? SNINE : (dreg == r2) ? 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); } } /* extended double precision test */ for (r1=0, r2=1, r3=2; r3 < FPA_NSHORT_REGS; 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,DTWO_M,DTWO_L)) return; if (write_datareg(r3,DFOUR_M,DFOUR_L)) return; inst = XDP_R1_R3aR2xO | X_REG2(r2); if (write_fpa((u_int *)inst,DTHREE_M,ON)) return; inst = X_LSW| X_REG1(r1) | X_REG3(r3); if (write_fpa((u_int *)inst,DTHREE_L,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) ? DTEN_M : (dreg == r2) ? DTWO_M : (dreg == r3) ? 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 pointers 1 thru 4 using command register instructions. * This function uses the operation: reg1 = reg3 + (reg2 * reg4). * Where reg1 uses data register 0 thru 28, and should hold result 16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -