//D1SimDec.bcpl // Last edited: 4 June 1981 get "d1.d" get "d1sim.d" manifest [ get "d1dmux.d" ] external [ // OS Zero // MINIT0 @MBlock // MASM LCycle; GetField // D1ASM MIRtoIM; IMtoMIR // D1I0 @DMuxTab; @OldDMuxTab; DChecked; DWrong // D1CONFIG HaveMemC; HaveIFU // D1SimCon SimControl // D1SimAsm SimALU // D1SimMem SimMemory // D1SimMemX SimMemX // D1SimIfu SimIfu // Defined here DSimulate; oldoldFFfunc ] static [ oldoldFFfunc ]; //DSimulate checks the consistency of the signals read from the DMux after //a particular clock. Only signal values predictable from other DMux //(i.e., passive) signals are checked. The arguments are: // Tn Clock after which DMux was read (0, 1, 2, or 3) // MIRvec Pointer to vector that was loaded into MIR by SimTest // for checking (argument not supplied by SimGo) //Detected errors are left in DWrong, and a count of errors detected is //returned. //When called by SimTest or SimGo, Tn is 2 and the checking includes //signals propagated from the prevous T0, for which DMuxTab was saved. //In these cases, RunRefresh is false. //**HOW THE SIMULATOR IS ORGANIZED** //Names beginning "old" are signal values at Tn-2. "T1" names are values //of T0-clocked signals just prior to the previous T1 (available for //Tn ge 1). "T2" names are values of T1-clocked signals prior to the //previous T0 (available for Tn ne 1). Names with no prefix are current //(Tn) signals. The program arranges to get the "T1xx" and "T2xx" signal //values from either DMuxTab or OldDMuxTab according to the value of Tn. //In other words, to predict the output of a T1-clocked flipflop whose //input is some logic function of input signals, the name "T1xx" would be //used for an input term "xx" clocked at T0, "oldxx" for an input clocked //at the previous T1. Similarly, the output of a T0-clocked flipflop //would be predicted from terms named "oldxx" (T0-clocked input), "T2xx" //(T1-clocked input). //When a signal is only valid or only predictable during one-half of the //cycle, then the simulator only predicts it when Tn is appropriate. //Double-clocked signals are an instance of this. Many other complications //result in conditional prediction, normally commented. let UnpackInstr(DVec,DTab,lvrstk) be [ MIRtoIM(DVec,DTab+dSaveMIR) let rstk,aluf,bsel,lc,asel = nil,nil,nil,nil,nil let block,ff,jcn = nil,nil,nil let FFok,FFfunc,BExt = nil,nil,nil let Hold,gMD,gMDI,SWx,NextMacro = nil,nil,nil,nil,nil rstk = GetField(0,4,DVec) aluf = GetField(4,4,DVec) bsel = GetField(10B,3,DVec) lc = GetField(13B,3,DVec) asel = GetField(16B,3,DVec) block = GetField(21B,1,DVec) ff = GetField(22B,10B,DVec) jcn = GetField(32B,10B,DVec) //**It would be better to use the independently mufflered values of //**FFok' on ProcH, ProcL, and ContA. Consequence of using the predicted //**value is that if any FFok' signal should fail, some extraneous errors //**are produced FFok = (bsel < 4) & (jcn ge 20B) FFfunc = (asel < 4 ? ff & 77B,ff) & FFok BExt = DTab>>P1.BgExt ne 0 Hold = HaveMemC ? (DTab!dHOLD & #7000) ne #7000,DTab>>P0.Holda gMD = DTab>>P1.gMD gMDI = DTab>>P1.gMDI SWx = DTab>>C.bSWdx NextMacro = DTab>>P1.NextMacro MBlock(lvrstk,lv rstk,16) ] //**Should check MIR against IMOUT on SimGo call of DSimulate. and DSimulate(Tn,IMvec; numargs NA) = valof [ let Correct,T = DWrong,nil //Initialize Correct to values read from the hardware. If a particular //bit is not checked this time, then that bit in Correct is not modified, //so no error is produced. MBlock(Correct,DMuxTab,200B) let Tneven = (Tn & 1) eq 0 let DVec = vec 4 //Check MIR against load on SimTest. if NA > 1 do [ IMtoMIR(DVec,IMvec) MBlock(Correct+dSaveMIR,DVec,4) ] //Instruction fields from MIR are a foundation for much of the checking let rstk,aluf,bsel,lc,asel = nil,nil,nil,nil,nil let block,ff,jcn,FFok,FFfunc = nil,nil,nil,nil,nil let BExt,Hold,gMD,gMDI = nil,nil,nil,nil let SWx,NextMacro = nil,nil UnpackInstr(DVec,DMuxTab,lv rstk) //This stuff is irrelevant but harmless for Tn < 2. let oldrstk,oldaluf,oldbsel,oldlc,oldasel = nil,nil,nil,nil,nil let oldblock,oldff,oldjcn,oldFFok,oldFFfunc = nil,nil,nil,nil,nil let oldBExt,oldHold,oldgMD,oldgMDI = nil,nil,nil,nil let oldSWx,oldNextMacro = nil,nil UnpackInstr(DVec,OldDMuxTab,lv oldrstk) let T1aluf,T1bsel,T1asel = nil,nil,nil let T1ff,T1FFok,T1FFfunc,T1BExt = nil,nil,nil,nil let T1DTab = nil let T2DTab,HoldDly = nil,nil test Tneven ifso [ T1aluf,T1bsel,T1asel = oldaluf,oldbsel,oldasel T1ff,T1FFok,T1FFfunc,T1BExt = oldff,oldFFok,oldFFfunc,oldBExt T1DTab = OldDMuxTab T2DTab,HoldDly = DMuxTab,Hold ] ifnot [ T1aluf,T1bsel,T1asel = aluf,bsel,asel T1ff,T1FFok,T1FFfunc,T1BExt = ff,FFok,FFfunc,BExt T1DTab = DMuxTab T2DTab,HoldDly = OldDMuxTab,oldHold ] //HoldReq will consist of StkError on the processor, the TaskingOff //term on ContA (computed by SimControl), the IfuHoldReq term on ContA //(computed by SimIfu), the hold simulator (not computed), and //external hold requests (presently none). let HoldReq = DMuxTab>>P1.StkError let T2DoCBr,T2RepeatCur = nil,nil let RepeatCur = SimControl(Tn,Correct,T1DTab,T2DTab,Tneven, block,ff,jcn,FFfunc,oldblock,oldjcn,oldFFfunc, lv T2RepeatCur,lv T2DoCBr,lv HoldReq) //Have to disable memory and IFU simulation for Tn ge 2 when doing //multiphase instructions, so let MemIfuTn = (oldjcn & 347B) eq 147B ? Tn & 1,Tn let cIfuMARvalx = HaveIFU ? SimIfu(MemIfuTn,Correct,Tneven,FFfunc,asel, oldNextMacro & not T2DoCBr, OldDMuxTab>>P1.NextDatax xor 1,HoldDly,oldFFfunc, T1DTab,T1FFfunc,T2DTab,lv HoldReq,NextMacro), DMuxTab!dMAR let cMBBypass = NextMacro let RBaseWriteEnx = DMuxTab>>P1.RBaseWriteEnx let CurreqNextx = DMuxTab>>P0.CurreqNextx let NoSwitchOrHold = (not CurreqNextx) & (not Hold) let cSelRBaseWadrx = RepeatCur % (NoSwitchOrHold & (not RBaseWriteEnx) & (not Tneven)) Correct>>P1.SelRBaseWadrx = cSelRBaseWadrx //The following simulation is only done for Tn ge 1, but even if Tn eq 0, //it is still possible to check signals duplicated on several boards for //consistency. Hence, the code here derives a signal and stores its //value in one place. Then outside the Tn ge 1 conditional, the value //in that place is copied to all others where it appears. if Tn ge 1 do [ //**Simulation of stuff derived from values at Tn-2** if Tn ge 2 do [ let cBCWriteEnx,cMBWriteEnx = 0,not oldNextMacro let ChkRbWadr,RbWadr = 17B,oldrstk //Predict lc bits from table with bits aligned with muffler bits: // RbWriteEnx = 20040 (-1, -1, 0, -1, 0, 0, 0, 0) // TbWriteEnx = 2004 (-1, 0, 0, 0, -1, 0, -1, 0) // TbSelMd = 1002 (oldlc eq 2) % (oldlc eq 3) // RbSelMd = 10020 (oldlc & 2) eq 0 let clcstuff = table [ 32064B; 30060B; 1002B; 21042B; 12024B; 10020B; 2004B; 0 ] !oldlc switchon oldFFfunc rshift 3 into [ case 4B to 5B: RbWadr = oldff & 17B; endcase case 22B to 23B: RbWadr<>P1.BCWriteEnx = cBCWriteEnx Correct>>P1.MBWriteEnx = cMBWriteEnx Correct>>P0.IOBoutSaved = OldDMuxTab>>P0.IOBout Correct>>P1.RbWadr = (RbWadr & ChkRbWadr)+ (DMuxTab>>P1.RbWadr & not ChkRbWadr) Correct>>P0.CkMdParityx = ((not oldgMD) % HoldDly) & ((not gMDI) % Hold) ] //**Beginning of simulation for signals clocked at T1** let cT1Shiftx = T1asel ne 7 let cT1AmuxMd,cT1AmuxIFU,cT1AmuxSC = 0,0,0 let cT1AmuxQ,cT1AmuxT,cT1AmuxEnx = 0,0,not cT1Shiftx let cT1MarMuxEn = 0 switchon T1asel into [ case 5: cT1AmuxIFU = -1; endcase case 6: cT1AmuxT = -1; endcase case 2 to 3: switchon (T1FFok ? T1ff rshift 6,3) into [ case 0: cT1AmuxMd = -1; endcase case 1: cT1AmuxIFU = -1; endcase case 2: cT1AmuxQ = -1; endcase case 3: cT1AmuxT = -1; endcase ] case 0 to 1: cT1MarMuxEn = -1 case 4: case 7: endcase ] let T1NextMacrox = not T1DTab>>P1.NextMacro let cT1IOBout,cT1IOBinx = 0,-1 let cT1ShcWriteEnx,cT1TIOAWriteEnx = -1,-1 let cT1LdHoldSimx = -1 let cT1QshiftR = T1BExt & (T1bsel eq 3) let cT1QshiftL = cT1QshiftR let cT1ShiftBitsEnx = 4000B let cT1Pmux,cT1MBMux = 0,0 let cT1RBaseWriteEnx = T1NextMacrox let cT1BmuxEnx = 0 let T1F2 = T1FFfunc & 17B //ALU simulation could be completed at Tn eq 0 except for the effects //of ALU shifts and Carry20 (**muffle Carry20?**). let lshiftmask,rshiftmask,alushiftbit = -1,-1,0 let aluCorrect,aluOverflow,aluCarryOut = nil,nil,nil let aluArithmetic = SimALU(lv aluOverflow,lv aluCarryOut,lv aluCorrect,0) if T1FFok do [ switchon T1FFfunc rshift 3 into [ case 0B to 1B: cT1AmuxSC = -1 case 2B: if T1FFfunc < 24B then cT1AmuxEnx = 0; endcase case 12B: cT1MarMuxEn = -1; endcase case 16B to 17B: cT1BmuxEnx = 2004B; endcase case 20B to 21B: cT1RBaseWriteEnx = 0; endcase case 24B: cT1TIOAWriteEnx = 0; endcase case 27B: cT1ShiftBitsEnx = 0 case 26B: cT1Pmux = table [ 0000B; 0000B; 2004B; 2004B 0401B; 0401B; 3006B; 3407B 1403B; 1403B; 1403B; 1403B 1002B; 1002B; 1002B; 1002B ] !T1F2 endcase case 30B to 33B: cT1MBMux = 1 default: endcase ] switchon T1FFfunc into [ case 21B: cT1AmuxT = -1; endcase case 22B: cT1AmuxMd = -1; endcase case 23B: cT1AmuxQ = -1; endcase case 26B: SimALU(lv aluOverflow,lv aluCarryOut,lv aluCorrect,#20) endcase case 36B: cT1IOBout = 4010B; endcase case 37B: cT1MBMux = 2; endcase case 73B: cT1QshiftR = -1 case 150B: cT1QshiftL = -1; endcase case 151B: cT1QshiftR = -1; endcase case 106B to 107B: cT1RBaseWriteEnx = 0; endcase case 152B: cT1TIOAWriteEnx = 0; endcase case 154B: cT1LdHoldSimx = 0; endcase case 155B to 157B: cT1ShcWriteEnx = 0; endcase case 32B to 33B: cT1IOBinx,cT1Pmux = 0,2405B case 271B: alushiftbit = aluCorrect & 1; endcase //rcy case 72B: cT1ShiftBitsEnx,cT1Pmux = 0,1403B //multiply cT1QshiftR = -1 case 272B: test aluArithmetic //brsh ifso alushiftbit = aluCarryOut ifnot rshiftmask = 77777B; endcase case 273B: //arsh case 275B: alushiftbit = aluCorrect rshift 15 //lcy endcase case 276B to 277B: cT1QshiftL = -1 //divide, cdivide lshiftmask = 177776B; endcase case 250B to 253B: cT1MBMux = 3; endcase default: endcase ] ] //Pmux encodings are: // 0 ALU // 1 0's mask Cnt, or Pointers // 2 left shift // 3 right shift // 4 ALUFM // 5 Input // 6 TIOA&StkP // 7 Shc let Pmux = DMuxTab>>P0.Pmux //If not a shift or if Pmux odd, can predict shmv without knowing ShC let cSHMV = (Pmux & 1) ne 0 if cSHMV % (T1asel ne 7) do Correct!dSHMV = cSHMV let CheckALU = -1 let shmv = DMuxTab!dSHMV let alul1 = aluCorrect lshift 1 let alur1 = aluCorrect rshift 1 switchon Pmux into [ case 0: aluCorrect = aluCorrect & not shmv //Can't check all the bits if MD shift is in progress. if (Tn < 2) % ((oldaluf ge 10B) & (oldasel eq 7B)) then CheckALU = not shmv endcase //This simulates the hardware even when shmv is incorrect and for //any kind of shift case 2: aluCorrect = ((alul1 & not shmv)+(alur1 & shmv)) % alushiftbit CheckALU = lshiftmask; endcase case 3: aluCorrect = alur1+(alushiftbit lshift 15) CheckALU = rshiftmask; endcase default: CheckALU = 0; endcase ] CheckALU = SimALU1(CheckALU) Correct!dALUCON = (Correct!dALUCON & not CheckALU)+ (CheckALU & SimALU1(aluCorrect)) //SimIfu computes MAR' when Tn eq 2 or the actual value of MAR' for Tn ne 2 test cT1MarMuxEn ifso if cT1Shiftx then Correct!dMAR = not DMuxTab!dALUA ifnot Correct!dMAR = cIfuMARvalx let cT1Amux = (20040B & (cT1AmuxSC % cT1AmuxQ % cT1AmuxMd))+ (10020B & (cT1AmuxT % cT1AmuxQ % (cT1AmuxIFU & ((T1bsel & 3) ne 2)))) if (cT1Amux eq 20040B) & cT1AmuxSC then Correct!dALUA = (Correct!dALUA & not cT1Shiftx) % T1F2 let cT1Bmux = table [ 0; 401B; 1002B; 1403B; 0; 0; 0; 0 ] ! T1bsel if T1bsel ge 4 do [ let T1alub = (T1bsel & 1) ne 0 ? 177400B+T1ff,T1ff test cT1Shiftx ifso Correct!dALUB = T1bsel < 6 ? T1alub,LCycle(T1alub,10B) ifnot cT1Bmux = 1403B ] //**Violate structures to save space here Correct!dABCON = cT1Amux+cT1IOBout+cT1Bmux+cT1BmuxEnx+ ((((cT1Amux & 40B) ne 0) % not cT1MarMuxEn) & 100200B)+ (cT1AmuxEnx & 40100B) //ALUFWriteEn' filled in later Correct!dQPDCON = ((not cT1QshiftL) & 100200B)+ ((not cT1QshiftR) & 40100B)+ (((cT1Pmux & 1) eq 0)&(((T1aluf & 4) eq 0)%cT1Shiftx)&20040B)+ ((cT1Shiftx % ((T1aluf & 2) eq 0)) & 10020B)+ cT1Pmux+cT1ShiftBitsEnx Correct>>P0.IOBinx = cT1IOBinx Correct>>P0.ShcWriteEnx = cT1ShcWriteEnx Correct>>P0.LdHoldSimx = cT1LdHoldSimx Correct>>P1.TIOAWriteEnx = cT1TIOAWriteEnx Correct>>P1.MBMux = cT1MBMux Correct>>P1.RBaseWriteEnx = cT1RBaseWriteEnx Correct>>P1.StkPSaveEnx = T1NextMacrox % Hold Correct>>P1.RBaseBypassx = not (cSelRBaseWadrx & (T1NextMacrox % Hold)) ] //**Simulation of unclocked signals** let cShiftx,cAmuxIFU,cAmuxMd = -1,0,0 switchon asel into [ case 5: cAmuxIFU = -1; endcase case 7: cShiftx = 0 case 0: case 1: case 6: case 4: endcase case 2: case 3: if FFok then switchon ff rshift 6 into [ case 0: cAmuxMd = -1; endcase case 1: cAmuxIFU = -1 case 2 to 3: endcase ] endcase ] let cRisIFdata,cTisIFdata = 0,0 if (bsel & 1) eq 0 then cRisIFdata = cAmuxIFU if (bsel & 3) ne 2 then cTisIFdata = cAmuxIFU let cLoadCntx,cTIOABypass = -1,0 let cALUFWriteEnx,cReSchedWrEnx,cLdTaskSimx = -1,-1,-1 let cStkSel = block & (not DMuxTab>>P0.EMUx) let cStkPWriteEnx = not cStkSel let cStkPMux1 = 0 let cBumpRSTK,cBumpRBase = 0,0 let cBExt = 0 switchon FFfunc rshift 3 into [ case 4B to 5B: cBumpRSTK = -1; endcase case 16B to 17B: cBExt = -1; endcase case 22B to 23B: cBumpRBase = -1; endcase case 24B: cTIOABypass = -1; endcase case 25B: if FFfunc ge 254B then endcase case 30B to 33B: cMBBypass = -1; endcase case 34B to 35B: cLoadCntx = 0 default: endcase ] let cgMDI = ((not cShiftx) & (aluf ge 10B)) % ((bsel eq 0) & not cBExt) % cAmuxMd switchon FFfunc into [ case 22B: cAmuxMd,cgMDI = -1,-1; endcase case 34B: cRisIFdata = -1; endcase case 35B: cTisIFdata = -1; endcase case 37B: case 105B: case 107B: cMBBypass = -1; endcase case 132B to 133B: cReSchedWrEnx = 0; endcase case 145B: cStkPMux1 = 1 case 144B: cStkPWriteEnx = 0; endcase case 146B: cLoadCntx = 0; endcase case 152B: cTIOABypass = -1; endcase case 154B: cLdTaskSimx = 0; endcase case 262B: cALUFWriteEnx = 0 default: endcase ] Correct>>P1.FFokxb = not FFok Correct>>P1.RisIFdata = cRisIFdata Correct>>P1.TisIFdata = cTisIFdata Correct>>P1.NextDatax = (not cRisIFdata) & (not cTisIFdata) Correct>>P1.FFmem = (ff rshift 6) % (not FFok) Correct>>P1.gMDI = cgMDI Correct>>P1.gMD = table [ 0; 0; 1; 1; 1; 1; 0; 0 ] !lc Correct>>P1.BgExt = cBExt Correct!dPJUNK = MaskPut(Correct+dPJUNK,066377B) Correct>>C.bFFokxc = not FFok let cFAx = FFok ? table [ 7B; 13B; 15B; 16B ] !(FFfunc rshift 6),17B Correct>>C.FAeq01x = cFAx rshift 2 Correct>>P0.FAx = cFAx Correct>>P0.Shiftx = cShiftx Correct>>P0.FFshiftx = cShiftx % (bsel < 4B) Correct>>P0.StkSela = cStkSel Correct>>P1.BumpRBase = cBumpRBase Correct>>P1.BumpRSTK = cBumpRSTK Correct>>P1.StkPMux1 = cStkPMux1 Correct>>P1.StkPWriteEnx = cStkPWriteEnx Correct>>P0.LoadCntx = cLoadCntx Correct>>P0.ALUFWriteEnx = cALUFWriteEnx Correct>>P0.LdTaskSimx = cLdTaskSimx Correct>>P1.ReSchedWrEnx = cReSchedWrEnx Correct>>P1.TIOABypass = cTIOABypass & NoSwitchOrHold Correct>>P1.MBBypass = cMBBypass & NoSwitchOrHold if DMuxTab>>P0.DecCntx eq 1 then Correct>>P0.PropCntx = 1 test DMuxTab>>P0.BmuxEnx ne 0 ifso Correct!dALUB = not DMuxTab!dBMUX //Ext bmux to int ifnot Correct!dBMUX = DMuxTab!dALUB //Int bmux to ext if Tn ne 1 do [ let TbBypass = (not DMuxTab>>P0.LasteqCurrx) & (not HoldDly) & (not DMuxTab>>P1.TbWriteEnx) & (not cTisIFdata) Correct!dRTSB = (TbBypass & 1) ne 0 ? Correct!dRTSB % 401B,Correct!dRTSB & 177376B ] if HaveMemC do [ let T2StartMap = SimMemory(MemIfuTn,Correct,Tneven,DMuxTab>>P1.FFmem, asel,gMD,gMDI,T2RepeatCur,SWx,OldDMuxTab>>P1.FFmem, oldasel,oldgMD,oldgMDI,oldSWx,DMuxTab>>P0.gMDSaved ne 0, T1FFfunc,HoldReq,Hold,oldHold) Correct>>C.bHoldA = Hold Correct>>P0.Holda = Hold SimMemX(MemIfuTn,Correct,T2DTab,T2StartMap,T1FFfunc) ] //Copy values computed for ProcL into equivalent bits for ProcH MaskPut(Correct+dPRFA,377B) MaskPut(Correct+dSCCON,110777B) let NWrong = 0 for I = 0 to 177B do [ let Bad = (DMuxTab!I xor Correct!I) & DChecked!I DWrong!I = Bad while Bad ne 0 do //Count 1's in Bad [ NWrong = NWrong+1 Bad = Bad - (Bad & -Bad) ] ] //d1simifu needs this to check for IFUM write in progress. oldoldFFfunc = oldFFfunc resultis NWrong ] and MaskPut(Vec,Mask) be [ rv Vec = ((rv Vec) & Mask)+(((rv Vec) lshift 8) & not Mask) ] //Fill in Pdata00, 04, 08, and 12 of ALUCON for the selected table and SimALU1(val) = (val & 100000B)+ ((val & 4000B) lshift 3)+ ((val & 200B) rshift 1)+ ((val & 10B) lshift 2)