ArbQuickTests.mesa
Copyright c 1986 by Xerox Corporation. All rights reserved.
E. McCreight, January 14, 1988 6:38:32 pm PST
Last Edited by: McCreight January 19, 1988 7:05:08 pm PST
DIRECTORY
AMTypes, Arbiter, BitOps, CedarProcess, Core, CoreOps, FS, IO, Ports, PrintTV, Rope, Rosemary, RosemaryUser;
ArbQuickTests: CEDAR MONITOR
IMPORTS AMTypes, BitOps, CedarProcess, CoreOps, FS, IO, Ports, PrintTV, Rope, Rosemary, RosemaryUser
=
BEGIN OPEN Arbiter;
ArbWires: TYPE = {
OtherArbIn, nBusyIn, nStopAct, nRequestOut, nOwnerOut, nBOwnerIn,
nSharedOut, nBSharedIn, nSStopOut, nBSStopIn, DBus, SlotNo, BdVersion, Clock,
nLongGrant, nHiPGrant, nGrant, ArbReqOut, nBusyOut, nStartGrant, nBOwnerOut,
nOwnerIn, nBSharedOut, nSharedIn, nBSStopOut, nSStopIn, nBdSel,
nDHybridSel, CKOut, TInv, TRec2V, TIOBus
};
ArbWireNames: ARRAY ArbWires OF IO.ROPEALL[NIL];
GetNames: PROC [ ] = {
IF ArbWireNames[LAST[ArbWires]] = NIL THEN {
st: IO.STREAMIO.ROS[];
PrintTV.PrintType[type: AMTypes.UnderType[CODE[ArbWires]], put: st, depth: 4, width: 40000];
st ← IO.RIS[IO.RopeFromROS[st]];
WHILE st.GetChar[] # '{ DO ENDLOOP;
FOR w: ArbWires IN ArbWires DO
ArbWireNames[w] ← st.GetTokenRope[].token;
ENDLOOP;
};
};
State: TYPE = REF StateRec ← NIL;
StateRec: TYPE = RECORD [
cellType: Core.CellType ← NIL,
p: Ports.Port ← NIL,
eval: PROC [memory: BOOLTRUE, clockEval: BOOLFALSE, checkPorts: BOOLTRUE] ← NIL,
pi: ARRAY ArbWires OF NATALL[0], -- indexes in cellType.public
s: IO.STREAMNIL,
cycle: INT ← 0
];
st: State ← NIL;
GetAllState: PROC [cellType: Core.CellType, p: Ports.Port, eval: PROC [memory: BOOLTRUE, clockEval: BOOLFALSE, checkPorts: BOOLTRUE]] RETURNS [ st: State ] = {
st ← NEW[StateRec ← []];
st.cellType ← cellType;
st.p ← p;
TRUSTED { st.eval ← eval };
GetNames[];
FOR aw: ArbWires IN ArbWires DO
[st.pi[aw]] ← Ports.PortIndexes[st.cellType.public, ArbWireNames[aw]];
ENDLOOP;
};
PortToStream: PROC [ p: Ports.Port ] = {
PutBool: PROC [ b: BOOL, d: Ports.Drive ] = {
st.s.PutRope[(SELECT d FROM
< none => (IF b THEN "H" ELSE "L"),
none => "X",
<= force => (IF b THEN "T" ELSE "F"),
ENDCASE => (IF b THEN "1" ELSE "0")
)];
};
PutLevel: PROC [ l: Ports.Level, d: Ports.Drive ] = {
st.s.PutRope[(SELECT d FROM
< none => (SELECT l FROM
H => "H",
L => "L",
ENDCASE => "X"),
none => "X",
<= force => (SELECT l FROM
H => "T",
L => "F",
ENDCASE => "X"),
ENDCASE => (SELECT l FROM
H => "1",
L => "0",
ENDCASE => "X")
)];
};
IF p.levelType=composite THEN FOR i: NAT IN [0..p.size) DO
PortToStream[p[i]];
ENDLOOP
ELSE {
SELECT p.levelType FROM
l => PutLevel[p.l, p.d];
ls =>
FOR i: NAT IN [0..p.ls.size) DO
PutLevel[p.ls[i], (IF p.driveType=aggregate THEN p.d ELSE p.ds[i])];
ENDLOOP;
b => PutBool[p.b, p.d];
bs =>
FOR i: NAT IN [0..p.bs.size) DO
PutBool[p.bs[i], (IF p.driveType=aggregate THEN p.d ELSE p.ds[i])];
ENDLOOP;
c =>
FOR i: NAT IN [p.fieldStart..16) DO
PutBool[BitOps.EBFW[p.c, i], p.d];
ENDLOOP;
lc =>
FOR i: NAT IN [p.fieldStart..32) DO
PutBool[BitOps.EBFW[p.lc, i], p.d];
ENDLOOP;
q =>
FOR i: NAT IN [p.fieldStart..64) DO
PutBool[BitOps.EBFW[p.q[i/16], (i MOD 16)], p.d];
ENDLOOP;
ENDCASE => ERROR;
};
};
makeOtherVectors: BOOLFALSE;
Openem: PROC [ name: IO.ROPENIL ] = {
IF makeOtherVectors THEN {
st.s ← FS.StreamOpen[fileName: IO.PutFR["%s.av", IO.rope[IF name.Length = 0 THEN "ArbQuikT" ELSE name]], accessOptions: $create];
st.s.PutF[" %g\n", IO.time[]];
FOR aw: ArbWires IN ArbWires DO
st.s.PutF[" %g [%g]\n", IO.rope[ArbWireNames[aw]],
IO.int[CoreOps.WireBits[st.cellType.public[st.pi[aw]]]]];
ENDLOOP;
st.s.PutRope["\n\n"];
};
};
Closem: PROC = {
IF st.s # NIL THEN {
st.s.Close[];
st.s ← NIL;
};
};
Eval: PROC [ ignoreX: BOOLFALSE ] = {
ENABLE Rosemary.Stop =>
IF ignoreX AND (reason = $BoolWireHasX) THEN RESUME ELSE REJECT;
st.p[st.pi[CKOut]].d ← expect;
st.p[st.pi[CKOut]].b ← st.p[st.pi[Clock]].b;
st.p[st.pi[nBusyIn]].b ← st.p[st.pi[nBusyOut]].b;
st.eval[clockEval: TRUE];
st.eval[clockEval: FALSE];
IF makeOtherVectors AND (st.s # NIL) THEN {
FOR aw: ArbWires IN ArbWires DO
PortToStream[st.p[st.pi[aw]]];
ENDLOOP;
st.s.PutF["\n"];
};
};
EvalIgnoreX: PROC = {
Eval[ignoreX: TRUE];
};
DoClk: PROC [ cycles: INT ← 1, ignoreX: BOOLFALSE ] = {
FOR i: INT IN [0..cycles) DO
st.p[st.pi[Clock]].b ← FALSE;
Eval[ignoreX];
st.p[st.pi[Clock]].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.pi[DBus]].bs[DAddress] ← TRUE;
EvalIgnoreX[];
DDShift[16, val];
st.p[st.pi[DBus]].bs[DAddress] ← FALSE;
EvalIgnoreX[];
};
DDShift: PROC [ size: [1..16], val: BitOps.BitWord ] = {
FOR i: NAT IN [0..size) DO
st.p[st.pi[DBus]].bs[DSerialIn] ← BitOps.EBFW[val, i, size];
st.p[st.pi[DBus]].bs[DShiftCK] ← FALSE;
EvalIgnoreX[];
st.p[st.pi[DBus]].bs[DShiftCK] ← TRUE;
EvalIgnoreX[];
ENDLOOP;
};
DDShiftCheck: PROC [ size: [1..16], valIn: BitOps.BitWord, valOut: BitOps.BitWord ] = {
FOR i: NAT IN [0..size) DO
st.p[st.pi[DBus]].bs[DSerialIn] ← BitOps.EBFW[valIn, i, size];
st.p[st.pi[DBus]].bs[DShiftCK] ← FALSE;
st.p[st.pi[DBus]].bs[DSerialOut] ← BitOps.EBFW[valOut, i, size];
st.p[st.pi[DBus]].ds[DSerialOut] ← expect;
EvalIgnoreX[];
st.p[st.pi[DBus]].ds[DSerialOut] ← none;
st.p[st.pi[DBus]].bs[DShiftCK] ← TRUE;
EvalIgnoreX[];
ENDLOOP;
};
nCheckBits: NAT = 8;
checkBits: BitOps.BitWord = 05AH;
DRCheck: PROC [ width: NAT ] = {
FOR i: NAT IN [0..width+nCheckBits) DO
in: BitOps.BitWord = IF i<nCheckBits THEN BitOps.ECFW[checkBits, i, 1, nCheckBits] ELSE 0;
IF i<width THEN DDShift[1, in]
ELSE DDShiftCheck[1, in, BitOps.ECFW[checkBits, i-width, 1, nCheckBits]];
ENDLOOP;
};
Setup: PROC = {
FOR w: ArbWires IN ArbWires DO
IF st.p[st.pi[w]].d = expect THEN st.p[st.pi[w]].d ← inspect;
IF st.p[st.pi[w]].d = force THEN st.p[st.pi[w]].d ← driveMediumWeak;
ENDLOOP;
FOR i: NAT IN (DSerialOut..DShiftCK] DO
st.p[st.pi[DBus]].ds[i] ← drive;
st.p[st.pi[DBus]].bs[i] ← FALSE;
ENDLOOP;
st.p[st.pi[DBus]].ds[DSerialOut] ← none;
st.p[st.pi[DBus]].bs[DExecute] ← FALSE;
st.p[st.pi[DBus]].bs[nDFreeze] ← TRUE;
st.p[st.pi[DBus]].bs[nDReset] ← FALSE;
st.p[st.pi[DBus]].bs[DSerialIn] ← FALSE;
st.p[st.pi[DBus]].bs[DShiftCK] ← FALSE;
st.p[st.pi[DBus]].bs[DAddress] ← FALSE;
st.p[st.pi[DBus]].bs[DSerialOut] ← TRUE;
st.p[st.pi[DBus]].ds[DSerialOut] ← driveWeak;
FOR i: NAT IN [0..6) DO
st.p[st.pi[TIOBus]].ds[i] ← driveStrong; -- we really don't care about this bus
st.p[st.pi[TIOBus]].bs[i] ← FALSE;
ENDLOOP;
FOR i: NAT IN [0..2) DO
st.p[st.pi[TRec2V]].ds[i] ← drive;
st.p[st.pi[TRec2V]].bs[i] ← TRUE;
ENDLOOP;
st.p[st.pi[TRec2V]].ds[2] ← inspect;
st.p[st.pi[TInv]].ds[0] ← drive;
st.p[st.pi[TInv]].bs[0] ← FALSE;
st.p[st.pi[TInv]].ds[1] ← inspect;
st.p[st.pi[nStopAct]].b ← TRUE;
st.cycle ← 0;
FOR d: Devices IN Devices DO
st.p[st.pi[nRequestOut]][d].c ← 3; -- no request
st.p[st.pi[nRequestOut]][d].d ← drive;
ENDLOOP;
FOR oa: OtherArbiters IN OtherArbiters DO
st.p[st.pi[OtherArbIn]][oa].c ← 7; -- no request
st.p[st.pi[OtherArbIn]][oa].d ← drive;
ENDLOOP;
DoClkIgnoreX[6]; -- allow some X's to relax out
st.p[st.pi[DBus]].bs[DShiftCK] ← TRUE;
st.p[st.pi[nStopAct]].b ← FALSE;
DoClkIgnoreX[6]; -- allow more X's to relax out
};
RunDBusTest: PROC = {
Setup[];
FOR sn: NAT IN [0..16) DO -- try all slot numbers
DAShift[1000H*sn]; -- check signature
FOR a: NAT IN [0..16) DO -- compare
st.p[st.pi[SlotNo]].c ← a;
EvalIgnoreX[];
ENDLOOP;
ENDLOOP;
FOR sn: NAT IN [1..1) DO
a: Arbiters ← (sn+3) MOD 8;
st.p[st.pi[SlotNo]].c ← sn;
DAShift[1000H*sn]; -- check signature
DDShiftCheck[16, 0, 5041H];
Check out the two ways of doing hybrid select: decoded and encoded
DAShift[1000H*sn+1]; -- check DevPriority
DRCheck[72];
DAShift[1000H*sn+2]; -- load arbiter number
DRCheck[4];
DDShift[4, 2*a+1]; -- decoded hybrid select
DAShift[1000H*sn+300H]; -- address hybrid 3
st.p[st.pi[nDHybridSel]].d ← expect;
st.p[st.pi[nDHybridSel]].c ← 01FH-4; -- decoded
EvalIgnoreX[];
st.p[st.pi[nDHybridSel]].d ← none;
DAShift[1000H*sn+2]; -- load arbiter number
DDShift[4, 2*a]; -- now encoded
DAShift[08000H+1000H*a+300H]; -- address hybrid 3
st.p[st.pi[nDHybridSel]].d ← expect;
st.p[st.pi[nDHybridSel]].c ← 01FH-6; -- encoded, 5 bits
EvalIgnoreX[];
st.p[st.pi[nDHybridSel]].d ← none;
st.p[st.pi[BdVersion]].c ← 2;
DAShift[1000H*sn+400H]; -- address hybrid 4
DDShift[1, 0]; -- load BdVersion shadow
DAShift[1000H*sn+3H]; -- read the board version
DDShiftCheck[2, 0, 2];
st.p[st.pi[BdVersion]].c ← 1;
DAShift[1000H*sn+400H]; -- address hybrid 4
DDShift[1, 0]; -- load BdVersion shadow
DAShift[1000H*sn+3H]; -- read the board version
DDShiftCheck[2, 0, 1];
ENDLOOP;
};
RunLocalGrantTest: PROC = {
sn: NAT ← 1;
a: Arbiters ← (sn+3) MOD 8;
stopCycle: INT;
Setup[];
st.p[st.pi[SlotNo]].c ← sn;
DAShift[1000H*sn+1]; -- load DevPriority
FOR d: Devices IN Devices DO
DDShift[9, 031H]; -- all the same priority
ENDLOOP;
DAShift[1000H*sn+2]; -- load arbiter number
DDShift[4, 2*a+1]; -- decoded hybrid select
DoClkIgnoreX[5];
st.p[st.pi[DBus]].bs[nDReset] ← TRUE; -- end of main reset
DoClk[5];
st.p[st.pi[nStopAct]].b ← TRUE; -- end of arbiter reset
DoClk[10];
FOR d: Devices IN Devices DO
st.p[st.pi[nRequestOut]][d].c ← 0; -- high request
ENDLOOP;
DoClk[6];
FOR d: Devices IN Devices DO
st.p[st.pi[nRequestOut]][d].c ← 1; -- low request
ENDLOOP;
DoClk[6];
FOR d: Devices IN Devices DO
st.p[st.pi[nRequestOut]][d].c ← 3; -- no request
ENDLOOP;
stopCycle ← st.cycle+30;
WHILE stopCycle > st.cycle DO
DoClk[1];
IF NOT st.p[st.pi[nStartGrant]].b THEN stopCycle ← st.cycle+30;
ENDLOOP;
};
RunGlobalGrantTest: PROC = {
sn: NAT ← 1;
a: Arbiters ← (sn+3) MOD 8;
stopCycle: INT;
Setup[];
st.p[st.pi[SlotNo]].c ← sn;
DAShift[1000H*sn+1]; -- load DevPriority
FOR d: Devices IN Devices DO
DDShift[9, 031H]; -- all the same priority
ENDLOOP;
DAShift[1000H*sn+2]; -- load arbiter number
DDShift[4, 2*a+1]; -- decoded hybrid select
DoClkIgnoreX[5];
st.p[st.pi[DBus]].bs[nDReset] ← TRUE; -- end of main reset
DoClk[5];
st.p[st.pi[nStopAct]].b ← TRUE; -- end of arbiter reset
DoClk[10];
FOR oa: OtherArbiters IN OtherArbiters DO
st.p[st.pi[OtherArbIn]][oa].c ← 0; -- high priority request
ENDLOOP;
st.p[st.pi[nRequestOut]][0].c ← 0; -- high request
DoClk[6];
st.p[st.pi[nRequestOut]][0].c ← 1; -- low request
DoClk[6];
st.p[st.pi[nRequestOut]][0].c ← 3; -- no request
DoClk[80];
FOR oa: OtherArbiters IN OtherArbiters DO
st.p[st.pi[OtherArbIn]][oa].c ← 1; -- in-between priority request
ENDLOOP;
stopCycle ← st.cycle+10;
WHILE stopCycle > st.cycle DO
DoClk[1];
IF NOT st.p[st.pi[nStartGrant]].b THEN stopCycle ← st.cycle+10;
ENDLOOP;
FOR oa: OtherArbiters IN OtherArbiters DO
st.p[st.pi[OtherArbIn]][oa].c ← 4; -- low priority request
ENDLOOP;
DoClk[50];
FOR oa: OtherArbiters IN OtherArbiters DO
st.p[st.pi[OtherArbIn]][oa].c ← 5; -- very low priority request
ENDLOOP;
stopCycle ← st.cycle+10;
WHILE stopCycle > st.cycle DO
DoClk[1];
IF NOT st.p[st.pi[nStartGrant]].b THEN stopCycle ← st.cycle+10;
ENDLOOP;
};
ArbDBus: ENTRY RosemaryUser.TestProc = {
ENABLE UNWIND => Closem[];
st ← GetAllState[cellType, p, Eval];
Openem[];
CedarProcess.DoWithPriority[priority: background, action: RunDBusTest];
Closem[]};
LocalGrants: ENTRY RosemaryUser.TestProc = {
ENABLE UNWIND => Closem[];
st ← GetAllState[cellType, p, Eval];
CedarProcess.DoWithPriority[priority: background, action: RunLocalGrantTest];
Openem[];
Closem[]};
GlobalGrants: ENTRY RosemaryUser.TestProc = {
ENABLE UNWIND => Closem[];
st ← GetAllState[cellType, p, Eval];
CedarProcess.DoWithPriority[priority: background, action: RunGlobalGrantTest];
Openem[];
Closem[]};
RosemaryUser.RegisterTestProc["ArbDBus", ArbDBus];
RosemaryUser.RegisterTestProc["LocalGrants", LocalGrants];
RosemaryUser.RegisterTestProc["GlobalGrants", GlobalGrants];
END.