DIRECTORY Basics, Commander, Core, CoreIO, CoreClasses, CoreOps, CoreProperties, Dragon, DragonRosemary, DragOpsCross, EqualCheck, IFUTop, IFUPLA, IFUPublic, IFUPLAFetchControl, IFUPLAInstrDecode, IFUPLAInterlock, IFUPLAMainPipeControl, IFUPLAStackControl, IO, Ports, REFBit, Rope, Rosemary, TerminalIO, UncountedAssignHack; IFUTopImpl: CEDAR PROGRAM IMPORTS Basics, Commander, CoreClasses, CoreIO, CoreOps, CoreProperties, DragonRosemary, EqualCheck, IFUPLA, IFUPublic, IO, Rope, Rosemary, Ports, REFBit, TerminalIO, UncountedAssignHack EXPORTS IFUTop = BEGIN version: [0..255] _ IFUPublic.CurrentIFUVersion; IFUInconsistent: PUBLIC ERROR = CODE; ROPE: TYPE = Rope.ROPE; II: TYPE = IFUPublic.II; IFUState: TYPE = IFUTop.IFUState; IFUStateRec: TYPE = IFUTop.IFUStateRec; ModSim: TYPE = IFUTop.ModSim; ModSimRec: TYPE = IFUTop.ModSimRec; ModuleSimProc: TYPE = IFUTop.ModuleSimProc; IFURoseClass: ROPE = Rosemary.Register [roseClassName: "IFU", init: IFUInit, evalSimple: IFUSimple]; PortData: TYPE = RECORD [ name: ROPE, width: NAT _ 1, drive: Ports.Drive _ none ]; Two: TYPE = RECORD[w0, w1: WORD]; Swap: PROC[in: Two] RETURNS[out: Two] = {RETURN[[in.w1, in.w0]]}; ToStatus: PROC[word: Dragon.Word] RETURNS[DragOpsCross.StackedStatusWord] = {RETURN[LOOPHOLE[Swap[LOOPHOLE[word]]]]}; FromStatus: PROC[status: DragOpsCross.StackedStatusWord] RETURNS[Dragon.Word] = {RETURN[LOOPHOLE[Swap[LOOPHOLE[status]]]]}; debugRegSize: NAT = 32; IFUPre: PUBLIC ModuleSimProc = { OPEN state; p[II[VbbGen].ORD].b _ TRUE; p[II[PhAOut].ORD].b _ p[II[Clk].ORD].b; p[II[PhBOut].ORD].b _ NOT p[II[Clk].ORD].b; LoadStage1Bc _ ph=B AND NOT NotBcLoadStage1AB; X2ASrcLit2Ac _ ph=A AND X2ASrcLit1BA; IF ph=A THEN { ResetAB _ p[II[Reset ].ORD].b; DPFaultAB _ DPFaultBA}; IF ph=B AND NOT drShWt THEN { ResetBA _ ResetAB; RescheduleBA _ p[II[Reschedule ].ORD].b; IPData _ p[II[IPData ].ORD].lc; IPRejectBA _ p[II[IPReject ].ORD].b; IPFaultingBA _ p[II[IPFaulting ].ORD].b; DPFaultBA _ VAL[ p[II[DPFault ].ORD].c]; DPRejectBA _ p[II[DPReject ].ORD].b; EUCondition2BA _ p[II[EUCondition ].ORD].b }; IF p[II[DShA].ORD].b THEN { inputBit: BOOL = NOT p[II[DShIn].ORD].b; DragonRosemary.Assert [ NOT p[II[DShRd].ORD].b, "Error in IFU shifter clocking sequence" ]; IF NOT p[II[DShB].ORD].b THEN { -- shift drShifterAB from drShifterBA drShifterAB.bits[0] _ inputBit; FOR i: NAT IN [1..drShifterAB.size) DO drShifterAB.bits[i] _ drShifterBA.bits[i-1]; ENDLOOP} ELSE { -- mass copy drShifterAB from DShIn FOR i: NAT IN [0..drShifterAB.size) DO drShifterAB.bits[i] _ drShifterBA.bits[i] _ inputBit; ENDLOOP } }; DragonRosemary.Assert[ NOT (p[II[DShRd].ORD].b AND p[II[DShWt].ORD].b), "Error in IFU shifter clocking sequence"]; IF p[II[DShWt].ORD].b THEN 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 inv: BOOL _ REFBit.Get[IFUPublic.scanDrInv, offset+i]; REFBit.Set[buf, i, drShifterAB.bits[offset+i] # inv]; ENDLOOP}; ENDLOOP; ENDLOOP }; IFUPreRef: ModSim _ NEW[ModSimRec _ [IFUPre]]; IFUPost: PUBLIC ModuleSimProc = { OPEN state; IF p[II[DShRd].ORD].b THEN {-- broadside copy into shift register xbus: LONG CARDINAL _ XBus; 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 inv: BOOL _ REFBit.Get[IFUPublic.scanDrInv, offset+i]; drShifterAB.bits[offset+i] _ REFBit.Get[buf, i] # inv; ENDLOOP}; ENDLOOP; ENDLOOP; FOR i: INT IN [0..debugRegSize) DO drShifterAB.bits[drShifterAB.size-debugRegSize+i] _ (xbus MOD 2)=1; xbus _ xbus/2 ENDLOOP}; IF p[II[DShB].ORD].b THEN { -- shift drShifterBA from drShifterAB FOR i: NAT IN [0..drShifterAB.size) DO drShifterBA.bits[i] _ drShifterAB.bits[i]; ENDLOOP}; p[II[DShOut].ORD].b _ NOT drShifterBA.bits[drShifterBA.size-1]}; IFUPostRef: ModSim _ NEW[ModSimRec _ [IFUPost]]; IFUInstrDecode: PUBLIC ModuleSimProc = { OPEN state; X1ASrcSLimitAc _ ph=A AND x1ASrcSLimitBA; X1ADstSLimitAc _ ph=A AND x1ADstSLimitBA; SELECT ph FROM A => { }; ab => { IF NOT drShWt THEN { inTYPE: TYPE = IFUPLAInstrDecode.InstrDecodeIn; inRec: inTYPE _ [ reset: ResetAB, state: StateAB, instReady: InstReadyAB, op: DragOpsCross.Inst[VAL[OpAB]], alpha: AlphaAB, beta: BetaAB, pushPending: PushPendingAB, popPending: PopPendingAB, userMode0: UserMode0AB ]; NARROW[ plaBuffers[instrDecode0][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode1][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode2][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode3][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode4][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode5][input], REF inTYPE]^ _ inRec; NARROW[ plaBuffers[instrDecode6][input], REF inTYPE]^ _ inRec } }; B => { PLAEval[state, instrDecode0]; PLAEval[state, instrDecode1]; PLAEval[state, instrDecode2]; PLAEval[state, instrDecode3]; PLAEval[state, instrDecode4]; PLAEval[state, instrDecode5]; PLAEval[state, instrDecode6]; [ nextMacro: NextMacroBA, pcNext: PCNextBA, pcBusSrc: PCBusSrcBA, pcPipeSrc: PCPipeSrcBA, x2ALitSource: X2ALitSourceBA, kIsRtOp0: KIsRtOp0BA, push0: Push0BA ] _ NARROW[plaBuffers[instrDecode6][output], REF IFUPLAInstrDecode.InstrDecodeOut6]^; [ instStarting0: InstStarting0BA, microCycleNext: MicroCycleNextBA, protMicroCycle: ProtMicroCycleBA, pop0: Pop0BA, dPCmnd: DPCmndBA, dPCmndIsRd0: DPCmndIsRd0BA, dPCmndSel: DPCmndSelBA ] _ NARROW[plaBuffers[instrDecode5][output], REF IFUPLAInstrDecode.InstrDecodeOut5]^; [ flagSrc: FlagSrcBA, lSource: [LSourceLtBA, LSourceRtBA], sSource: [SSourceLtBA, SSourceRtBA], popSa: PopSaBA, popSb: PopSbBA ] _ NARROW[plaBuffers[instrDecode4][output], REF IFUPLAInstrDecode.InstrDecodeOut4]^; [ kPadsIn0: KPadsIn0BA, fCtlIsRtOp0: FCtlIsRtOp0BA, pushSc: PushScBA, cReg: [CRegLtBA, CRegRtBA, CRegOffBA, CRegModBA] ] _ NARROW[plaBuffers[instrDecode3][output], REF IFUPLAInstrDecode.InstrDecodeOut3]^; [ bReg: [BRegLtBA, BRegRtBA, BRegOffBA, BRegModBA] ] _ NARROW[plaBuffers[instrDecode2][output], REF IFUPLAInstrDecode.InstrDecodeOut2]^; [ aReg: [ARegLtBA, ARegRtBA, ARegOffBA, ARegModBA] ] _ NARROW[plaBuffers[instrDecode1][output], REF IFUPLAInstrDecode.InstrDecodeOut1]^; [ aluOp: AluOpBA, aluOpIsOp47: AluOpIsOp47BA, condSel: CondSelBA, condSelIsOp57: CondSelIsOp57BA, condEffect0: CondEffect0BA, x1ADstSLimit: x1ADstSLimitBA, x1ASrcSLimit: x1ASrcSLimitBA, x1ADstStack: X1ADstStackBA, x1ASrcStack: X1ASrcStackBA, xBusStackL: XBusStackLBA, xBusStackEldest: XBusStackEldestBA, cIsField0: CIsField0BA ] _ NARROW[plaBuffers[instrDecode0][output], REF IFUPLAInstrDecode.InstrDecodeOut0]^}; ba => NULL; ENDCASE => ERROR IFUInconsistent}; IFUInstrDecodeRef: ModSim _ NEW[ModSimRec _ [IFUInstrDecode]]; IFUMainPipeControl: PUBLIC ModuleSimProc = { OPEN state; MCPIN: REF IFUPLAMainPipeControl.MainPipeControlIn _ NARROW[plaBuffers[mainPipeControl][input]]; MCPOUT: REF IFUPLAMainPipeControl.MainPipeControlOut _ NARROW[plaBuffers[mainPipeControl][output]]; SELECT ph FROM A => { LoadStage1Ac _ MCPOUT.loadStage1; LoadStage2Ac _ MCPOUT.loadStage2; LoadStage3Ac _ MCPOUT.loadStage3; Stage1BHoldingAB _ MCPOUT.stage1BHolding; NotBcLoadStage1AB _ MCPOUT.notBcLoadStage1; Stage2BNormalAB _ MCPOUT.stage2B=normal; Stage2BAbortAB _ MCPOUT.stage2B=abort; Stage3BCPipeNormalAB _ MCPOUT.stage3BCPipe=normal; Stage3BCPipeAbortAB _ MCPOUT.stage3BCPipe=abort; MicroExcptJmpAB _ MCPOUT.microExcptJmp; ExceptAB _ MCPOUT.except; RschClearAB _ MCPOUT.rschClear; RschWaitingAB _ MCPOUT.rschWaiting; IF NOT drShWt THEN MCPIN.rschClearIn _ RschClearAB; PLAEval[state, mainPipeControl]; RschWaitingAB _ MCPOUT.rschWaiting}; ab => { LoadStage1Ac _ FALSE; LoadStage2Ac _ FALSE; LoadStage3Ac _ FALSE}; B => { IF NOT drShWt THEN MCPIN^ _ [ reset: ResetBA, -- Pre dPReject: DPRejectBA, -- Pre dPFaulting: DPFaultBA # none, -- Pre protMicroCycle: ProtMicroCycleBA, -- InstrDecode microExcptJmpBubble: MicroExcptJmpAB=bubble, stage2BAbort: Stage2BAbortAB, stage1BHold: Stage1BHoldBA, -- Interlock condEffect1: CondEffect1BA, -- ControlPipe condEffect2: CondEffect2BA, -- ControlPipe eUCondition2: EUCondition2BA, -- Pre trapsEnabled2: TrapsEnabled2BA, -- Status eStkOverflow2: EStkOverflow2BA, -- ControlPipe instStarting2: InstStarting2BA, -- ControlPipe reschedule: RescheduleBA, rschWaitingIn: RschWaitingAB, push2: Push2AB, instFault2: InstFault2BA, -- ControlPipe iStkNearlyFull: IStkNearlyFullBA, -- StackControl rschClearIn: RschClearAB ]; -- PRESERVE PhA change PLAEval[state, mainPipeControl]; Stage2ANormalBA _ MCPOUT.stage2A=normal; Stage2ABubbleBA _ MCPOUT.stage2A=bubble; Stage3ANormalBA _ MCPOUT.stage3A=normal; Stage3AAbortBA _ MCPOUT.stage3A=abort}; ba => { }; ENDCASE => ERROR IFUInconsistent}; IFUMainPipeControlRef: ModSim _ NEW[ModSimRec _ [IFUMainPipeControl]]; IFUMicroCycle: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { StateAB _ (SELECT MicroExcptJmpAB FROM none => StateBA MOD 128, -- 0sss ssss bubble => StateBA MOD 128+128, -- 1sss ssss microJump => 48, -- 0011 0000 resetting => 112, -- exception 0111 0000 trap => 116, -- exception 0111 0100 cJump => 120, -- exception 0111 1000 ENDCASE => ERROR IFUInconsistent) }; ab => { }; B => { StateBA _ SELECT MicroCycleNextBA FROM clear => 0, hold => StateAB, next => StateAB +1, ENDCASE => ERROR IFUInconsistent}; ba => { }; ENDCASE => ERROR IFUInconsistent}; IFUMicroCycleRef: ModSim _ NEW[ModSimRec _ [IFUMicroCycle]]; IFUStatus: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { UserMode0AB _ userMode [0][a] _ nextUserModeBA; trapsEnabled [0][a] _ nextTrapsEnabledBA; IF LoadStage1Ac THEN { userMode [1][a] _ userMode [0][b]; trapsEnabled [1][a] _ trapsEnabled [0][b]}; IF LoadStage2Ac THEN SELECT TRUE FROM Stage2ABubbleBA => { userMode [2][a] _ TRUE; trapsEnabled [2][a] _ FALSE}; Stage2ANormalBA => { userMode [2][a] _ userMode [1][b]; trapsEnabled [2][a] _ trapsEnabled [1][b]}; ENDCASE => IFUInconsistent; IF LoadStage3Ac THEN { userMode [3][a] _ userMode [2][b]; trapsEnabled [3][a] _ trapsEnabled [2][b]} }; ab => NULL; B => { status: DragOpsCross.StackedStatusWord; SELECT FlagSrcBA FROM same => { nextUserModeBA _ userMode [0][a]; nextTrapsEnabledBA _ trapsEnabled [0][a]}; clear => { nextUserModeBA _ FALSE; nextTrapsEnabledBA _ FALSE}; stack => { nextUserModeBA _ ToStatus[LFStkTopAB].userMode; nextTrapsEnabledBA _ ToStatus[LFStkTopAB].trapsEnabled}; lev3 => { nextUserModeBA _ userMode [3][a]; nextTrapsEnabledBA _ trapsEnabled [3][a]}; ENDCASE => ERROR IFUInconsistent; userMode [0][b] _ userMode [0][a]; trapsEnabled [0][b] _ trapsEnabled [0][a]; IF LoadStage1Bc THEN { userMode [1][b] _ userMode [1][a]; trapsEnabled [1][b] _ trapsEnabled [1][a] }; userMode [2][b] _ userMode [2][a]; trapsEnabled [2][b] _ trapsEnabled [2][a]; p[II[ UserMode].ORD].b _ userMode [2] [b]; TrapsEnabled2BA _ trapsEnabled [2] [b]; status _ ToStatus[LFPipe3BA]; status.version _ version; status.userMode _ userMode [3][a]; status.trapsEnabled _ trapsEnabled [3][a]; LFPipe3BA _ FromStatus[status]}; ba => NULL; ENDCASE => ERROR IFUInconsistent} ; IFUStatusRef: ModSim _ NEW[ModSimRec _ [IFUStatus]]; IFUInterlock: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A, ab => NULL; B => { IF NOT drShWt THEN NARROW[plaBuffers[interlock][input], REF IFUPLAInterlock.InterlockIn]^ _ [ kIsRtOp1: KIsRtOp1BA, -- ControlPipe fCtlIsRtOp1: FCtlIsRtOp1BA, -- ControlPipe cIsField2: CIsField2AB, cIsField3: CIsField3AB, dPCmndIsRd2: DPCmndIsRd2BA, -- ControlPipe a1IsC2: A1IsC2B, -- ABC a1IsC3: A1IsC3B, -- ABC b1IsC2: B1IsC2B, -- ABC b1IsC3: B1IsC3B ]; -- ABC PLAEval[state, interlock]; -- static [ stage1BHold: Stage1BHoldBA, eUAluLeftSrc1: EUAluLeftSrc1B, eUAluRightSrc1: EUAluRightSrc1B, eUStore2ASrc1: EUStore2ASrc1B, eUSt3AIsCBus1: EUSt3AIsCBus1BA ] _ NARROW[plaBuffers[interlock][output], REF IFUPLAInterlock.InterlockOut]^}; ba => NULL; ENDCASE => ERROR IFUInconsistent }; IFUInterlockRef: ModSim _ NEW[ModSimRec _ [IFUInterlock]]; IFUFetch: PUBLIC ModuleSimProc = { OPEN state; FCIN: REF IFUPLAFetchControl.FetchControlIn _ NARROW[plaBuffers[fetchControl][input]]; FCOUT: REF IFUPLAFetchControl.FetchControlOut _ NARROW[plaBuffers[fetchControl][output]]; PA4BFromCard: PROC [ in: [0..16) ] RETURNS [ out: PACKED ARRAY [0..4) OF BOOL] = TRUSTED { out _ LOOPHOLE[in]; }; PA16BFromCard: PROC [ in: CARDINAL] RETURNS [ out: PACKED ARRAY [0..16) OF BOOL] = TRUSTED { out _ LOOPHOLE[in] }; p[II[IPData].ORD].d _ (IF ph=A THEN drive ELSE none); SELECT ph FROM A => { wtAB _ wtBA; rdAB _ rdBA; FetchWtAB _ (wtAB MOD 16)/4; IF NOT drShWt THEN NARROW[plaBuffers[fetchRdDecode][input], REF IFUPLAFetchControl.FetchRdDecodeIn]^ _ [ fetchRd: FetchRdBA]; PLAEval[state, fetchRdDecode]; -- static FetchBufRdByteAc _ PA16BFromCard[NARROW[plaBuffers[fetchRdDecode][output], REF IFUPLAFetchControl.FetchRdDecodeOut]^]; p[II[IPData].ORD].lc _ IPData _ fetchAddrBA/4; -- Byte to word happens here fetchAddrAB _ fetchAddrBA+(IF NewFetchBA THEN 4 ELSE 0); -- byte offset in 30,31 OpAB _ iBuf[(rdBA+0) MOD 16]; AlphaAB _ iBuf[(rdBA+1) MOD 16]; BetaAB _ iBuf[(rdBA+2) MOD 16]; GammaAB _ iBuf[(rdBA+3) MOD 16]; DeltaAB _ iBuf[(rdBA+4) MOD 16]; FetchingAB _ FetchingBA; FetchBytesM1AB _ (wtBA-rdBA-1+64) MOD 32; IF NOT drShWt THEN { FCIN.op _ VAL[OpAB] / 32; -- (3 msbs) Fetch FCIN.fetchBytesM1 _ FetchBytesM1AB}; -- Fetch PLAEval[state, fetchControl]; [ jumpPending: JumpPendingAB, iPFaulted: IPFaultedAB, notInstReady: NotInstReadyAB, jumpOffset: JumpOffsetAB, opLength: OpLengthAB -- A latched copy for fetch indexing ] _ FCOUT^; IF DragonRosemary.OpLength[OpAB] # OpLengthAB THEN ERROR; InstReadyAB _ NOT NotInstReadyAB}; ab => { FetchBufRdByteAc _ ALL[FALSE]}; B => { FCIN^ _ [ nextMacroJump: NextMacroBA=jump, reset: ResetBA, -- Pre iPReject: IPRejectBA, -- Pre jumpPendingIn: JumpPendingAB, fetchingIn: FetchingAB, fetchBytesM1: FCIN.fetchBytesM1, -- PRESERVE PhA changes iPFaultedIn: IPFaultedAB, iPFaulting: IPFaultingBA, -- Pre (this can be pipeline delayed) op: FCIN.op ]; -- PRESERVE PhA changes PLAEval[state, fetchControl]; -- static [ newFetch: NewFetchBA, fetching: FetchingBA, fetchWtIndexCtl: FetchWtIndexCtlBA, opLengthb: OpLengthbBA, -- B latched copy for pc adjustment instFault0: InstFault0BA ] _ FCOUT^; p[II[IPCmdFetch].ORD].b _ NewFetchBA; SELECT FetchWtIndexCtlBA FROM -- from FetchIndexing clear => wtBA _ 0; hold => wtBA _ wtAB; inc => wtBA _ (wtAB+4) MOD 32; ENDCASE => ERROR IFUInconsistent; rdBA _ (SELECT NextMacroBA FROM jump => PCBusB MOD DragOpsCross.bytesPerWord, get => (rdAB+OpLengthAB) MOD 32, hold => rdAB, ENDCASE => ERROR); FetchRdBA _ rdBA MOD 16; IF NOT drShWt THEN NARROW[plaBuffers[fetchWtDecode][input], REF IFUPLAFetchControl.FetchWtDecodeIn]^ _ [ fetching: FetchingAB, fetchWt: FetchWtAB]; PLAEval[state, fetchWtDecode]; -- static FetchBufWtWdBc _ PA4BFromCard[NARROW[plaBuffers[fetchWtDecode][output], REF IFUPLAFetchControl.FetchWtDecodeOut]^]; fetchAddrBA _ (IF NextMacroBA=jump THEN PCBusB ELSE fetchAddrAB); IF FetchingAB THEN { base: [0..16) = 4*((wtAB MOD 16)/4); iWd: Basics.LongNumber; iWd.lc _ IPData; iBuf[base+0] _ iWd.hh; iBuf[base+1] _ iWd.hl; iBuf[base+2] _ iWd.lh; iBuf[base+3] _ iWd.ll } }; ba => { FetchBufWtWdBc _ ALL[FALSE]}; ENDCASE => ERROR IFUInconsistent}; IFUFetchRef: ModSim _ NEW[ModSimRec _ [IFUFetch]]; IFULitGen: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { IF LoadStage1Ac THEN xaPipe1AB _ xaPipe0BA; IF X2ASrcLit2Ac THEN XBus _ xaPipe1BA}; ab => NULL; B => { xaPipe0BA _ SELECT X2ALitSourceBA FROM none => 0, -- but will not drive XBus in 2A zero => 0, alpha => AlphaAB, alphaBeta => AlphaAB*LONG[256] + BetaAB, alpBetGamDel => ((AlphaAB*LONG[256] + BetaAB)*256 + GammaAB)*256 + DeltaAB, ENDCASE => ERROR IFUInconsistent; IF LoadStage1Bc THEN xaPipe1BA _ xaPipe1AB}; ba => NULL; ENDCASE => ERROR IFUInconsistent}; IFULitGenRef: ModSim _ NEW[ModSimRec _ [IFULitGen]]; IFUPC: PUBLIC ModuleSimProc = { 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 _ OpLengthbBA + 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 Stage3AAbortBA => pcPipe[2][b], -- pc of aborting micro Stage3ANormalBA => pcAltPipe[2][b], -- whatever top of pipe suggested ENDCASE => ERROR IFUInconsistent) }; pcAB _ SELECT PCNextBA FROM incr => pcSum, fromPCBus => npcBA, ENDCASE => ERROR IFUInconsistent; PCForLogAB _ pcAB }; ab => 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 JumpOffsetAB FROM alpha => SExtnd[AlphaAB], beta => SExtnd[BetaAB], alphaBeta => SExtnd[AlphaAB]*256 + BetaAB, xa => xAB, ENDCASE => ERROR IFUInconsistent ); targetPCBA _ pcSum _ pcBranchOSetB + pcAB; pcBA _ pcAB; PCBusB _ npcBA _ (SELECT PCBusSrcBA FROM offSetPC => pcSum, pc => pcAB, x => xAB, xopGen => DragOpsCross.bytesPerWord*(DragOpsCross.XopBase + DragOpsCross.TrapWidthWords*OpAB), trapGen => DragOpsCross.bytesPerWord* (DragOpsCross.TrapBase+DragOpsCross.TrapWidthWords*( SELECT ExceptAB.type FROM specialCode => 00B + ExceptAB.code.ORD MOD 20B, condCode => 20B + EUCondSel3AB.ORD, -- TrapIndex[ALUCondFalse] dpFault => 40B + (DPFaultAB.ORD MOD 8),-- TrapIndex[MemAccessFault] ENDCASE => ERROR)), alpBetGamDel => ((AlphaAB*LONG[256]+BetaAB)*256+GammaAB)*256+DeltaAB, pipe3 => PCPipe3BA, stack => PCStkTopAB, ENDCASE => ERROR IFUInconsistent); OpBA _ OpAB; AlphaBA _ AlphaAB; BetaBA _ BetaAB }; ba => NULL; ENDCASE => ERROR IFUInconsistent }; IFUPCRef: ModSim _ NEW[ModSimRec _ [IFUPC]]; IFUStack: PUBLIC ModuleSimProc = { OPEN state; IF X1ADstStackBA THEN { -- static multiplexer pWrtBufA _ XBus; lWrtBufA _ XBus} ELSE { pWrtBufA _ PCPipe3BA; lWrtBufA _ LFPipe3BA}; SELECT ph FROM A => { adderMuxA: [0..32); addendA: [0..32); carryA: [0..1]; sumA: [0..32); sdo: IFUPLAStackControl.StackDecodeOut _ NARROW[plaBuffers[stackDecode][output], REF IFUPLAStackControl.StackDecodeOut]^; StkLdPAc _ LOOPHOLE[sdo.stkLdP]; StkLdLAc _ LOOPHOLE[sdo.stkLdL]; StkRdAc _ LOOPHOLE[sdo.stkRd]; PLAEval[state, stackAControl]; -- dynamic [ stackAdjTos: StackAdjTosAB, stackAddendIsOnes: StackAddendIsOnesAB, stackCarryIsOne: StackCarryIsOneAB ] _ NARROW[plaBuffers[stackAControl][output], REF IFUPLAStackControl.StackAControlOut]^; adderMuxA _ IF StackAdjTosAB THEN TosBA ELSE BosBA; addendA _ IF StackAddendIsOnesAB THEN 31 ELSE 0; carryA _ IF StackCarryIsOneAB THEN 1 ELSE 0; sumA _ (adderMuxA+addendA+carryA) MOD 32; TosAB _ SELECT TRUE FROM ResetBA => 0, StackAdjTosAB => sumA, ENDCASE => TosBA; -- needed because StackAdjTosAB might glitch BosAB _ BosAB _ SELECT TRUE FROM ResetBA => 1, NOT StackAdjTosAB => sumA, ENDCASE => BosBA; -- needed because StackAdjTosAB 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 LFPipe3BA ELSE FOR index: NAT IN [0..16) DO IF StkRdAc[index] THEN { lRdBufA _ lStack[index]; pRdBufA _ pStack[index]}; ENDLOOP; PCStkTopAB _ pRdBufA; LFStkTopAB _ lRdBufA; IF X1ASrcStackBA THEN XBus _ (IF XBusStackLBA THEN lRdBufA ELSE pRdBufA)}; ab => {StkLdLAc _ StkLdPAc _ StkRdAc _ ALL[FALSE]}; B => { StackDiffBA _ (32+TosAB-BosAB) MOD 32; IF NOT drShWt THEN NARROW[plaBuffers[stackBControl][input], REF IFUPLAStackControl.StackBControlIn]^ _ [ stackDiff: StackDiffBA, -- Stack microExcptJmpTrap: MicroExcptJmpAB=trap, pushIn3: Push3AB, popIn3: Pop3AB ]; PLAEval[state, stackBControl]; -- static [ push3: Push3BA, pop3: Pop3BA, iStkNearlyFull: IStkNearlyFullBA ] _ NARROW[plaBuffers[stackBControl][output], REF IFUPLAStackControl.StackBControlOut]^; TosBA _ TosAB; BosBA _ BosAB; IF NOT drShWt THEN NARROW[plaBuffers[stackDecode][input], REF IFUPLAStackControl.StackDecodeIn]^ _ [ bos: BosBA, -- was BosAB Stack tos: TosBA, -- was TosAB Stack x1ASrcStack: X1ASrcStackBA, -- InstrDecode x1ADstStack: X1ADstStackBA, -- InstrDecode xBusStackEldest: XBusStackEldestBA, -- InstrDecode xBusStackL: XBusStackLBA, -- InstrDecode push3: Push3BA, -- Stack pop3: Pop3BA ]; -- Stack PLAEval[state, stackDecode] }; ba => { 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 }; IFUStackRef: ModSim _ NEW[ModSimRec _ [IFUStack]]; IFULS: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { LAB _ LBA; 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 MOD 256; IF X1ASrcSLimitAc THEN XBus _ sLimitAB}; ab => NULL; B => { status: DragOpsCross.StackedStatusWord; lBusLtB, lBusRtB: Dragon.HexByte; sBusLt, sBusRt: Dragon.HexByte; DeltaSBA _ ( 256 + (IF PushScBA THEN 1 ELSE 0) + (IF PopSaBA THEN -1 ELSE 0) + (IF PopSbBA THEN -1 ELSE 0) ) MOD 256; 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 => ToStatus[LFStkTopAB].lBase, 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]; lPipe[3][b] _ lPipe[3][a]; status _ ToStatus[LFPipe3BA]; status.lBase _ lPipe[3][b]; LFPipe3BA _ FromStatus[status]; EStkOverflow1BA _ ((SAB+(255-sLimitAB)+1) MOD 128) IN [0..16)}; ba => NULL; ENDCASE => ERROR IFUInconsistent}; IFULSRef: ModSim _ NEW[ModSimRec _ [IFULS]]; IFUABC: PUBLIC ModuleSimProc = { OPEN state; noStore: Dragon.HexByte = DragOpsCross.ProcessorRegister[euJunk].ORD; SELECT ph FROM A => { A1IsC2B _ A1IsC3B _ B1IsC2B _ B1IsC3B _ 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 Stage2ABubbleBA => noStore, Stage2ANormalBA => cPipe[1][b], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN cPipe[3][a] _ (SELECT TRUE FROM Stage3AAbortBA => noStore, Stage3ANormalBA => cPipe[2][b], ENDCASE => ERROR IFUInconsistent)}; ab => NULL; B => { aBusLt, aBusRt: Dragon.HexByte; bBusLt, bBusRt: Dragon.HexByte; cBusLt, cBusRt: Dragon.HexByte; aBusLt _ SELECT ARegLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, s => SAB, l => LAB, zero => 0, ENDCASE => ERROR IFUInconsistent; aBusRt _ SELECT ARegRtBA FROM alpha => AlphaBA, alpha47 => AlphaBA MOD 16, op47 => OpBA MOD 16, beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, ENDCASE => SELECT ARegOffBA 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 ARegModBA FROM half => (aBusLt + aBusRt) MOD 128, full => (aBusLt + aBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; bBusLt _ SELECT BRegLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, s => SAB, l => LAB, zero => 0, ENDCASE => ERROR IFUInconsistent; bBusRt _ SELECT BRegRtBA FROM op47 => OpBA MOD 16, alpha => AlphaBA, alpha47 => AlphaBA MOD 16, beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, ENDCASE => SELECT BRegOffBA 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 BRegModBA FROM half => (bBusLt + bBusRt) MOD 128, full => (bBusLt + bBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; cBusLt _ SELECT CRegLtBA FROM cBase => DragOpsCross.ProcessorRegister[euConstant].ORD, aBase => DragOpsCross.ProcessorRegister[euAux].ORD, l => LAB, s => SAB, zero => 0, ENDCASE => ERROR IFUInconsistent; cBusRt _ SELECT CRegRtBA FROM beta => BetaBA, beta03 => BetaBA/16, beta47 => BetaBA MOD 16, op47 => OpBA MOD 16, alpha => AlphaBA, alpha47 => AlphaBA MOD 16, ENDCASE => SELECT CRegOffBA 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 CRegModBA FROM half => (cBusLt + cBusRt) MOD 128, full => (cBusLt + cBusRt) MOD 256, ENDCASE => ERROR IFUInconsistent; IF (a1BEarly1AB # cPipe[2][a]) THEN A1IsC2B _ FALSE; IF (a1BEarly1AB # cPipe[3][a]) THEN A1IsC3B _ FALSE; IF (b1BEarly1AB # cPipe[2][a]) THEN B1IsC2B _ FALSE; IF (b1BEarly1AB # cPipe[3][a]) THEN B1IsC3B _ 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 Stage2BAbortAB => noStore, Stage2BNormalAB => cPipe[2][a], ENDCASE => ERROR IFUInconsistent); cPipe[3][b] _ (SELECT TRUE FROM Stage3BCPipeAbortAB => noStore, Stage3BCPipeNormalAB => cPipe[3][a], ENDCASE => ERROR IFUInconsistent); AReg0BA _ aPipe[0][b]; BReg0BA _ bPipe[0][b]; CReg0BA _ cPipe[0][b] }; ba => NULL; ENDCASE => ERROR IFUInconsistent }; IFUABCRef: ModSim _ NEW[ModSimRec _ [IFUABC]]; IFUControlPipe: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { IF LoadStage1Ac THEN ctlPipe1AB _ [ x2ASrcLit: X2ALitSourceBA # none, push: Push0BA, pop: Pop0BA, kPadsIn: KPadsIn0BA, dpCmnd: DPCmnd0BA, aluOp: EUAluOp0BA, kIsRtOp: KIsRtOp0BA, condSel: CondSel0BA, condEffect: CondEffect0BA, fCtlIsRtOp: FCtlIsRtOp0BA, cIsField: CIsField0BA, rdFromPBus: DPCmndIsRd0BA, writeToPBus: (Basics.BITAND[DPCmnd0BA.ORD, Dragon.wrt] = Dragon.wrt), instFault: InstFault0BA, firstMicro: InstStarting0BA ]; IF LoadStage2Ac THEN ctlPipe2AB _ (SELECT TRUE FROM Stage2ANormalBA => [ 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, rdFromPBus: ctlPipe1BA.rdFromPBus, writeToPBus: ctlPipe1BA.writeToPBus, eStkOverflow: EStkOverflow1BA, st3AisCBus: EUSt3AIsCBus1BA, instFault: ctlPipe1BA.instFault, firstMicro: ctlPipe1BA.firstMicro ], Stage2ABubbleBA => [ x2ASrcLit: FALSE, push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, aluOp: Or, condSel: False, condEffect: bubble, cIsField: FALSE, rdFromPBus: FALSE, writeToPBus: FALSE, eStkOverflow: FALSE, st3AisCBus: FALSE, instFault: FALSE, firstMicro: FALSE ], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN ctlPipe3AB _ (SELECT TRUE FROM Stage3ANormalBA => [ push: ctlPipe2BA.push, pop: ctlPipe2BA.pop, kPadsIn: ctlPipe2BA.kPadsIn, dpCmnd: ctlPipe2BA.dpCmnd, condSel: ctlPipe2BA.condSel, cIsField: ctlPipe2BA.cIsField, rdFromPBus: ctlPipe2BA.rdFromPBus, writeToPBus: ctlPipe2BA.writeToPBus ], Stage3AAbortBA => [ push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, condSel: ctlPipe2BA.condSel, cIsField: FALSE, rdFromPBus: FALSE, writeToPBus: FALSE ], ENDCASE => ERROR IFUInconsistent); PushPendingAB _ ctlPipe1AB.push OR ctlPipe2AB.push OR ctlPipe3AB.push; PopPendingAB _ ctlPipe1AB.pop OR ctlPipe2AB.pop OR ctlPipe3AB.pop; p[II[EUAluOp].ORD].c _ ctlPipe2AB.aluOp.ORD; p[II[EUCondSel].ORD].c _ ctlPipe2AB.condSel.ORD; CondEffect2AB _ ctlPipe2AB.condEffect; CIsField2AB _ ctlPipe2AB.cIsField; CIsField3AB _ ctlPipe3AB.cIsField; EUCondSel3AB _ ctlPipe3AB.condSel; p[II[EURdFromPBus].ORD].b _ ctlPipe3AB.rdFromPBus; p[II[EUWriteToPBus].ORD].b _ ctlPipe3AB.writeToPBus; Push2AB _ ctlPipe2AB.push; Push3AB _ ctlPipe3AB.push; Pop3AB _ ctlPipe3AB.pop; }; ab => NULL; B => { DPCmnd0BA _ SELECT DPCmndSelBA FROM beta => LOOPHOLE[BetaAB], ENDCASE => DPCmndBA; EUAluOp0BA _ IF AluOpIsOp47BA THEN LOOPHOLE[OpAB MOD 16] ELSE AluOpBA; CondSel0BA _ IF CondSelIsOp57BA THEN LOOPHOLE[OpAB MOD 8] ELSE CondSelBA; 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, rdFromPBus: ctlPipe1AB.rdFromPBus, writeToPBus: ctlPipe1AB.writeToPBus, instFault: ctlPipe1AB.instFault, firstMicro: ctlPipe1AB.firstMicro ]; ctlPipe2BA _ (SELECT TRUE FROM Stage2BNormalAB => [ push: ctlPipe2AB.push, pop: ctlPipe2AB.pop, kPadsIn: ctlPipe2AB.kPadsIn, dpCmnd: ctlPipe2AB.dpCmnd, condSel: ctlPipe2AB.condSel, condEffect: ctlPipe2AB.condEffect, cIsField: ctlPipe2AB.cIsField, rdFromPBus: ctlPipe2AB.rdFromPBus, writeToPBus: ctlPipe2AB.writeToPBus, eStkOverflow: ctlPipe2AB.eStkOverflow, st3AisCBus: ctlPipe2AB.st3AisCBus, instFault: ctlPipe2AB.instFault, firstMicro: ctlPipe2AB.firstMicro ], Stage2BAbortAB => [ push: FALSE, pop: FALSE, kPadsIn: FALSE, dpCmnd: NoOp, condSel: False, condEffect: bubble, cIsField: FALSE, rdFromPBus: FALSE, writeToPBus: FALSE, eStkOverflow: FALSE, st3AisCBus: FALSE, instFault: FALSE, firstMicro: FALSE ], ENDCASE => ERROR IFUInconsistent); ctlPipe3BA _ [ kPadsIn: ctlPipe3AB.kPadsIn, cIsField: ctlPipe3AB.cIsField ]; X2ASrcLit1BA _ ctlPipe1BA.x2ASrcLit; KIsRtOp1BA _ ctlPipe1BA.kIsRtOp; FCtlIsRtOp1BA _ ctlPipe1BA.fCtlIsRtOp; CondEffect1BA _ ctlPipe1BA.condEffect; DPCmndIsRd2BA _ ctlPipe2BA.rdFromPBus; CondEffect2BA _ ctlPipe2BA.condEffect; EStkOverflow2BA _ ctlPipe2BA.eStkOverflow; EUSt3AIsCBus2BA _ ctlPipe2BA.st3AisCBus; InstFault2BA _ ctlPipe2BA.instFault; InstStarting2BA _ ctlPipe2BA.firstMicro; KPadsIn3BA _ ctlPipe3BA.kPadsIn; DPCmnd2BA _ IF (Stage3ANormalBA AND NOT DPRejectBA) THEN ctlPipe2BA.dpCmnd ELSE NoOp; p[II[DPCmd].ORD].c _ DPCmnd2BA.ORD}; ba => NULL; ENDCASE => ERROR IFUInconsistent }; IFUControlPipeRef: ModSim _ NEW[ModSimRec _ [IFUControlPipe]]; IFUKBusIn: PUBLIC ModuleSimProc = {OPEN state; IF ph=A AND KPadsIn3BA THEN XBus _ p[II[KBus].ORD].lc}; IFUKBusInRef: ModSim _ NEW[ModSimRec _ [IFUKBusIn]]; IFUKBusOut: PUBLIC ModuleSimProc = { OPEN state; IF ph=B THEN XBus _ LOOPHOLE[IFUTop.RegAddrRec[ aAddr: aPipe[1][b], bAddr: bPipe[1][b], cAddr: cPipe[3][b], st3AisC: EUSt3AIsCBus2BA, aluLeftSrc: EUAluLeftSrc1B, aluRightSrc: EUAluRightSrc1B, storeSrc: EUStore2ASrc1B ]]; 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 }; IFUKBusOutRef: ModSim _ NEW[ModSimRec _ [IFUKBusOut]]; IFULogger: PUBLIC ModuleSimProc = { OPEN state; log: IO.STREAM _ NIL; NewDisposition: PROC [ pipeState: IFUTop.LogPipeState, disp: IFUTop.MicroInstDisposition ] RETURNS [ newPipeState: IFUTop.LogPipeState ] = { newPipeState _ pipeState; newPipeState.disposition _ disp}; SELECT ph FROM A => { bHigh _ FALSE; dpRejectedAB _ DPRejectBA; IF LoadStage1Ac THEN opPipe[1][a] _ opPipe[0][b]; IF LoadStage2Ac THEN opPipe[2][a] _ (SELECT TRUE FROM Stage2ANormalBA => opPipe[1][b], Stage2ABubbleBA => NewDisposition[opPipe[1][b], interlocked], ENDCASE => ERROR IFUInconsistent); IF LoadStage3Ac THEN opPipe[3][a] _ (SELECT TRUE FROM Stage3ANormalBA => opPipe[2][b], Stage3AAbortBA => NewDisposition[opPipe[2][b], killed3a], ENDCASE => ERROR IFUInconsistent)}; ab => bHigh _ FALSE; B => { bHigh _ TRUE; opPipe[0][b] _ [ pc: PCForLogAB, op: VAL[OpAB], alpha: AlphaAB, beta: BetaAB, gamma: GammaAB, delta: DeltaAB, microCyc: StateAB, disposition: IF InstReadyAB THEN valid ELSE unready ]; IF LoadStage1Bc THEN opPipe[1][b] _ opPipe[1][a]; opPipe[2][b] _ (SELECT TRUE FROM Stage2BNormalAB => opPipe[2][a], Stage2BAbortAB => NewDisposition[opPipe[2][a], killed2b], ENDCASE => ERROR IFUInconsistent); opPipe[3][b] _ opPipe[3][a]; IF Stage3BCPipeAbortAB THEN opPipe[3][b].disposition _ killed3b; xbusBCopy _ XBus; IF last#B THEN { IF ((log _ state.data.getLog[state.data.data]) # NIL) AND (ExceptAB # [specialCode, reset]) THEN { IF (ExceptAB # [specialCode, none]) OR InstReadyAB THEN { log.PutF["\n%5g%5g", IO.int[state.data.getCycle[state.data.data]], IO.int[instrCount] ]; SELECT TRUE FROM ExceptAB=[specialCode, reseting ] => log.PutF["**Reseting "]; ExceptAB=[specialCode, reset ] => log.PutF["**Reset "]; ExceptAB=[dpFault ] => log.PutF["**DPFault "]; dpRejectedAB => log.PutF["**DPReject "]; ExceptAB=[condCode ] => log.PutF["**EUCC "]; ExceptAB=[specialCode, bubble ] => log.PutF["**Bubble "]; ExceptAB=[specialCode, cJump ] => log.PutF["**CJRestrt "]; ExceptAB=[specialCode, rschlWait ] => log.PutF["**Reschdl "]; ExceptAB=[specialCode, iStkOFlow ] => log.PutF["**IStkOver "]; ExceptAB=[specialCode, eStkOFlow ] => log.PutF["**EStkOver "]; ExceptAB=[specialCode, ipFault ] => log.PutF["**IPgFault "]; ExceptAB=[specialCode, none ] => log.PutF[" "]; ENDCASE => log.PutF[" cy: %2g ", IO.card[ExceptAB.code.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 StateAB=0 THEN "" ELSE IO.PutFR["-%g", IO.int[StateAB]])]]]; 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 ExceptAB = [specialCode, reset] THEN instrCount _ -1 } }; -- of b ba => 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 113 => {trapped _ FALSE; instrCount _ -1}; -- Reset finished 116 => {trapped _ TRUE}; -- first cycle of trap 0 => { incrInstrCount: BOOL _ SELECT opPipe[3][b].disposition FROM valid => TRUE, killed3a, killed3b => (StateAB = 116), -- trap that will apply to new instr ENDCASE => FALSE; IF NOT DPRejectBA AND incrInstrCount 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}; -- end of ba ENDCASE => ERROR IFUInconsistent; last _ ph}; IFULoggerRef: ModSim _ NEW[ModSimRec _ [IFULogger]]; normalConvergencePasses: NAT _ 1; modulesA: LIST OF REF ANY _ LIST[IFUPreRef, IFUInstrDecodeRef, IFUControlPipeRef, IFUFetchRef, IFUKBusInRef, IFULitGenRef, IFUPCRef, IFULSRef, IFUStatusRef, IFUABCRef, IFUInterlockRef, IFUStackRef, IFUMainPipeControlRef, IFUMicroCycleRef, IFUPostRef, IFUKBusOutRef, IFULoggerRef]; modulesB: LIST OF REF ANY _ LIST[IFUPreRef, IFUInstrDecodeRef, IFUControlPipeRef, IFUKBusInRef, IFULitGenRef, IFUPCRef, IFULSRef, IFUFetchRef, IFUStatusRef, IFUABCRef, IFUInterlockRef, IFUStackRef, IFUMainPipeControlRef, IFUMicroCycleRef, IFUPostRef, IFUKBusOutRef, IFULoggerRef]; CreateIFU: PUBLIC PROC[ typeData: REF IFUTop.IFUTypeData, fullIFU, quickIFU, rawIFU: BOOL _ FALSE ] RETURNS [ ct: Core.CellType ] = { ct _ SELECT TRUE FROM rawIFU => ERROR, fullIFU => CoreOps.Recast[CoreIO.RestoreCellType["IFU"]], ENDCASE => CoreOps.CreateCellType[ class: CoreClasses.unspecifiedCellClass, public: IFUPublic.IfuInitializedPublic[], name: "IFU"]; CoreProperties.PutCellTypeProp[ct, $ClusterInfo, typeData]; MarkMemoryWires[ct.public[CoreOps.GetWireIndex[ct.public, "DPFault"]]]; MarkMemoryWires[ct.public[CoreOps.GetWireIndex[ct.public, "IPFaulting"]]]; MarkMemoryWires[ct.public[CoreOps.GetWireIndex[ct.public, "DPReject"]]]; MarkMemoryWires[ct.public[CoreOps.GetWireIndex[ct.public, "IPReject"]]]; MarkMemoryWires[ct.public[CoreOps.GetWireIndex[ct.public, "IPData"]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: IFURoseClass]}; MarkMemoryWires: PUBLIC PROC[wire: Core.Wire] = { IF wire.size=0 THEN []_Rosemary.SetWire[wire, L, charge, TRUE]; FOR i: INT IN [0..wire.size) DO MarkMemoryWires[wire[i]] ENDLOOP}; IFUInit: PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL, steady: BOOL _ FALSE] RETURNS [stateAny: REF ANY _ NIL ] -- Rosemary.InitProc -- = { state: IFUState _ NEW[IFUStateRec]; oldState: IFUState _ NEW[IFUStateRec]; currentOffset: NAT _ 0; state.data _ NARROW[CoreProperties.GetCellTypeProp[cellType, $ClusterInfo]]; state.public _ cellType.public; state.oldP _ Ports.CreatePort[cellType]; state.maxConvergPasses _ 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 + debugRegSize; 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}; PLAEval: PROC [ state: IFUState, pla: IFUPLA.PLAs ] = { 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]}; IFUSimple: PROC [ p: Ports.Port, stateAny: REF ANY ] -- Rosemary.EvalProc -- = { state: IFUState = NARROW[stateAny]; OnePass: PROC [ modules: LIST OF REF ANY _ NIL ] = { IF modules = NIL THEN modules _ (SELECT state.ph FROM A, ab => modulesA, B, ba => 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 _ ab; (state.ph = B) => state.ph _ ba; ENDCASE => NULL; state.drShWt _ p[II[DShWt].ORD].b; FOR pass: NAT IN [1..state.maxConvergPasses] DO OnePass[] ENDLOOP; DO sameVals: BOOL _ TRUE; Ports.CopyPortValue[from: p, to: state.oldP]; state.initialized _ state.oldState.initialized OR state.ph=ba; 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 ROPE = EqualCheck.FindDif[state, state.oldState]; IF state.initialized THEN { TerminalIO.PutF[ "IFU state, including field %g, failed to converge after %g passes.\n", IO.rope[difFields.first], IO.int[state.maxConvergPasses] ]; state.maxConvergPasses _ state.maxConvergPasses+1}; LOOP}; IF sameVals THEN EXIT; state.maxConvergPasses _ state.maxConvergPasses+1; ENDLOOP}; 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: mainPipeControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: mainPipeControl, 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: ltDrPadIO, sense: input]], NEW[PLAShiftChainEntry _ [pla: fetchControl, sense: input]], NEW[PLAShiftChainEntry _ [pla: fetchControl, 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: rtDrPadIO, 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]] ]; IFUCmdProc: PROC -- Commander.CommandProc [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] = {NULL}; Commander.Register["IFUTop", IFUCmdProc]; END. ¬IFUTopImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. McCreight, June 6, 1986 4:25:49 pm PDT Don Curry April 20, 1987 11:27:19 am PST Last Edited by: Louis Monier April 7, 1987 1:16:36 pm PST Last Edited by: Don Curry July 14, 1987 9:06:01 am PDT X2ASrcStatus2Ac _ ph=A AND X2ASrcStatus1BA; buf: REF ANY = plaBuffers[pla][sense]; rtIO: IFUPLAPass.RtDrPadIO _ [ dPReject: BOOL _ FALSE, -- BA <= B dual dPFault: Dragon.PBusFaults _ none, -- BA <= B dPFaultCode: PBusFaultCode _ memAccess, -- BA => BAA dPFaultCodeD: PBusFaultCode _ memAccess, -- AB <= BAA dPCmnd3: Dragon.PBusCommands _ NoOp, -- BA => BAA userMode2: BOOL _ FALSE, -- BA => BAA eUAluOp2: Dragon.ALUOps _ Or, -- AB => ABB eUCondSel2: Dragon.CondSelects _ False, -- AB => ABB eUCondition2: BOOL _ FALSE, -- BA <= B eUWriteToPBus3: BOOL _ FALSE, -- AB => ABB eURdFromPBus3: BOOL _ FALSE, -- AB => ABB K0PadsIn4: BOOL _ FALSE, -- Ac <= BA K1PadsIn4: BOOL _ FALSE, -- Ac <= BA K0PadsOut3: BOOL _ FALSE, -- BA <= BA K1PadsOut3: BOOL _ FALSE, -- BA <= BA X2ASrcLit1: BOOL _ FALSE, -- BA => BAA X2ASrcLit2: BOOL _ FALSE, -- Ac <= BAA dual debugABGD: BOOL _ FALSE, -- debugPC: BOOL _ FALSE, -- debugLSC: BOOL _ FALSE, -- debugABStLim: BOOL _ FALSE ]; -- ltIO: IFUPLAPass.LtDrPadIO _ [ iPReject: BOOL _ FALSE, -- B => BA iPFaulting: BOOL _ FALSE, -- B => BA newFetch: BOOL _ FALSE, -- BAA <= BA reset: BOOL _ FALSE, -- AB => BA reschedule: BOOL _ FALSE ]; -- AB => BA broadside copy from shift register to drivers All seven instruction decoding sub-PLA's are strung on these input wires, and attached to the same input record. x1ASrcStackL: x1ASrcStackP: [ loadStage1: LoadStage1Ac, loadStage2: LoadStage2Ac, loadStage3: LoadStage3Ac, stage1BHolding: Stage1BHoldingAB, notBcLoadStage1: NotBcLoadStage1AB, -- really just Stage1BHoldingAB stage2B: Stage2B, stage3BCPipe: Stage3BCPipe, microExcptJmp: MicroExcptJmpAB, except: ExceptAB, rschClear: RschClearAB, rschWaiting: RschWaitingAB ] _ MCPOUT^; See: IFUPLAMainPipeControl.MicroExcptJmp IFUStatus: PUBLIC ModuleSimProc = { OPEN state; SELECT ph FROM A => { newstatusRec: DragOpsCross.IFUStatusRec _ DragOpsCrossUtils.WordToStatus[DragOpsCrossUtils.CardToWord[XBus]]; rsPipe[a] _ RescheduleBA; status[a] _ [ version: IFUTop.CurrentIFUVersion, rescheduleKeep: TRUE ]; status[a].reschedule _ (RescheduleBA AND NOT rsPipe[b]) OR (IF ~X1ADstStatusBA THEN status[b].reschedule ELSE IF newstatusRec.rescheduleKeep THEN status[b].reschedule ELSE newstatusRec.reschedule); status[a].userMode _ NOT ClearUserModeBA AND (IF ~X1ADstStatusBA THEN status[b].userMode ELSE IF newstatusRec.userModeKeep THEN status[b].userMode ELSE newstatusRec.userMode); status[a].trapsEnabled _ NOT ClearTrapsEnabledBA AND (IF ~X1ADstStatusBA THEN status[b].trapsEnabled ELSE IF newstatusRec.trapsEnabledKeep THEN status[b].trapsEnabled ELSE newstatusRec.trapsEnabled); IF X2ASrcStatus2Ac THEN { XBus _ DragOpsCrossUtils.WordToCard[DragOpsCrossUtils.StatusToWord[statPipe[b]]]}; IF LoadStage1Ac THEN statPipe[a] _ status[b]; UserMode0AB _ status[a].userMode }; ab => NULL; B => { status[b] _ status[a]; rsPipe[b] _ rsPipe[a]; IF LoadStage1Bc THEN statPipe[b] _ statPipe[a]; RschWaiting2BA _ status[b].reschedule AND NOT X1ADstStatusBA; -- just in case TrapsEnabled2BA _ status[b].trapsEnabled AND NOT ClearTrapsEnabledBA }; ba => NULL; ENDCASE => ERROR IFUInconsistent}; stage1BHoldIfReject: Stage1BHoldIfRejectBA, p[II[IPCmdFetch].ORD].b _ (IF ph=A THEN NewFetchBA ELSE FALSE); FetchIndexing from FetchAddr There are three PC values that may be needed for an instruction: the PC of the instruction itself, the PC of the next sequential instruction, and the PC of a call or jump target. The instruction PC is carried down pcPipe. One of the other two PC's, which may be needed as the return address of a call-type instruction or as the alternate PC of a failed conditional jump, is carried down altPcPipe. The third PC, if any, is passed immediately to the prefetcher. The two pipelined PC's merge at stage 3A, based on conditions computed at stage 2B. In the normal case, the merged value is altPc. In case of a trap or fault, the merged value is the pc of the offending instruction, carried in pcPipe. Memory reference instructions fail within stage 3, so they must specify PCLSPipeSrcBA = old. This shouldn't be a problem, since the only instructions that need to do otherwise are conditional jumps. doTrap3BA _ SELECT ExceptAB.code FROM none, cJump => FALSE, ENDCASE => TRUE; Log instruction at the beginning of Ph0B. The first microinstruction of a new macroinstruction instrCount+1 is now committed to retire, either in victory or defeat (as in "trapped"). This means that all register stores for the macroinstruction instrCount are completed, and none for macroinstruction instrCount+1 have yet occurred. quickIFU, Ports.CheckError[IO.PutFR ["IFU state, including field %g, failed to converge after %g passes.", IO.rope[difFields.first], IO.int[state.maxConvergPasses]]]; Left column ... Right column ... Κ:²˜™Jšœ Οmœ1™Jšžœ#žœ˜>Jšžœ#žœ˜>Jšžœ#žœ˜>Jšžœ#žœ˜>Jšžœ#žœ˜>Jšžœ#žœ˜B——˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜šœžœ Ÿœž˜.Jšœ Ÿœ˜$——šœ˜Jšœ!˜!Jšœ"˜"Jšœ"˜"Jšœ˜Jšœ˜Jšœ˜Jš œžœ Ÿœžœ!Ÿœ˜n—˜Jšœ˜Jšœ'˜'Jšœ'˜'J˜J˜Jš œžœ Ÿœžœ!Ÿœ˜U—˜Jšœ˜Jšœ˜J˜Jšœ4˜4Jš œžœ Ÿœžœ!Ÿœ˜U—šœ˜Jšœ4˜4Jš œžœ Ÿœžœ!Ÿœ˜U—šœ˜Jšœ4˜4Jš œžœ Ÿœžœ!Ÿœ˜U—˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ™ Jšœ ™ Jšœ˜Jšœ$˜$Jšœ˜Jš œžœ Ÿœžœ!Ÿœ˜V——Jšœžœ˜ Jšžœžœžœ˜"J˜——Jšœžœ˜@J˜šœžœ˜-Jšžœ˜ šžœžœ(˜2Jšœžœ%˜-—šžœžœŸ˜4Jšœžœ&˜.—šžœž˜˜šœ™Jšœ™Jšœ™Jšœ™Jšœ"™"JšœC™CJšœ™Jšœ™Jšœ ™ Jšœ™Jšœ™Jšœ!žœ™)—J˜Jšœžœ ˜#Jšœžœ ˜#Jšœžœ ˜#Jšœžœ˜*Jšœžœ˜,Jšœžœ˜)Jšœžœ˜(Jšœžœ˜2Jšœžœ˜0Jšœžœ˜(Jšœžœ˜Jšœžœ ˜"Jšœžœ ˜%šžœžœž˜Jšžœ˜ —Jšœ ˜ Jšœžœ˜&—šœž˜Jšœžœ˜Jšœžœ˜Jšœžœ˜—˜šžœžœžœžœ˜Jšœ‘˜ Jšœ‘˜$Jšœ"‘˜(Jšœ&‘˜4Jšœ,˜,Jšœ˜Jšœ"‘ ˜.Jšœ"‘˜0Jšœ"‘˜0Jšœ"‘˜(Jšœ$‘ ˜-Jšœ$‘˜2Jšœ&‘˜4Jšœ˜Jšœ˜Jšœ˜Jšœ ‘˜.Jšœ&‘˜5Jšœ"‘˜8—Jšœ ˜ Jšœžœ˜(Jšœžœ˜(Jšœžœ˜(Jšœžœ˜(—Jšœ ˜ Jšžœžœ˜"J˜——Jšœ žœ#˜FJ˜šœžœ˜*Jšžœ˜ šžœž˜˜Jšœ(™(šœ žœž˜&Jšœžœ‘ ˜(Jšœžœ ‘ ˜,Jšœ‘ ˜#Jšœ‘˜-Jšœ‘˜)Jšœ‘˜)Jšžœžœ˜%——Jšœ ˜ ˜šœ žœž˜&Jšœ˜Jšœ˜Jšœ˜Jšœžœžœ˜#——Jšœ ˜ Jšžœžœ˜"J˜——Jšœžœ˜>J˜šœžœ˜'Jšžœ˜ šžœž˜˜JšŸ œ˜Jšœ#˜#Jšœ*˜*šžœžœ˜Jšœ%˜%Jšœ,˜,—šžœžœž˜%šœ˜Jšœžœ˜Jšœžœ˜—šœ˜Jšœ%˜%Jšœ,˜,—Jšžœ˜—šžœžœ˜Jšœ%˜%Jšœ.˜.——Jšœžœ˜ ˜Jšœ'˜'šžœŸ œž˜šœ ˜ Jšœ#˜#Jšœ*˜*—šœ ˜ Jšœžœ˜Jšœžœ˜—šœ ˜ Jšœ0˜0Jšœ8˜8—šœ ˜ Jšœ#˜#Jšœ*˜*—Jšžœžœ˜!—Jšœ%˜%Jšœ+˜+šžœžœ˜Jšœ%˜%Jšœ-˜-—Jšœ&˜&Jšœ,˜,JšœžœŸœžœ˜+JšŸœ˜*Jšœ!˜!Jšœ˜Jšœ$˜$Jšœ*˜*JšŸ œ˜"—Jšœžœ˜ šžœžœžœ˜#J˜———šœžœ™'Jšžœ™ šžœž™™šœ)™)JšœC™C—Jšœ™šœ ™ Jšœ$™$Jšœžœ™—šœ™Jšœžœžœ ž™#šœžœ™Jšžœ™šžœžœ™#Jšžœ™Jšžœ™———šœžœž™,šœžœ™Jšžœ™šžœžœ™!Jšžœ™Jšžœ™———šœžœž™4šœžœ™Jšžœ™šžœžœ™%Jšžœ™Jšžœ™ ———šžœžœ™JšœR™R—šžœž™Jšœ™—Jšœ#™#—Jšœžœ™ ™Jšœ™Jšœ™Jšžœžœ™/Jšœ'žœžœ‘™NJšœ)žœžœ™G—Jšœžœ™ Jšžœžœžœ™"—J™—Jšœžœ˜7J˜šœžœ˜*Jšžœ˜ šžœž˜Jšœ žœ˜šœ˜šžœžœž˜šžœžœŸ œ˜JJšœ*˜*Jšœ.˜.Jšœ˜Jšœ˜Jšœ,˜,Jšœ˜Jšœ˜Jšœ˜Jšœ˜——Jšœ‘ ˜$šœ˜Jšœ˜Jšœ+™+Jšœ˜Jšœ!˜!Jšœ˜Jšœ˜Jšœžœ žœŸ œ˜N——Jšœžœ˜ Jšžœžœžœ˜#—J˜—Jšœžœ˜=J˜šœžœ˜&Jšžœ˜ šžœžœŸ˜+Jšœžœ"˜*—šžœžœŸ˜-Jšœžœ#˜+—š  œžœžœžœžœžœžœ˜PJšžœ žœ˜ J˜—š  œžœžœžœžœžœ žœžœ˜RJšžœ žœ˜—J˜Jš œžœ žœ žœžœžœ˜7Jš œžœ žœžœžœ žœžœ™?J˜šžœž˜˜J˜šœ ™ Jšœ˜Jšœ˜Jšœžœ˜—šžœžœž˜šžœ#žœŸœ˜UJšœ˜——Jšœ‘ ˜(Jšœ!žœ$žœŸœ˜vJ˜Jšœžœ žœ‘˜Kšœžœ žœžœ‘˜PJ˜—Jšœžœ˜Jšœžœ˜!Jšœžœ˜ Jšœžœ˜ Jšœžœ˜!J˜Jšœ˜Jšœ"žœ˜)J˜šžœžœžœ˜Jšžœ žœ‘˜1Jšžœ!‘ ˜2—Jšœ˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜šœ‘$˜:Jšœžœ˜ ——J˜Jšžœ,žœžœ˜9Jšœžœ˜"—J˜šœ˜Jšœžœžœ˜—J˜˜š’œ˜ Jšœ!˜!Jšœ‘˜Jšœ‘˜!Jšœ˜Jšœ˜Jšœ’œ‘˜9Jšœ˜Jšœ‘&˜CJšœ’œ ‘˜,—Jšœ'˜'šœ˜Jšœ˜Jšœ˜Jšœ$˜$Jšœ‘#˜>Jšœ!’œ˜(—J˜Jšœžœ žœ˜%J˜šžœžœ‘˜3Jšœ˜Jšœ˜Jšœžœ˜Jšžœžœ˜!—šœžœ ž˜Jšœžœ˜.Jšœžœ˜!Jšœ˜Jšžœžœ˜—Jšœžœ˜šžœžœž˜šžœ#žœŸœ˜UJšœ˜Jšœ˜——Jšœ‘ ˜(Jšœžœ$žœŸœ˜sJ˜šœžœžœžœ˜AJšœ™—J˜šžœ žœ˜Jšœžœ˜&Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—J˜—˜Jšœžœžœ˜—J˜Jšžœžœ˜"—J˜—Jšœžœ˜6J˜šœžœ˜'Jšžœ˜ šžœž˜˜Jšžœžœ˜+Jšžœžœ˜'—Jšœžœ˜ ˜šœ žœž˜'Jšœ‘ ˜.Jšœ ˜ Jšœ˜Jšœžœ˜+Jšœžœ-˜KJšžœžœ˜#—Jšžœžœ˜,—Jšœžœ˜ Jšžœžœžœ˜"J˜——Jšœžœ˜7J˜šžœžœ˜%Jšžœ˜ JšœΟ™ΟJ™Jšœμ™μJ˜šΠbnœžœžœžœ˜1Jš žœžœžœžœ žœžœ˜5J˜—šžœž˜˜Jšœ˜šžœžœ˜Jšœ˜šœžœ ž˜)Jšœ‘!œ˜3Jšœ‘œ˜6Jšœ‘3œ˜DJšžœžœ˜"—JšœΗ™Η—JšžœžœB˜Všžœžœ˜šœžœžœž˜ Jšœ!‘˜8Jšœ$‘!˜EJšžœžœ˜$——šœžœ ž˜Jšœ˜Jšœ˜Jšžœžœ˜#—Jšœ˜—J˜Jšœžœ˜ J˜˜JšžœžœB˜VJšœ?˜?Jšœ(˜(šœžœž˜)Jšœ˜Jšœ˜Jšœ*˜*Jšœ ˜ Jšžœžœ˜$—Jšœ*˜*Jšœ ˜ šœžœ ž˜(Jšœ˜Jšœ˜Jšœ ˜ Jšœ`˜`šœZ˜Zšžœž˜Jšœ$žœžœ˜0Jšœ!žœ‘˜@Jšœžœžœ‘˜DJšžœžœ˜——Jšœžœ'˜EJšœ˜Jšœ˜Jšžœžœ˜$—Jšœ ˜ Jšœ˜Jšœ˜J˜—Jšœžœ˜ Jšžœžœžœ˜#J˜——Jšœžœžœ˜0J˜šœžœ˜'Jšžœ˜ J˜šžœ˜šžœ‘˜Jšœ˜Jšœ˜—šžœ˜Jšœ˜Jšœ˜——šžœž˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜šœ+žœ"ž˜VJšœŸœ˜$—Jšœ žœ ˜!Jšœ žœ ˜ Jšœ žœ ˜J˜Jšœ‘ ˜)šœ˜Jšœ˜Jšœ'˜'Jšœ#˜#Jšœžœ$žœŸœ˜X—J˜Jšœ žœžœžœ˜5Jšœ žœžœžœ˜2Jšœ žœžœžœ˜/Jšœ$žœ˜+J˜šœžœžœž˜Jšœ˜Jšœ˜Jšžœ‘,˜BJ˜—šœžœžœž˜ Jšœ˜Jšžœ˜Jšžœ‘,˜B—J˜šžœžœžœ ž˜Jšžœžœ˜1Jšžœžœ˜1Jšžœ˜J˜—šžœ˜ šžœ‘ ˜Jšœžœ˜)Jšœ‘˜#Jšœ‘˜#—šž˜šžœžœžœ ž˜šžœžœ˜Jšœ˜Jšœ˜—Jšžœ˜———J˜Jšœ˜Jšœ˜J˜šžœž˜Jšœžœžœ žœ ˜4—J˜—Jšœ'žœžœ˜3J˜šœ˜Jšœžœ˜&J˜š žœžœž œ#žœŸœ˜hJšœ-˜-Jšœ(˜(Jšœ˜Jšœ˜—Jšœ‘ ˜(šœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœžœ$žœŸœ˜XJ˜—Jšœ˜Jšœ˜J˜š žœžœž œ!žœŸ œ˜dJšœ‘˜%Jšœ‘˜%Jšœ‘˜1Jšœ‘˜1Jšœ%‘˜7Jšœ‘˜/Jšœ‘ ˜!Jšœ‘ ˜"—Jšœ˜J˜J˜—šœ˜šžœžœž˜šžœ#žœŸœ˜UJšœ˜Jšœ˜Jšœ#˜#Jšœ˜Jšœ˜Jšœ˜———Jšžœžœžœ˜#J˜——Jšœžœ˜6J˜šžœžœ˜%Jšžœ˜ J˜šžœž˜˜Jšžœžœ˜ Jšžœžœ˜ šžœžœ˜Jšœ˜Jšœ˜—šžœžœ˜Jšœ˜Jšœ˜—šžœžœ˜Jšœ˜Jšœ˜—Jšžœžœžœ˜/Jšžœžœ˜(—J˜Jšœžœ˜ J˜˜Jšœ'˜'Jšœ!˜!Jšœ˜J˜šœ˜Jšœžœ žœžœ˜Jšœžœ žœžœ˜Jš œžœ žœžœžœ˜(—J˜Jšœžœ˜šœ žœ ž˜!Jšœžœ˜ Jšœžœ˜ Jšœ ˜ Jšœ˜Jšžœžœ˜!—šœ žœ ž˜!Jšœ ˜ Jšœ˜Jšœ%˜%Jšœ ˜ Jšžœžœ˜!—Jšžœžœ˜"J˜Jšœžœ˜šœ žœ ž˜ Jšœžœ˜ Jšœžœ˜ Jšœ˜Jšœ˜Jšžœžœ˜!—šœ žœ ž˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšžœžœ˜!—Jšžœžœ˜"J˜šžœžœ˜Jšœ˜Jšœ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœžœžœžœ ˜?J˜—Jšœžœ˜ J˜Jšžœžœžœ˜"—J˜—Jšœžœžœ˜0J˜šžœžœ˜%Jšžœ˜ JšœAžœ˜Ešžœž˜šœ˜Jšœ(žœ‘ ˜:šžœžœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœžœžœ žœ ˜DJšœžœžœ žœ ˜Dš žœžœžœžœž˜4Jšœ˜Jšœ˜Jšžœžœ˜%—š žœžœžœžœž˜4Jšœ˜Jšœ˜Jšžœžœ˜&—J˜—Jšœžœ˜ J˜šœ˜Jšœ˜Jšœ˜Jšœ˜J˜šœ žœ ž˜Jšœ5žœ˜9Jšœ0žœ˜4Jšœžœ˜ Jšœžœ˜ Jšœ ˜ Jšžœžœ˜!—šœ žœ ž˜Jšœ˜Jšœžœ˜Jšœžœ˜Jšœ˜Jšœ˜Jšœžœ˜šžœžœ ž˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšžœžœ˜!——šœžœ ž˜#Jšœžœ˜#Jšœžœ˜#Jšžœžœ˜!—J˜šœ žœ ž˜Jšœ4žœ˜8Jšœ/žœ˜3Jšœžœ˜ Jšœžœ˜ Jšœ ˜ Jšžœžœ˜!—šœ žœ ž˜Jšœžœ˜Jšœ˜Jšœžœ˜Jšœ˜Jšœ˜Jšœžœ˜šžœžœ ž˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšžœžœ˜!——šœžœ ž˜#Jšœžœ˜#Jšœžœ˜"Jšžœžœ˜!J˜—šœ žœ ž˜Jšœ5žœ˜9Jšœ0žœ˜4Jšœžœ˜ Jšœžœ˜ Jšœ ˜ Jšžœžœ˜!—šœ žœ ž˜Jšœ˜Jšœ˜Jšœžœ˜Jšœžœ˜Jšœ˜Jšœžœ˜šžœžœ ž˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšžœžœ˜!——šœžœ ž˜#Jšœžœ˜#Jšœžœ˜#Jšžœžœ˜!—J˜Jšžœžœ žœ˜4Jšžœžœ žœ˜4Jšžœžœ žœ˜4Jšžœžœ žœ˜4J˜šžœžœ˜Jšœ‘œ˜3Jšœ‘œ˜3Jšœ˜—šœžœžœž˜Jšœ˜Jšœ ˜ Jšžœžœ˜&—šœžœžœž˜Jšœ˜Jšœ$˜$Jšžœžœ˜&J˜—Jšœ˜Jšœ˜Jšœ˜J˜—Jšœžœ˜ J˜Jšžœžœžœ˜#—J˜—Jšœžœžœ˜2J˜šœžœ˜+Jšžœ˜ J˜J˜šžœž˜˜šžœžœ˜#Jšœ"˜"Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ žœ˜FJšœ˜Jšœ˜—š žœžœžœžœž˜3šœ˜Jšœ!˜!Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#Jšœ ˜ Jšœ#˜#Jšœ%˜%Jšœ˜Jšœ˜Jšœ"˜"Jšœ%˜%—šœ˜Jšœ žœ˜Jšœ žœ˜Jšœžœ˜Jšœ žœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ žœ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšœ žœ˜Jšœ žœ˜—Jšžœžœ˜"—š žœžœžœžœž˜3šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ#˜#Jšœ'˜'—šœ˜Jšœ žœ˜Jšœžœ˜Jšœ žœ˜Jšœ˜Jšœ˜Jšœ žœ˜Jšœ žœ˜Jšœžœ˜—Jšžœžœ˜"J˜—Jšœ žœžœ˜FJšœžœžœ˜BJ˜Jšœžœ žœžœ˜/Jšœžœ žœžœ˜3Jšœ+˜+Jšœ(˜(Jšœ(˜(Jšœ'˜'Jšœžœžœ˜3Jšœžœžœ˜5Jšœ!˜!Jšœ!˜!Jšœ˜Jšœ˜J˜—Jšœž˜ J˜˜šœ žœ ž˜#Jšœ žœ ˜Jšžœ ˜—šœ žœ˜Jšžœžœžœžœ ˜(—šœ žœ˜Jšžœžœžœžœ ˜)—J˜šžœžœ˜#Jšœ!˜!Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#Jšœ#˜#Jšœ ˜ Jšœ#˜#Jšœ%˜%Jšœ"˜"Jšœ%˜%J˜—šœžœžœž˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#Jšœ ˜ Jšœ#˜#Jšœ%˜%Jšœ&˜&Jšœ#˜#Jšœ"˜"Jšœ%˜%—šœ˜Jšœ žœ˜Jšœžœ˜Jšœ žœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ žœ˜Jšœ žœ˜Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšœ žœ˜Jšœ žœ˜—Jšžœžœ˜"—šœ˜Jšœ˜Jšœ#˜#J˜—Jšœ&˜&Jšœ#˜#Jšœ(˜(Jšœ(˜(J˜Jšœ'˜'Jšœ(˜(Jšœ+˜+Jšœ)˜)Jšœ'˜'Jšœ*˜*J˜Jšœ#˜#J˜šœ žœžœžœ ˜3Jšžœžœ˜!—Jšœžœžœžœ˜$J˜—Jšœžœ˜ Jšžœžœžœ˜#J˜——Jšœžœ˜@J˜šœžœ˜%Jš œžœžœžœ žœ žœžœ˜DJ˜—Jšœžœ˜7J˜šœžœ˜(Jšžœ˜ šžœžœžœ˜/Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœžœ ˜šžœžœžœžœ ˜$Jš žœžœžœžœžœ ˜Jšœ.€ œ˜—šžœ ˜Jšžœžœžœ˜;—šžœ ˜Jšžœžœžœ˜=Jšžœ˜—Jšœžœžœ‘˜BJšœžœžœ‘˜BJšœžœ˜———J˜—Jšžœ!žœ˜D—J˜—šœ˜šžœžœ‘˜(Jšœžœ˜šžœžœ˜šžœ/žœžœ˜—Jšœžœ˜&Jšœžœ˜(Jšœžœ˜Jšœžœ9˜PJšœ"˜"Jšœ,˜,Jšœ1˜1Jšœ˜Jšœ‘4˜Gšžœžœžœžœžœžœžœž˜EJšœžœžœ ˜1Jšœ7˜7Jšœžœ ˜DJšžœ˜—JšœO˜Oš žœžœžœžœž˜&JšœIžœ˜`JšœJžœ˜`Jšžœ˜—Jšœ˜J˜—š œžœžœ ˜8Jšžœ˜ JšœQžœ˜hJšžœ˜šžœžœž˜JšœXžœ˜o—J˜—š   œžœžœžœ‘œ˜QJšœžœ ˜#š œžœ žœžœžœžœžœ˜4šžœ žœž˜šœ žœ ž˜Jšœ˜Jšœ˜Jšžœžœ˜——šžœžœžœžœžœžœžœž˜9Jšœžœ ˜!Jšœ˜Jšžœ˜ ——šžœžœž˜Jšœžœžœ˜!Jšœžœžœ˜"Jšœ!˜!Jšœ!˜!Jšžœžœ˜—Jšœžœžœ˜"Jš žœžœžœžœ žœ˜Bšž˜Jšœ žœžœ˜Jšœ-˜-Jšœ/žœ ˜>J˜J˜ šœI˜IJšœ žœžœ˜0—šžœžœ˜"Jšœ žœžœ2˜Dšžœžœ˜šœ˜JšœG˜GJšžœžœ˜;—šœžœ™šœF™FJšžœžœ™;——Jšœ3˜3—Jšžœ˜—Jšžœ žœžœ˜Jšœ2˜2Jšžœ˜ ——J˜š œžœžœžœžœ ˜LJ˜—š œžœžœžœžœ‘œžœ˜FJ™Jšžœ9˜˜AJšžœ;˜>Jšžœ<˜?Jšžœ;˜>Jšžœ<˜?Jšžœ:˜=Jšžœ;˜>Jšžœ8˜;Jšžœ;˜>Jšžœ<˜?Jšžœ;˜>Jšžœ<˜?Jšžœ;˜>Jšžœ<˜?J˜Jšœ™Jšžœ8˜;Jšžœ<˜?Jšžœ<˜?Jšžœ<˜?Jšžœ<˜?Jšžœ<˜?Jšžœ<˜?Jšžœ<˜?Jšžœ=˜@—J˜š  œž‘˜)Jš œžœ žœžœ žœžœžœ˜SJ˜—Jšœ)˜)J˜Jšžœ˜J˜——…—¬”ϋς