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. 6IFU2Impl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. McCreight, June 6, 1986 4:25:49 pm PDT All seven instruction decoding sub-PLA's are strung on these input wires, and attached to the same input record. stage1HoldIfReject: Stage1BHoldIfRejectBA, FOR j: [0..16) IN [0..16) DO -- from FetchBuffer IF IBufRdByteAc[j] THEN { preOpA _ AND[preOpA, iBuf[j]]; preAlphaA _ AND[preAlphaA, iBuf[(j+1) MOD 16]]; preBetaA _ AND[preBetaA, iBuf[(j+2) MOD 16]]; preGammaA _ AND[preGammaA, iBuf[(j+3) MOD 16]]; preDeltaA _ AND[preDeltaA, iBuf[(j+4) MOD 16]] }; ENDLOOP; FOR j: [0..4) IN [0..4) DO IF IBufWrtWdBc[j] THEN FOR k: NAT IN [0..4) DO iBuf[4*j+k] _ SelectByte[p[II[IPData].ORD].lc, k]; ENDLOOP; ENDLOOP; 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. condEffect2: EUCondEffect2AB, dpCmndRd3: DPCmndRd3BA, stage1BHoldIfReject: Stage1BHoldIfRejectBA, 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. Left column ... Right column ... Κ:΅˜™ Icodešœ Οmœ1™J˜J˜šœžœ˜&Jšžœžœ˜J˜šžœž˜˜Jšœ  ˜*šœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœžœ"žœ$˜S—J˜Jšœ+˜+J˜Jšœ˜Jšœ˜šœžœž˜+Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšžœžœ˜"—Jšœ˜—J˜Jšœ žœ˜J˜˜Jšœ"˜"Jšœžœ žœžœ˜BJšœžœžœ˜,Jšœ˜Jšœ)žœ˜Gšœ˜Jšžœ ˜Jšžœžœ˜1šžœž˜šœ˜Jšžœžœ˜'Jšžœ žœ˜!—Jšœ˜——Jšœ!žœ˜3Jšœ!˜!šœžœž˜+Jšœ˜Jšœ˜Jšœ˜Jšœžœžœ˜"—Jšœ˜J˜—šœ ˜ šžœžœž˜šžœ!žœ&˜PJšœ˜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šœžœ žœ˜FJšœ˜Jšœ˜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šœ ž˜Jšœ˜—Jšžœžœ˜"—š žœžœžœžœž˜3šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ%˜%Jšœ$˜$Jšœ˜—šœ˜Jšœ žœ˜Jšœžœ˜Jšœ žœ˜Jšœ˜Jšœ˜Jšœ žœ˜Jšœžœ˜Jšœž˜Jšœ˜—Jšžœžœ˜"J˜—Jšœ žœžœ˜FJšœžœžœ˜BJ˜Jšœ&˜&Jšœžœ žœžœ˜1Jšœžœžœžœ˜5Jšœ)˜)Jšœ$˜$J˜Jšœ$˜$Jšœžœžœžœ˜?Jšœžœ žœžœ˜#Jšœžœžœ˜7Jšœžœžœ˜7Jšœ$˜$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šœžœ˜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˜šΟn œžœžœžœžœžœžœ˜QJšžœžœžœžœ˜&J˜—š‘ œžœžœžœžœžœ žœžœ˜TJšžœžœžœžœ˜%J˜—Jšœžœ˜J˜Jš œžœ žœžœžœžœ˜5J˜šžœž˜˜J˜Jšœ ˜#Jšœ ˜ šžœžœž˜šžœ#žœ&˜RJšœ˜Jšœžœ˜Jšœ˜——Jšœ  ˜(Jšœžœ$žœ'˜qJ˜Jšœ$žœ˜+J˜Jšœ  ˜4Jšœ˜Jšœ˜Jšœ!˜!Jšœžœ žœžœ žœžœžœžœ˜mJ˜Jšœžœ žœ ˜Bšœžœžœžœ ˜ZJ˜—šžœ žœ žœ ™0šžœžœ™Jšœ žœ™ Jšœ žœžœ™/Jšœ žœžœ™/Jšœ žœžœ™/Jšœ žœžœ™2—Jšžœ™—Jšœžœ˜"Jšœ$žœ˜,Jšœ"žœ˜*Jšœ$žœ˜,Jšœ$žœ˜,J˜Jšœ˜—J˜šœ ˜ Jšœžœžœ ˜0J˜—J˜˜šžœžœž˜šžœ"žœ(˜SJšœ˜Jšœ žœ #˜6Jšœ˜Jšœžœ žœ˜#Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ žœžœ 6˜{Jšœ˜——Jšœ  ˜'šœ ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ#žœ&˜V—J˜J˜Jšœ˜J˜šžœ žœ ˜*Jšœ˜Jšœ˜Jšœžœ˜Jšžœžœ˜!—šœžœžœž˜Jšœžœ˜4Jšœ#žœ˜*Jšžœ ˜—šžœžœž˜šžœ#žœ(˜TJšœ˜Jšœžœ˜Jšœ˜——Jšœ  ˜(Jšœžœ$žœ'˜oJ˜Jšœ ˜/J˜Jšœžœ žœžœ ˜NJ˜šžœ žœž™šžœž™šžœžœžœž™Jšœžœžœžœ ™2Jšžœ™—Jšžœ™——šžœ žœ˜Jšœžœ˜Jšœ˜Jšœ žœ žœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ ˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—˜ Jšœžœžœ ˜/J˜—J˜Jšžœžœ˜!J˜—šžœžœž˜šžœ$žœ,˜YJšœžœ˜Jšœ˜Jšœ˜Jšœ˜——Jšœ   ˜)šœ ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ%žœ*˜\J˜—šœC˜CJšœP˜P—Jšœžœ˜J˜Jšžœžœ˜ J˜Jšžœ˜—J˜šœžœ˜2J˜J˜—šœ žœ˜!Jšžœžœ˜Jš žœžœ žœ žœžœ˜6Jšžœ˜—J˜Jšœžœ˜4˜J˜—šœ žœ˜!Jšžœžœ˜J˜šžœž˜˜Jšžœžœ˜+Jšžœžœ˜%Jšœ˜—J˜Jšœ žœ˜J˜˜šœ žœž˜'Jšœ˜Jšœ˜Jšœžœ˜+Jšœžœ-˜KJšžœ1 ˜G—Jšžœžœ˜+Jšœ˜J˜—Jšœ žœ˜J˜Jšžœžœ˜!J˜—Jšžœ˜—J˜šœžœ˜4J˜J˜—šœ žœ˜ Jšžœžœ˜J˜šžœžœ ˜-Jšœ˜Jšœžœ˜J˜—šžœ˜Jšœ˜Jšœ˜J˜J˜—šžœž˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœ  ˜)šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ$žœ'˜X—J˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœ žœ žœžœ˜-Jšœ žœžœžœ˜*Jšœ žœ žœžœ˜&Jšœ"žœ˜)J˜šœžœžœž˜ Jšœ ˜ Jšœ˜Jšžœ  &˜8J˜—šœžœžœž˜ Jšœ ˜ Jšžœ˜Jšžœ  &˜8—J˜šžœžœžœ ž˜Jšžœžœ˜1Jšžœžœ˜1Jšžœ˜J˜—šžœ žœ  ˜Jšœžœ˜)Jšœ ˜#Jšœ ˜"Jšœ˜—šž˜šžœžœžœ ž˜šžœžœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœ˜——J˜Jšœ˜Jšœ˜J˜šžœž˜Jšœžœžœ žœ ˜3—Jšœ˜J˜—Jšœ*žœžœ˜6J˜šœ˜Jšœ'˜'Jšœ!žœ˜(J˜šžœžœž˜šžœ#žœ)˜UJšœ ˜ Jšœ˜Jšœ   ˜J˜——Jšœ  ˜(šœ˜Jšœ ˜ Jšœžœ$žœ'˜XJ˜—šžœžœž˜šžœ!žœ'˜QJšœ   ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ#˜#Jšœ˜Jšœ˜Jšœ ˜ J˜——Jšœ  ˜&Jšœžœ"žœ%˜VJšœ žœ ˜ Jšœ žœ ˜ Jšœ žœ ˜J˜Jšœ˜Jšœ˜J˜J˜J˜—šœ ˜ šžœžœž˜šžœ#žœ)˜UJšœ˜Jšœ˜Jšœ#˜#Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜——Jšœ˜—J˜Jšžœžœ˜!J˜—Jšžœ˜—J˜šœžœ˜2J˜J˜—šžœžœ˜Jšžœžœ˜JšœΟ™ΟJ™Jšœμ™μJ˜šΠbnœžœžœžœ˜1Jš žœžœžœžœ žœžœ˜5J˜—šžœž˜˜Jšœ˜J˜šžœžœ˜Jšœ˜šœžœ ž˜)Jšœ !œ˜3Jšœ œ˜6Jšœ 3œ˜DJšžœžœ˜#—šœ˜JšœΗ™ΗJ˜——JšžœžœB˜Všžœžœ˜šœžœžœž˜ Jšœ! ˜8Jšœ% !˜FJšžœžœ˜!—J˜J˜—šœžœ ž˜Jšœ˜Jšœ˜Jšžœžœ˜#—Jšœ˜J˜Jšœ˜Jšœ˜—J˜Jšœ žœ˜J˜˜JšžœžœB˜VJšœ?˜?Jšœ(˜(šœžœž˜,Jšœ˜Jšœ˜Jšœ*˜*Jšœ ˜ Jšžœžœ˜$J˜—Jšœ*˜*Jšœ ˜ J˜šœžœ ž˜'Jšœ˜Jšœ˜Jšœ ˜ Jšœ`˜`šœZ˜Zšžœž˜šœ 0˜>Jšœžœ˜—šœ 1˜@Jšœ žœžœ˜—Jšžœžœžœ˜)——Jšœžœ'˜EJšœ˜Jšœ˜Jšžœžœ˜$J˜—Jšœ ˜ Jšœ˜Jšœ˜Jšœ žœžœ žœ˜'Jšœ˜J˜—Jšœ žœ˜J˜Jšžœžœ˜!J˜—Jšžœ˜—J˜šœžœžœ˜,J˜J˜—šžœžœ˜Jšžœžœ˜J˜Jšœžœ žœžœžœ žœžœžœ žœžœžœ˜pJ˜šžœž˜˜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šœm˜mJšœ˜šœ ˜ Jšœ˜Jšœž˜Jšœ˜—šœžœžœ˜DJšžœžœžœ˜LJšžœžœžœžœ˜SJšžœžœžœ ˜$—š œžœžœžœžœ˜XJš žœžœžœžœžœ˜`Jš žœžœžœžœžœžœ˜h—š œžœžœžœžœ˜cJš žœžœžœžœžœ˜kJš žœžœžœžœžœžœ˜s—Jšžœžœ=˜Qšžœžœ˜šœ˜JšœJ˜J—Jšœ˜—Jšœ!˜!Jšœ˜—J˜Jšœ žœ˜J˜˜Jšœ˜Jšœ˜Jšžœžœ@˜TJšœ&žœžœ ˜MJšœ)žœžœ˜DJšœžœžœ˜)Jšœ˜J˜—Jšœ žœ˜J˜Jšžœžœ˜!J˜—Jšžœ˜—J˜šœžœ˜4J˜J˜—šžœžœ˜Jšžœžœ˜JšœAžœ˜Ešžœž˜šœ˜Jšœ0žœ  ˜Bšžœžœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœžœžœ žœ ˜DJšœžœžœ žœ ˜Dš žœžœžœžœž˜4Jšœ˜Jšœ ˜ Jšžœžœ˜"—š žœžœžœžœž˜4Jšœ˜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šœ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šœ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šžœžœ žœ˜6Jšžœžœ žœ˜6Jšžœžœ žœ˜6Jšžœžœ žœ˜6J˜šžœžœ˜Jšœ œ˜3Jšœ œ˜3Jšœ˜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˜šœ˜šžœžœž˜šžœžœ"˜JJšœ™J˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœ˜Jšœ™Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜——Jšœ  ˜$šœ˜Jšœ˜Jšœ+™+Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœ žœ ˜MJ˜—šœžœ ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ˜J˜—Jšœ žœ˜J˜Jšžœžœ˜!J˜—Jšžœ˜—J˜šœžœ˜:J˜J˜—šœ žœ˜"Jšžœžœ˜Jšžœžœ ˜š žœžœžœžœ ž˜)Jš œžœžœžœžœ ˜6—Jšžœžœžœ ˜Jšžœ˜—J˜šœžœ˜6J˜J˜—šœ žœ˜!Jšžœžœ˜J˜Jšœžœžœžœ˜J˜š‘œžœ9žœ#˜wJšœ˜Jšœ ˜ Jšœ˜J˜—Jšžœž˜˜šœ˜Jšœžœ˜Jšœ˜Jšœ˜Jšžœžœ˜1š žœžœžœžœž˜5Jšœ!˜!Jšœ>˜>Jšžœžœ˜"—š žœžœžœžœž˜5Jšœ!˜!Jšœ:˜:Jšžœžœ˜"—Jšœ˜—J˜Jšœžœ˜J˜šœ˜Jšœžœ˜ šœ˜Jšœ˜Jšœžœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ žœ žœžœ˜3Jšœ˜—Jšžœžœ˜2šœžœžœž˜ Jšœ!˜!Jšœ:˜:Jšžœžœ˜"—Jšœ˜Jšžœ žœ%˜8Jšœ˜J˜šœ žœž˜'Jšœžœ˜Jšžœžœ˜J˜—šžœžœ˜Jšœ)™)šžœ/žœžœžœ˜Zšžœžœ žœ˜1Jšœžœ,žœ˜Xšžœžœž˜šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ ˜ Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šœ˜Jšœ˜—šž˜Jšœžœžœ˜:——Jšœžœ˜*šžœžœž˜Jšœ2˜2Jšžœ/˜2šžœ˜ Jšœ1˜1šœžœ+˜?Jš œžœžœžœžœžœ˜J—šžœ ˜Jšžœžœžœ˜>—šžœ ˜Jšžœžœžœ˜;—šžœ ˜Jšžœžœžœ˜=Jšžœ˜—Jšœžœžœ ˜BJšœžœžœ ˜BJšœžœ˜Jšœ˜——J˜—Jšœ˜J˜—šžœžœ˜.J˜—J˜—Jšœ˜J˜—šœ˜šžœžœ ˜(Jšœžœ˜šžœžœ˜šžœ/žœžœ˜Jšžœ:˜=Jšžœ;˜>Jšžœ8˜;Jšžœ9˜Jšžœ:˜=Jšžœ;˜>Jšžœ9˜