TestMC.mesa
Copyright © 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
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];
CaptureVectors[h];
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];
RandomTest[h, Eval, ramdomOps];
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]];
--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
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.