<> <> 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. <<>> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>