DIRECTORY Basics, BitOps, CD, CDCommandOps, CDProperties, CDSequencer, CDIO, Core, CoreFlat, CDViewer, DRam, DynaBusInterface, IO, Ports, Random, Rosemary, RosemaryUser, RosemaryVector, ResponseChecker, Sisyph, TerminalIO; TestMC: CEDAR PROGRAM IMPORTS Basics, BitOps, CDCommandOps, CDIO, CoreFlat, CDProperties, CDViewer, DRam, DynaBusInterface, IO, Ports, Random, Rosemary, RosemaryUser, RosemaryVector, ResponseChecker, Sisyph, TerminalIO ~ BEGIN SharedIn, DReqTP, DGrantTP, OwnerIn, ResetIn, HeaderCycleIn, Clock, DataIn, DBus, DSelect, Vdd, Gnd: NAT; dSerialOut: NAT _ 0; dSerialIn: NAT _ 1; nDReset: NAT _ 2; nDFreeze: NAT _ 3; dExecute: NAT _ 4; dAddress: NAT _ 5; dShiftCK: NAT _ 6; ROPE: TYPE = Core.ROPE; Port: TYPE = Ports.Port; Quad: TYPE = DynaBusInterface.Quad; Cmd: TYPE = DynaBusInterface.Cmd; ModeError: TYPE = DynaBusInterface.ModeError; Shared: TYPE = DynaBusInterface.Shared; DeviceID: TYPE = DynaBusInterface.DeviceID; Address: TYPE = DynaBusInterface.Address; qZero: Quad = BitOps.BitQWordZero; REProc: TYPE = PROC [memory: BOOL _ TRUE]; TProc: TYPE = PROC [h: Handle, Eval: REProc]; ownerDelay: CARDINAL = 10; SHIFT: PROC [value: WORD, count: INTEGER] RETURNS [WORD] = Basics.BITSHIFT; BITAND: Basics.BitOp = Basics.BITAND; BITNOT: PROC [WORD] RETURNS [WORD] = Basics.BITNOT; Log2: PROC [n: INT] RETURNS [INT] = BitOps.Log2; dBusRegAddBits: NAT = 3; dBusWidth: NAT = 7; dBusRegAdd: TYPE = [0..8); arbiterTimeout: CARDINAL _ 200; ownerDelayBuf: ARRAY [0..ownerDelay] OF RECORD [owner, shared: BOOL]; cmdCount: INT _ 0; seed: INT _ 1234; ramdomOps: INT _ 100; design: CD.Design _ NIL; CallIOWrite: TProc ~ {IOWrite0[h, Eval, 6, TRUE, TRUE, 0, 28, 28, 22, 22]}; CallWB: TProc ~ {WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]}; CallRB: TProc ~ {ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]}; CallRBSh: TProc ~ {ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0], FALSE, TRUE]}; CallRBOwn: TProc ~ {ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0], TRUE, FALSE]}; CallRBOwnSh: TProc ~ {ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0], TRUE, TRUE]}; CallFB: TProc ~ {FlushBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]}; CallWS: TProc ~ {WriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah]]}; CallWSSh: TProc ~ {WriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], TRUE]}; CallCWS: TProc ~ {CondWriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah]]}; CallCWSSh: TProc ~ {CondWriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], TRUE]}; CallIOR: TProc ~ {IORRqst[h, Eval, [0,0,30h, 0], 0]}; CallBIOW: TProc ~ {BIOWRqst[h, Eval, [0,0,0,0], [0,0,0,0Bh]]}; CallDeMap: TProc ~ {DeMapRqst[h, Eval, [0,0,0,0], [0,0,0,0Ch]]}; opProcs: INT = 13; op: ARRAY [0..opProcs) OF TProc _ [CallIOWrite, CallWB, CallRB, CallRBSh, CallRBOwn, CallRBOwnSh, CallFB, CallWS, CallWSSh, CallCWS, CallCWSSh, CallBIOW, CallDeMap]; Handle: TYPE = REF HandleRec; HandleRec: TYPE = RECORD[ tester: RosemaryUser.Tester _ NIL, rootCT: Core.CellType _ NIL, vecFile: RosemaryVector.VectorFile _ NIL, captureVectors: BOOL _ FALSE, testFlatCell: CoreFlat.FlatCellType _ NIL, testPort: Ports.Port _ NIL, port: Port _ NIL ]; SimpleTest: RosemaryUser.TestProc = { DoSimpleTest: TProc ~ { ENABLE UNWIND => IF h.captureVectors THEN RosemaryVector.CloseVectorFile[h.vecFile]; InitPortIndicies[cellType]; cmdCount _ 0; Reset[h, Eval]; ReadID[h, Eval]; CircularAccessTest[h, Eval]; CmdTest[h, Eval]; OwnerTest[h, Eval]; SingleErrorTest[h, Eval]; DoubleErrorTest[h, Eval]; AddressTest[h, Eval]; CrossProdTest[h, Eval]; FlushPipe[h, Eval]; IF h.captureVectors THEN RosemaryVector.CloseVectorFile[h.vecFile]; }; h: Handle _ NEW[HandleRec]; IF design=NIL THEN ERROR; --use ExtractMC in the SPACE-P menu first h.tester _ NARROW[CDProperties.GetDesignProp[design, $DAUserRoseTester]]; h.rootCT _ NARROW[CDProperties.GetDesignProp[design, $DAUserCellType]]; h.port _ p; DoSimpleTest[h, Eval]; }; ReadID: TProc ~ { ENABLE Rosemary.Stop => IF reason = $BoolWireHasX THEN RESUME; DBusRegRead[h, Eval, 0, 5180h, 16]; --header=5, type=6, version=0 }; Reset: TProc ~ { ENABLE Rosemary.Stop => IF reason = $BoolWireHasX THEN RESUME; p: Port _ h.port; TerminalIO.PutRope["***Reset***\n"]; p[DSelect].b _ FALSE; p[DBus].bs[dShiftCK] _ FALSE; DBusRegWrite[h, Eval, 1, 0, 10]; p[SharedIn].b _ FALSE; p[OwnerIn].b _ FALSE; p[ResetIn].b _ TRUE; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ qZero; p[DReqTP].c _ 0; -- no request Cycle[h, Eval, 7]; p[ResetIn].b _ FALSE; Cycle[h, Eval, 2]; p[DGrantTP].d _ expect; p[DGrantTP].b _ FALSE; IOWrite0[h, Eval, 6, TRUE, TRUE, 0, 28, 28, 22, 22]; IOWrite1[h, Eval, 1, 10]; IOWrite2[h, Eval, 1, 10]; FlushPipe[h, Eval]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; WriteBlockRqst[h, Eval, [0,0,0,0], [0,0,0,0], [1,1,1,1], [2,2,2,2], [3,3,3,3]]; FlushPipe[h, Eval]; }; CircularAccessTest: TProc ~ { TerminalIO.PutRope["***Circular Access Test***\n"]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; ReadBlockRqst[h, Eval, [0,0,0,2], [2,2,2,2], [1,1,1,1], [0,0,0,0], [3,3,3,3]]; ReadBlockRqst[h, Eval, [0,0,0,4], [1,1,1,1], [0,0,0,0], [3,3,3,3], [2,2,2,2]]; ReadBlockRqst[h, Eval, [0,0,0,6], [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1]]; ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; }; BankTest: TProc ~ { TerminalIO.PutRope["***Bank Test***\n"]; IOWrite1[h, Eval, 2, 10, 1]; --two banks, one megabit drams, bank add=1, IOWrite2[h, Eval, 2, 10, 1]; FlushPipe[h, Eval]; WriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], FALSE, TRUE]; WriteSingleRqst[h, Eval, [0,0,0,8], [0,0,0,0Ah], FALSE, FALSE]; CondWriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], FALSE, TRUE]; CondWriteSingleRqst[h, Eval, [0,0,0,8], [0,0,0,0Ah], FALSE, FALSE]; BIOWRqst[h, Eval, [0,0,0,0], [0,0,0,0Bh], TRUE]; BIOWRqst[h, Eval, [0,0,0,8], [0,0,0,0Bh], FALSE]; DeMapRqst[h, Eval, [0,0,0,0], [0,0,0,0Ch], TRUE]; DeMapRqst[h, Eval, [0,0,0,8], [0,0,0,0Ch], FALSE]; }; AddressTest: TProc ~ { quad: Quad; TerminalIO.PutRope["***Address Test***\n"]; IOWrite1[h, Eval, 1, 10]; --single bank, one megabit drams IOWrite2[h, Eval, 1, 10]; Cycle[h, Eval, 10]; WriteBlockRqst[h, Eval, [0,0,0,00h], [0,0,0,00h], [0,0,0,00h], [0,0,0,00h], [0,0,0,00h]]; FOR i: NAT DECREASING IN [43..60] DO quad _ BitOps.BitQWordZero; quad _ BitOps.IBIQ[TRUE, quad, i]; WriteBlockRqst[h, Eval, quad, quad, quad, quad, quad]; ENDLOOP; ReadBlockRqst[h, Eval, [0,0,0,00h], [0,0,0,00h], [0,0,0,00h], [0,0,0,00h], [0,0,0,00h]]; FOR i: NAT DECREASING IN [43..60] DO quad _ BitOps.BitQWordZero; quad _ BitOps.IBIQ[TRUE, quad, i]; ReadBlockRqst[h, Eval, quad, quad, quad, quad, quad]; ENDLOOP; }; DoubleErrorTest: TProc ~ { lowBitsState: REF _ Rosemary.GetState[h.tester.display.simulation, NEW[CoreFlat.FlatCellTypeRec _ CoreFlat.ParseCellTypePath[h.tester.display.cellType, "/Bits63to71", NIL]]]; TerminalIO.PutRope["***Double Error Test***\n"]; IOWrite3[h, Eval]; --clear error status WriteBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6]]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FlushPipe[h, Eval]; DRam.DoubleBitError[lowBitsState, 03Ch, 6, 8]; ReadBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6], FALSE, FALSE, [TRUE, FALSE, FALSE, FALSE]]; ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FlushPipe[h, Eval]; IORRqst[h, Eval, [0, 0, 30h, 0], 0f0h]; IORRqst[h, Eval, [0, 0, 30h, 1], 8 + SHIFT[Basics.BITXOR[62, 66], 5]]; --two bit error, bits 62, 66 ReadBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6], FALSE, FALSE, [TRUE, FALSE, FALSE, FALSE]]; FlushPipe[h, Eval]; IORRqst[h, Eval, [0, 0, 30h, 0], 0f0h]; IORRqst[h, Eval, [0, 0, 30h, 1], 9 + SHIFT[Basics.BITXOR[62, 66], 5]]; --two bit error, mult. mem errors, bits 62, 66 FlushPipe[h, Eval]; DBusRegRead[h, Eval, 2, 0f0h, 32]; DBusRegRead[h, Eval, 3, 9 + SHIFT[Basics.BITXOR[62, 66], 5], 12]; }; SingleErrorTest: TProc ~ { lowBitsState: REF _ Rosemary.GetState[h.tester.display.simulation, NEW[CoreFlat.FlatCellTypeRec _ CoreFlat.ParseCellTypePath[h.tester.display.cellType, "/Bits63to71", NIL]]]; TerminalIO.PutRope["***Single Error Test***\n"]; IOWrite3[h, Eval]; --clear error status WriteBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6]]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FlushPipe[h, Eval]; DRam.SingleBitError[lowBitsState, 03Ch, 8]; ReadBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6]]; ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FlushPipe[h, Eval]; IORRqst[h, Eval, [0, 0, 30h, 0], 0f0h]; IORRqst[h, Eval, [0, 0, 30h, 1], 2 + SHIFT[62,5]]; --single bit error, bit 62 ReadBlockRqst[h, Eval, [0,0,0,0f0h], [9,9,9,9], [8,8,8,8], [7,7,7,7], [6,6,6,6]]; FlushPipe[h, Eval]; IORRqst[h, Eval, [0, 0, 30h, 0], 0f0h]; IORRqst[h, Eval, [0, 0, 30h, 1], 3 + SHIFT[62,5]]; --single bit error, mult. mem errors, bit 62 FlushPipe[h, Eval]; DBusRegRead[h, Eval, 2, 0f0h, 32]; DBusRegRead[h, Eval, 3, 3 + SHIFT[62,5], 12]; }; RandomTest: PROC [h: Handle, Eval: REProc, count: INT _ LAST[INT]] ~ { rs: Random.RandomStream _ Random.Create[opProcs, seed]; TerminalIO.PutRope["***Random Test***\n"]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FOR i: INT IN [0..count) DO op[Random.NextInt[rs]][h, Eval]; ENDLOOP; FlushPipe[h, Eval]; }; CrossProdTest: TProc ~ { TerminalIO.PutRope["***Cross Product Test***\n"]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FOR i: INT IN [0..opProcs) DO FOR j: INT IN [0..opProcs) DO op[i][h, Eval]; op[j][h, Eval]; ENDLOOP; ENDLOOP; FlushPipe[h, Eval]; }; OwnerTest: TProc ~ { TerminalIO.PutRope["***Owner Test***\n"]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; ReadBlockRqst[h, Eval, [0,0,0,0], qZero, qZero, qZero, qZero, TRUE, FALSE]; WriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], TRUE]; CondWriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah], TRUE]; ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0], FALSE, TRUE]; }; CmdTest: TProc ~ { TerminalIO.PutRope["***Command Test***\n"]; IOWrite0[h, Eval, 6, TRUE, TRUE, 0, 28, 28, 22, 22]; IOWrite1[h, Eval, 1, 10]; IOWrite2[h, Eval, 1, 10]; WriteBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; ReadBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; FlushBlockRqst[h, Eval, [0,0,0,0], [3,3,3,3], [2,2,2,2], [1,1,1,1], [0,0,0,0]]; WriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah]]; CondWriteSingleRqst[h, Eval, [0,0,0,0], [0,0,0,0Ah]]; IORRqst[h, Eval, [0,0,30h,0], 0]; --data read is address of previous cmd BIOWRqst[h, Eval, [0,0,0,0], [0,0,0,0Bh]]; DeMapRqst[h, Eval, [0,0,0,0], [0,0,0,0Ch]]; }; ReadBlockRqst: PROC [h: Handle, Eval: REProc, add: Address, data0, data1, data2, data3: Quad, owner, shared: BOOL _ FALSE, doubleError: ARRAY [0..4) OF BOOL _ ALL[FALSE], noReply: BOOL _ FALSE] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) RBRqst, owner: %g, shared: %g\n", IO.int[cmdCount], IO.bool[owner], IO.bool[shared]]]; p[DataIn].q _ MakeHeader[cmd: RBRqst, add: add]; p[HeaderCycleIn].b _ TRUE; ownerDelayBuf[ownerDelay] _ [owner, shared]; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; IF ~owner AND ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: RBRply, add: add, sh: shared], [data0, data1, data2, data3], doubleError]; }; WriteBlockRqst: PROC [h: Handle, Eval: REProc, add: Address, data0, data1, data2, data3: Quad, noReply: BOOL _ FALSE] ~ { WBorFBRqst[h, Eval, WBRqst, add, data0, data1, data2, data3, noReply]; }; FlushBlockRqst: PROC [h: Handle, Eval: REProc, add: Address, data0, data1, data2, data3: Quad, noReply: BOOL _ FALSE] ~ { WBorFBRqst[h, Eval, FBRqst, add, data0, data1, data2, data3, noReply]; }; WBorFBRqst: PROC [h: Handle, Eval: REProc, cmd: Cmd, add: Address, data0, data1, data2, data3: Quad, noReply: BOOL _ FALSE] ~ { reqHeader: Quad _ MakeHeader[cmd: cmd, add: add]; p: Port _ h.port; AcquireBus[h, Eval, 5]; TerminalIO.PutRope[IO.PutFR["%g) %g\n", IO.int[cmdCount], IO.rope[IF cmd=WBRqst THEN "WBRqst" ELSE "FBRqst"]]]; p[DataIn].q _ reqHeader; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ data0; Cycle[h, Eval, 1]; p[DataIn].q _ data1; Cycle[h, Eval, 1]; p[DataIn].q _ data2; Cycle[h, Eval, 1]; p[DataIn].q _ data3; FinalCycle[h, Eval]; p[DataIn].q _ qZero; IF ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: SUCC[cmd], add: add], [reqHeader, qZero, qZero, qZero]]; }; WriteSingleRqst: PROC [h: Handle, Eval: REProc, add: Address, data0: Quad, shared: BOOL _ FALSE, noReply: BOOL _ FALSE] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) WSRqst, shared: %g\n", IO.int[cmdCount], IO.bool[shared]]]; p[DataIn].q _ MakeHeader[cmd: WSRqst, add: add]; p[HeaderCycleIn].b _ TRUE; ownerDelayBuf[ownerDelay] _ [FALSE, shared]; Cycle[h, Eval, 1]; p[DataIn].q _ data0; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; IF ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: WSRply, add: add, sh: shared], [data0, qZero, qZero, qZero]]; }; CondWriteSingleRqst: PROC [h: Handle, Eval: REProc, add: Address, data0: Quad, shared: BOOL _ FALSE, noReply: BOOL _ FALSE] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) CWSRqst, shared: %g\n", IO.int[cmdCount], IO.bool[shared]]]; p[DataIn].q _ MakeHeader[cmd: CWSRqst, add: add]; p[HeaderCycleIn].b _ TRUE; ownerDelayBuf[ownerDelay] _ [FALSE, shared]; Cycle[h, Eval, 1]; p[DataIn].q _ data0; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; IF ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: CWSRply, add: add, sh: shared], [data0, data0, data0, data0]]; }; IORRqst: PROC [h: Handle, Eval: REProc, add: Address, data: LONG CARDINAL] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) IORRqst\n", IO.int[cmdCount]]]; p[DataIn].q _ MakeHeader[cmd: IORRqst, add: add]; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; ResponseChecker.ExpectReply[MakeHeader[cmd: IORRply, add: add], [[0, 0, Basics.HighHalf[data], Basics.LowHalf[data]], qZero, qZero, qZero]]; }; IOWrite0: PROC [h: Handle, Eval: REProc, ownerFifoDelay: [0..8), enbCorr: BOOL, enbOpReflect: BOOL _ TRUE, selRefCk: [0..4), pchgDelay, refDelay, wrDelay, rdDelay: [0..32)] ~ { data: LONG CARDINAL _ 0; address: Quad _ [0,0,30h,0]; p: Port _ h.port; reqHeader: Quad _ MakeHeader[cmd: IOWRqst, add: address, mode: TRUE]; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[ownerFifoDelay]], 24]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[IF enbCorr THEN 1 ELSE 0]], 23]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[selRefCk]], 21]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[IF enbOpReflect THEN 1 ELSE 0]], 20]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[pchgDelay]], 15]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[refDelay]], 10]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[wrDelay]], 5]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[rdDelay]], 0]].lc; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) IOW0Rqst\n", IO.int[cmdCount]]]; p[DataIn].q _ reqHeader; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ [0, 0, Basics.HighHalf[data], Basics.LowHalf[data]]; FinalCycle[h, Eval]; p[DataIn].q _ qZero; ResponseChecker.ExpectReply[MakeHeader[cmd: IOWRply, add: address, mode: TRUE], [reqHeader, qZero, qZero, qZero]]; }; IOWrite1: PROC [h: Handle, Eval: REProc, banks: [1..16], ramAddWires: [9..14], bankAdd: [0..16) _ 0, pageAdd: CARDINAL _ 0] ~ { data: LONG CARDINAL _ 0; address: Quad _ [0,0,30h,1]; p: Port _ h.port; pageMatch: CARDINAL _ BITAND[SHIFT[0ffffh, (ramAddWires-9)*2 + Log2[banks]], 03fffh]; reqHeader: Quad _ MakeHeader[cmd: IOWRqst, add: address, mode: TRUE]; IF BitOps.TwoToTheLog2[banks]#banks THEN ERROR; --no. of banks must be a power of two IF bankAdd>banks-1 THEN ERROR; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[pageMatch]], 14]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[pageAdd]], 0]].lc; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) IOW1Rqst\n", IO.int[cmdCount]]]; p[DataIn].q _ reqHeader; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ [0, 0, Basics.HighHalf[data], Basics.LowHalf[data]]; FinalCycle[h, Eval]; p[DataIn].q _ qZero; ResponseChecker.ExpectReply[MakeHeader[cmd: IOWRply, add: address, mode: TRUE], [reqHeader, qZero, qZero, qZero]]; }; IOWrite2: PROC [h: Handle, Eval: REProc, banks: [1..16], ramAddWires: [9..14], bankAdd: [0..16) _ 0] ~ { data: LONG CARDINAL _ 0; address: Quad _ [0,0,30h,2]; p: Port _ h.port; lowAdd: CARDINAL _ Log2[banks]; highAdd: CARDINAL _ ramAddWires - 9 + Log2[banks]; bankMask: CARDINAL _ BITAND[BITNOT[SHIFT[0fh, Log2[banks]]], 0fh]; reqHeader: Quad _ MakeHeader[cmd: IOWRqst, add: address, mode: TRUE]; IF BitOps.TwoToTheLog2[banks]#banks THEN ERROR; --no. of banks must be a power of two IF bankAdd>banks-1 THEN ERROR; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[lowAdd]], 12]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[highAdd]], 8]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[bankMask]], 4]].lc; data _ Basics.DoubleOr[[lc[data]], Basics.DoubleShiftLeft[[lc[bankAdd]], 0]].lc; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) IOW2Rqst\n", IO.int[cmdCount]]]; p[DataIn].q _ reqHeader; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ [0, 0, Basics.HighHalf[data], Basics.LowHalf[data]]; FinalCycle[h, Eval]; p[DataIn].q _ qZero; ResponseChecker.ExpectReply[MakeHeader[cmd: IOWRply, add: address, mode: TRUE], [reqHeader, qZero, qZero, qZero]]; }; IOWrite3: TProc ~ { p: Port _ h.port; address: Quad _ [0,0,30h,3]; reqHeader: Quad _ MakeHeader[cmd: IOWRqst, add: address, mode: TRUE]; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) IOW3Rqst\n", IO.int[cmdCount]]]; p[DataIn].q _ reqHeader; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[HeaderCycleIn].b _ FALSE; p[DataIn].q _ qZero; FinalCycle[h, Eval]; p[DataIn].q _ qZero; ResponseChecker.ExpectReply[MakeHeader[cmd: IOWRply, add: address, mode: TRUE], [reqHeader, qZero, qZero, qZero]]; }; BIOWRqst: PROC [h: Handle, Eval: REProc, add: Address, data0: Quad, noReply: BOOL_FALSE] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) BIOWRqst\n", IO.int[cmdCount]]]; p[DataIn].q _ MakeHeader[cmd: BIOWRqst, add: add]; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[DataIn].q _ data0; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; IF ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: BIOWRply, add: add], [data0, qZero, qZero, qZero]]; }; DeMapRqst: PROC [h: Handle, Eval: REProc, add: Address, data0: Quad, noReply: BOOL_FALSE] ~ { p: Port _ h.port; AcquireBus[h, Eval]; TerminalIO.PutRope[IO.PutFR["%g) DeMapRqst\n", IO.int[cmdCount]]]; p[DataIn].q _ MakeHeader[cmd: DeMapRqst, add: add]; p[HeaderCycleIn].b _ TRUE; Cycle[h, Eval, 1]; p[DataIn].q _ data0; p[HeaderCycleIn].b _ FALSE; FinalCycle[h, Eval]; IF ~noReply THEN ResponseChecker.ExpectReply[MakeHeader[cmd: DeMapRply, add: add], [data0, qZero, qZero, qZero]]; }; DBusRegSel: PROC [h: Handle, Eval: REProc, add: dBusRegAdd] ~ { bits: CARDINAL _ add; p: Port _ h.port; p[DSelect].b _ FALSE; p[DBus].bs[dAddress] _ TRUE; FOR i: NAT IN [0..dBusRegAddBits) DO p[DBus].bs[dSerialIn] _ Basics.BITAND[bits, 4]#0; --send MSB first bits _ Basics.BITSHIFT[bits, 1]; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ TRUE; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ FALSE; MyEval[h, Eval]; ENDLOOP; p[DBus].bs[dAddress] _ FALSE; }; DBusRegRead: PROC [h: Handle, Eval: REProc, add: dBusRegAdd, data: BitOps.BitDWord, regWidth: [1..BitOps.bitsPerDWord]] ~ { p: Port _ h.port; DBusRegSel[h, Eval, add]; p[DSelect].b _ TRUE; IF add#0 THEN { --circumvents a bug in the 6.1 version-- p[DBus].bs[dExecute] _ TRUE; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ TRUE; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ FALSE; MyEval[h, Eval]; p[DBus].bs[dExecute] _ FALSE; MyEval[h, Eval]; }; p[DBus].ds[dSerialOut] _ expect; p[DBus].bs[dSerialOut] _ BitOps.EBFD[data, 0, regWidth]; MyEval[h, Eval]; FOR i: NAT IN [1..regWidth) DO p[DBus].bs[dShiftCK] _ TRUE; p[DBus].bs[dSerialOut] _ BitOps.EBFD[data, i, regWidth]; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ FALSE; MyEval[h, Eval]; ENDLOOP; p[DBus].ds[dSerialOut] _ none; p[DSelect].b _ FALSE; }; DBusRegWrite: PROC [h: Handle, Eval: REProc, add: dBusRegAdd, data: BitOps.BitDWord, regWidth: [1..BitOps.bitsPerDWord]] ~ { p: Port _ h.port; DBusRegSel[h, Eval, add]; p[DSelect].b _ TRUE; FOR i: NAT IN [0..regWidth) DO p[DBus].bs[dSerialIn] _ BitOps.EBFD[data, i, regWidth]; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ TRUE; MyEval[h, Eval]; p[DBus].bs[dShiftCK] _ FALSE; MyEval[h, Eval]; ENDLOOP; p[DSelect].b _ FALSE; }; Cycle: PROC [h: Handle, Eval: REProc, n: CARDINAL _ 1] ~ { p: Port _ h.port; THROUGH [0..n) DO p[OwnerIn].b _ ownerDelayBuf[0].owner; p[SharedIn].b _ ownerDelayBuf[0].shared; FOR i: NAT IN [0..ownerDelay) DO ownerDelayBuf[i] _ ownerDelayBuf[i+1]; ENDLOOP; ownerDelayBuf[ownerDelay] _ [FALSE, FALSE]; p[Clock].b _ TRUE; MyEval[h, Eval]; p[Clock].b _ FALSE; MyEval[h, Eval]; ENDLOOP; }; CaptureVectors: PROC [h: Handle] ~ { testCellType: Core.CellType _ NIL; h.testFlatCell _ NEW[CoreFlat.FlatCellTypeRec _ CoreFlat.ParseCellTypePath[h.rootCT, "/MemoryController"]]; testCellType _ CoreFlat.ResolveFlatCellType[h.rootCT, h.testFlatCell^].cellType; h.testPort _ Ports.CreatePort[cellType: testCellType, testerPort: TRUE]; h.vecFile _ RosemaryVector.OpenVectorFile["MC.vector", h.testPort, FALSE]; h.captureVectors _ TRUE; }; MyEval: TProc ~ { Eval[]; IF h.captureVectors THEN { Rosemary.SettleToTest[h.tester.display.simulation, h.testFlatCell, h.testPort]; RosemaryVector.WriteVector[h.vecFile]; }; }; FlushPipe: TProc ~ { WHILE ~ResponseChecker.IsEmpty[] DO Cycle[h, Eval, 1]; ENDLOOP; }; AcquireBus: PROC [h: Handle, Eval: REProc, cycles: NAT _ 2 ] ~ { timer: CARDINAL _ arbiterTimeout; p: Port _ h.port; p[DReqTP].c _ (SELECT cycles FROM 2 => 2, 5 => 3, ENDCASE => ERROR); Cycle[h, Eval, 1]; p[DReqTP].c _ 0; -- no further request p[DGrantTP].d _ inspect; -- p[DGrantTP].b = FALSE WHILE NOT p[DGrantTP].b DO Cycle[h, Eval, 1]; timer _ timer-1; IF timer=0 THEN ERROR; --bus timeout ENDLOOP; p[DGrantTP].d _ expect; -- p[DGrantTP].b = TRUE }; FinalCycle: TProc ~ { p: Port _ h.port; p[DGrantTP].b _ FALSE; Cycle[h, Eval, 1]; cmdCount _ cmdCount+1; }; MakeHeader: PROC [cmd: Cmd, mode: ModeError _ FALSE, sh: Shared _ FALSE, id: DeviceID _ 0, add: Address _ qZero] RETURNS [header: Quad] ~ { header _ qZero; header _ DynaBusInterface.InsertCmd[header, cmd]; header _ DynaBusInterface.InsertModeError[header, mode]; header _ DynaBusInterface.InsertShared[header, sh]; header _ DynaBusInterface.InsertDeviceID[header, id]; header _ DynaBusInterface.InsertAddress[header, add]; }; CDExtract: PROC [comm: CDSequencer.Command] = { ct: Core.CellType _ NIL; design _ comm.design; ct _ Sisyph.ExtractSchematicByName["MemoryBankLayout.sch", Sisyph.Create[design]]; CDProperties.PutDesignProp[design, $DAUserCellType, ct]; }; Extract: PROC [fileName: ROPE _ "///Users/Gasbarro.pa/MC/MC.dale", wDir: ROPE _ "///Commands/"] ~ { ct: Core.CellType _ NIL; IF design=NIL THEN { design _ CDIO.ReadDesign[fileName, NIL, wDir]; Viewer[]; }; ct _ Sisyph.ExtractSchematicByName["MemoryBankLayout.sch", Sisyph.Create[design]]; CDProperties.PutDesignProp[design, $DAUserCellType, ct]; }; Viewer: PROC ~ { [] _ CDViewer.CreateViewer[design]; }; StartTest: PROC ~ { RosemaryUser.StartTest[NARROW[CDProperties.GetDesignProp[design, $DAUserRoseTester], RosemaryUser.Tester]]; }; InitPortIndicies: PROC [ct: Core.CellType] ~ { [SharedIn, OwnerIn, ResetIn, DBus, DSelect, DReqTP, DGrantTP] _ Ports.PortIndexes[ct.public, "SharedIn", "OwnerIn", "ResetIn", "DBus", "DSelect", "DReqTP", "DGrantTP"]; [HeaderCycleIn, Clock, DataIn] _ Ports.PortIndexes[ct.public, "HeaderCycleIn", "Clock", "DataIn"]; Vdd _ Ports.PortIndex[ct.public, "Vdd"]; Gnd _ Ports.PortIndex[ct.public, "Gnd"]; }; Simulate: PROC = { ITDList: PROC [indicies: LIST OF NAT, initDrive: Ports.Drive] ~ { FOR l: LIST OF NAT _ indicies, l.rest WHILE l#NIL DO [] _ Ports.InitTesterDrive[wire: ct.public[l.first], initDrive: initDrive]; ENDLOOP; }; IPList: PROC [indicies: LIST OF NAT, levelType: Ports.LevelType] ~ { FOR l: LIST OF NAT _ indicies, l.rest WHILE l#NIL DO [] _ Ports.InitPort[wire: ct.public[l.first], levelType: levelType]; ENDLOOP; }; tester: RosemaryUser.Tester _ NIL; ct: Core.CellType _ NIL; ds: Ports.DriveSequence _ NEW[Ports.DriveSequenceRec[dBusWidth]]; IF design=NIL THEN ERROR; ct _ NARROW[CDProperties.GetDesignProp[design, $DAUserCellType]]; FOR i: NAT IN [0..dBusWidth) DO ds[i] _ IF i=dSerialOut THEN none ELSE force; ENDLOOP; InitPortIndicies[ct]; ITDList[LIST[SharedIn, OwnerIn, ResetIn, HeaderCycleIn, Clock, DataIn, DSelect, DReqTP], force]; IPList[LIST[DReqTP], c]; IPList[LIST[DataIn], q]; [] _ Ports.InitPort[wire: ct.public[DBus], levelType: bs]; [] _ Ports.InitTesterDrive[wire: ct.public[DBus], initDrives: ds]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tester _ RosemaryUser.TestProcedureViewer[cellType: ct, testButtons: LIST["SimpleTest"], name: "Memory Controller Tester", displayWires: RosemaryUser.DisplayPortLeafWires[ct], cutSet: CoreFlat.CreateCutSet[labels: LIST["Logic", "LogicMacro", "FSA"], cellTypes: LIST["DRam", "ResponseChecker"]]]; CDProperties.PutDesignProp[design, $DAUserRoseTester, tester]; }; RosemaryUser.RegisterTestProc["SimpleTest", SimpleTest]; CDCommandOps.RegisterWithMenu[ menu: $ProgramMenu, entry: "Extract MC", doc: "", proc: CDExtract ]; END. šTestMC.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: Gasbarro June 1, 1987 5:11:45 pm PDT Last Edited by: McCreight June 8, 1987 5:36:10 pm PDT CaptureVectors[h]; RandomTest[h, Eval, ramdomOps]; --Ignore the low order bit: it signifies the 32-bit address --Don't test the next two low order bits: they signify the nibble rotatation address --Test the next 18 bits Êߘ™ Icodešœ Ïmœ1™˜DKšŸœ=žœ˜LKšŸœB˜IKšŸ œAžœ˜QKšŸœ/˜6KšŸœ7˜?KšŸ œ8˜AK˜Kšœ žœ˜KšœžœžœŒ˜¥K˜Kšœžœžœ ˜šœ žœžœ˜Kšœžœ˜"Kšœž˜Kšœ%žœ˜)Kšœžœžœ˜Kšœ&žœ˜*Kšœžœ˜Kšœ ž˜K˜—K˜šŸ œ˜%šŸ œ ˜Kšžœžœžœžœ+˜TK™K˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ™Kšœ˜Jšžœžœ+˜CJ˜J˜—Kšœ žœ ˜Kš žœžœžœžœÏc)˜DKšœ žœ8˜IKšœ žœ6˜GK˜ K˜J˜J˜—šŸœ ˜Kšžœžœžœžœ˜>Kšœ$ ˜BK˜K˜—šŸœ ˜Kšžœžœžœžœ˜>K˜Kšœ$˜$Kšœžœ˜Kšœžœ˜Kšœ ˜ Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ  ˜K˜šœžœ˜K˜—K˜Kšœžœ˜Kšœžœžœ˜4Kšœ˜Kšœ˜Kšœ˜KšœO˜OKšœO˜OKšœ˜K˜K˜—šŸœ ˜Kšœ3˜3KšœO˜OKšœN˜NKšœN˜NKšœN˜NKšœN˜NK˜K˜—šŸœ ˜Kšœ(˜(Kšœ -˜IKšœ˜Kšœ˜Kšœ1žœžœ˜>Kšœ1žœžœ˜?Kšœ5žœžœ˜BKšœ5žœžœ˜CKšœ*žœ˜0Kšœ*žœ˜1Kšœ+žœ˜1Kšœ+žœ˜2K˜K˜—šŸ œ ˜K˜ Kšœ+˜+Kšœ  ˜:šœ˜K˜—KšœY˜YKšœ;™;KšœT™TKšœ™š žœžœž œžœ ž˜$Kšœ˜Kšœžœžœ ˜"Kšœ6˜6Kšžœ˜—KšœX˜Xš žœžœž œžœ ž˜$Kšœ˜Kšœžœžœ ˜"Kšœ5˜5Kšžœ˜—K˜K˜—šŸœ ˜Kšœžœ2žœažœ˜®Kšœ0˜0Kšœ ˜'KšœR˜RKšœO˜OKšœ˜Kšœ.˜.Kš œQžœžœžœžœžœžœ˜|KšœN˜NKšœ˜Kšœ'˜'Kšœ%žœžœ ˜cKš œQžœžœžœžœžœžœ˜|Kšœ˜Kšœ'˜'Kšœ%žœžœ .˜uKšœ˜J˜"Jšœžœžœ˜AKšœ˜K˜—šŸœ ˜Kšœžœ2žœažœ˜®Kšœ0˜0Kšœ ˜'KšœR˜RKšœO˜OKšœ˜Kšœ+˜+KšœQ˜QKšœN˜NKšœ˜Kšœ'˜'Kšœ%žœ  ˜MKšœQ˜QKšœ˜Kšœ'˜'Kšœ%žœ  ,˜_Kšœ˜J˜"Jšœžœ ˜-Kšœ˜K˜—š Ÿ œžœ"žœžœžœ˜FKšœ7˜7Kšœ*˜*KšœO˜Ošžœžœžœ ž˜Kšœ ˜ Kšžœ˜—Kšœ˜Kšœ˜K˜—šŸ œ ˜Kšœ1˜1KšœO˜Ošžœžœžœž˜šžœžœžœž˜Kšœ˜Kšœ˜Kšžœ˜—Kšžœ˜—Kšœ˜Kšœ˜—K˜šŸ œ ˜Kšœ)˜)KšœO˜OKšœ>žœžœ˜KKšœ1žœ˜7Kšœ5žœ˜;KšœNžœžœ˜[K˜K˜—šŸœ ˜Kšœ+˜+Kšœžœžœ˜4Kšœ˜Kšœ˜KšœO˜OKšœN˜NKšœO˜OKšœ1˜1Kšœ5˜5Kšœ" &˜HKšœ*˜*Kšœ+˜+K˜K˜—šŸ œžœZžœžœžœžœžœžœžœ žœžœ˜ÅK˜K˜Kš œžœ.žœžœžœ˜wKšœ0˜0Kšœžœ˜Kšœ,˜,K˜Kšœžœ˜Kšœ˜Kšžœžœ žœw˜’Kšœ˜K˜—šŸœžœTžœžœ˜yKšœF˜FK˜K˜—šŸœžœTžœžœ˜yKšœF˜FK˜K˜—šŸ œžœ^žœžœ˜Kšœ1˜1K˜K˜Kš œžœžœžœžœ žœ žœ ˜oKšœ˜Kšœžœ˜K˜Kšœžœ˜Kšœ˜K˜Kšœ˜K˜Kšœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšžœ žœ-žœ4˜uKšœ˜K˜—š Ÿœžœ>žœžœ žœžœ˜{K˜K˜Kšœžœ#žœžœ˜\Kšœ0˜0Kšœžœ˜Kšœžœ ˜,K˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ žœj˜zKšœ˜K˜—š Ÿœžœ>žœžœ žœžœ˜K˜K˜Kšœžœ$žœžœ˜]Kšœ1˜1Kšœžœ˜Kšœžœ ˜,K˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ žœk˜{Kšœ˜K˜—šŸœžœ/žœžœ˜NK˜K˜Kšœžœžœ˜@Kšœ1˜1Kšœžœ˜K˜Kšœžœ˜Kšœ˜KšœŒ˜ŒKšœ˜K˜—š Ÿœžœ<žœžœžœG˜°Kšœžœžœ˜Kšœ˜Kšœ˜Kšœ?žœ˜EKšœX˜XKšœ>žœ žœžœ˜bKšœR˜RKšœ>žœžœžœ˜gKšœS˜SKšœR˜RKšœP˜PKšœP˜PK˜Kšœžœžœ˜AKšœ˜Kšœžœ˜K˜Kšœžœ˜KšœB˜BKšœ˜Kšœ˜KšœIžœ%˜rKšœ˜K˜—šŸœžœ`žœ ˜Kšœžœžœ˜Kšœ˜Kšœ˜Kšœ žœžœžœ4˜VKšœ?žœ˜EKšžœ"žœžœ %˜UKšžœžœžœ˜KšœS˜SKšœP˜PK˜Kšœžœžœ˜AKšœ˜Kšœžœ˜K˜Kšœžœ˜KšœB˜BKšœ˜Kšœ˜KšœIžœ%˜rKšœ˜K˜—šŸœžœZ˜hKšœžœžœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšœ žœ!˜2Kš œ žœžœžœžœ˜BKšœ?žœ˜EKšžœ"žœžœ %˜UKšžœžœžœ˜KšœP˜PKšœP˜PKšœQ˜QKšœP˜PK˜Kšœžœžœ˜AKšœ˜Kšœžœ˜K˜Kšœžœ˜KšœB˜BKšœ˜Kšœ˜KšœIžœ%˜rKšœ˜K˜—šŸœ ˜Kšœ˜Kšœ˜Kšœ?žœ˜EK˜Kšœžœžœ˜AKšœ˜Kšœžœ˜K˜Kšœžœ˜Kšœ˜Kšœ˜Kšœ˜KšœIžœ%˜rKšœ˜K˜—šŸœžœ?žœžœ˜\Kšœ˜Kšœ˜Kšœžœžœ˜AKšœ2˜2Kšœžœ˜K˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ žœ`˜pKšœ˜K˜—šŸ œžœ?žœžœ˜]Kšœ˜Kšœ˜Kšœžœžœ˜BKšœ3˜3Kšœžœ˜K˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ žœa˜qKšœ˜K˜—K˜šŸ œžœ/˜?Kšœžœ˜Kšœ˜Kšœžœ˜Kšœžœ˜šžœžœžœž˜$Kšœžœ  ˜BKšœžœ ˜ Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ˜—Kšœžœ˜K˜K˜—šŸ œžœj˜{Kšœ˜Kšœ˜Kšœžœ˜K˜šžœžœ )˜8Kšœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜Kšœ˜K˜—K˜Kšœ ˜ Kšœ žœ˜8Kšœ˜K˜šžœžœžœž˜Kšœžœ˜Kšœ žœ˜8Kšœ˜Kšœžœ˜Kšœ˜Kšžœ˜—Kšœ˜Kšœžœ˜Kšœ˜K˜—šŸ œžœj˜|Kšœ˜Kšœ˜Kšœžœ˜šžœžœžœž˜Kšœžœ˜7Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšžœ˜—Kšœžœ˜Kšœ˜K˜—šŸœžœžœ ˜:Kšœ˜šžœž˜K˜&K˜(šžœžœžœž˜ K˜&Kšžœ˜—Kšœžœžœ˜+Kšœ žœ˜Kšœ˜Kšœ žœ˜Kšœ˜Kšžœ˜—K˜K˜—šŸœžœ˜$Kšœžœ˜"KšœžœW˜kKšœP˜PKšœBžœ˜HKšœCžœ˜JKšœžœ˜K˜K˜—šŸœ ˜K˜šžœžœ˜KšœO˜OKšœ&˜&K˜—K˜—K˜šŸ œ ˜šžœž˜#K˜Kšžœ˜—K˜K˜—šŸ œžœ Ÿœžœ ˜@Kšœžœ˜!K˜šœžœž˜!Kšœ˜Kšœ˜Kšžœžœ˜—K˜Kšœ ˜&Kšœ ˜1šžœžœž˜K˜Kšœ˜Kšžœ žœžœ  ˜$Kšžœ˜—Kšœ ˜/K˜K˜—šŸ œ ˜K˜Kšœžœ˜K˜K˜K˜K˜—š Ÿ œžœžœžœ*žœ˜‹Kšœ˜Kšœ1˜1Kšœ8˜8Kšœ3˜3Kšœ5˜5Kšœ5˜5K˜K˜—šŸ œžœ ˜/Kšœžœ˜Kšœ˜KšœR˜RKšœ8˜8K˜K˜—šŸœžœ žœ,žœ˜cKšœžœ˜šžœžœžœ˜Kšœ žœžœ˜.K˜ K˜—KšœR˜RKšœ8˜8K˜K˜—šŸœžœ˜K˜#K˜K˜—šŸ œžœ˜JšœžœN˜kK˜K˜—šŸœžœ˜.Kšœ¨˜¨Kšœb˜bKšœ(˜(Kšœ(˜(K˜—K˜šŸœžœ˜š Ðbnœžœ žœžœžœ˜Aš žœžœžœžœžœžœž˜4KšœK˜KKšžœ˜—K˜K˜—š ¡œžœ žœžœžœ!˜Dš žœžœžœžœžœžœž˜4KšœD˜DKšžœ˜—K˜—K˜Kšœžœ˜"Kšœžœ˜Kšœžœ$˜AK˜Kšžœžœžœžœ˜Kšœžœ6˜Ašžœžœžœž˜Kšœžœžœžœ˜-Kšžœ˜—Kšœ˜KšœžœT˜`Kšœžœ ˜Kšœžœ ˜Kšœ:˜:KšœB˜BKšœ.˜.Kšœ.˜.K˜K™KšœEžœžœ+žœ˜§Kšœ>˜>K˜K˜K˜—Kšœ8˜8K˜šœ˜Jšœ˜Jšœ˜J˜Jšœ˜Jšœ˜—Kšžœ˜K˜J˜J˜—…—fÌE