DIRECTORY BitOps, Cache, CacheOps, Dragon, IO, Process, Rope, RoseEventsImpl, RoseRun, RoseTypes; CacheTester: CEDAR MONITOR IMPORTS BitOps, Cache, CacheOps, Dragon, IO, Process, Rope, RoseEventsImpl, RoseRun, RoseTypes SHARES Cache = BEGIN OPEN BitOps, IO; BitsInDRegister: NAT = 186; Phase: TYPE = [0..4); PhaseLetter: TYPE = {A, B, N}; IOTrafficProc: TYPE = PROC[data: REF ANY]; ThreadProc: TYPE = PROC[data: REF ANY]; MCommandRef: TYPE = REF MCommandRec; MCommandRec: TYPE = RECORD[ slave: BOOL _ FALSE, arb, newRequest: BOOL _ FALSE, releaseBus: BOOL _ TRUE, refuseGrantCount: NAT _ 0, WQ, WQNoOp: BOOL _ FALSE, wqNotReadyCount: NAT _ 0, WQAddress, WQData0, WQData1, WQData2, WQData3: Dragon.Word _ 0, IOR, IOW, IONoOp: BOOL _ FALSE, IOAddress, IOData: Dragon.Word _ 0, IOTraffic: IOTrafficProc _ NIL, IOTrafficData: REF ANY _ NIL, RQ, RQNoOp, shared: BOOL _ FALSE, rqNotReadyCount: NAT _ 0, RQAddress, RQData0, RQData1, RQData2, RQData3: Dragon.Word _ 0, WS, WSNoOp: BOOL _ FALSE, WSAddress, WSData: Dragon.Word _ 0, CF: BOOL _ FALSE, CFData: Dragon.Word _ 0]; PReferenceRef: TYPE = REF PReferenceRec; PReferenceRec: TYPE = RECORD[ command: Dragon.PBusCommands, address, data: Dragon.Word, rejects: INT _ 0, fault: Dragon.PBusFaults _ None]; clockPhase: Phase; cycleNumber: NAT; pushWaitCount: NAT; evalWaitCount: NAT; evalCount: NAT; threadCount: NAT _ 0; pushWait: CONDITION; evalWait: CONDITION; entryEvalWait: CONDITION; drive: REF Cache.CacheDrive; instructions: Cache.CacheIORef; handle: RoseTypes.CellTestHandle; value: Cache.CacheIORef _ NEW[Cache.CacheIORec]; checkPParityB, checkMParityBA, checkDDataOutAB, checkPData, checkMNShared: BOOL; killThreads, clocksSkewed: BOOL; ignoreWarnings: BOOL; EtuBrute: ERROR = CODE; CacheTest: Cache.CacheTester = { priority: Process.Priority _ Process.GetPriority[]; clocksSkewed _ FALSE; { Process.SetPriority[Process.priorityBackground]; ReallyCacheTest[i, d, h ! UNWIND => Process.SetPriority[priority]; EtuBrute => GOTO quit]; EXITS quit => NULL; }; Process.SetPriority[priority]; IF clocksSkewed THEN Complain["clocks out of sync"]; }; ReallyCacheTest: Cache.CacheTester = { OPEN value; clockPhase _ 3; cycleNumber _ 0; pushWaitCount _ 0; evalWaitCount _ 0; evalCount _ 0; drive _ d; instructions _ i; handle _ h; killThreads _ FALSE; ignoreWarnings _ FALSE; UNTIL threadCount=0 DO Process.Yield[]; ENDLOOP; PhA _ FALSE; PhB _ FALSE; ThreadStart[MainThread]; UNTIL threadCount=0 DO EntryEval[]; ENDLOOP; }; MainThread: ThreadProc = { OPEN value; DoAReset[]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, WQ: TRUE, WQAddress: 0, WQData0: 1, WQData1: 2, WQData2: 3, WQData3: 4]]]; THROUGH [0..5) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, RQ: TRUE, RQAddress: 5, RQData0: 6, RQData1: 7, RQData2: 8, RQData3: 9]]]; THROUGH [0..6) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, WS: TRUE, WSAddress: 10, WSData: 11]]]; THROUGH [0..2) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, CF: TRUE, CFData: 12]]]; THROUGH [0..2) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: IOFetchHold, address: 2, data: 00060001H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, releaseBus: FALSE, IOR: TRUE, IOAddress: 2, IOData: 00060001H]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- arbitrate R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- io R[B]; R[]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: IOStoreHold, address: 3, data: 00070001H, rejects: 4]]]; R[A]; R[]; R[B]; R[]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [releaseBus: FALSE, IOW: TRUE, IOAddress: 3, IOData: 00070001H]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- io R[B]; R[]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: IOFetch, address: 4, data: 00080001H, rejects: 4]]]; R[A]; R[]; R[B]; R[]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [IOR: TRUE, IOAddress: 4, IOData: 00080001H]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- io R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; R[B]; R[]; -- release bus ThreadStart[PReference, NEW[PReferenceRec _ [command: Store, address: 1, data: 2, rejects: 15]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, IOR: TRUE, IOAddress: 0C0H, IOData:00010000H, RQ: TRUE, rqNotReadyCount: 2, shared: TRUE, RQAddress:00010001H, RQData0: 00020001H, RQData1: 00020002H, RQData2: 00020003H, RQData3: 00020004H, WS: TRUE, WSAddress:00010001H, WSData:02H]]]; THROUGH [0..16) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; MNShared _ TRUE; F[]; drive.MCmdBA _ FALSE; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 1, data: 2]]]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 0, data: 00020004H]]]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 2, data: 00020002H]]]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 3, data: 00020003H]]]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 4, data: 00040000H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00010004H, RQData0: 00040000H, RQData1: 00040001H, RQData2: 00040002H, RQData3: 00040003H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; ThreadStart[PReference, NEW[PReferenceRec _ [command: FetchHold, address: 6, data: 00040002H, rejects: 3]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, releaseBus: FALSE]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; drive.MCmdBA _ TRUE; MCmdBA _ Reserve14; E[]; drive.MCmdBA _ FALSE; P[B]; MCmdBA _ NoOp; E[]; R[]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Store, address: 6, data: 00040012H]]]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: StoreHold, address: 6, data: 00040112H, rejects: 3]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, newRequest: TRUE, releaseBus: FALSE]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; drive.MCmdBA _ TRUE; MCmdBA _ Reserve14; E[]; drive.MCmdBA _ FALSE; P[B]; MCmdBA _ NoOp; E[]; R[]; R[A]; R[]; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 6, data: 00040112H]]]; R[A]; R[]; R[B]; R[]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ []]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; MNShared _ TRUE; E[]; drive.MCmdBA _ FALSE; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 8, data: 00080000H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00010008H, RQData0: 00080000H, RQData1: 00080001H, RQData2: 00080002H, RQData3: 00080003H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 0CH, data: 000C0000H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:0001000CH, RQData0: 000C0000H, RQData1: 000C0001H, RQData2: 000C0002H, RQData3: 000C0003H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 10H, data: 00100000H, rejects: 13]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, WQ: TRUE, wqNotReadyCount: 3, WQAddress: 00010000H, WQData0: 00020004H, WQData1: 00000002H, WQData2: 00020002H, WQData3: 00020003H, RQ: TRUE, RQAddress:00010010H, RQData0: 00100000H, RQData1: 00100001H, RQData2: 00100002H, RQData3: 00100003H]]]; THROUGH [0..16) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 14H, data: 00140000H, rejects: 10]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, WQ: TRUE, WQAddress: 00010004H, WQData0: 00040000H, WQData1: 00040001H, WQData2: 00040112H, WQData3: 00040003H, RQ: TRUE, RQAddress:00010014H, RQData0: 00140000H, RQData1: 00140001H, RQData2: 00140002H, RQData3: 00140003H]]]; THROUGH [0..13) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 18H, data: 00180000H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00010018H, RQData0: 00180000H, RQData1: 00180001H, RQData2: 00180002H, RQData3: 00180003H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; R[]; drive.MCmdBA _ FALSE; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, WQ: TRUE, WQAddress: 00010018H, WQData0: 00190001H, WQData1: 00190002H, WQData2: 00190003H, WQData3: 00190004H]]]; THROUGH [0..5) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, RQ: TRUE, shared: TRUE, RQAddress: 00010018H, RQData0: 00190001H, RQData1: 00190002H, RQData2: 00190003H, RQData3: 00190004H]]]; THROUGH [0..6) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, WS: TRUE, WSAddress: 00010018H, WSData: 00200001H]]]; THROUGH [0..2) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, RQ: TRUE, shared: TRUE, RQAddress: 00010018H, RQData0: 00200001H, RQData1: 00190002H, RQData2: 00190003H, RQData3: 00190004H]]]; THROUGH [0..6) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, CF: TRUE, CFData: 00010000H]]]; THROUGH [0..2) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Store, address: 1, data: 2, rejects: 6, fault: WriteProtectFault]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, IOR: TRUE, IOAddress: 0C0H, IOData:00000002H]]]; THROUGH [0..6) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: IOFetch, address: 0, data: 00050000H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, IOR: TRUE, IOAddress: 0, IOData: 00050000H]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- arbitrate R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- io R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- release bus R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: IOStore, address: 2, data: 00050001H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, IOW: TRUE, IOAddress: 2, IOData: 00050001H]]]; R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- arbitrate R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- io R[B]; R[]; R[A]; R[]; R[B]; R[]; R[A]; R[]; -- release bus R[B]; R[]; DoAReset[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Store, address: 00010000H, data: 00000011H, rejects: 9]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, IOR: TRUE, IOAddress: 00010080H, IOData:00020000H, RQ: TRUE, RQAddress:00020000H, RQData0: 00000001H, RQData1: 00000002H, RQData2: 00000003H, RQData3: 00000004H]]]; THROUGH [0..12) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 00010004H, data: 00000005H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00020004H, RQData0: 00000005H, RQData1: 00000006H, RQData2: 00000007H, RQData3: 00000008H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 00010008H, data: 00000009H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00020008H, RQData0: 00000009H, RQData1: 0000000AH, RQData2: 0000000BH, RQData3: 0000000CH]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 0001000CH, data: 0000000DH, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:0002000CH, RQData0: 0000000DH, RQData1: 0000000EH, RQData2: 0000000FH, RQData3: 00000010H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, RQ: TRUE, shared: TRUE, RQAddress: 00020000H, RQData0: 00000011H, RQData1: 00000002H, RQData2: 00000003H, RQData3: 00000004H]]]; THROUGH [0..6) DO R[B]; R[]; R[A]; R[]; ENDLOOP; ThreadStart[MCommand, NEW[MCommandRec _ [slave: TRUE, WS: TRUE, WSAddress: 00010000H, WSData: 00200001H]]]; THROUGH [0..2) DO R[B]; R[]; R[A]; R[]; ENDLOOP; R[B]; R[]; ThreadStart[PReference, NEW[PReferenceRec _ [command: Fetch, address: 00010010H, data: 00000011H, rejects: 5]]]; R[A]; R[]; ThreadStart[MCommand, NEW[MCommandRec _ [arb: TRUE, RQ: TRUE, RQAddress:00020010H, RQData0: 00000011H, RQData1: 00000012H, RQData2: 00000013H, RQData3: 00000014H]]]; THROUGH [0..8) DO R[B]; R[]; R[A]; R[]; ENDLOOP; }; DoAReset: PROC = { OPEN value; Vdd _ TRUE; Gnd _ FALSE; PadVdd _ TRUE; PadGnd _ FALSE; drive.PData _ TRUE; PData _ [0,0]; checkPData _ TRUE; drive.PParityB _ TRUE; PParityB _ FALSE; PCmdA _ NoOp; drive.PRejectB _ TRUE; PRejectB _ FALSE; drive.PFaultB _ TRUE; PFaultB _ None; drive.PNPError _ TRUE; PNPError _ TRUE; drive.MDataBA _ TRUE; MDataBA _ [0,0]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; drive.MNShared _ TRUE; MNShared _ TRUE; checkMNShared _ FALSE; drive.MParityBA _ TRUE; MParityBA _ FALSE; drive.MNError _ TRUE; MNError _ TRUE; MReadyBA _ TRUE; MRq _ FALSE; drive.MNewRq _ TRUE; MNewRq _ FALSE; MGnt _ FALSE; ResetAB _ TRUE; DHoldAB _ FALSE; DShiftAB _ FALSE; DExecuteAB _ FALSE; DNSelectAB _ TRUE; DDataInAB _ FALSE; checkDDataOutAB _ FALSE; ignoreWarnings _ TRUE; THROUGH [0..2) DO R[A]; R[]; R[B]; R[]; ENDLOOP; ignoreWarnings _ FALSE; drive.PData _ FALSE; checkPParityB _ FALSE; drive.PParityB _ FALSE; drive.PRejectB _ FALSE; drive.PFaultB _ FALSE; drive.PNPError _ FALSE; drive.MDataBA _ FALSE; drive.MCmdBA _ FALSE; drive.MNShared _ FALSE; drive.MParityBA _ FALSE; checkMParityBA _ FALSE; drive.MNError _ FALSE; drive.MNewRq _ FALSE; ResetAB _ FALSE; THROUGH [0..2) DO R[A]; R[]; R[B]; R[]; ENDLOOP; }; MCommand: ThreadProc = { masterCtl: MCommandRef _ NARROW [data]; { OPEN value, masterCtl; IF (slave AND (arb OR Dragon.MoreThanOneOf[WQ, IOR, RQ, WS])) OR (NOT slave AND CF) THEN ERROR; IF arb THEN { P[B]; MRq _ TRUE; IF newRequest THEN MNewRq _ TRUE; E[]; R[]; P[A]; R[]; P[B]; MNewRq _ FALSE; E[]; R[]; THROUGH [0..refuseGrantCount) DO P[A]; MGnt _ FALSE; E[]; R[]; R[B]; R[]; ENDLOOP; P[A]; MGnt _ TRUE; E[]; R[]; }; IF WQ THEN { IF slave THEN {drive.MCmdBA _ TRUE; drive.MDataBA _ TRUE; drive.MParityBA _ TRUE}; IF WQNoOp THEN {P[B]; MCmdBA _ NoOp; F[]}; P[B]; MCmdBA _ WriteQuad; SetMData[WQAddress]; F[]; THROUGH [0..wqNotReadyCount) DO P[B]; MReadyBA _ FALSE; MCmdBA _ DataTransport; SetMData[WQData0]; checkMParityBA _ TRUE; F[]; ENDLOOP; P[B]; MReadyBA _ TRUE; MCmdBA _ DataTransport; SetMData[WQData0]; checkMParityBA _ TRUE; F[]; P[B]; MCmdBA _ DataTransport; SetMData[WQData1]; F[]; P[B]; MCmdBA _ DataTransport; SetMData[WQData2]; F[]; P[B]; MCmdBA _ DataTransport; SetMData[WQData3]; F[]; checkMParityBA _ FALSE; IF slave THEN {MCmdBA _ NoOp; E[]; drive.MCmdBA _ FALSE; drive.MDataBA _ FALSE; drive.MParityBA _ FALSE}; }; IF IOR THEN { dropGrant: BOOL _ NOT slave AND NOT RQ AND NOT WS AND releaseBus; IF IONoOp THEN {P[B]; MCmdBA _ NoOp; F[]}; P[B]; MCmdBA _ IORead; SetMData[IOAddress]; F[]; IF IOTraffic#NIL THEN IOTraffic[IOTrafficData]; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ IOReadDone; drive.MDataBA _ TRUE; SetMData[IOData]; F[]; drive.MCmdBA _ FALSE; drive.MDataBA _ FALSE; P[B]; MCmdBA _ NoOp; IF dropGrant THEN MRq _ FALSE; F[]; P[B]; MCmdBA _ NoOp; E[]; R[]; R[A]; IF dropGrant THEN {MGnt _ FALSE; E[]}; R[]; }; IF RQ THEN { dropGrant: BOOL _ NOT slave AND NOT WS AND releaseBus; IF RQNoOp THEN {P[B]; MCmdBA _ NoOp; F[]}; P[B]; IF slave THEN {drive.MCmdBA _ TRUE; drive.MDataBA _ TRUE}; MCmdBA _ ReadQuad; SetMData[RQAddress]; MNShared _ TRUE; checkMNShared _ TRUE; F[]; P[B]; MCmdBA _ NoOp; IF slave THEN MNShared _ NOT shared; E[]; R[]; P[A]; E[]; IF NOT slave AND shared THEN {drive.MNShared _ TRUE; MNShared _ FALSE}; E[]; R[]; drive.MNShared _ FALSE; checkMNShared _ FALSE; P[B]; IF slave AND shared THEN drive.MDataBA _ FALSE ELSE {drive.MDataBA _ TRUE; drive.MParityBA _ TRUE}; MCmdBA _ DataTransport; IF rqNotReadyCount=0 THEN {SetMData[RQData0]; checkMParityBA _ TRUE} ELSE MReadyBA _ FALSE; F[]; IF rqNotReadyCount>0 THEN { THROUGH [0..rqNotReadyCount-1) DO P[B]; F[]; ENDLOOP; P[B]; SetMData[RQData0]; checkMParityBA _ TRUE; MReadyBA _ TRUE; F[]; }; P[B]; SetMData[RQData1]; F[]; P[B]; IF dropGrant THEN MRq _ FALSE; SetMData[RQData2]; F[]; P[B]; SetMData[RQData3]; E[]; R[]; R[A]; IF dropGrant THEN MGnt _ FALSE; E[]; R[]; IF slave THEN {MCmdBA _ NoOp; E[]}; drive.MDataBA _ FALSE; drive.MCmdBA _ FALSE; drive.MParityBA _ FALSE; checkMParityBA _ FALSE; }; IF WS THEN { dropGrant: BOOL _ NOT slave AND releaseBus; IF WSNoOp THEN {P[B]; MCmdBA _ NoOp; F[]}; P[B]; IF slave THEN {drive.MCmdBA _ TRUE; drive.MDataBA _ TRUE; drive.MParityBA _ TRUE}; MCmdBA _ WriteSingle; SetMData[WSAddress]; IF dropGrant THEN MRq _ FALSE; F[]; P[B]; MCmdBA _ DataTransport; SetMData[WSData]; checkMParityBA _ TRUE; E[]; R[]; R[A]; IF dropGrant THEN {MGnt _ FALSE; E[]}; R[]; IF slave THEN {MCmdBA _ NoOp; E[]}; drive.MDataBA _ FALSE; drive.MCmdBA _ FALSE; drive.MParityBA _ FALSE; checkMParityBA _ FALSE; }; IF IOW THEN { IF IONoOp THEN {P[B]; MCmdBA _ NoOp; F[]}; P[B]; MCmdBA _ IOWrite; SetMData[IOAddress]; F[]; IF IOTraffic#NIL THEN { P[B]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; SetMData[IOData]; F[]; drive.MCmdBA _ FALSE; IOTraffic[IOTrafficData]; P[B]; drive.MCmdBA _ TRUE; MCmdBA _ IOWriteDone; F[]; drive.MCmdBA _ FALSE; } ELSE { P[B]; drive.MCmdBA _ TRUE; MCmdBA _ IOWriteDone; SetMData[IOData]; F[]; drive.MCmdBA _ FALSE; }; P[B]; MCmdBA _ NoOp; IF releaseBus THEN MRq _ FALSE; F[]; P[B]; MCmdBA _ NoOp; E[]; R[]; R[A]; IF releaseBus THEN {MGnt _ FALSE; E[]}; R[]; }; IF NOT (slave OR IOR OR RQ OR WS OR IOW) AND releaseBus THEN { P[B]; MRq _ FALSE; F[]; R[B]; R[]; R[A]; MGnt _ FALSE; E[]; R[]; drive.MCmdBA _ TRUE; MCmdBA _ NoOp; E[]; drive.MCmdBA _ FALSE; }; IF CF THEN { P[B]; drive.MCmdBA _ TRUE; drive.MDataBA _ TRUE; MCmdBA _ ChangeFlags; SetMData[CFData]; F[]; IF slave THEN {MCmdBA _ NoOp; E[]}; drive.MDataBA _ FALSE; drive.MCmdBA _ FALSE; P[B]; MCmdBA _ NoOp; F[]; }; }; }; PReference: ThreadProc = { pRefCtl: PReferenceRef _ NARROW [data]; { OPEN value, pRefCtl; fetch: BOOL _ command=Fetch OR command=FetchHold OR command=IOFetch OR command=IOFetchHold; store: BOOL _ command=Store OR command=StoreHold OR command=IOStore OR command=IOStoreHold; P[A]; PNPError _ TRUE; PRejectB _ FALSE; PFaultB _ None; E[]; PData _ ILID[address, PData, 32, 0, 32]; drive.PData _ TRUE; checkPData _ TRUE; PCmdA _ command; E[]; R[]; IF fetch THEN drive.PData _ FALSE; PCmdA _ NoOp; E[]; P[B]; IF rejects>0 THEN {PRejectB _ TRUE; IF fetch THEN checkPData _ FALSE} ELSE {PRejectB _ FALSE; IF fetch THEN {checkPParityB _ TRUE; SetPData[data]}}; E[]; IF store THEN {checkPParityB _ TRUE; drive.PParityB _ TRUE; SetPData[data]}; E[]; R[]; checkPParityB _ FALSE; IF store THEN {drive.PData _ FALSE; drive.PParityB _ FALSE}; IF rejects=0 THEN RETURN; THROUGH [0..rejects-2) DO P[A]; PRejectB _ FALSE; E[]; R[]; P[B]; PRejectB _ TRUE; E[]; R[]; ENDLOOP; P[A]; PRejectB _ FALSE; E[]; R[]; P[B]; PRejectB _ TRUE; PFaultB _ fault; E[]; R[]; P[A]; PRejectB _ FALSE; PFaultB _ None; E[]; IF fault#None THEN RETURN; R[]; P[B]; IF fetch THEN {checkPData _ TRUE; SetPData[data]; IF command=Fetch THEN checkPParityB _ TRUE}; E[]; R[]; checkPParityB _ FALSE; }; }; ThreadStart: PROC[thread:ThreadProc, data: REF ANY _ NIL] = TRUSTED { ThreadUp[]; Process.Detach[FORK ThreadFork[thread, data]]; }; ThreadFork: PROC[thread:ThreadProc, data: REF ANY] = { { thread[data ! UNWIND, EtuBrute => GOTO quit] EXITS quit => NULL; }; ThreadDown[]; }; ThreadUp: ENTRY PROC = { threadCount _ threadCount + 1; }; ThreadDown: ENTRY PROC = { threadCount _ threadCount - 1; NOTIFY pushWait; NOTIFY entryEvalWait; }; P: ENTRY PROC [phase: PhaseLetter _ N] = { OPEN value; waitPhase: Phase _ clockPhase; newPhase: Phase _ (clockPhase + 1) MOD 4; IF (phase=A AND newPhase#0) OR (phase=B AND newPhase#2) OR (phase=N AND (newPhase#1 AND newPhase#3)) THEN { clocksSkewed _ TRUE; Kick[]; RETURN WITH ERROR EtuBrute; }; pushWaitCount _ pushWaitCount + 1; NOTIFY entryEvalWait; WHILE waitPhase=clockPhase DO IF pushWaitCount=threadCount THEN { clockPhase _ (clockPhase + 1) MOD 4; SELECT clockPhase FROM 0 => {PhA _ TRUE; cycleNumber _ cycleNumber + 1}; 1 => PhA _ FALSE; 2 => PhB _ TRUE; 3 => PhB _ FALSE; ENDCASE => ERROR; pushWaitCount _ 0; BROADCAST pushWait; RETURN; }; WAIT pushWait; IF killThreads THEN RETURN WITH ERROR EtuBrute; ENDLOOP; }; E: ENTRY PROC = { waitCount: NAT _ evalCount; evalWaitCount _ evalWaitCount + 1; NOTIFY entryEvalWait; WHILE waitCount=evalCount DO WAIT evalWait; IF killThreads THEN RETURN WITH ERROR EtuBrute; ENDLOOP; }; EntryEval: ENTRY PROC = { UNTIL evalWaitCount+pushWaitCount=threadCount AND evalWaitCount>0 DO IF threadCount=0 THEN RETURN; WAIT entryEvalWait; IF killThreads THEN RETURN WITH ERROR EtuBrute; ENDLOOP; ReallyEval[!UNWIND => Kick[]]; }; ReallyEval: INTERNAL PROC = { OPEN value; instructions.PhA _ PhA; instructions.PhB _ PhB; instructions.Vdd _ Vdd; instructions.Gnd _ Gnd; instructions.PadVdd _ PadVdd; instructions.PadGnd _ PadGnd; IF drive.PData THEN instructions.PData _ PData; IF drive.PParityB THEN instructions.PParityB _ PParityB; instructions.PCmdA _ PCmdA; IF drive.PRejectB THEN instructions.PRejectB _ PRejectB; IF drive.PFaultB THEN instructions.PFaultB _ PFaultB; IF drive.PNPError THEN instructions.PNPError _ PNPError; IF drive.MDataBA THEN instructions.MDataBA _ MDataBA; IF drive.MCmdBA THEN instructions.MCmdBA _ MCmdBA; IF drive.MNShared THEN instructions.MNShared _ MNShared; IF drive.MParityBA THEN instructions.MParityBA _ MParityBA; IF drive.MNError THEN instructions.MNError _ MNError; instructions.MReadyBA _ MReadyBA; IF drive.MNewRq THEN instructions.MNewRq _ MNewRq; instructions.MGnt _ MGnt; instructions.ResetAB _ ResetAB; instructions.DHoldAB _ DHoldAB; instructions.DShiftAB _ DShiftAB; instructions.DExecuteAB _ DExecuteAB; instructions.DNSelectAB _ DNSelectAB; instructions.DDataInAB _ DDataInAB; [] _ RoseRun.Eval[handle ! Dragon.AssertionFailed => IF ignoreWarnings THEN RESUME ELSE REJECT; RoseTypes.Stop => IF data = $FailedAssertion AND ignoreWarnings THEN RESUME ELSE REJECT; RoseEventsImpl.Warning => IF ignoreWarnings THEN RESUME ELSE REJECT]; IF checkPData AND instructions.PData#PData THEN Complain["PData"]; IF checkPParityB AND instructions.PParityB#PParityB THEN Complain["PParityB"]; IF instructions.PRejectB#PRejectB THEN Complain["PRejectB"]; IF instructions.PFaultB#PFaultB THEN Complain["PFaultB"]; IF instructions.PNPError#PNPError THEN Complain["PNPError"]; IF instructions.MDataBA#MDataBA THEN Complain["MDataBA"]; IF instructions.MCmdBA#MCmdBA THEN Complain["MCmdBA"]; IF checkMNShared AND instructions.MNShared#MNShared THEN Complain["MNShared"]; IF checkMParityBA AND instructions.MParityBA#MParityBA THEN Complain["MParityBA"]; IF instructions.MNError#MNError THEN Complain["MNError"]; IF instructions.MRq#MRq THEN Complain["MRq"]; IF instructions.MNewRq#MNewRq THEN Complain["MNewRq"]; IF checkDDataOutAB AND instructions.DDataOutAB#DDataOutAB THEN Complain["DDataOutAB"]; evalWaitCount _ 0; evalCount _ evalCount + 1; BROADCAST evalWait; }; F: PROC={E[];R[];R[A];R[]}; R: PROC [phase: PhaseLetter _ N] = {P[phase];E[]}; Complain: PROC [r: ROPE] = {IF NOT ignoreWarnings THEN RoseTypes.Stop[Rope.Concat[r, PutFR[" in cycle %g phase %g", int[cycleNumber], int[clockPhase]]], $FailedAssertion]}; SetMData: PROC[dw: Dragon.Word] = { value.MDataBA _ ILID[dw, value.MDataBA, 32, 0, 32]; value.MParityBA _ CacheOps.Parity32[dw]; }; SetPData: PROC[dw: Dragon.Word] = { value.PData _ ILID[dw, value.PData, 32, 0, 32]; value.PParityB _ CacheOps.Parity32[dw]; }; Kick: INTERNAL PROC = { killThreads _ TRUE; BROADCAST pushWait; BROADCAST evalWait; BROADCAST entryEvalWait; }; Cache.RegisterCacheTester[CacheTest]; END. NCacheTester.mesa Last Edited by: Barth, May 31, 1984 5:09:34 pm PDT Invariant: Each thread always calls P before changing anything in value or drive. All threads must have called P before P actually advances the clock and lets the evaluation procede. E only executes when all threads are hung on P or E. Check that a write single causes master to be reset. The following note is not up to date !!! Bits in the debug shift register in order of appearance. Put them in and read them out backwards! Multiple bit quantities within CacheMx appear low order bit first, within CachePx appear high order bit first. There is currently a total of 33+1+8+26+12+0+30+30+12+33+1 or 186 bits. CacheMRAMDriver 33 shiftDataParity shiftData[32] CacheMCtlRAMCtl 1 shiftHighAddress CacheMCtlFlagCtl 8 sVPValid sRPValid sRPDirty sMaster sShared sVictim sTIP sBroken CacheMCtlSequencer 26 cycleShifterAB[7] currentSequenceAB[7] currentPDemandsBA[7] slaveAB forceSlaveBA wonArbitrationAB mWantsMBA samplePDemandsBA CacheMCtlEntryCtl 12 sMAdrLow sMAdrHigh sReadEntry sWriteEntry sCellAdr[8] CacheMCtlCAMCtl 0 CacheMCAMDriver 30 shiftData[30] CachePCAMDriver 30 shiftData[30] CachePCtl 12 loadEnable loadMustBeOne pCmdShift[4] rejectShift parityShift requestShift readVA pAdrLowShift pAdrHighShift CachePRAMDriver 33 shiftData[32] parityShift CacheMPads 1 shiftAB Ê'Y˜Jšœ™J™2Icode˜KšÏk œ"œ4˜aK˜šÐbx œœœ˜Kšœ"œ3˜^Kšœ˜—K˜Kšœœ œ˜J˜Jšœœ˜Jšœœ ˜Jš œ œœœœ˜Jš Ïn œœœœœ˜*Jš Ÿ œœœœœ˜'Jšœ œœ ˜$šœ œœ˜Jšœœœ˜Jš œœœœœœ˜RJšœ œœœE˜sJšœœ œœAœœœœ˜JšœœœœE˜{Jšœ œœ%˜=Jšœœœ˜+—Jšœœœ˜(šœœœ˜Jšœ˜Jšœ˜Jšœ œ˜Jšœ!˜!—J˜Jšœ˜Jšœ œ˜Kšœœ˜Kšœœ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Jšœœ˜J˜J˜!Jšœœ˜0JšœKœ˜PJšœœ˜ Jšœœ˜Jšœ œœ˜K˜šœ ˜ Jšœ3˜3Jšœœ˜šœ˜Jšœ0˜0šœ˜Jšœœ"˜*Jšœ œ˜—š˜Jšœœ˜ —J˜—Jšœ˜Jšœœ ˜4J˜—šœ&˜&Jšœ˜ Jšœ˜Jšœ˜Kšœ˜Kšœ˜Kšœ˜Jšœ ˜ Jšœ˜J˜ Jšœœ˜Jšœœ˜J™J™íJ™šœ˜Jšœ˜Jšœ˜—Jšœœ˜ Jšœœ˜ Jšœ˜šœ˜J˜ Jšœ˜Jšœ˜——J˜šœ˜Jšœ˜ J˜ J˜Jšœœœ˜ J˜Jš œœœœœB˜€Jšœœœœœœœœœ˜0Jš œœœœœB˜€Jšœœœœœœœœœ˜0Jš œœœœœ˜]Jšœœœœœœœœœ˜0Jš œœœœœ˜NJšœœœœœœœœœ˜0Jšœœœ˜ J˜Jš œœTœœœ˜yJš œœœœœœ%˜uJšœœœœœœœœœœœœÏc ˜8Jšœœœœœœœœœœœœ ˜1Jšœœœœœœœœœ˜ JšœœTœœœœœœœœœ˜Jš œœœœœ%˜jJšœœœœœœœœœœœœ ˜1Jšœœœœœœœœœ˜ JšœœPœœœœœœœœœ˜‹Jšœœœœ%˜WJšœœœœœœœœœœœœ ˜1Jšœœœœœœœœœœœœœœœ ˜EJ˜JšœœF˜aJšœœ˜Jšœ˜Jšœœœœœ%œœœgœœ%˜ Jšœ œœœœœœœœ˜1Jš œœœœœœ˜VJšœœœ˜ Jšœœ:œœœœœœ˜jJšœœBœœœœœœ˜rJšœœBœœœœœœ˜rJšœœBœœœœœœ˜rJ˜Jš œœNœœœ˜sJš œœœœœi˜¥Jšœœœœœœœœœ˜0Jš œœœœœœ˜IJ˜Jš œœRœœœ˜wJšœœœœ˜IJšœœœœœœœœœœœœ˜+Jšœœœœ˜CJšœœœœœœœœœœ˜4JšœœBœœœœœœ˜rJš œœRœœœ˜wJš œœœœœ˜[Jšœœœœœœœœœœœœ˜+Jšœœœœ˜CJšœœœœœœœœœœ˜4JšœœBœœœœœœ˜rJšœœœœ˜8Jšœœœœœœœœœœœœ˜+Jšœœœœœœœ˜ZJ˜Jš œœNœœœ˜sJš œœœœœi˜¥Jšœœœœœœœœœ˜0Jš œœœœœœ˜IJ˜Jš œœPœœœ˜uJš œœœœœi˜¥Jšœœœœœœœœœ˜0Jš œœœœœœ˜IJ˜Jš œœQœœœ˜vJš œœœœœ|œœi˜©Jšœ œœœœœœœœ˜1Jš œœœœœœ˜IJ˜Jš œœQœœœ˜vJš œœœœœhœœi˜•Jšœ œœœœœœœœ˜1Jš œœœœœœ˜IJ˜Jš œœPœœœ˜uJš œœœœœi˜¥Jšœœœœœœœœœ˜0Jš œœœœœœ˜IJ˜Jšœœœ˜ J˜Jš œœœœœj˜¨Jšœœœœœœœœœ˜0Jš œœœœœ œj˜¶Jšœœœœœœœœœ˜0Jš œœœœœ-˜kJšœœœœœœœœœ˜0Jš œœœœœ œj˜¶Jšœœœœœœœœœ˜0Jš œœœœœ˜UJšœœœœœœœœœ˜0J˜Jšœœœ˜ J˜Jšœœ_˜zJšœœœ˜ Jš œœœœœ'˜dJšœœœœœœœœœ˜0J˜Jšœœœ˜ J˜Jš œœPœœœ˜uJš œœœœœ%˜bJšœœœœœœœœœœœœ  ˜8Jšœœœœœœœœœœœœ ˜1Jšœœœœœœœœœœœœ ˜:J˜Jšœœœ˜ J˜Jš œœPœœœ˜uJš œœœœœ%˜bJšœœœœœœœœœœœœ  ˜8Jšœœœœœœœœœœœœ ˜1Jšœœœœœœœœœœœœ ˜:J˜Jšœœœ˜ J˜ J˜J™4J˜Jš œœVœœœ˜{Jš œœœœœ*œœi˜ØJšœ œœœœœœœœ˜1Jšœœœ˜ Jš œœVœœœ˜{Jš œœœœœi˜¥Jšœœœœœœœœœ˜0Jšœœœ˜ Jš œœVœœœ˜{Jš œœœœœi˜¥Jšœœœœœœœœœ˜0Jšœœœ˜ Jš œœVœœœ˜{Jš œœœœœi˜¥Jšœœœœœœœœœ˜0Jš œœœœœ œj˜¶Jšœœœœœœœœœ˜0Jš œœœœœ-˜kJšœœœœœœœœœ˜0Jšœœœ˜ Jš œœVœœœ˜{Jš œœœœœi˜¥Jšœœœœœœœœœ˜0J˜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šœœœœœœœœœ˜0Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœœœœœœœœœ˜0J˜J˜—šœ˜Jšœœ˜'šœ˜Jšœ˜Jšœœœœœœœœœœœœœ˜_šœœ˜ Jšœœ œœ œ œœ˜8Jšœ˜Jšœœ˜Jšœ˜Jšœœ œœ˜Jšœ˜šœ˜ Jšœœ œœ˜Jšœ˜Jšœœ˜Jšœ˜Jšœ˜—Jšœœ œœ˜Jšœ˜J˜—šœœœ˜ Jš œœœœœ˜RJš œœœœœ˜*Jšœœ,œ˜3šœ˜Jš œœœœ<œœ˜^Jšœ˜—Jš œœœœ<œœ˜]Jšœœ.œ˜5Jšœœ.œ˜5Jšœœ.œœ˜MJš œœœœœœ˜iJ˜—šœœœ˜ Jšœ œœœœœœœœœ ˜AJš œœœœœ˜*Jšœœ)œ˜0Jšœ œœ˜/Jšœœœ'œœœœ˜‰Jš œœœ œœœ˜8Jšœœœœœœœ œ œœœ˜PJ˜—šœœœ˜ Jš œ œœœœœœ ˜6Jš œœœœœ˜*Jšœœœœœœ6œœœ˜”Jš œœœœ œ œ˜>Jšœ˜Jšœœœœœœœœ œœ˜WJšœœœ˜3Jšœœœœœœœœœœœ&œœ œœ˜âšœœ˜šœ˜!Jšœœœ˜ Jšœ˜—Jš œœ'œ œœ˜EJ˜—Jšœœœ˜Jš œœœ œœœ˜œœœœœœ œ œœœœœœœœœœ˜„J˜—šœœœ˜ Jš œœœœœ˜*Jšœœ*œ˜1šœ œœ˜Jš œœœ#œœ˜VJšœ˜Jš œœœœœ˜KJ˜—šœ˜Jš œœœ*œœ˜]J˜—Jš œœœ œœœ˜9Jšœœœœœœœ œ œœœ˜QJ˜—šœœœœœœœœœœœ œ˜>Jšœœ œœ˜Jšœœœœœ œœœœœœ˜gJ˜—šœœœ˜ Jšœœœœ)œœœœœœ˜®Jšœœœ˜J˜—J˜—J˜J˜—šœ˜Jšœœ˜'šœ˜Jšœ˜Jš œœœœœ˜[Jš œœœœœ˜[Jšœœœ œœ œ+œœœ˜£Jš œœœœœ˜:Jš&œœœ œ œœœœœ œœœœœœœœœœ˜ñJš œœœœœœ˜XJšœ œœ˜šœ˜Jšœœœœ˜Jšœ˜Jšœœœœ˜Jšœ˜Jšœ˜—Jšœœœœ˜Jšœ˜Jšœœœœ˜,Jšœ˜Jšœœœœ˜,Jšœ œœ˜Jšœ˜Jšœœœœœœœœœ˜iJšœœ˜J˜—J˜J˜—š Ÿ œœœœœœ˜EK˜ Jšœœ˜.J˜K˜—šŸ œœœœ˜6šœ˜šœ ˜ Jšœœœ˜ —š˜Jšœœ˜ —J˜—K˜ J˜K˜—šŸœœœ˜Jšœ˜J˜K˜—šŸ œœœ˜Jšœ˜Jšœ ˜Jšœ˜J˜K˜—šœœœœ˜*Kšœ˜ Jšœ˜Jšœ#œ˜)šœœœ œœœ œœœ œœ˜kJšœœ˜Jšœ˜Jšœœœ ˜J˜—Kšœ"˜"Jšœ˜šœ˜šœœ˜#Jšœœ˜$šœ ˜Jšœ œ!˜1Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ˜—Jšœ˜Jš œ ˜Jšœ˜J˜—Jšœ ˜Jš œ œœœœ ˜/Jšœ˜—Jšœ˜—J˜šœœœ˜Jšœ œ ˜Kšœ"˜"Kšœ˜šœ˜Jšœ ˜Jš œ œœœœ ˜/Jšœ˜—J˜K˜—šŸ œœœ˜šœ)œ˜DJšœœœ˜Jšœ˜Jš œ œœœœ ˜/Jšœ˜—Jšœ œ ˜J˜—J˜šŸ œœœ˜Kšœ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Jšœ œ˜/Jšœœ"˜8Kšœ˜Jšœœ"˜8Jšœœ ˜5Jšœœ"˜8Jšœœ ˜5Jšœœ˜2Jšœœ"˜8Jšœœ$˜;Jšœœ ˜5Kšœ!˜!Jšœœ˜2Kšœ˜Kšœ˜Kšœ˜Kšœ!˜!Kšœ%˜%Kšœ%˜%Kšœ#˜#šœ˜Jš œœœœœœ˜FJš œœœœœœœ˜XJš œœœœœœ˜E—Jšœ œœ˜BJšœœ œ˜NJšœ œ˜