DIRECTORY RoseTypes, RoseCreate, Rope, DragOpsCross, BitOps, Dragon, RoseRun, DragOpsCrossUtils; eu: CEDAR PROGRAM IMPORTS RoseCreate, BitOps, Dragon, RoseRun, RoseTypes, DragOpsCrossUtils = BEGIN OPEN RoseTypes, BitOps; PBusFaults: TYPE = Dragon.PBusFaults; ALULeftSources: TYPE = Dragon.ALULeftSources; ALURightSources: TYPE = Dragon.ALURightSources; Store2ASources: TYPE = Dragon.Store2ASources; ALUOps: TYPE = Dragon.ALUOps; CondSelects: TYPE = Dragon.CondSelects; RegisterCells: PROC = BEGIN [] _ RoseCreate.RegisterCellType[name: "EU", expandProc: NIL, ioCreator: CreateEUIO, initializer: InitializeEU, evals: [EvalSimple: EUEvalSimple], tests: LIST[[name: "ExerciseEveryBlock", proc: EUTestExerciseEveryBlock, stateToo: FALSE]], ports: CreateEUPorts[], driveCreator: CreateEUDrive]; END; otherss: SymbolTable _ RoseCreate.GetOtherss["eu.pass"]; CreateEUPorts: PROC RETURNS [ports: Ports] = {ports _ RoseCreate.PortsFromFile["eu.EU.rosePorts"]}; EUIORef: TYPE = REF EUIORec; EUIORec: TYPE = MACHINE DEPENDENT RECORD [ PhA(0): BOOLEAN, nPhA(1): BOOLEAN, PhB(2): BOOLEAN, nPhB(3): BOOLEAN, Vdd(4): BOOLEAN, Gnd(5): BOOLEAN, PadVdd(6): BOOLEAN, PadGnd(7): BOOLEAN, MHold(8): BOOLEAN, MnReset(9): BOOLEAN, DShift(10): BOOLEAN, DExecute(11): BOOLEAN, DNSelect(12): BOOLEAN, DDataIn(13): BOOLEAN, DDataOut(14): BOOLEAN, EPData(15): ARRAY [0..2) OF CARDINAL, EPParityB(17): BOOLEAN, EPRejectB(18): BOOLEAN, EPFaultB(19): PBusFaults, EPNPErrorB(20): BOOLEAN, KBus(21): ARRAY [0..2) OF CARDINAL, EUAluLeftSrc1BA(23): ALULeftSources, EUAluRightSrc1BA(24): ALURightSources, EUStore2ASrc1BA(25): Store2ASources, EUAluOp2AB(26): ALUOps, EUCondSel2AB(27): CondSelects, EURes3AisCBus2BA(28): BOOLEAN, EUSt3AisCBus2BA(29): BOOLEAN, EUCondition2BA(30): BOOLEAN, EURes3BisPBus3AB(31): BOOLEAN, EUCheckParity3AB(32): BOOLEAN, EULoadField3BA(33): BOOLEAN, EUWriteToPBus3AB(34): BOOLEAN]; EUDriveRef: TYPE = REF EUDriveRec; EUDriveRec: TYPE = RECORD [tag: DriveTagType, s: PACKED ARRAY EUPort OF DriveLevel]; EUPort: TYPE = MACHINE DEPENDENT { PhA, nPhA, PhB, nPhB, Vdd, Gnd, PadVdd, PadGnd, MHold, MnReset, DShift, DExecute, DNSelect, DDataIn, DDataOut, EPData, EPParityB, EPRejectB, EPFaultB, EPNPErrorB, KBus, EUAluLeftSrc1BA, EUAluRightSrc1BA, EUStore2ASrc1BA, EUAluOp2AB, EUCondSel2AB, EURes3AisCBus2BA, EUSt3AisCBus2BA, EUCondition2BA, EURes3BisPBus3AB, EUCheckParity3AB, EULoadField3BA, EUWriteToPBus3AB, (39)}; CreateEUIO: PROC [ct: CellType] RETURNS [ioAsAny: REF ANY] --IOCreator-- = { ioAsAny _ NEW[EUIORec]; }; CreateEUDrive: PROC [ct: CellType] RETURNS [driveAsAny: REF ANY] --DriveCreator-- = { driveAsAny _ NEW[EUDriveRec]; }; EUStateRef: TYPE = REF EUStateRec; EUStateRec: TYPE = RECORD [ leftOp2AB, rightOp2AB, store2AB, result2BA, store2BA, result3AB, store3AB, result3BA: Dragon.HexWord, aAdr, bAdr, cAdr: Dragon.HexByte, ram: ARRAY Dragon.HexByte OF Dragon.HexWord, field: Dragon.HexWord, -- Field descriptor for the field unit. A copy is kept as RAM[fieldAdr], another copy is in the field unit. Any write is performed to both physical locations (specified by the EULoadField3BA only), any read is from the most convenient location: RAM for usual reads, field for field unit control. kBusAB: Dragon.HexWord, -- a register to hold KBus for use in the field unit if required carryAB, carryBA: BOOL, -- carryBA is the output of the adder modified by the opcode of the previous operation and latched if no trap; carryAB is a copy of carryBA if there is no reject or fault. rejectBA: BOOL, -- a copy of EPRejectB stable during PhiA faultBA: BOOL, -- a latched version of EPFaultB#None AND rejectBA; it carries a heavy responsibility: on the following cycle, the IFU promises to send cAdr=euMAR, and the EU promises to preserve the carry. parityStore3AB: BOOL, hold1BA, hold2AB, hold2BA, hold3AB: BOOL ]; InitializeEU: Initializer = { IF leafily THEN BEGIN ioRec: EUIORef _ NARROW[cell.realCellStuff.newIO]; state: EUStateRef _ NEW[EUStateRec]; cell.realCellStuff.state _ state; BEGIN OPEN ioRec, state; ram[Dragon.PRtoByte[euConstant]] _ 0; -- done by IFU END; END; }; EUEvalSimple: CellProc = BEGIN newIO: EUIORef _ NARROW[cell.realCellStuff.newIO]; state: EUStateRef _ NARROW[cell.realCellStuff.state]; BEGIN OPEN newIO, state; IF PhA THEN {hold2AB _ hold1BA; hold3AB _ hold2BA;}; IF PhA AND ~hold2BA THEN BEGIN IF NOT (rejectBA OR EUCondition2BA) THEN carryAB _ carryBA; EPData _ Dragon.LTD[result2BA]; IF EULoadField3BA THEN field _ result3BA; IF NOT rejectBA THEN BEGIN kBusAB _ Dragon.LFD[KBus]; leftOp2AB _ SELECT EUAluLeftSrc1BA FROM aBus => ram[aAdr], rBus => result2BA, cBus => result3BA, ENDCASE => ERROR; rightOp2AB _ SELECT EUAluRightSrc1BA FROM bBus => ram[bAdr], rBus => result2BA, cBus => result3BA, kBus => Dragon.LFD[KBus], ENDCASE => ERROR; store2AB _ SELECT EUStore2ASrc1BA FROM bBus => ram[bAdr], cBus => result3BA, rBus => result2BA, ENDCASE => ERROR; result3AB _ SELECT EURes3AisCBus2BA FROM TRUE => result3BA, ENDCASE => result2BA; store3AB _ SELECT EUSt3AisCBus2BA FROM TRUE => result3BA, ENDCASE => store2BA; SELECT TRUE FROM cAdr IN [Dragon.PRtoByte[euStack] .. Dragon.PRtoByte[euBogus]) => ram[cAdr] _ result3BA; cAdr IN [Dragon.PRtoByte[ifuXBus] .. Dragon.PRtoByte[ifuLast]] => KBus _ Dragon.LTD[result3BA]; ENDCASE => Dragon.Assert[FALSE, "EU cAdr out of range"]; END; END; IF PhB THEN {hold1BA _ MHold; hold2BA _ hold2AB;}; IF PhB AND ~hold3AB THEN -- EPFaultB ??? BEGIN PlusOrMinusAluRight, aluOut: Dragon.HexWord; c32, overflow, conditionB: BOOL; rejectBA _ EPRejectB; faultBA _ EPFaultB#Dragon.None AND EPRejectB; aAdr _ ECFD[KBus, 32, 0, 8]; bAdr _ ECFD[KBus, 32, 8, 8]; cAdr _ ECFD[KBus, 32, 16, 8]; Dragon.Assert[ aAdr IN [0..128) -- stack OR aAdr IN [130..135] -- euMAR, euField, and FP add OR aAdr IN [140..143] -- FP mult OR aAdr IN [144..155] -- constants OR aAdr IN [160..176)]; -- aux Dragon.Assert[ bAdr IN [0..128) -- stack OR bAdr IN [130..135] -- euMAR, euField, and FP add OR bAdr IN [140..143] -- FP mult OR bAdr IN [144..155] -- constants OR bAdr IN [160..176)]; -- aux Dragon.Assert[ -- EUMar cannot be written using cAdr cAdr IN [0..128] -- stack+euJunk OR cAdr IN [131..135] -- no MAR, but euField and FP add OR cAdr IN [140..143] -- FP mult OR cAdr IN [144..155] -- constants OR cAdr IN [160..176] -- aux OR cAdr IN [240..255]]; -- IFU regs Dragon.Assert[NOT (EUWriteToPBus3AB AND EURes3BisPBus3AB)]; -- just for simulation IF EUWriteToPBus3AB THEN -- store in progress BEGIN EPData _ Dragon.LTD[store3AB]; -- send data to Cache (Store) result3BA _ result3AB -- save the address in result3BA, done normally since NOT EURes3BisPBus3AB END ELSE -- either a fetch, an op, or a move in progress, but no write on the PBus SELECT TRUE FROM ~rejectBA AND EURes3BisPBus3AB => -- Fetch without reject result3BA _ Dragon.LFD[EPData]; rejectBA OR (~rejectBA AND ~EURes3BisPBus3AB) => -- Fetch with reject, op, move result3BA _ result3AB; ENDCASE => ERROR; store2BA _ store2AB; carryBA _ carryAB; -- ??? SELECT EUAluOp2AB FROM SAdd => { [aluOut, c32] _ DoubleADD[leftOp2AB, rightOp2AB, carryAB]; result2BA _ aluOut; carryBA _ FALSE}; SSub => { [aluOut, c32] _ DoubleSUB[leftOp2AB, rightOp2AB, carryAB]; result2BA _ aluOut; carryBA _ FALSE}; UAdd => { [aluOut, c32] _ DoubleADD[leftOp2AB, rightOp2AB, carryAB]; result2BA _ aluOut; carryBA _ c32}; USub => { [aluOut, c32] _ DoubleSUB[leftOp2AB, rightOp2AB, carryAB]; result2BA _ aluOut; carryBA _ NOT c32}; VAdd, VAdd2 => { [aluOut, c32] _ DoubleADD[leftOp2AB, rightOp2AB, FALSE]; result2BA _ aluOut}; VSub => { [aluOut, c32] _ DoubleSUB[leftOp2AB, rightOp2AB, FALSE]; result2BA _ aluOut}; LAdd => { [aluOut, c32] _ DoubleADD[leftOp2AB, rightOp2AB, FALSE]; result2BA _ aluOut; carryBA _ FALSE}; LSub => { [aluOut, c32] _ DoubleSUB[leftOp2AB, rightOp2AB, FALSE]; result2BA _ aluOut; carryBA _ FALSE}; FOP => { -- field descriptor provided by Field result2BA _ aluOut _ FieldOp[leftOp2AB, rightOp2AB, field]}; FOPK => { -- field descriptor provided by kBusAB. Otherwise identical to FOP result2BA _ aluOut _ FieldOp[leftOp2AB, rightOp2AB, kBusAB]}; And => { result2BA _ aluOut _ WordOp[and, leftOp2AB, rightOp2AB]}; Or => { result2BA _ aluOut _ WordOp[or, leftOp2AB, rightOp2AB]}; Xor => { result2BA _ aluOut _ WordOp[xor, leftOp2AB, rightOp2AB]}; BndChk => { [aluOut, c32] _ DoubleSUB[leftOp2AB, rightOp2AB, FALSE]; result2BA _ leftOp2AB}; MulLd, MulStep, RdMQ, DivLdDbl, DivCk, DivStep, DivAdjQ, DivAdjR => {NULL}; -- ??? ENDCASE => ERROR Stop["Invalid ALU Operation"]; SELECT EUAluOp2AB FROM SSub, USub, VSub, LSub => [PlusOrMinusAluRight, ] _ DoubleSUB[0, rightOp2AB, FALSE]; ENDCASE => PlusOrMinusAluRight _ rightOp2AB; overflow _ (EBFL[leftOp2AB, 0] = EBFL[PlusOrMinusAluRight, 0]) AND (EBFL[leftOp2AB, 0] # EBFL[aluOut, 0]); conditionB _ SELECT EUCondSel2AB FROM False => FALSE, EZ => aluOut=0, -- not necessarily after a sub!!! LZ => EBFL[aluOut, 0], -- aluOut<0 by checking the high-order bit LE => (aluOut=0) OR EBFL[aluOut, 0], -- aluOut<=0, True => TRUE, NE => aluOut#0, GE => NOT EBFL[aluOut, 0], GZ => NOT ((aluOut=0) OR EBFL[aluOut, 0]), -- aluOut>0, OvFl => overflow, BC => EBFL[leftOp2AB, 0] OR -- arg < 0 NOT EBFL[aluOut, 0], -- arg-limit >= 0 IL => (EBFL[leftOp2AB, 0]#EBFL[leftOp2AB, 1]) OR (EBFL[rightOp2AB, 0]#EBFL[rightOp2AB, 1]) OR (EBFL[aluOut, 0]#EBFL[aluOut, 1]), -- No: 3 bits!!! DivOvFl => FALSE, -- for now... NotOvFl => NOT overflow, NotBC => NOT EBFL[leftOp2AB, 0] -- 0<=arg -- AND EBFL[aluOut, 0] -- arg-limit<0 --, NotIL => NOT ((EBFL[leftOp2AB, 0]#EBFL[leftOp2AB, 1]) OR (EBFL[rightOp2AB, 0]#EBFL[rightOp2AB, 1]) OR (EBFL[aluOut, 0]#EBFL[aluOut, 1])), Kernal => ECFD[Dragon.LTD[aluOut], 32, 0, 4]=0, -- msb(aluOut, 4)=0 ENDCASE => ERROR Stop["Invalid EUCondition2BA Code"]; EUCondition2BA _ conditionB; END; END; END; EUTestExerciseEveryBlock: CellTestProc = BEGIN instructions: EUIORef _ NARROW[io]; drive: EUDriveRef _ NARROW[driveAsAny]; BEGIN OPEN instructions; END; END; fieldAdr: INTEGER = Dragon.PRtoByte[euField]; marAdr: INTEGER = Dragon.PRtoByte[euMAR]; fpAluClear: INTEGER = Dragon.PRtoByte[fpAluClear]; fpAluSgl: INTEGER = Dragon.PRtoByte[fpAluSgl]; fpAluLsw: INTEGER = Dragon.PRtoByte[fpAluLsw]; fpAluMsw: INTEGER = Dragon.PRtoByte[fpAluMsw]; fpMultClear: INTEGER = Dragon.PRtoByte[fpMultClear]; fpMultSgl: INTEGER = Dragon.PRtoByte[fpMultSgl]; fpMultLsw: INTEGER = Dragon.PRtoByte[fpMultLsw]; fpMultMsw: INTEGER = Dragon.PRtoByte[fpMultMsw]; Remark: PROC [ message: Rope.ROPE ] = {RoseRun.DisableableStop[Remark, message]}; FieldOp: PROC[aluLeft, rightOp2AB, fieldDesc: Dragon.HexWord] RETURNS [result:Dragon.HexWord] = BEGIN fd: DragOpsCross.FieldDescriptor _ DragOpsCrossUtils.CardToFieldDescriptor[fieldDesc MOD 65536]; shiftout: BitDWord _ [0,0]; -- to begin cleanly maskhole: BitDWord _ doubleMasks[fd.mask]; Dragon.Assert[fd.shift < 33]; Dragon.Assert[fd.mask < 33]; SELECT fd.shift FROM 0 => shiftout _ Dragon.LTD[aluLeft]; -- no shift 32 => shiftout _ Dragon.LTD[rightOp2AB]; -- full shift IN (0..32) => BEGIN shiftout _ MDTD [Dragon.LTD[aluLeft], 32, fd.shift, 32-fd.shift, shiftout, 32, 0, 32-fd.shift]; shiftout _ MDTD [Dragon.LTD[rightOp2AB], 32, 0, fd.shift, shiftout, 32, 32-fd.shift, fd.shift]; END; ENDCASE => ERROR; result _ Dragon.LFD[DAND[shiftout, maskhole]]; -- mask shiftout IF fd.insert THEN BEGIN mask2: BitDWord _ doubleMasks[fd.shift]; -- another intermediate mask maskhole _ DNOT[DXOR[maskhole, mask2],32]; result _ WordOp[or, result, WordOp[and, rightOp2AB, Dragon.LFD[maskhole] ] ]; END; END; DoubleADD: PROC[al, bl: Dragon.HexWord, carry: BOOL] RETURNS [sl: Dragon.HexWord, c32: BOOL] = BEGIN Xor: PROC[x, y: BOOL] RETURNS [z: BOOL] = {RETURN[~x=y]}; ai, bi: BOOL; s: BOOL _ FALSE; c: BOOL _ carry; i: INTEGER; sum: BitDWord _ [0,0]; FOR i IN [1..32] DO ai _ EBFL[al, 32-i]; bi _ EBFL[bl, 32-i]; s _ Xor[ai, Xor[bi, c]]; c _ (ai AND bi) OR (bi AND c) OR (ai AND c); sum _ IBID[s, sum, 32, 32-i]; ENDLOOP; RETURN[Dragon.LFD[sum], c]; END; DoubleSUB: PROC[a, b: Dragon.HexWord, carry: BOOL] RETURNS [dif: Dragon.HexWord, c32: BOOL] = {[dif, c32] _ DoubleADD[a, WordOp[not,b], ~carry]}; WordOp: PROC[op: {not, or, and, xor}, left, right: Dragon.HexWord _ 0] RETURNS[result: Dragon.HexWord] = { RETURN[Dragon.LFD[SELECT op FROM not => DNOT [Dragon.LTD[left], 32], or => DOR [Dragon.LTD[left], Dragon.LTD[right]], and => DAND [Dragon.LTD[left], Dragon.LTD[right]], xor => DXOR [Dragon.LTD[left], Dragon.LTD[right]], ENDCASE => ERROR]] }; EBFL: PROC[word: Dragon.HexWord, index: CARDINAL] RETURNS[BOOL] = { RETURN[ EBFD[Dragon.LTD[word], 32, index]] }; DblShiftRt: PROC[msb: BOOL, ltIn, rtIn: Dragon.HexWord] RETURNS[ltOut, rtOut: Dragon.HexWord] = {rtOut _ ShiftRt[EBFL[ltIn, 31], rtIn]; ltOut _ ShiftRt[msb, ltIn]}; ShiftRt: PROC[msb: BOOL, w: Dragon.HexWord] RETURNS[r: Dragon.HexWord] = {r_Dragon.LFD[IBID[msb, MDTD[Dragon.LTD[w],32,0,31,[0,0],32,1,31],32,0]]}; DblShiftLt: PROC[ltIn, rtIn: Dragon.HexWord, lsb: BOOL] RETURNS[cry: BOOL, ltOut, rtOut: Dragon.HexWord] = {cry _ EBFL[ltIn,0]; ltOut _ ShiftLt[ltIn, EBFL[rtIn, 0]]; rtOut _ ShiftLt[rtIn, lsb]}; ShiftLt: PROC[w: Dragon.HexWord, lsb: BOOL] RETURNS[r: Dragon.HexWord] = {r_Dragon.LFD[IBID[lsb, MDTD[Dragon.LTD[w],32,1,31,[0,0],32,0,31],32,31]]}; RegisterCells[]; END. Πeu.Mesa created by RoseTranslate 2.8.8 of January 28, 1985 2:26 pm PST from eu.Rose of June 10, 1985 12:11:20 pm PDT created for gunther.pa created at June 17, 1985 4:19:58 pm PDT Signal Type decls -- Pipeline registers -- RAM, RAM addresses and various aliased registers -- The RAM is actually 128 bits wide. -- The RAM is organised as follows (Ref DragOpsCross): registers 0 through 127 constitute the stack 128: euJunk i.e. no write 129: (currently spare) 130: euMAR, stores the address causing a cache fault, one cycle after the fault 131: euField aliased with field (when writing in euField, IFU also sends EULoadField3BA) 132 through 143 are FP registers 144 through 155 are constants 156 through 159 (currently spare) 160 through 175 are auxilliary 176 through 239: not legal 240 through 255: not in EU but on cAdr trigger drive of KBus; easily detected as 1111xxxx -- Registers physically present in the EU: 0..127 128 Stack 128, 129 130,131 4 junk, spare, MAR, field 132..143 12 FP regs 144..155 12 constants 160..175 16 auxilliary ---- Total 172 -- Bits and pieces for the ALU and the Field Unit -- Other pieces from the Control pipeline -- PhA phase. Note that rejectBA alone inhibits almost any state change during PhA -- DBus update Cycle carry if no reject and no trap in sight -- Always send address to Cache during PhiA (reject???) -- Loading field -- It is particularly important that no store in the RAM happens during rejectBA: rejectBA should run through the cAdr decoder -- cAdr IN 0 to 175 -- cAdr IN 240 to 255 -- PhiB phase. Most of the computations take place during PhiB -- DBus update Temporary EPRejectB is valid at the end of PhiB but bogus during PhiA, so it must be latched at the end of PhiB. A current problem is that the source for result3BA depends upon EPRejectB, and the choice is made during the same PhiB as it is received. So this statement has to be first. I'll try to get rid of this pb by shooting all cases where EPRejectB is needed during PhiB. Updating the RAM addresses aAdr in proper range (push in finer simulation???) bAdr in proper range cAdr in proper range -- PBus: notice that in case of reject during a store, we keep sending the data even though it is useless -- The default source for result3BA is result3AB; the only case where we update that register with the value found on the PBus is when a fetch terminates with no reject. Data pipe Alu and Field Unit computation Set Default values of state -- Here we compute the overflow by checking the high-order bits of the operands (leftOp2AB and rightOp2AB or - rightOp2AB) and of the result -- Condition and trap generation -- All test code is in euTest.mesa explicitly requested CEDAR: --Replace by straight logic functions; no case statements maskhole _ a cloud of zeros followed by fd.mask ones Insert 32-fd.shift bits of aluLeft on the left of shiftout Insert fd.shift bits of rightOp2AB on the right of shiftout Maskhole _ zeros, then fd.mask-fd.shift ones, then fd.shift zeros. Merge shiftout and rightOp2AB using the mask Returns a+b+carry and c32, where a and b are considered to be signed numbers Returns a-b-carry and c32, where a and b are considered to be signed numbers Implemented as a+(~b)+1+(~carry) ΚN˜Icodešœ™Kšœl™lKšœ™Kšœ'™'K˜K˜šΟk ˜ K˜V—K˜šΠblœœ˜KšœD˜K—K˜šœ˜ K˜—K˜šœ™Kšœ œ˜%Kšœœ˜-Kšœœ˜/Kšœœ˜-Kšœœ˜Kšœ œ˜'K˜—K˜šΟn œœ˜Kš˜˜,Kšœ œ˜K˜1K˜"KšœœHœ˜[K˜K˜—Kšœ˜—K˜8K˜KšŸ œœœH˜cK˜Kšœ œœ ˜š œ œœ œœ˜*Kšœœ˜Kšœ œ˜Kšœœ˜Kšœ œ˜Kšœœ˜Kšœœ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœœ˜Kšœœ˜Kšœ œ˜Kšœœ˜Kšœ œœœ˜%Kšœœ˜Kšœœ˜K˜Kšœœ˜Kšœ œœœ˜#K˜$K˜&K˜$K˜K˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜—K˜Kšœ œœ ˜"Kš œ œœœœœ ˜Tšœœœ œ˜"K˜φ—K˜š Ÿ œœœ œœΟc œ˜LKšœ œ ˜K˜—K˜š Ÿ œœœœœ œ˜UKšœ œ ˜K˜—K˜Kšœ œœ ˜"šœ œœ˜J™J˜ J˜J˜J˜J˜J™3J™%™6J™,J™J™J™OJ™XJ™ J™J™!J™J™J™Y—™*J™J™/J™J™J™J™ J™J™—J˜!Jšœœœ˜,Jšœ §˜ΎJ™J™1Jšœ @˜XJšœœ «˜ΓJ˜J™)Jšœ œ )˜9Jšœ œ Ύ˜ΝJšœœ˜Jšœ$˜(K˜—K˜˜šœ ˜Kš˜Kšœœ˜2Kšœœ ˜$K˜!šœœ˜Jšœ& ˜5J˜J˜Kšœ˜—Kšœ˜—K˜—K˜˜Kš˜Kšœœ˜2šœœ˜5šœœ˜J˜J™RJ™J™Jšœœ)˜4J™šœœ ˜Jš˜J™Jšœ-™-Jšœœ œœ˜;J™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™šœœ7˜>J˜—J™šœœ7˜>Jšœœ ˜ —Jšœœ˜8—Jšœ˜—Jšœ˜—J™J™J™>J˜J™Jšœœ'˜2J˜šœœ œ ˜)Jš˜Jšœ ™ J˜,Jšœœ˜ J˜˜J™ο—Jšœœ ˜-J˜J™Jšœœ˜Jšœœ˜Jšœœ˜Jšœ2™2˜Jšœœ  ˜Jšœœ  ˜3Jšœœ   ˜ Jšœœ   ˜"Jšœœ ˜—Jšœ™˜Jšœœ  ˜Jšœœ  ˜3Jšœœ   ˜ Jšœœ   ˜"Jšœœ ˜—Jšœ™šœ %˜4Jšœœ  ˜"Jšœœ  "˜8Jšœœ   ˜ Jšœœ   ˜"Jšœœ  ˜Jšœœ  ˜#—J˜J˜J™iJ™©Jšœœœ ˜RJ˜šœœ ˜.Jš˜Jšœœ  ˜=Jšœ J˜`Jš˜—šœ I˜Ošœœ˜šœ œ ˜9Jšœœ ˜—šœ œ œ ˜PJ˜—Jšœœ˜——J˜J™ J˜J˜J™™Jšœ ˜—šœ ˜˜ J˜:J˜Jšœ œ˜—˜ J˜:J˜Jšœ œ˜—˜ J˜:J˜J˜—˜ J˜:J˜Jšœ œ˜—˜Jšœ1œ˜8J˜—˜ Jšœ1œ˜8J˜—˜ Jšœ1œ˜8J˜Jšœ œ˜—˜ Jšœ1œ˜8J˜Jšœ œ˜—šœ %˜.J˜<—šœ B˜LJ˜=—˜J˜9—˜J˜8—˜J˜9—˜ Jšœ1œ˜8J˜—JšœEœ ˜RJšœœ˜/J˜—™Œšœ ˜˜Jšœ3œ˜:—Jšœ%˜,—Jš œ œœœœœ ˜j—J˜J™ šœ œ˜%Jšœ œ˜Jšœ !˜3Jšœœ  *˜CJšœœœ   ˜4Jšœ œ˜Jšœ˜Jšœœœ ˜Jš œœ œœ  ˜9J˜Jš œœœ  œœœ ˜VJšœœœœœœœœ œ ˜›Jšœ œ  ˜Jšœ œ ˜Jš œ œœ  œœœ  œ˜TJšœ œœœœœœœœ œ˜’Jšœ œœ ˜CJšœœ%˜5—J˜Jšœ˜——Kšœ˜—Kšœ˜—K˜˜(Kš˜Kšœœ˜#šœœ ˜'šœœ˜J™J™"—Kšœ˜—Kšœ˜—K˜šœ™Jšœ œ˜.Jšœ œ˜*J˜Jšœ œ˜2Jšœ œ˜/Jšœ œ˜.Jšœ œ˜.J˜Jšœ œ ˜4Jšœ œ˜0Jšœ œ˜0Jšœ œ˜0J˜JšŸœœœ0˜QJ˜J™9šŸœœ0˜=Jšœ˜!Jš˜˜"Jšœ2œ˜=—Jšœ ˜/˜,J™4—J˜;šœ ˜Jšœœ   ˜0Jšœœ  ˜6šœ ˜Jš˜J™;šœ ˜JšœœD˜O—J™;šœ ˜JšœœD˜O—Jšœ˜—Jšœœ˜—Jšœœœ ˜?šœ ˜Jš˜šœ* ˜FJ™B—šœ œœ˜*J™,—Jšœ<œ˜NJšœ˜—Jšœ˜—J˜J™Lš Ÿ œœ œœœ˜_Jš˜Jš Ÿœœœœœœ˜9J˜Jšœœ˜ Jšœœœ˜Jšœœ ˜Jšœœ˜ J˜šœœ ˜Jš˜Jšœœ ˜Jšœœ ˜J˜Jš œœœœœœ˜,Jšœœ˜Jšœ˜—Jšœœ ˜Jšœ˜—J˜J™LJ™ šŸ œœœ˜2šœœ˜*J˜3——J˜šŸœœ:˜FJšœ˜#šœœœ˜ Jšœ œ œ ˜%Jšœ œ œœ ˜3Jšœ œ œœ ˜4Jšœ œ œœ ˜4Jšœœ˜——J˜š œœœœœ˜CJšœœœ˜-—J˜šŸ œœœ˜7šœ!˜(Jšœœ/˜D——šŸœœœœ˜IJš œ œœœœ#˜J—J˜šŸ œœ"œ˜7Jšœœ!˜2Jšœœ œ(˜W—šŸœœœœ˜HJš œ œœœœ$˜K—J˜J˜—K˜K˜K˜K˜Kšœ˜—…—4Q: