<> <> <> DIRECTORY Basics, Commander, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, Dragon, DragonRosemary, DragOpsCross, DragOpsCrossUtils, EqualCheck, IFU2, IFUPLA, IFUPLAFetchControl, IFUPLAFetchPreDecode, IFUPLAFetchDecode, IFUPLAInstrDecode, IFUPLAInterlock, IFUPLAMainControl, IFUPLAStackControl, IO, Ports, REFBit, Rope, Rosemary, UncountedAssignHack; IFU2Impl: CEDAR PROGRAM IMPORTS Basics, Commander, CoreClasses, CoreCreate, CoreOps, CoreProperties, DragonRosemary, DragOpsCrossUtils, EqualCheck, IFUPLA, IO, Rope, Rosemary, Ports, REFBit, UncountedAssignHack EXPORTS IFU2 = BEGIN OPEN IFU2, Core; IFUName: ROPE = Rosemary.Register[roseClassName: "IFU", init: IFUInit, evalSimple: IFUSimple]; PortData: TYPE = RECORD [ name: Core.ROPE, width: NAT _ 1, drive: Ports.Drive _ none ]; iITypes: ARRAY II OF PortData _ [ KBus: ["KBus", 32], EUAluOp2AB: ["EUAluOp2AB", 4, drive], EUCondSel2AB: ["EUCondSel2AB", 4, drive], EUCondition2B: ["EUCondition2B"], EURes3BisPBus3AB: ["EURes3BisPBus3AB", , drive], EUWriteToPBus3AB: ["EUWriteToPBus3AB", , drive], -- EU DPCmdA: ["DPCmdA", 8, drive], -- Data cache DPRejectB: ["DPRejectB"], DPFaultB: ["DPFaultB", 5], IPData: ["IPData", 32], -- Instruction cache IPCmdA: ["IPCmdA", 8, drive], IPRejectB: ["IPRejectB"], IPFaultB: ["IPFaultB", 5], DrShA: ["DrShA"], DrShB: ["DrShB"], DrShRd: ["DrShRd"], DrShWt: ["DrShWt"], DrShIn: ["DrShIn"], DrShOut: ["DrShOut"], PhA: ["PhA"], PhB: ["PhB"], ResetAB: ["ResetAB"], RescheduleAB: ["RescheduleAB"] ]; IFUPre: PUBLIC ModuleSimProc = BEGIN OPEN state; LoadStage1Ac _ ph=a AND wantNewMicro0BA; -- set conditional pipeline advance clocks LoadStage1Bc _ ph=b AND NOT stage1BHoldingAB; LoadStage2Ac _ ph=a AND (NOT (DPRejectedBA -- AND Stage1BHoldIfRejectBA -- ) OR ResetBA); LoadStage3Ac _ ph=a AND (NOT DPRejectedBA OR ResetBA); IF ph=a THEN { stage1BHoldingAB _ (EUCondEffect1BA # bubble AND (Stage1BHoldBA OR (DPRejectedBA -- AND Stage1BHoldIfRejectBA -- ))) OR ResetBA; }; IF ph=b THEN { ResetBA _ p[II[ResetAB].ORD].b; DPRejectedBA _ p[II[DPRejectB].ORD].b; }; IF p[II[DrShA].ORD].b THEN { inputBit: BOOL = p[II[DrShIn].ORD].b; DragonRosemary.Assert[ NOT p[II[DrShRd].ORD].b, "Error in IFU shifter clocking sequence" ]; IF NOT p[II[DrShB].ORD].b THEN { -- shift drShifterAB from drShifterBA drShifterAB.bits[0] _ inputBit; FOR i: NAT IN [1..drShifterAB.size) DO drShifterAB.bits[i] _ NOT drShifterBA.bits[i-1]; ENDLOOP; } ELSE { -- mass copy drShifterAB from DrShIn FOR i: NAT IN [0..drShifterAB.size) DO drShifterAB.bits[i] _ NOT inputBit; ENDLOOP; }; }; DragonRosemary.Assert[ NOT (p[II[DrShRd].ORD].b AND p[II[DrShWt].ORD].b), "Error in IFU shifter clocking sequence"]; IF p[II[DrShWt].ORD].b THEN -- broadside copy from shift register FOR pla: IFUPLA.PLAs IN IFUPLA.PLAs DO FOR sense: IFUPLA.Sense IN IFUPLA.Sense DO IF plaOffsets[pla][sense] > 0 THEN { offset: NAT = plaOffsets[pla][sense]; buf: REF ANY = plaBuffers[pla][sense]; FOR i: NAT IN [0..IFUPLA.plaSizes[pla][sense]) DO REFBit.Set[buf, i, drShifterAB.bits[offset+i]]; ENDLOOP; }; ENDLOOP; ENDLOOP; END; IFUPreRef: ModSim _ NEW[ModSimRec _ [IFUPre]]; IFUPost: PUBLIC ModuleSimProc = BEGIN OPEN state; NormalStage2B2AB _ NOT AbortStage2B2AB; -- set default multiplexer stages NormalStage2A1BA _ NOT BubbleStage2A1BA; NormalStage2A1BA _ NOT BubbleStage2A1BA; NormalStage3A2BA _ NOT AbortStage3A2BA; IF p[II[DrShRd].ORD].b THEN -- broadside copy into shift register FOR pla: IFUPLA.PLAs IN IFUPLA.PLAs DO FOR sense: IFUPLA.Sense IN IFUPLA.Sense DO IF plaOffsets[pla][sense] > 0 THEN { offset: NAT = plaOffsets[pla][sense]; buf: REF ANY = plaBuffers[pla][sense]; FOR i: NAT IN [0..IFUPLA.plaSizes[pla][sense]) DO drShifterAB.bits[offset+i] _ NOT REFBit.Get[buf, i]; ENDLOOP; }; ENDLOOP; ENDLOOP; IF p[II[DrShB].ORD].b THEN { -- shift drShifterBA from drShifterAB FOR i: NAT IN [0..drShifterAB.size) DO drShifterBA.bits[i] _ NOT drShifterAB.bits[i]; ENDLOOP; }; p[II[DrShOut].ORD].b _ drShifterBA.bits[drShifterAB.size-1]; END; IFUPostRef: ModSim _ NEW[ModSimRec _ [IFUPost]]; IFUInstrDecode: PUBLIC ModuleSimProc = BEGIN OPEN state; X1ASrcSLimitAc _ ph=a AND x1ASrcSLimitBA; X1ADstSLimitAc _ ph=a AND x1ADstSLimitBA; SELECT ph FROM a => { PCBusSrcB _ offSetPC; -- precharge }; postA => { IF NOT drShWt THEN NARROW[plaBuffers[instrDecode0][input], REF IFUPLAInstrDecode.InstrDecodeIn]^ _ [ state: StateAB, instReady: InstReadyAB, op: DragOpsCross.Inst[VAL[OpAB]], alpha: AlphaAB, beta: BetaAB, pushPending: PushPendingAB, popPending: PopPendingAB, userMode: UserMode0AB ]; <> }; b => { nextMacroBA: IFUPLAInstrDecode.NextMacro; preEUAluOp0BA: Dragon.ALUOps; aluOpIs47BA: BOOL; preEUCondSel0BA: Dragon.CondSelects; condSelIsOp57BA: BOOL; preDPCmnd0BA: Dragon.PBusCommands; preDPCmndSel0BA: IFUPLAInstrDecode.DPCmndSel; PLAEval[state, instrDecode0]; -- all precharged PLAEval[state, instrDecode1]; PLAEval[state, instrDecode2]; PLAEval[state, instrDecode3]; PLAEval[state, instrDecode4]; PLAEval[state, instrDecode5]; PLAEval[state, instrDecode6]; [ instStarting0: InstStarting0BA, nextMacro: nextMacroBA, macroJump: MacroJumpBA, pcNext: PCNextBA, pcBusSrc: PCBusSrcB, pcPipeSrc: PCPipeSrcBA, x2ALitSource: X2ALitSourceBA, kPadsIn: KPadsIn0BA, push: Push0BA ] _ NARROW[plaBuffers[instrDecode0][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [ microCycleNext: MicroCycleNextBA, clearTrapsEnbled: ClearTrapsEnbledBA, clearUserMode: ClearUserModeBA, pop: Pop0BA, dpCmnd: preDPCmnd0BA, dpCmndIsRd: DPCmndRd0BA, dpCmndSel: preDPCmndSel0BA ] _ NARROW[plaBuffers[instrDecode1][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [aReg: [ASourceLtBA, ASourceRtBA, ASourceOffBA, ASourceModBA] ] _ NARROW[plaBuffers[instrDecode2][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [bReg: [BSourceLtBA, BSourceRtBA, BSourceOffBA, BSourceModBA] ] _ NARROW[plaBuffers[instrDecode3][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [ kIsRtOp: KIsRtOp0BA, fCtlIsRtOp: FCtlIsRtOp0BA, pushSc: PushSc0BA, cReg: [CSourceLtBA, CSourceRtBA, CSourceOffBA, CSourceModBA] ] _ NARROW[plaBuffers[instrDecode4][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [ lSource: [LSourceLtBA, LSourceRtBA], sSource: [SSourceLtBA, SSourceRtBA], popSa: PopSa0BA, popSb: PopSb0BA ] _ NARROW[plaBuffers[instrDecode5][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; [ aluOp: preEUAluOp0BA, aluOpIsOp47: aluOpIs47BA, condSel: preEUCondSel0BA, condSelIsOp57: condSelIsOp57BA, condEffect: EUCondEffect0BA, x1ASrcSLimit: x1ASrcSLimitBA, x2ASrcStatus: X2ASrcStatusBA, x1ASrcStack: X1ASrcStackBA, x1ADstSLimit: x1ADstSLimitBA, x1ADstStatus: X1ADstStatusBA, x1ADstStack: X1ADstStackBA, xBusStackEldest: XBusStackEldestBA, xBusStackL: XBusStackLBA, cRegIsField: CIsField0BA ] _ NARROW[plaBuffers[instrDecode6][output], REF IFUPLAInstrDecode.InstrDecodeOut]^; DPCmnd0BA _ SELECT preDPCmndSel0BA FROM beta => LOOPHOLE[BetaAB], ENDCASE => preDPCmnd0BA; EUAluOp0BA _ IF aluOpIs47BA THEN LOOPHOLE[OpAB MOD 16] ELSE preEUAluOp0BA; EUCondSel0BA _ IF condSelIsOp57BA THEN LOOPHOLE[OpAB MOD 8] ELSE preEUCondSel0BA; X2ASrcLit0BA _ X2ALitSourceBA # none; GetNextInstBA _ nextMacroBA=get; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUInstrDecodeRef: ModSim _ NEW[ModSimRec _ [IFUInstrDecode]]; IFUMainControl: PUBLIC ModuleSimProc = BEGIN OPEN state; SELECT ph FROM a => { PLAEval[state, mainControl]; -- precharged [ abortPipe: abortPipeAB, microExcptJmp: MicroExcptJmpAB, exceptionCode: ExceptionCodeAB ] _ NARROW[plaBuffers[mainControl][output], REF IFUPLAMainControl.MainControlOut]^; wantNewMicro0AB _ MicroExcptJmpAB # bubble; AbortStage2B2AB _ abortPipeAB; microCycleAB _ microCycleBA; MicroCycleAB _ (SELECT MicroExcptJmpAB FROM none => microCycleBA, microJump => 64, bubble => 112, resetting => 116, trap => 120, cJump => 124, ENDCASE => ERROR IFUInconsistent); }; postA => NULL; b => { wantNewMicro0BA _ wantNewMicro0AB; dpFaultedBA _ p[II[DPFaultB].ORD].c # Dragon.PBusFaults[none].ORD; euCondition2BA _ p[II[EUCondition2B].ORD].b; abortPipeBA _ abortPipeAB; willBeProtMicroCycBA _ MicroCycleAB>=112 AND (MicroCycleNextBA = next); stage2FailedBA _ ResetBA OR abortPipeBA OR (EUCondEffect2BA=macroTrap AND euCondition2BA) OR (TrapsEnbled2BA AND (EStkOverflow2BA OR (InstStarting2BA AND RschWaiting2BA) OR (Push2BA AND IStkNearlyFullBA) )); BubbleStage2A1BA _ Stage1BHoldBA OR stage2FailedBA; AbortStage3A2BA _ stage2FailedBA; microCycleBA _ SELECT MicroCycleNextBA FROM clear => 0, hold => microCycleAB, next => MicroCycleAB +1, ENDCASE => ERROR IFUInconsistent; }; postB => { IF NOT drShWt THEN NARROW[plaBuffers[mainControl][input], REF IFUPLAMainControl.MainControlIn]^ _ [ reseting: ResetBA, protMicroCyc: willBeProtMicroCycBA, dpFaulted: dpFaultedBA, dpRejected: DPRejectedBA, euCondition2: euCondition2BA, euCondEffect2: EUCondEffect2BA, stage1Hold: Stage1BHoldBA, <> condEffect1: EUCondEffect1BA, instStarting2: InstStarting2BA, ipFaulted2: IPFaulted2BA, trapsEnbled2: TrapsEnbled2BA, rschlWaiting2: RschWaiting2BA, eStkOverflow2: EStkOverflow2BA, iStkNearlyFull2: IStkNearlyFullBA, push2: Push2BA ]; }; ENDCASE => ERROR IFUInconsistent; END; IFUMainControlRef: ModSim _ NEW[ModSimRec _ [IFUMainControl]]; IFUControlPipe: PUBLIC ModuleSimProc = BEGIN OPEN state; SELECT ph FROM a => { IF LoadStage1Ac THEN ctlPipe1AB _ [ x2ASrcLit: X2ASrcLit0BA, push: Push0BA, pop: Pop0BA, kPadsIn: KPadsIn0BA, dpCmnd: DPCmnd0BA, aluOp: EUAluOp0BA, kIsRtOp: KIsRtOp0BA, condSel: EUCondSel0BA, condEffect: EUCondEffect0BA, fCtlIsRtOp: FCtlIsRtOp0BA, cIsField: CIsField0BA, res3BisPBus: DPCmndRd0BA, writeToPBus: (Basics.BITAND[DPCmnd0BA.ORD, Dragon.wrt] = Dragon.wrt), instFault: IPFaulted0BA, firstMicro: InstStarting0BA ]; IF LoadStage2Ac THEN ctlPipe2AB _ (SELECT TRUE FROM NormalStage2A1BA => [ x2ASrcLit: ctlPipe1BA.x2ASrcLit, push: ctlPipe1BA.push, pop: ctlPipe1BA.pop, kPadsIn: ctlPipe1BA.kPadsIn, dpCmnd: ctlPipe1BA.dpCmnd, aluOp: ctlPipe1BA.aluOp, condSel: ctlPipe1BA.condSel, condEffect: ctlPipe1BA.condEffect, cIsField: ctlPipe1BA.cIsField, res3BisPBus: ctlPipe1BA.res3BisPBus, writeToPBus: ctlPipe1BA.writeToPBus, eStkOverflow: EStkOverflow1BA, st3AisCBus: EUSt3AisCBus1BA, instFault: ctlPipe1BA.instFault, firstMicro: ctlPipe1BA.firstMicro ], BubbleStage2A1BA => [ x2ASrcLit: FALSE, push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, aluOp: Or, condSel: False, condEffect: bubble, cIsField: FALSE, res3BisPBus: FALSE, writeToPBus: FALSE, eStkOverflow: FALSE, st3AisCBus: FALSE, instFault: FALSE, firstMicro: FALSE ], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN ctlPipe3AB _ (SELECT TRUE FROM NormalStage3A2BA => [ push: ctlPipe2BA.push, pop: ctlPipe2BA.pop, kPadsIn: ctlPipe2BA.kPadsIn, dpCmnd: ctlPipe2BA.dpCmnd, condSel: ctlPipe2BA.condSel, cIsField: ctlPipe2BA.cIsField, res3BisPBus: ctlPipe2BA.res3BisPBus, writeToPBus: ctlPipe2BA.writeToPBus ], AbortStage3A2BA => [ push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, condSel: ctlPipe2BA.condSel, cIsField: FALSE, res3BisPBus: FALSE, writeToPBus: FALSE ], ENDCASE => ERROR IFUInconsistent); PushPendingAB _ ctlPipe1AB.push OR ctlPipe2AB.push OR ctlPipe3AB.push; PopPendingAB _ ctlPipe1AB.pop OR ctlPipe2AB.pop OR ctlPipe3AB.pop; X2ASrcLit1BA _ ctlPipe2AB.x2ASrcLit; p[II[EUAluOp2AB].ORD].c _ ctlPipe2AB.aluOp.ORD; p[II[EUCondSel2AB].ORD].c _ ctlPipe2AB.condSel.ORD; EUCondEffect2AB _ ctlPipe2AB.condEffect; CIsField2AB _ ctlPipe2AB.cIsField; EUCondSel3AB _ ctlPipe3AB.condSel; DPCmnd3A _ IF DPRejectedBA THEN NoOp ELSE ctlPipe3AB.dpCmnd; p[II[DPCmdA].ORD].c _ DPCmnd3A.ORD; p[II[EURes3BisPBus3AB].ORD].b _ ctlPipe3AB.res3BisPBus; p[II[EUWriteToPBus3AB].ORD].b _ ctlPipe3AB.writeToPBus; CIsField3AB _ ctlPipe3AB.cIsField; }; postA => NULL; b => { IF LoadStage1Bc THEN ctlPipe1BA _ [ x2ASrcLit: ctlPipe1AB.x2ASrcLit, push: ctlPipe1AB.push, pop: ctlPipe1AB.pop, kIsRtOp: ctlPipe1AB.kIsRtOp, dpCmnd: ctlPipe1AB.dpCmnd, aluOp: ctlPipe1AB.aluOp, kPadsIn: ctlPipe1AB.kPadsIn, condSel: ctlPipe1AB.condSel, condEffect: ctlPipe1AB.condEffect, fCtlIsRtOp: ctlPipe1AB.fCtlIsRtOp, cIsField: ctlPipe1AB.cIsField, res3BisPBus: ctlPipe1AB.res3BisPBus, writeToPBus: ctlPipe1AB.writeToPBus, instFault: ctlPipe1AB.instFault, firstMicro: ctlPipe1AB.firstMicro ]; ctlPipe2BA _ (SELECT TRUE FROM NormalStage2B2AB => [ push: ctlPipe2AB.push, pop: ctlPipe2AB.pop, kPadsIn: ctlPipe2AB.kPadsIn, dpCmnd: ctlPipe2AB.dpCmnd, condSel: ctlPipe2AB.condSel, condEffect: ctlPipe2AB.condEffect, cIsField: ctlPipe2AB.cIsField, res3BisPBus: ctlPipe2AB.res3BisPBus, writeToPBus: ctlPipe2AB.writeToPBus, eStkOverflow: ctlPipe2AB.eStkOverflow, st3AisCBus: ctlPipe2AB.st3AisCBus, instFault: ctlPipe2AB.instFault, firstMicro: ctlPipe2AB.firstMicro ], AbortStage2B2AB => [ push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, condSel: False, condEffect: bubble, cIsField: FALSE, res3BisPBus: FALSE, writeToPBus: FALSE, eStkOverflow: FALSE, st3AisCBus: FALSE, instFault: FALSE, firstMicro: FALSE ], ENDCASE => ERROR IFUInconsistent); ctlPipe3BA _ [ push: ctlPipe3AB.push OR (MicroExcptJmpAB = trap), pop: ctlPipe3AB.pop, kPadsIn: ctlPipe3AB.kPadsIn, cIsField: ctlPipe3AB.cIsField, res3BisPBus: ctlPipe3AB.res3BisPBus ]; KIsRtOp1BA _ ctlPipe1BA.kIsRtOp; FCtlIsRtOp1BA _ ctlPipe1BA.fCtlIsRtOp; EUCondEffect1BA _ ctlPipe1BA.condEffect; DPCmndRd2BA _ ctlPipe2BA.res3BisPBus; Push2BA _ ctlPipe2BA.push; EUCondEffect2BA _ ctlPipe2BA.condEffect; EStkOverflow2BA _ ctlPipe2BA.eStkOverflow; EUSt3AisCBus2BA _ ctlPipe2BA.st3AisCBus; IPFaulted2BA _ ctlPipe2BA.instFault; InstStarting2BA _ ctlPipe2BA.firstMicro; DPCmndRd3BA _ ctlPipe3BA.res3BisPBus; Push3BA _ ctlPipe3BA.push; Pop3BA _ ctlPipe3BA.pop; KPadsIn3BA _ ctlPipe3BA.kPadsIn; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUControlPipeRef: ModSim _ NEW[ModSimRec _ [IFUControlPipe]]; IFUFetch: PUBLIC ModuleSimProc = BEGIN OPEN state; PA4BFromCard: PROC [ in: [0..16) ] RETURNS [ out: PACKED ARRAY [0..4) OF BOOL ] = TRUSTED BEGIN out _ LOOPHOLE[in]; END; PA16BFromCard: PROC [ in: CARDINAL ] RETURNS [ out: PACKED ARRAY [0..16) OF BOOL ] = TRUSTED BEGIN out _ LOOPHOLE[in] END; ipf, notInstReady: BOOL; p[II[IPData].ORD].d _ (IF ph=a THEN drive ELSE none); SELECT ph FROM a => { wtAB _ wtBA; -- from FetchIndexing rdAB _ rdBA; IF NOT drShWt THEN NARROW[plaBuffers[fetchRdDecode][input], REF IFUPLAFetchDecode.FetchRdDecodeIn]^ _ [ fetchRd: rdBA MOD 16 ]; PLAEval[state, fetchRdDecode]; -- static IBufRdByteAc _ PA16BFromCard[NARROW[plaBuffers[fetchRdDecode][output], REF IFUPLAFetchDecode.FetchRdDecodeOut]^]; BufBytesOccM1A _ (4*wtBA-rdBA-1+64) MOD 32; jumpPendingAB _ jumpPendingBA; -- from FetchControl faultedAB _ faultedBA; FetchingAB _ fetchingBA; bufBytesOccM1AB _ BufBytesOccM1A; p[II[IPCmdA].ORD].c _ (IF newFetchBA THEN Dragon.PBusCommands[Fetch].ORD ELSE Dragon.PBusCommands[NoOp].ORD); p[II[IPData].ORD].lc _ fetchAddrBA/4; -- Byte to word happens here fetchAddrAB _ fetchAddrBA+(IF IncrPFetchAddrBA THEN 4 ELSE 0); -- byte offset in loc 30,31 <> <> <> <> <> <> <> <> OpAB _ preOpA _ iBuf[rdBA MOD 16]; AlphaAB _ preAlphaA _ iBuf[(rdBA+1) MOD 16]; BetaAB _ preBetaA _ iBuf[(rdBA+2) MOD 16]; GammaAB _ preGammaA _ iBuf[(rdBA+3) MOD 16]; DeltaAB _ preDeltaA _ iBuf[(rdBA+4) MOD 16]; }; postA => { IBufRdByteAc _ ALL[FALSE]; -- from FetchIndexing }; b => { IF NOT drShWt THEN NARROW[plaBuffers[fetchControl][input], REF IFUPLAFetchControl.FetchControlIn]^ _ [ jump: MacroJumpBA, getNext: FALSE, -- not used, formerly GetNextInstBA reset: ResetBA, reject: p[II[IPRejectB].ORD].b, jumpPending: jumpPendingAB, fetching: FetchingAB, bytesOccM1: bufBytesOccM1AB, faulted: faultedAB, ipPageFault: (p[II[IPFaultB].ORD].c = Dragon.PBusFaults[page].ORD) -- this may be a long path; it can be pipeline delayed ]; PLAEval[state, fetchControl]; -- static [ -- from FetchControl jumpPending: jumpPendingBA, newFetch: newFetchBA, fetching: fetchingBA, faulted: faultedBA, wtIndexCtl: FetchWtB ] _ NARROW[plaBuffers[fetchControl][output], REF IFUPLAFetchControl.FetchControlOut]^; IncrPFetchAddrBA _ newFetchBA; SELECT FetchWtB FROM -- from FetchIndexing clear => wtBA _ 0; hold => wtBA _ wtAB; inc => wtBA _ (wtAB+1) MOD 8; ENDCASE => ERROR IFUInconsistent; rdBA _ (SELECT TRUE FROM MacroJumpBA => PCBusB MOD DragOpsCross.bytesPerWord, GetNextInstBA => (rdAB+OpLengthAB) MOD 32, ENDCASE => rdAB); IF NOT drShWt THEN NARROW[plaBuffers[fetchWtDecode][input], REF IFUPLAFetchDecode.FetchWtDecodeIn]^ _ [ fetching: FetchingAB, fetchWt: wtAB MOD 4 ]; PLAEval[state, fetchWtDecode]; -- static IBufWrtWdBc _ PA4BFromCard[NARROW[plaBuffers[fetchWtDecode][output], REF IFUPLAFetchDecode.FetchWtDecodeOut]^]; OpLengthBA _ OpLengthAB; -- from FetchPreDecode fetchAddrBA _ (IF MacroJumpBA THEN PCBusB ELSE fetchAddrAB); -- from FetchAddr <> <> <> <> <> <> IF FetchingAB THEN { base: [0..16) = 4*(wtAB MOD 4); iWd: Basics.LongNumber; iWd.lc _ p[II[IPData].ORD].lc; iBuf[base+0] _ iWd.hh; iBuf[base+1] _ iWd.hl; iBuf[base+2] _ iWd.lh; iBuf[base+3] _ iWd.ll; }; preOpA _ 255; -- prechargefrom FetchBuffer preAlphaA _ 255; preBetaA _ 255; preGammaA _ 255; preDeltaA _ 255; }; postB => { IBufWrtWdBc _ ALL[FALSE]; -- from FetchIndexing }; ENDCASE => ERROR IFUInconsistent; IF NOT drShWt THEN NARROW[plaBuffers[fetchPreDecode][input], REF IFUPLAFetchPreDecode.FetchPreDecodeIn]^ _ [ preOp: VAL[OpAB], bytesOccM1: BufBytesOccM1A, fault: faultedAB ]; PLAEval[state, fetchPreDecode]; -- static [ -- from FetchPreDecode opLength: OpLengthAB, jumpOffset: JumpOffsetSelAB, notInstReady: notInstReady, doIPageFault: ipf ] _ NARROW[plaBuffers[fetchPreDecode][output], REF IFUPLAFetchPreDecode.FetchPreDecodeOut]^; DragonRosemary.Assert[(DragonRosemary.OpLength[OpAB] = OpLengthAB), "DragonRosemary.OpLength # IFUPLAFetchPreDecode.GenFetchPreDecodePLA.OpLength"]; InstReadyAB _ NOT notInstReady; IF ph=b THEN IPFaulted0BA _ ipf; END; IFUFetchRef: ModSim _ NEW[ModSimRec _ [IFUFetch]]; IFUKBusIn: PUBLIC ModuleSimProc = BEGIN OPEN state; IF ph=a AND KPadsIn3BA THEN XBus _ p[II[KBus].ORD].lc; END; IFUKBusInRef: ModSim _ NEW[ModSimRec _ [IFUKBusIn]]; IFULitGen: PUBLIC ModuleSimProc = BEGIN OPEN state; SELECT ph FROM a => { IF LoadStage1Ac THEN xaPipe1AB _ xaPipe0BA; IF X2ASrcLit1BA THEN XBus _ xaPipe1BA }; postA => NULL; b => { xaPipe0BA _ SELECT X2ALitSourceBA FROM alpha => AlphaAB, beta => BetaAB, alphaBeta => AlphaAB*LONG[256] + BetaAB, alpBetGamDel => ((AlphaAB*LONG[256] + BetaAB)*256 + GammaAB)*256 + DeltaAB, ENDCASE => AlphaAB; --changed by JH IF LoadStage1Bc THEN xaPipe1BA _ xaPipe1AB; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFULitGenRef: ModSim _ NEW[ModSimRec _ [IFULitGen]]; IFUStack: PUBLIC ModuleSimProc = BEGIN OPEN state; IF X1ADstStackBA THEN { -- static multiplexer pWrtBufA _ XBus; lWrtBufA _ XBus MOD 256; } ELSE { pWrtBufA _ PCPipe3BA; lWrtBufA _ LPipe3BA; }; SELECT ph FROM a => { adderMuxA: [0..32); addendA: [0..32); carryA: [0..1]; sumA: [0..32); PLAEval[state, stackAControl]; -- dynamic [ adjTos: AdjTosA, addendIsOnes: AddendIsOnesA, carryIsOne: CarryIsOneA ] _ NARROW[plaBuffers[stackAControl][output], REF IFUPLAStackControl.StackAControlOut]^; StkLdLAc _ stkLdLBA; StkLdPAc _ stkLdPBA; StkRdAc _ stkRdBA; adderMuxA _ IF AdjTosA THEN tosBA ELSE bosBA; addendA _ IF AddendIsOnesA THEN 31 ELSE 0; carryA _ IF CarryIsOneA THEN 1 ELSE 0; sumA _ (adderMuxA+addendA+carryA) MOD 32; TosAB _ tosAB _ SELECT TRUE FROM ResetBA => 0, AdjTosA => sumA, ENDCASE => tosBA; -- needed because AdjTosA might glitch BosAB _ bosAB _ SELECT TRUE FROM ResetBA => 1, NOT AdjTosA => sumA, ENDCASE => bosBA; -- needed because AdjTosA might glitch FOR index: NAT IN [0..16) DO IF StkLdLAc[index] THEN lStack[index] _ lWrtBufA; IF StkLdPAc[index] THEN pStack[index] _ pWrtBufA; ENDLOOP; IF Push3BA THEN { -- bypass DragonRosemary.Assert[NOT X1ADstStackBA]; pRdBufA _ pWrtBufA; -- or PCPipe3BA lRdBufA _ lWrtBufA; -- or LPipe3BA } ELSE FOR index: NAT IN [0..16) DO IF StkRdAc[index] THEN { lRdBufA _ lStack[index]; pRdBufA _ pStack[index] }; ENDLOOP; PCStkTopAB _ pRdBufA; LStkTopAB _ lRdBufA; IF X1ASrcStackBA THEN XBus _ (IF XBusStackLBA THEN lRdBufA ELSE pRdBufA); }; postA => {StkLdLAc _ StkLdPAc _ StkRdAc _ ALL[FALSE]}; b => { sdo: IFUPLAStackControl.StackDecodeOut; DifBA _ difBA _ (32+tosAB-bosAB) MOD 32; IF NOT drShWt THEN NARROW[plaBuffers[stackBControl][input], REF IFUPLAStackControl.StackBControlIn]^ _ [ diff: DifBA, push3: Push3BA, pop3: Pop3BA -- unused ]; PLAEval[state, stackBControl]; -- static [ iStkNearlyFull: IStkNearlyFullBA ] _ NARROW[plaBuffers[stackBControl][output], REF IFUPLAStackControl.StackBControlOut]^; IF NOT drShWt THEN NARROW[plaBuffers[stackDecode][input], REF IFUPLAStackControl.StackDecodeIn]^ _ [ diff: DifBA, -- unused tos: TosAB, bos: BosAB, x1ASrcStack: X1ASrcStackBA, x1ADstStack: X1ADstStackBA, xBusStackEldest: XBusStackEldestBA, xBusStackL: XBusStackLBA, push3: Push3BA, pop3: Pop3BA ]; PLAEval[state, stackDecode]; -- static sdo _ NARROW[plaBuffers[stackDecode][output], REF IFUPLAStackControl.StackDecodeOut]^; stkLdPBA _ LOOPHOLE[sdo.stkLdP]; stkLdLBA _ LOOPHOLE[sdo.stkLdL]; stkRdBA _ LOOPHOLE[sdo.stkRd]; tosBA _ tosAB; bosBA _ bosAB; }; postB => { IF NOT drShWt THEN NARROW[plaBuffers[stackAControl][input], REF IFUPLAStackControl.StackAControlIn]^ _ [ x1ASrcStack: X1ASrcStackBA, x1ADstStack: X1ADstStackBA, xBusStackEldest: XBusStackEldestBA, xBusStackL: XBusStackLBA, push3: Push3BA, pop3: Pop3BA ]; }; ENDCASE => ERROR IFUInconsistent; END; IFUStackRef: ModSim _ NEW[ModSimRec _ [IFUStack]]; IFUPC: PUBLIC ModuleSimProc = BEGIN OPEN state; <> <<>> <> SExtnd: PROC[b: Dragon.HexByte] RETURNS [INT] = { RETURN[ IF b>=128 THEN (LONG[b]-256) ELSE LONG[b]] }; SELECT ph FROM a => { pcSum _ OpLengthBA + pcBA; IF LoadStage1Ac THEN { pcPipe[1][a] _ pcBA; pcAltPipe[1][a] _ SELECT PCPipeSrcBA FROM seqPC => pcSum -- next sequential instruction -- , offSetPC => targetPCBA -- jump target instruction -- , thisPC => pcBA -- for traps that are recognized only at stage 0 -- , ENDCASE => ERROR IFUInconsistent; }; <> IF LoadStage2Ac THEN {pcPipe[2][a] _ pcPipe[1][b]; pcAltPipe[2][a] _ pcAltPipe[1][b]}; IF LoadStage3Ac THEN { pcPipe[3][a] _ (SELECT TRUE FROM AbortStage3A2BA => pcPipe[2][b], -- pc of aborting micro NormalStage3A2BA => pcAltPipe[2][b], -- whatever top of pipe suggested ENDCASE => ERROR IFUInconsistent) }; pcAB _ SELECT PCNextBA FROM incr => pcSum, fromPCBus => npcBA, ENDCASE => ERROR IFUInconsistent; PCForLogAB _ pcAB; dpFaultAB _ dpFaultBA; }; postA => NULL; b => { IF LoadStage1Bc THEN {pcPipe[1][b] _ pcPipe[1][a]; pcAltPipe[1][b] _ pcAltPipe[1][a]}; pcPipe[2][b] _ pcPipe[2][a]; pcAltPipe[2][b] _ pcAltPipe[2][a]; PCPipe3BA _ pcPipe[3][b] _ pcPipe[3][a]; pcBranchOSetB _ (SELECT JumpOffsetSelAB FROM alpha => SExtnd[AlphaAB], beta => SExtnd[BetaAB], alphaBeta => SExtnd[AlphaAB]*256 + BetaAB, xAB => xAB, ENDCASE => ERROR IFUInconsistent ); targetPCBA _ pcSum _ pcBranchOSetB + pcAB; pcBA _ pcAB; PCBusB _ npcBA _ (SELECT PCBusSrcB FROM offSetPC => pcSum, pc => pcAB, xA => xAB, xopGen => DragOpsCross.bytesPerWord*(DragOpsCross.XopBase + DragOpsCross.TrapWidthWords*OpAB), trapGen => DragOpsCross.bytesPerWord* (DragOpsCross.TrapBase+DragOpsCross.TrapWidthWords*( SELECT ExceptionCodeAB FROM cTrap => 20B -- = DragOpsCross.TrapIndex[ALUCondFalse].ORD -- +EUCondSel3AB.ORD, dpFault => 40B -- = DragOpsCross.TrapIndex[EUPageFault].ORD-1 -- +(dpFaultAB.ORD MOD 8), ENDCASE => ExceptionCodeAB.ORD MOD 20B)), alpBetGamDel => ((AlphaAB*LONG[256]+BetaAB)*256+GammaAB)*256+DeltaAB, pipe3 => PCPipe3BA, stack => PCStkTopAB, ENDCASE => ERROR IFUInconsistent); OpBA _ OpAB; AlphaBA _ AlphaAB; BetaBA _ BetaAB; dpFaultBA _ VAL[p[II[DPFaultB].ORD].c]; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUPCRef: ModSim _ NEW[ModSimRec _ [IFUPC]]; IFULS: PUBLIC ModuleSimProc = BEGIN OPEN state; DeltaSBA _ (256+(IF PushSc0BA THEN 1 ELSE 0)+(IF PopSa0BA THEN -1 ELSE 0)+(IF PopSb0BA THEN -1 ELSE 0)) MOD 256; SELECT ph FROM a => { LAB _ lAB _ lBA; SAB _ sAB _ sBA; IF LoadStage1Ac THEN { lPipe[1][a] _ lPipe[0][b]; sPipe[1][a] _ sPipe[0][b]; }; IF LoadStage2Ac THEN { lPipe[2][a] _ lPipe[1][b]; sPipe[2][a] _ sPipe[1][b]; }; IF LoadStage3Ac THEN { lPipe[3][a] _ lPipe[2][b]; sPipe[3][a] _ sPipe[2][b]; }; IF X1ADstSLimitAc THEN sLimitAB _ XBus; IF X1ASrcSLimitAc THEN XBus _ sLimitAB; }; postA => NULL; b => { lBusLtB, lBusRtB: Dragon.HexByte; sBusLt, sBusRt: Dragon.HexByte; lPipe[0][b] _ lAB; lBusLtB _ SELECT LSourceLtBA FROM l => LAB, s => SAB, zero => 0, l3 => lPipe[3][a], ENDCASE => ERROR IFUInconsistent; lBusRtB _ SELECT LSourceRtBA FROM zero => 0, alpha => AlphaBA, stack => LStkTopAB, one => 1, ENDCASE => ERROR IFUInconsistent; lBA _ (lBusLtB + lBusRtB) MOD 128; sPipe[0][b] _ sAB; sBusLt _ SELECT SSourceLtBA FROM s => SAB, l => LAB, s2 => sPipe[2][a], s3 => sPipe[3][a], ENDCASE => ERROR IFUInconsistent; sBusRt _ SELECT SSourceRtBA FROM deltaS => DeltaSBA, alpha => AlphaBA, zero => 0, one => 1, ENDCASE => ERROR IFUInconsistent; sBA _ (sBusLt+sBusRt+256) MOD 128; IF LoadStage1Bc THEN { lPipe[1][b] _ lPipe[1][a]; sPipe[1][b] _ sPipe[1][a]; }; lPipe[2][b] _ lPipe[2][a]; sPipe[2][b] _ sPipe[2][a]; LPipe3BA _ lPipe[3][b] _ lPipe[3][a]; EStkOverflow1BA _ ((SAB+(255-sLimitAB --NOT sLimitAB-- )+1) MOD 128) IN [0..16); }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFULSRef: ModSim _ NEW[ModSimRec _ [IFULS]]; IFUStatus: PUBLIC ModuleSimProc = BEGIN OPEN state; SELECT ph FROM a => { newstatusRec: DragOpsCross.IFUStatusRec _ DragOpsCrossUtils.WordToStatus[DragOpsCrossUtils.CardToWord[XBus]]; rsPipe[a] _ RescheduleBA; status[a] _ [ version: CurrentIFUVersion, rescheduleKeep: TRUE ]; status[a].reschedule _ (NOT X1ADstStatusBA AND status[b].reschedule) OR (X1ADstStatusBA AND newstatusRec.rescheduleKeep AND status[b].reschedule) OR (X1ADstStatusBA AND NOT newstatusRec.rescheduleKeep AND newstatusRec.reschedule) OR (RescheduleBA AND NOT rsPipe[b]); status[a].userMode _ (NOT ClearUserModeBA AND NOT X1ADstStatusBA AND status[b].userMode) OR (NOT ClearUserModeBA AND X1ADstStatusBA AND newstatusRec.userModeKeep AND status[b].userMode) OR (NOT ClearUserModeBA AND X1ADstStatusBA AND NOT newstatusRec.userModeKeep AND newstatusRec.userMode); status[a].trapsEnabled _ (NOT ClearTrapsEnbledBA AND NOT X1ADstStatusBA AND status[b].trapsEnabled) OR (NOT ClearTrapsEnbledBA AND X1ADstStatusBA AND newstatusRec.trapsEnabledKeep AND status[b].trapsEnabled) OR (NOT ClearTrapsEnbledBA AND X1ADstStatusBA AND NOT newstatusRec.trapsEnabledKeep AND newstatusRec.trapsEnabled); IF LoadStage1Ac THEN {x2ASrcStatus[a] _ X2ASrcStatusBA; statPipe[a] _ status[b]}; IF x2ASrcStatus[b] THEN { XBus _ DragOpsCrossUtils.WordToCard[DragOpsCrossUtils.StatusToWord[statPipe[b]]]; }; UserMode0AB _ status[a].userMode; }; postA => NULL; b => { status[b] _ status[a]; rsPipe[b] _ rsPipe[a]; IF LoadStage1Bc THEN {x2ASrcStatus[b] _ x2ASrcStatus[a]; statPipe[b] _ statPipe[a]}; RschWaiting2BA _ status[b].reschedule AND NOT X1ADstStatusBA; -- just in case TrapsEnbled2BA _ status[b].trapsEnabled AND NOT ClearTrapsEnbledBA; RescheduleBA _ p[II[RescheduleAB].ORD].b; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUStatusRef: ModSim _ NEW[ModSimRec _ [IFUStatus]]; IFUABC: PUBLIC ModuleSimProc = BEGIN OPEN state; noStore: Dragon.HexByte = DragOpsCross.ProcessorRegister[euJunk].ORD; SELECT ph FROM a => { aRegIsC2B _ aRegIsC3B _ bRegIsC2B _ bRegIsC3B _ TRUE; -- precharge IF LoadStage1Ac THEN { aPipe[1][a] _ aPipe[0][b]; bPipe[1][a] _ bPipe[0][b]; cPipe[1][a] _ cPipe[0][b]; }; a1BEarly1AB _ IF stage1BHoldingAB THEN aPipe[1][b] ELSE aPipe[1][a]; b1BEarly1AB _ IF stage1BHoldingAB THEN bPipe[1][b] ELSE bPipe[1][a]; IF LoadStage2Ac THEN cPipe[2][a] _ (SELECT TRUE FROM BubbleStage2A1BA => noStore, NormalStage2A1BA => cPipe[1][b], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN cPipe[3][a] _ (SELECT TRUE FROM AbortStage3A2BA => noStore, NormalStage3A2BA => cPipe[2][b], ENDCASE => ERROR IFUInconsistent); }; postA => NULL; b => { aBusLt, aBusRt: Dragon.HexByte; bBusLt, bBusRt: Dragon.HexByte; cBusLt, cBusRt: Dragon.HexByte; aBusLt _ SELECT ASourceLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, s => SAB, l => LAB, zero => 0, ENDCASE => ERROR IFUInconsistent; aBusRt _ SELECT ASourceRtBA FROM alpha => AlphaBA, alpha47 => AlphaBA MOD 16, op47 => OpBA MOD 16, beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, ENDCASE => SELECT ASourceOffBA FROM zero => 0, one => 1, two => 2, three => 3, minus4 => 256-4, minus3 => 256-3, minus2 => 256-2, minus1 => 256-1, ENDCASE => ERROR IFUInconsistent; aPipe[0][b] _ SELECT ASourceModBA FROM half => (aBusLt + aBusRt) MOD 128, full => (aBusLt + aBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; bBusLt _ SELECT BSourceLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, s => SAB, l => LAB, zero => 0, ENDCASE => ERROR IFUInconsistent; bBusRt _ SELECT BSourceRtBA FROM op47 => OpBA MOD 16, alpha => AlphaBA, alpha47 => AlphaBA MOD 16, beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, ENDCASE => SELECT BSourceOffBA FROM zero => 0, one => 1, two => 2, three => 3, minus4 => 256-4, minus3 => 256-3, minus2 => 256-2, minus1 => 256-1, ENDCASE => ERROR IFUInconsistent; bPipe[0][b] _ SELECT BSourceModBA FROM half => (bBusLt + bBusRt) MOD 128, full => (bBusLt + bBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; cBusLt _ SELECT CSourceLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, l => LAB, s => SAB, zero => 0, ENDCASE => ERROR IFUInconsistent; cBusRt _ SELECT CSourceRtBA FROM beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, op47 => OpBA MOD 16, alpha => AlphaBA, alpha47 => AlphaBA MOD 16, ENDCASE => SELECT CSourceOffBA FROM minus4 => 256-4, minus3 => 256-3, minus2 => 256-2, minus1 => 256-1, zero => 0, one => 1, two => 2, three => 3, ENDCASE => ERROR IFUInconsistent; cPipe[0][b] _ SELECT CSourceModBA FROM half => (cBusLt + cBusRt) MOD 128, full => (cBusLt + cBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; IF (a1BEarly1AB # cPipe[2][a]) THEN aRegIsC2B _ FALSE; IF (a1BEarly1AB # cPipe[3][a]) THEN aRegIsC3B _ FALSE; IF (b1BEarly1AB # cPipe[2][a]) THEN bRegIsC2B _ FALSE; IF (b1BEarly1AB # cPipe[3][a]) THEN bRegIsC3B _ FALSE; IF LoadStage1Bc THEN { aPipe[1][b] _ aPipe[1][a] -- ( = a1BEarly1AB ) -- ; bPipe[1][b] _ bPipe[1][a] -- ( = b1BEarly1AB ) -- ; cPipe[1][b] _ cPipe[1][a]; }; cPipe[2][b] _ (SELECT TRUE FROM AbortStage2B2AB => noStore, NormalStage2B2AB => cPipe[2][a], ENDCASE => ERROR IFUInconsistent); cPipe[3][b] _ (SELECT TRUE FROM dpFaultedAB => noStore, NOT dpFaultedAB => cPipe[3][a], ENDCASE => ERROR IFUInconsistent); AReg0BA _ aPipe[0][b]; BReg0BA _ bPipe[0][b]; CReg0BA _ cPipe[0][b]; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUABCRef: ModSim _ NEW[ModSimRec _ [IFUABC]]; IFUInterlock: PUBLIC ModuleSimProc = BEGIN OPEN state; SELECT ph FROM a, postA => NULL; b => { IF NOT drShWt THEN NARROW[plaBuffers[interlock][input], REF IFUPLAInterlock.InterlockIn]^ _ [ <> kIsRtOp: KIsRtOp1BA, fCtlIsRtOp: FCtlIsRtOp1BA, c2IsFieldCtl: CIsField2AB, c3IsFieldCtl: CIsField3AB, dpCmndRd2: DPCmndRd2BA, <> a1IsC2: aRegIsC2B, a1IsC3: aRegIsC3B, b1IsC2: bRegIsC2B, b1IsC3: bRegIsC3B ]; PLAEval[state, interlock]; -- static [ stage1BHold: Stage1BHoldBA, <> aluLt: EUAluLeftSrc1B, aluRt: EUAluRightSrc1B, st2A: EUStore2ASrc1B, st3AIsCbus: EUSt3AisCBus1BA ] _ NARROW[plaBuffers[interlock][output], REF IFUPLAInterlock.InterlockOut]^; XBus _ LOOPHOLE[RegAddrRec[ aAddr: aPipe[1][b], bAddr: bPipe[1][b], cAddr: cPipe[3][b], st3AisC: EUSt3AisCBus2BA, aluLeftSrc: EUAluLeftSrc1B, aluRightSrc: EUAluRightSrc1B, storeSrc: EUStore2ASrc1B ]]; }; postB => NULL; ENDCASE => ERROR IFUInconsistent; END; IFUInterlockRef: ModSim _ NEW[ModSimRec _ [IFUInterlock]]; IFUKBusOut: PUBLIC ModuleSimProc = BEGIN OPEN state; IF ph=a THEN xAB _ XBus; IF ph=b OR (ph=a AND NOT KPadsIn3BA) THEN {p[II[KBus].ORD].d _ drive; p[II[KBus].ORD].lc _ XBus} ELSE p[II[KBus].ORD].d _ none; END; IFUKBusOutRef: ModSim _ NEW[ModSimRec _ [IFUKBusOut]]; IFULogger: PUBLIC ModuleSimProc = BEGIN OPEN state; log: IO.STREAM _ NIL; NewDisposition: PROC [ pipeState: LogPipeState, disp: MicroInstDisposition ] RETURNS [ newPipeState: LogPipeState ] = { newPipeState _ pipeState; newPipeState.disposition _ disp; }; SELECT ph FROM a => { bHigh _ FALSE; dpRejectedAB _ DPRejectedBA; dpFaultedAB _ dpFaultedBA; IF LoadStage1Ac THEN opPipe[1][a] _ opPipe[0][b]; IF LoadStage2Ac THEN opPipe[2][a] _ (SELECT TRUE FROM NormalStage2A1BA => opPipe[1][b], BubbleStage2A1BA => NewDisposition[opPipe[1][b], interlocked], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN opPipe[3][a] _ (SELECT TRUE FROM NormalStage3A2BA => opPipe[2][b], AbortStage3A2BA => NewDisposition[opPipe[2][b], killed3a], ENDCASE => ERROR IFUInconsistent); }; postA => bHigh _ FALSE; b => { bHigh _ TRUE; opPipe[0][b] _ [ pc: PCForLogAB, op: VAL[OpAB], alpha: AlphaAB, beta: BetaAB, gamma: GammaAB, delta: DeltaAB, microCyc: MicroCycleAB, disposition: IF InstReadyAB THEN valid ELSE unready ]; IF LoadStage1Bc THEN opPipe[1][b] _ opPipe[1][a]; opPipe[2][b] _ (SELECT TRUE FROM NormalStage2B2AB => opPipe[2][a], AbortStage2B2AB => NewDisposition[opPipe[2][a], killed2b], ENDCASE => ERROR IFUInconsistent); opPipe[3][b] _ opPipe[3][a]; IF dpFaultedAB THEN opPipe[3][b].disposition _ killed3b; xbusBCopy _ XBus; doTrap3BA _ SELECT ExceptionCodeAB FROM none, cJump => FALSE, ENDCASE => TRUE; IF last#b THEN { <> IF ((log _ state.data.getLog[state.data.data]) # NIL) AND (ExceptionCodeAB # reset) THEN { IF (ExceptionCodeAB # none) OR InstReadyAB THEN { log.PutF["\n%5g%5g", IO.int[state.data.getCycle[state.data.data]], IO.int[instrCount] ]; SELECT TRUE FROM ExceptionCodeAB=reseting => log.PutF["**Reseting "]; ExceptionCodeAB=reset => log.PutF["**Reset "]; ExceptionCodeAB=dpFault => log.PutF["**DPFault "]; dpRejectedAB => log.PutF["**DPReject "]; ExceptionCodeAB=cTrap => log.PutF["**EUCC "]; ExceptionCodeAB=bubble => log.PutF["**Bubble "]; ExceptionCodeAB=cJump => log.PutF["**CJRestrt "]; ExceptionCodeAB=rschlWait => log.PutF["**Reschdl "]; ExceptionCodeAB=iStkOFlow => log.PutF["**IStkOver "]; ExceptionCodeAB=eStkOFlow => log.PutF["**EStkOver "]; ExceptionCodeAB=ipFault => log.PutF["**IPgFault "]; ExceptionCodeAB=none => log.PutRope[" "]; ENDCASE => log.PutF[" cy: %2g ", IO.card[ExceptionCodeAB.ORD]]; log.PutF["pc:%08x", IO.card[PCForLogAB] ]; SELECT TRUE FROM dpRejectedAB => log.PutF[" --EU reject delay..."]; NOT InstReadyAB => log.PutF[" --IFetch delay..."]; ENDCASE => { opLength: [0..5] = DragonRosemary.OpLength[OpAB]; log.PutF[" %-7g", IO.rope[Rope.Cat[DragonRosemary.OpName[OpAB], (IF MicroCycleAB=0 THEN "" ELSE IO.PutFR["-%g", IO.int[MicroCycleAB]])]]]; IF opLength > 1 THEN log.PutF[" %02x", IO.card[AlphaAB]] ELSE log.PutF[" "]; IF opLength > 2 THEN log.PutF["%02x", IO.card[BetaAB]] ELSE log.PutF[" "]; IF opLength > 3 THEN log.PutF["%02x%02x", IO.card[GammaAB], IO.card[DeltaAB]] ELSE log.PutF[" "]; log.PutF[" l:%02x", IO.card[LAB]]; -- at beginning of instruction log.PutF[ " s:%02x", IO.card[SAB]]; -- at beginning of instruction logRegistersB _ TRUE; }; }; }; IF ExceptionCodeAB=reset THEN instrCount _ -1; }; }; postB => IF bHigh THEN { -- the falling edge of B bHigh _ FALSE; IF logRegistersB THEN { IF ((log _ state.data.getLog[state.data.data]) # NIL) THEN { log.PutF[" a:%02x", IO.card[AReg0BA]]; log.PutF[ " b:%02x", IO.card[BReg0BA]]; log.PutF[ " c:%02x", IO.card[CReg0BA]]; }; logRegistersB _ FALSE; }; SELECT opPipe[3][b].microCyc FROM 117 => { -- Reset finished instrCount _ -1; trapped _ FALSE; }; 120 => { -- first cycle of trap trapped _ TRUE; }; 0 => IF NOT DPRejectedBA AND (SELECT opPipe[3][b].disposition FROM valid => TRUE, killed3a, killed3b => (MicroCycleAB = 120 -- trap that will apply to the new instruction -- ), ENDCASE => FALSE) THEN { <> instrCount _ instrCount+ state.data.checkSynch[ data: state.data.data, basicInst: [ -- the completed instruction cycle: cycle, instr: instrCount, trapped: trapped, trapPC: IF trapped THEN opPipe[3][b].pc ELSE 0, pc: firstMicroOfMacro.pc, op: firstMicroOfMacro.op, alpha: firstMicroOfMacro.alpha, beta: firstMicroOfMacro.beta, gamma: firstMicroOfMacro.gamma, delta: firstMicroOfMacro.delta ] ].deltaInstrCount; <<>> firstMicroOfMacro _ opPipe[3][b]; trapped _ FALSE; }; ENDCASE => NULL; }; ENDCASE => ERROR IFUInconsistent; last _ ph; END; IFULoggerRef: ModSim _ NEW[ModSimRec _ [IFULogger]]; IFUInconsistent: PUBLIC ERROR = CODE; PLAEval: PROC [ state: REF IFUState, pla: IFUPLA.PLAs ] = BEGIN OPEN state; UncountedAssignHack.UncountedSmallAssignPlease[src: plaBuffers[pla][input], dst: IFUPLA.plas[pla].data]; IFUPLA.IFUPLAEval[pla]; IF NOT state.drShWt THEN UncountedAssignHack.UncountedSmallAssignPlease[dst: state.plaBuffers[pla][output], src: IFUPLA.plas[pla].out]; END; IFU: PUBLIC PROC [ typeData: REF IFUTypeData ] RETURNS [ ct: Core.CellType ] = BEGIN WGet: PROC [ wireId: II ] RETURNS [ w: Core.Wire ] = { w _ ct.public[wireId.ORD]; }; wireList: LIST OF CoreCreate.WR _ NIL; FOR wireId: II DECREASING IN II DO wr: CoreCreate.WR _ (SELECT iITypes[wireId].width FROM 1 => iITypes[wireId].name, ENDCASE => CoreCreate.Seq[name: iITypes[wireId].name, size: iITypes[wireId].width] ); wireList _ CONS[wr, wireList]; ENDLOOP; ct _ CoreOps.CreateCellType[ class: CoreClasses.unspecifiedCellClass, public: CoreCreate.WireList[wireList], name: "IFU", props: CoreProperties.Props[[$ClusterInfo, typeData]] ]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: IFUName]; FOR wireId: II IN II DO [] _ Ports.InitPort[wire: ct.public[wireId.ORD], initType: (SELECT iITypes[wireId].width FROM 1 => b, <=16 => c, <=32 => lc, ENDCASE => ERROR), initDrive: iITypes[wireId].drive ]; ENDLOOP; END; PLAShiftChainEntry: TYPE = RECORD [ pla: IFUPLA.PLAs, sense: IFUPLA.Sense ]; plaShiftChain: LIST OF REF ANY -- REF PLAShiftChainEntry -- _ LIST [ <> NEW[PLAShiftChainEntry _ [pla: interlock, sense: input]], NEW[PLAShiftChainEntry _ [pla: interlock, sense: output]], NEW[PLAShiftChainEntry _ [pla: stackBControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: stackBControl, sense: output]], NEW[PLAShiftChainEntry _ [pla: stackAControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: stackAControl, sense: output]], NEW[PLAShiftChainEntry _ [pla: stackDecode, sense: input]], NEW[PLAShiftChainEntry _ [pla: stackDecode, sense: output]], NEW[PLAShiftChainEntry _ [pla: fetchWtDecode, sense: input]], NEW[PLAShiftChainEntry _ [pla: fetchWtDecode, sense: output]], NEW[PLAShiftChainEntry _ [pla: fetchRdDecode, sense: input]], NEW[PLAShiftChainEntry _ [pla: fetchRdDecode, sense: output]], NEW[PLAShiftChainEntry _ [pla: fetchControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: fetchControl, sense: output]], <> NEW[PLAShiftChainEntry _ [pla: passRtAB, sense: input]], NEW[PLAShiftChainEntry _ [pla: passRtBA, sense: input]], NEW[PLAShiftChainEntry _ [pla: instrDecode0, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode1, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode2, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode3, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode4, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode5, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode6, sense: output]], NEW[PLAShiftChainEntry _ [pla: instrDecode0, sense: input]], NEW[PLAShiftChainEntry _ [pla: passLtB, sense: output]], NEW[PLAShiftChainEntry _ [pla: mainControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: mainControl, sense: output]] ]; NewIFUState: PUBLIC PROC [ pattern: REF IFUState _ NIL ] RETURNS [ REF IFUState ] = BEGIN state: REF IFUState _ NEW[IFUState]; RETURN [ state ]; END; normalConvergencePasses: NAT _ 1; IFUInit: PROC [ cellType: Core.CellType, p: Ports.Port ] RETURNS [ stateAny: REF ANY _ NIL ] -- Rosemary.InitProc -- = { state: REF IFUState _ NewIFUState[]; oldState: REF IFUState _ NEW[IFUState]; currentOffset: NAT _ 0; state.data _ NARROW[CoreProperties.GetCellTypeProp[cellType, $ClusterInfo]]; state.public _ cellType.public; state.oldP _ Ports.CreatePort[state.public]; state.maxConvergencePasses _ normalConvergencePasses; state.oldState _ oldState; IFUPost[p, state]; -- gets multiplexers to a logically acceptable state FOR psc: LIST OF REF ANY _ plaShiftChain, psc.rest WHILE psc # NIL DO psce: REF PLAShiftChainEntry = NARROW[psc.first]; state.plaOffsets[psce.pla][psce.sense] _ currentOffset; currentOffset _ currentOffset+IFUPLA.plaSizes[psce.pla][psce.sense]; ENDLOOP; state.drShifterAB.size _ state.drShifterBA.size _ currentOffset; FOR pla: IFUPLA.PLAs IN IFUPLA.PLAs DO state.plaBuffers[pla][input] _ UncountedAssignHack.UncountedSmallNewProc[IFUPLA.plas[pla].data]; state.plaBuffers[pla][output] _ UncountedAssignHack.UncountedSmallNewProc[IFUPLA.plas[pla].out]; ENDLOOP; stateAny _ state; }; modulesA: LIST OF REF ANY _ LIST[IFUPreRef, IFUInstrDecodeRef, IFUControlPipeRef, IFUFetchRef, IFUKBusInRef, IFULitGenRef, IFUPCRef, IFULSRef, IFUStatusRef, IFUABCRef, IFUInterlockRef, IFUStackRef, IFUMainControlRef, IFUPostRef, IFUKBusOutRef, IFULoggerRef]; modulesB: LIST OF REF ANY _ LIST[IFUPreRef, IFUInstrDecodeRef, IFUControlPipeRef, IFUKBusInRef, IFULitGenRef, IFUPCRef, IFULSRef, IFUFetchRef, IFUStatusRef, IFUABCRef, IFUInterlockRef, IFUStackRef, IFUMainControlRef, IFUPostRef, IFUKBusOutRef, IFULoggerRef]; IFUSimple: PROC [ p: Ports.Port, stateAny: REF ANY ] -- Rosemary.EvalProc -- = BEGIN state: REF IFUState = NARROW[stateAny]; OnePass: PROC [ modules: LIST OF REF ANY _ NIL ] = { IF modules = NIL THEN modules _ (SELECT state.ph FROM a, postA => modulesA, b, postB => modulesB, ENDCASE => ERROR); FOR m: LIST OF REF ANY _ modules, m.rest WHILE m # NIL DO module: ModSim = NARROW[m.first]; module.proc[p, state]; ENDLOOP; }; SELECT TRUE FROM p[II[PhA].ORD].b => state.ph _ a; p[II[PhB].ORD].b => state.ph _ b; (state.ph = a) => state.ph _ postA; (state.ph = b) => state.ph _ postB; ENDCASE => NULL; state.drShWt _ p[II[DrShWt].ORD].b; FOR pass: NAT IN [1..state.maxConvergencePasses] DO OnePass[] ENDLOOP; DO sameVals: BOOL _ TRUE; Ports.CopyPortValue[from: p, to: state.oldP]; state.oldState^ _ state^; OnePass[]; Ports.CheckPortValue[root: state.public, truth: state.oldP, question: p ! Ports.CheckError => {sameVals _ FALSE; REJECT}]; IF state.oldState^ # state^ THEN { difFields: LIST OF Core.ROPE = EqualCheck.FindDif[state, state.oldState]; Ports.CheckError[IO.PutFR["IFU state, including field %g, failed to converge after %g passes.", IO.rope[difFields.first], IO.int[state.maxConvergencePasses]]]; sameVals _ FALSE; }; IF sameVals THEN EXIT; state.maxConvergencePasses _ state.maxConvergencePasses+1; ENDLOOP; END; IFU2CmdProc: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] -- Commander.CommandProc -- = {NULL}; Commander.Register["IFU2", IFU2CmdProc]; END.