<> <> <> <> <> DIRECTORY Arbiter, BitOps, CedarProcess, Core, CoreFlat, CoreProperties, IO, MTSVector, Ports, Random, Rosemary, RosemaryUser; ArbSysTests: CEDAR PROGRAM IMPORTS BitOps, CedarProcess, CoreFlat, CoreProperties, IO, MTSVector, Ports, Random, Rosemary, RosemaryUser EXPORTS Arbiter = BEGIN OPEN Arbiter; <> <<>> <> <<>> State: TYPE = REF StateRec _ NIL; StateRec: TYPE = RECORD [ tester: RosemaryUser.Tester _ NIL, simulation: Rosemary.Simulation _ NIL, cellType: Core.CellType _ NIL, capture: MTSVector.Capture _ NIL, testCycles: INT _ 100000, p: Ports.Port _ NIL, eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL_FALSE, checkPorts: BOOL_TRUE]_NIL, cycle, patchState: INT _ -1, noteBusBusyLast: INT _ -1, forceStop, forceBusy: BOOL _ FALSE, nRequestOuts, nGrants, nHiPGrants, nLongGrants, ArbReqs, DBus, nOwnerOuts, nBOwnerIn, nOwnerIns, nSharedOuts, nBShareds, nSharedIns, nSStopOuts, nBSStops, nSStopIns, nStopAct, SlotNos, nDHybridSels, DBdSels, nDynaBusBusy, nHolding, nBusyOuts, nBusyIn, Ck, TIOBus, --RecAdj, --TRec2v, TInv: NAT _ 0, <<..indexes in cellType.public>> arbs: ARRAY Arbiters OF REF _ ALL[NIL], devs: ARRAY Arbiters OF ARRAY Devices OF REF _ ALL[ALL[NIL]] ]; lastState: State _ NIL; rand: Random.RandomStream _ Random.Create[]; NewState: PROC [ cellType: Core.CellType, p: Ports.Port, eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL _ FALSE, checkPorts: BOOL _ TRUE]] RETURNS [ st: State ] = { GetState: PROC [ instName: IO.ROPE ] RETURNS [ ref: REF ] = { ref _ Rosemary.GetState[ st.tester.display.simulation, NEW[CoreFlat.FlatCellTypeRec _ CoreFlat.ParseCellTypePath[st.cellType, instName]] ] }; lastState _ st _ NEW[StateRec _ [tester: NARROW[CoreProperties.GetProp[cellType.properties, $Tester]] ]]; st.simulation _ st.tester.display.simulation; st.cellType _ st.tester.display.cellType; st.p _ p; TRUSTED { st.eval _ eval }; [st.nRequestOuts, st.nGrants, st.nHiPGrants, st.nLongGrants, st.ArbReqs] _ Ports.PortIndexes [st.cellType.public, "nRequestOuts", "nGrants", "nHiPGrants", "nLongGrants", "ArbReqs"]; [st.DBus] _ Ports.PortIndexes[st.cellType.public, "DBus"]; [st.SlotNos, st.nDHybridSels, st.DBdSels] _ Ports.PortIndexes[st.cellType.public, "SlotNos", "nDHybridSels", "DBdSels"]; [st.nOwnerOuts, st.nBOwnerIn, st.nOwnerIns] _ Ports.PortIndexes[st.cellType.public, "nOwnerOuts", "nBOwnerIn", "nOwnerIns"]; [st.nSharedOuts, st.nBShareds, st.nSharedIns] _ Ports.PortIndexes[st.cellType.public, "nSharedOuts", "nBShareds", "nSharedIns"]; [st.nSStopOuts, st.nBSStops, st.nSStopIns, st.nStopAct] _ Ports.PortIndexes[st.cellType.public, "nSStopOuts", "nBSStops", "nSStopIns", "nStopAct"]; [st.nDynaBusBusy, st.nHolding, st.nBusyOuts, st.nBusyIn, st.Ck] _ Ports.PortIndexes[st.cellType.public, "nDynaBusBusy", "nHolding", "nBusyOuts", "nBusyIn", "Ck"]; [st.TIOBus, --st.RecAdj, -- st.TRec2v, st.TInv] _ Ports.PortIndexes[st.cellType.public, "TIOBus", --"RecAdj", --"TRec2v", "TInv"]; FOR a: Arbiters IN Arbiters DO <> <<-- until I figure out how to do this ....>> FOR d: Devices IN Devices DO st.devs[a][d] _ GetState[IO.PutFR["/Arb%dReq%d", IO.int[a], IO.int[d]]]; ENDLOOP; ENDLOOP}; WhoAmI: PROC [ ref: REF ] RETURNS [ name: IO.ROPE ] = { FOR a: Arbiters IN Arbiters DO IF ref = lastState.arbs[a] THEN RETURN[IO.PutFR["Arbiter %d", IO.int[a]]]; FOR d: Devices IN Devices DO IF ref = lastState.devs[a][d] THEN RETURN[IO.PutFR["Device %d of arbiter %d", IO.int[d], IO.int[a]]] ENDLOOP ENDLOOP; name _ "Darned if I know!"}; extraResetCycles: NAT _ 1; nCheckBits: NAT _ 5; shouldMaskRev1Bug: BOOL _ FALSE; RunTest: PROC [ st: State, initializeAll: BOOL _ FALSE ] = { PipeDepth: NAT = 10; Eval: PROC [ ignoreX: BOOL _ FALSE ] = { ENABLE Rosemary.Stop => IF ignoreX AND (reason = $BoolWireHasX) THEN RESUME ELSE REJECT; MTSVector.EvalAndCapture[st.capture, st.eval, FALSE]; }; EvalIgnoreX: PROC = {Eval[ignoreX: TRUE]}; ReallyRunTest: PROC = { OrPorts: TYPE = {owner, shared, stop}; OrPipeEnt: TYPE = RECORD [ A: ARRAY Arbiters OF BOOL _ ALL[FALSE], inD: BOOL _ FALSE ]; OrPortParts: TYPE = RECORD [ outD, A, inD: NAT, pipe: ARRAY [0..PipeDepth) OF OrPipeEnt _ ALL[] ]; orPortState: ARRAY OrPorts OF OrPortParts _ [ owner: [outD: st.nOwnerOuts, A: st.nBOwnerIn, inD: st.nOwnerIns], shared: [outD: st.nSharedOuts, A: st.nBShareds, inD: st.nSharedIns], stop: [outD: st.nSStopOuts, A: st.nBSStops, inD: st.nSStopIns]]; DoClk: PROC [ cycles: INT _ 1, ignoreX: BOOL _ FALSE ] = { FOR i: INT IN [0..cycles) DO IgnoreOrPorts[]; MaskBug[]; st.p[st.Ck].b _ FALSE; Eval[ignoreX]; PredictOrPorts[]; st.p[st.Ck].b _ TRUE; Eval[ignoreX]; st.cycle _ st.cycle+1; ENDLOOP}; DoClkIgnoreX: PROC [ cycles: INT _ 1 ] = {DoClk[cycles, TRUE]}; DAShift: PROC [ val: BitOps.BitWord ] = { st.p[st.DBus][DAddress].b _ TRUE; EvalIgnoreX[]; DDShift[16, val]; st.p[st.DBus][DAddress].b _ FALSE; EvalIgnoreX[]}; DDShift: PROC [ size: [1..16], val: BitOps.BitWord ] = { FOR i: NAT IN [0..size) DO st.p[st.DBus][DSerialIn].b _ BitOps.EBFW[val, i, size]; st.p[st.DBus][DShiftCK].b _ FALSE; EvalIgnoreX[]; st.p[st.DBus][DShiftCK].b _ TRUE; EvalIgnoreX[]; ENDLOOP}; DDShiftCheck: PROC [ size: [1..16], valIn: BitOps.BitWord, valOut: BitOps.BitWord ] = { FOR i: NAT IN [0..size) DO st.p[st.DBus][DSerialIn].b _ BitOps.EBFW[valIn, i, size]; st.p[st.DBus][DShiftCK].b _ FALSE; st.p[st.DBus][DSerialOut].b _ BitOps.EBFW[valOut, i, size]; st.p[st.DBus][DSerialOut].d _ expect; EvalIgnoreX[]; st.p[st.DBus][DSerialOut].d _ none; st.p[st.DBus][DShiftCK].b _ TRUE; EvalIgnoreX[]; ENDLOOP}; IgnoreOrPorts: PROC = { FOR port: OrPorts IN [owner..owner] DO FOR dev: Devices IN Devices DO FOR arb: Arbiters IN Arbiters DO st.p[orPortState[port].outD][arb].d _ inspect; st.p[orPortState[port].inD][arb].d _ none; ENDLOOP; st.p[orPortState[port].A].d _ none ENDLOOP ENDLOOP; FOR port: OrPorts IN [shared..stop] DO FOR arb: Arbiters IN Arbiters DO FOR dev: Devices IN Devices DO st.p[orPortState[port].outD][arb][dev].d _ inspect; ENDLOOP; st.p[orPortState[port].A][arb].d _ none; st.p[orPortState[port].inD][arb].d _ none ENDLOOP ENDLOOP}; MaskBug: PROC = { k: INT _ st.cycle+PipeDepth; <> SELECT TRUE FROM k <= 2*PipeDepth => st.patchState _ 0; (st.patchState = 0) AND orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 1; shouldMaskRev1Bug AND (st.patchState = 1) AND st.p[st.nBusyIn].b => st.patchState _ 2; shouldMaskRev1Bug AND st.patchState IN [2..7] => st.patchState _ st.patchState+1; shouldMaskRev1Bug AND (st.patchState = 8) AND NOT orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 0; NOT shouldMaskRev1Bug AND (st.patchState = 1) AND NOT orPortState[stop].pipe[(k-3) MOD PipeDepth].inD => st.patchState _ 0; ENDCASE => NULL; st.p[st.nStopAct].b _ NOT (st.forceStop OR (st.patchState > 0)); IF NOT st.p[st.nStopAct].b THEN st.noteBusBusyLast _ st.cycle+6; st.p[st.nBusyOuts][maxArbiters].d _ drive; st.p[st.nBusyOuts][maxArbiters].b _ (st.patchState <= 2); IF st.forceBusy OR (st.cycle < st.noteBusBusyLast) THEN { st.p[st.nDynaBusBusy].d _ drive; st.p[st.nDynaBusBusy].b _ FALSE} ELSE st.p[st.nDynaBusBusy].d _ none}; PredictOrPorts: PROC = { k: INT _ st.cycle+PipeDepth; FOR port: OrPorts IN [owner..owner] DO orOutD: BOOL _ FALSE; orA: BOOL _ orPortState[port].pipe[(k-1) MOD PipeDepth].inD; orInD: BOOL _ orPortState[port].pipe[(k-3) MOD PipeDepth].inD; FOR arb: Arbiters IN Arbiters DO orOutD _ orOutD OR NOT st.p[orPortState[port].outD][arb].b; IF k > 2*PipeDepth THEN { st.p[orPortState[port].inD][arb].d _ expect; st.p[orPortState[port].inD][arb].b _ NOT orInD} ENDLOOP; IF k > 2*PipeDepth THEN { st.p[orPortState[port].A].d _ expect; st.p[orPortState[port].A].b _ NOT orA}; orPortState[port].pipe[k MOD PipeDepth].inD _ orOutD ENDLOOP; FOR port: OrPorts IN [shared..stop] DO orOutD: BOOL _ FALSE; FOR arb: Arbiters IN Arbiters DO orOutDA: BOOL _ FALSE; FOR dev: Devices IN Devices DO orOutDA _ orOutDA OR NOT st.p[orPortState[port].outD][arb][dev].b ENDLOOP; orPortState[port].pipe[k MOD PipeDepth].A[arb] _ orOutDA; orOutD _ orOutD OR orOutDA; IF k > 2*PipeDepth THEN { st.p[orPortState[port].A][arb].d _ expect; st.p[orPortState[port].A][arb].b _ NOT orPortState[port].pipe[(k-1) MOD PipeDepth].A[arb]; st.p[orPortState[port].inD][arb].d _ expect; st.p[orPortState[port].inD][arb].b _ NOT orPortState[port].pipe[(k-3) MOD PipeDepth].inD} ENDLOOP; orPortState[port].pipe[k MOD PipeDepth].inD _ orOutD ENDLOOP}; dBusInits: Arbiter.DBusInitList _ NARROW[ CoreProperties.GetProp[st.cellType.properties, $DBusInits]]; st.p[st.nStopAct].d _ drive; FOR i: NAT IN (DSerialOut..DShiftCK] DO st.p[st.DBus][i].d _ drive; st.p[st.DBus][i].b _ FALSE ENDLOOP; st.p[st.DBus][DSerialOut].d _ none; FOR a: Arbiters IN Arbiters DO st.p[st.SlotNos][a].c _ 8H+a ENDLOOP; st.p[st.DBus][DExecute].b _ FALSE; st.p[st.DBus][nDFreeze].b _ TRUE; st.p[st.DBus][nDReset].b _ FALSE; st.p[st.DBus][DSerialIn].b _ FALSE; st.p[st.DBus][DShiftCK].b _ FALSE; st.p[st.DBus][DAddress].b _ FALSE; st.p[st.DBus][DSerialOut].b _ TRUE; st.p[st.DBus][DSerialOut].d _ driveWeak; FOR i: NAT IN [0..6) DO st.p[st.TIOBus][i].d _ driveStrong; -- we really don't care about this bus st.p[st.TIOBus][i].b _ FALSE ENDLOOP; FOR i: NAT IN [0..2) DO st.p[st.TRec2v][i].d _ drive; st.p[st.TRec2v][i].b _ TRUE ENDLOOP; st.p[st.TRec2v][2].d _ expect; st.p[st.TRec2v][2].b _ NOT st.p[st.TRec2v][0].b; <> <> st.p[st.TInv][0].d _ drive; st.p[st.TInv][0].b _ FALSE; st.p[st.TInv][1].d _ expect; st.p[st.TInv][1].b _ NOT st.p[st.TInv][0].b; st.cycle _ 0; st.noteBusBusyLast _ -1; st.forceStop _ TRUE; st.forceBusy _ TRUE; -- no starvation errors yet DoClkIgnoreX[6]; -- allow some X's to relax out st.forceStop _ FALSE; -- release Stop while holding Reset st.p[st.DBus][DShiftCK].b _ TRUE; DoClkIgnoreX[6]; -- allow more X's to relax out IF st.cycle > st.testCycles THEN RETURN; IF dBusInits # NIL THEN { checkBits: Ports.BoolSequence _ NEW[Ports.BoolSequenceRec[nCheckBits]]; a: Arbiters _ 0; DAShift[08000H+1000H*a]; -- check signature DDShiftCheck[16, 0, 5041H]; <> DAShift[08000H+1000H*a+2]; -- load arbiter number DDShift[4, 2*a+1]; -- decoded hybrid select DAShift[08000H+1000H*a+300H]; -- address hybrid 3 st.p[st.nDHybridSels][a].d _ expect; st.p[st.nDHybridSels][a].c _ 01FH-4; -- decoded EvalIgnoreX[]; st.p[st.nDHybridSels][a].d _ none; DAShift[08000H+1000H*a+2]; -- load arbiter number DDShift[4, 2*a]; -- now encoded DAShift[08000H+1000H*a+300H]; -- address hybrid 3 st.p[st.nDHybridSels][a].d _ expect; st.p[st.nDHybridSels][a].c _ 01FH-6; -- encoded, 5 bits EvalIgnoreX[]; st.p[st.nDHybridSels][a].d _ none; DAShift[08000H+1000H*a+400H]; -- address hybrid 4 DDShift[1, 0]; -- load BdVersion shadow DAShift[08000H+1000H*a+3H]; -- read the board version DDShiftCheck[2, 0, 2]; FOR dbir: LIST OF REF ANY _ dBusInits, dbir.rest WHILE dbir#NIL DO WITH dbir.first SELECT FROM dbi: REF DBusInitItem => { DAShift[08000H+dbi.addr]; -- load DBus destination number FOR i: NAT IN [0..dbi.bits.size+checkBits.size) DO outVal: [0..2); cbi: INT = i - dbi.bits.size; IF i < checkBits.size THEN { outVal _ rand.ChooseInt[max: 1]; checkBits[i] _ (outVal > 0) } ELSE outVal _ (IF dbi.bits[i-checkBits.size] THEN 1 ELSE 0); IF cbi < 0 THEN DDShift[1, outVal] ELSE DDShiftCheck[1, outVal, (IF checkBits[cbi] THEN 1 ELSE 0)] ENDLOOP }; ENDCASE => ERROR ENDLOOP }; st.forceStop _ TRUE; <<... assert Stop. This causes LclGrant4 to become FALSE, and begins clearing X's out of the ArbReq and Grant paths.>> DoClkIgnoreX[10]; -- allow more X's to relax out st.forceStop _ FALSE; <<... release Stop. This applies a final reset to the Arbiter's input counters and the rover pointers.>> DoClkIgnoreX[10]; -- allow final X's to relax out DoClk[extraResetCycles]; -- see if any X's left st.forceStop _ TRUE; -- assert Stop, this terminates Arbiter's reset DoClk[6]; st.p[st.DBus][nDReset].b _ TRUE; -- release Reset, this terminates everybody else's reset st.p[st.DBus][nDFreeze].b _ TRUE; -- release Freeze, whatever that means DoClk[5]; st.forceStop _ FALSE; -- release Stop, begin arbitration DoClk[15]; st.forceBusy _ FALSE; -- allow starvation errors DoClk[st.testCycles - 1166]}; -- 1166 to init CedarProcess.DoWithPriority[priority: background, action: ReallyRunTest]}; simHighProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; simMediumProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; simLowProb: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ []]; normalProb: ProbabilitiesRec _ [request: ALL[400], hold: 1000, stop: 1000, owner: 1000, shared: 1000]; zeroProb: ProbabilitiesRec _ [request: ALL[10000000], hold: never, stop: never, owner: never, shared: never]; higherProb: ProbabilitiesRec _ [request: ALL[30], hold: 100, stop: 100, owner: 100, shared: 100]; evenHigherProb: ProbabilitiesRec _ [request: ALL[10], hold: 100, stop: 100, owner: 100, shared: 100]; userProb: ProbabilitiesRec _ normalProb; GeneralArbSysTest: PROC [cellType: Core.CellType, p: Ports.Port, Eval: PROC [memory: BOOL _ TRUE, clockEval: BOOL _ FALSE, checkPorts: BOOL _ TRUE], high, med, low: ProbabilitiesRec, captureVectors: BOOL _ FALSE, testCycles: INT _ 100000] = { st: State = NewState[cellType, p, Eval]; st.testCycles _ testCycles; FOR a: Arbiters IN Arbiters DO FOR d: Devices IN Devices DO rs: REF RequesterStateRec = NARROW[st.devs[a][d]]; rs.probs _ (SELECT TRUE FROM (a = 0) AND (d = 0) => simHighProb, (a = 0) => simMediumProb, ENDCASE => simLowProb) ENDLOOP ENDLOOP; simHighProb^ _ high; simMediumProb^ _ med; simLowProb^ _ low; IF captureVectors THEN st.capture _ MTSVector.CreateCapture[cellType]; RunTest[st, FALSE]; MTSVector.CloseCapture[st.capture]}; Test1Arb1Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, evenHigherProb, zeroProb, zeroProb, FALSE, 100000]}; Test1Arb8Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, FALSE, 100000]}; Test8Arb8Req: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, FALSE, 100000]}; Test1Arb8Req10: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, TRUE, 10]}; Test1Arb8Req2000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, higherProb, higherProb, zeroProb, TRUE, 2000]}; Test8Arb8ReqVec2000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, TRUE, 2000]}; Test8Arb8ReqVec10000: RosemaryUser.TestProc = {GeneralArbSysTest [cellType, p, Eval, normalProb, normalProb, normalProb, TRUE, 10000]}; GetSystemTests: PUBLIC PROC RETURNS [listOfTests: LIST OF IO.ROPE] = { listOfTests _ LIST[ "Test1Arb1Req", "Test1Arb8Req", "Test8Arb8Req", "Test1Arb8Req10", "Test1Arb8Req2000", "Test8Arb8ReqVec2000", "Test8Arb8ReqVec10000" ]}; RosemaryUser.RegisterTestProc["Test1Arb1Req", Test1Arb1Req]; RosemaryUser.RegisterTestProc["Test1Arb8Req", Test1Arb8Req]; RosemaryUser.RegisterTestProc["Test8Arb8Req", Test8Arb8Req]; RosemaryUser.RegisterTestProc["Test1Arb8Req10", Test1Arb8Req10]; RosemaryUser.RegisterTestProc["Test1Arb8Req2000", Test1Arb8Req2000]; RosemaryUser.RegisterTestProc["Test8Arb8ReqVec2000", Test8Arb8ReqVec2000]; RosemaryUser.RegisterTestProc["Test8Arb8ReqVec10000", Test8Arb8ReqVec10000]; END.