TestMI.mesa
Copyright © 1987 by Xerox Corporation. All rights reserved.
Krivacic, March 5, 1987 1:33:42 pm PST
Last Edited by: Krivacic March 30, 1987 12:47:59 pm PST
Last Edited by: Bell March 10, 1987 12:28:56 pm PST
DIRECTORY CDCommandOps, CDSequencer, CDProperties, Core, CoreCreate, CoreFlat, Ports, Rope, Rosemary, RosemaryUser, Sisyph, CoreClasses, Basics, BitOps, MIPadFrame, Random;
TestMI: CEDAR PROGRAM
IMPORTS
-- CoreFlat,
CDCommandOps, CDSequencer, CDProperties, CoreCreate, CoreClasses, Ports, Rosemary, RosemaryUser, Sisyph, Basics, BitOps, MIPadFrame, Random
= BEGIN
Binding
XA, XD,
XIOWbar, XIORbar, XCEbar,
XIORDY, XHOSTRESET, XLPRESET, XHOLD, XHOLDA, XPIRQ, XXIRQ0,
XPA, XWENTbar, XWENWbar, XCASbar, XRASbar, XRASXbar, XMEMRDY,
XCLOCK2, XHINT,
XPD, XPDTAG, XPDHI, XPDWP, XPDTP,
Vdd, Gnd, PadVdd, PadGnd: NATLAST[NAT];
-- Special Constants & Addresses
memoryoffset: NAT4000H;
statusregreset: NAT1300H;
statusregnorm: NAT0000H;
laststatus: CARD ← 0;
addrlatch: NAT5004H;
lastaddr, curriopaddr: CARD ← 0;
refreshlatch: NAT5002H;
lastrefresh, refreshcount: CARD ← 0;
refreshcycle, refreshhold, refreshrq, refreshinprogress: BOOLFALSE;
statuslatch: NAT5000H;
ILIST: TYPE = LIST OF CARD;
oddclock, statusignore: BOOL;
lastpd: CARD ← 0;
innerCell: Core.CellType;
outerCell: Core.CellType;
outerset: BOOLFALSE;
rs: Random.RandomStream;
MIInitPortIndicies: PROC [p: Core.Wire] ~ {
[XA, XD, XIOWbar, XIORbar, XCEbar, XIORDY, XHOSTRESET, XLPRESET, XHOLD, XHOLDA, XPIRQ, XXIRQ0] ←
Ports.PortIndexes[p, "XA", "XD", "XIOW'", "XIOR'", "XCE'", "XIORDY", "XHOSTRESET", "XLPRESET", "XHOLD", "XHOLDA", "XPIRQ", "XXIRQ0"];
[XPA, XWENTbar, XWENWbar, XCASbar, XRASbar, XRASXbar, XMEMRDY,] ←
Ports.PortIndexes[p, "XPA", "XWENT'", "XWENW'", "XCAS'", "XRAS'", "XRASX'", "XMEMRDY"];
[XCLOCK2, XHINT] ← Ports.PortIndexes[p, "XCLOCK2", "XHINT"];
[XPD, XPDTAG, XPDHI, XPDWP, XPDTP] ←
Ports.PortIndexes[p, "XPD", "XPDTAG", "XPDHI", "XPDWP", "XPDTP"];
[Vdd, Gnd, PadVdd, PadGnd] ← Ports.PortIndexes[p, "Vdd", "Gnd", "PadVdd", "PadGnd"];
};
MISetupInit: PROC [public: Core.Wire] = {
MIInitPortIndicies[public];
IPList[public, LIST[XCLOCK2], l, force];
IPList[public, LIST[
XIOWbar, XIORbar, XCEbar, XIORDY, XHOSTRESET, XLPRESET, XHOLD,
XHOLDA, XPIRQ, XXIRQ0, XWENTbar, XWENWbar, XCASbar, XRASXbar, XMEMRDY,
XPDWP, XPDTP], l, none];
IPList[public, LIST[
XA, XPA, XRASbar, XD, XPDTAG, XPDHI, XPD], ls, none];
[] ← Rosemary.SetFixedWire[public[Vdd], H];
[] ← Rosemary.SetFixedWire[public[Gnd], L];
[] ← Rosemary.SetFixedWire[public[PadGnd], L];
[] ← Rosemary.SetFixedWire[public[PadVdd], H];
};
Structure
MI: PUBLIC PROC RETURNS [cellType: CoreCreate.CellType] = {
public: Core.Wire ← CoreCreate.WireList[LIST[
"XA", "XD", "XIOW'", "XIOR'", "XCE'", "XIORDY", "XHOSTRESET", "XLPRESET", "XHOLD", "XHOLDA", "XPIRQ", "XXIRQ0", "XPA", "XWENT'", "XWENW'", "XCAS'", "XRAS'", "XRASX'", "XMEMRDY", "XCLOCK2", "XHINT", "XPDWP", "XPDTP",
CoreCreate.Seq["XA", 16],
CoreCreate.Seq["XD", 16],
CoreCreate.Seq["XPA", 12],
CoreCreate.Seq["XRAS", 4],
CoreCreate.Seq["XPD", 32],
CoreCreate.Seq["XPDTAG", 2],
CoreCreate.Seq["XPDHI", 6],
"Vdd", "Gnd"]];
cellType ← CoreClasses.CreateUnspecified[name: "MI", public: public];
};
Test
InitializeTest: PROC ~ {
outerset ← FALSE;
CDSequencer.ImplementCommand[key: $MIExtractAndSimulate, proc: MIExtractAndSimulate, queue: doQueue];
CDCommandOps.RegisterWithMenu[menu: $ProgramMenu, entry: "Extract *& Simulate MI", key: $MIExtractAndSimulate];
CDSequencer.ImplementCommand[key: $MISimulate, proc: MISetCellMISimulate, queue: doQueue];
CDCommandOps.RegisterWithMenu[menu: $ProgramMenu, entry: "Simulate MI", key: $MISimulate];
RosemaryUser.RegisterTestProc["MITest", MITest]; 
};
RemakePads: PROC = {outerCell← MIPadFrame.CreateWholeChip[innerCell];};
MISetOuter: PROC [ct: Core.CellType] = {
outerCell ← ct;
outerset ← TRUE;
};
MISetCellMISimulate: PROC [comm: CDSequencer.Command] ~ {
IF ~outerset THEN ERROR;
CDProperties.PutDesignProp[comm.design, $DAUserRoseDisplay, MISimulate[outerCell, "MI Layout Simulate"].display];
};
MIExtractAndSimulate: PROC [comm: CDSequencer.Command] ~ {
innerCell ← Sisyph.ExtractSchematicByName["MIInner.sch", Sisyph.Create[comm.design]];
RemakePads[];
CDProperties.PutDesignProp[comm.design, $DAUserRoseDisplay, MISimulate[outerCell, "MI Schematic Simulate"].display];
};
MISimulate: PROC [cellType: Core.CellType, title: Rope.ROPE] RETURNS [tester: RosemaryUser.Tester]~ {
public: Core.Wire ← cellType.public;
MISetupInit[public];
tester ← RosemaryUser.TestProcedureViewer[
cellType: cellType,
testButtons: LIST["MITest"],
name: title,
-- graphWires: x CoreFlat.CreateFlatWires
-- cutSet: CoreFlat.CreateCutSet[labels: LIST["Logic","LogicMacro"]]
displayWires: RosemaryUser.DisplayPortLeafWires[cellType]
];
};
MITest: RosemaryUser.TestProc ~ {
PROC [cellType: Core.CellType, p: Ports.Port, Eval: PROC]
SwapBits: PROC[value: BitOps.BitWord] RETURNS [newvalue: BitOps.BitWord] = {
oldc: BitOps.BitWord ← value;
newvalue ← 0;
FOR i: NAT ← 0, i+1 WHILE i < 16 DO
newvalue ← BitOps.IBIW[BitOps.EBFW[oldc, i, 16], newvalue, 15-i, 16];
ENDLOOP;
};
Parityof: PROC [value: CARD, size: NAT] RETURNS [bit: NAT] = {
p: BitOps.BitWord ← 0;
FOR i: NAT ← 0, i + 1 WHILE i < size DO
p ← BitOps.WXOR[p, BitOps.ECFD[value, i, 1, size]];
ENDLOOP;
bit ← p;
};
HiParity: PROC[hival: CARD] RETURNS [p: NAT] = {
p ← Parityof[hival, 6];
};
DataParity: PROC[data, tag: CARD]RETURNS [p: NAT] = {
p ← BitOps.WXOR[Parityof[data, 32], Parityof[tag, 2]];
};
SetPVal: PROC [port, value: CARD] = {
IF (port = XA) OR (port = XD) THEN value ← SwapBits[value];
SELECT p[port].levelType FROM
l => p[port].l ← IF value=0 THEN L ELSE H;
ls => Ports.LCToLS[value, p[port].ls];
c => p[port].c ← value;
lc => p[port].lc ← value;
b =>
SELECT value FROM
0 => p[port].b ← FALSE;
1 => p[port].b ← TRUE;
ENDCASE => ERROR;
ENDCASE => ERROR;
};
RasDecode: PROC [rasval: NAT] RETURNS [NAT] = {
RETURN[
IF refreshinprogress THEN 0
ELSE
SELECT rasval FROM
0 => 0EH,
1 => 0DH,
2 => 0BH,
3 => 07H,
7 => 0FH,
ENDCASE => ERROR];
};
RasXDecode: PROC [rasval: NAT] RETURNS [NAT] = {
RETURN[
IF refreshinprogress THEN 1
ELSE
SELECT rasval FROM
0 => 01H,
1 => 01H,
2 => 01H,
3 => 01H,
7 => 00H,
ENDCASE => ERROR];
};
SetP: PROC [port, value: CARD] = {
SetPVal[port, value];
p[port].d ← force;
IF port = XA THEN curriopaddr ← value;
IF port = XPD THEN lastpd ← value;
};
ClrP: PROC [port: CARD] = {
SELECT p[port].levelType FROM
l => p[port].l ← X;
ls => Ports.SetLS[p[port].ls, X];
c => p[port].c ← 0;
lc => p[port].lc ← 0;
b => p[port].b ← FALSE;
ENDCASE => ERROR;
p[port].d ← none;
};
ChkP: PROC [port, value: CARD] = {
SetPVal[port, value];
p[port].d ← expect;
};
ChkX: PROC [port: CARD] = {
ClrP[port];
p[port].d ← expect;
};
GoClock: PROC [cycles: NAT ← 1, extraEval: BOOLFALSE] = {
saveddrives: ARRAY [0..50] OF Ports.Drive;
ExpectsOff: PROC = {
FOR i: NAT ← 0, i + 1 WHILE i < p.size DO { -- Turn off Expects
saveddrives[i] ← p[i].d;
IF p[i].d = expect THEN p[i].d ← none;
};
ENDLOOP;
};
ExpectsOn: PROC = {
FOR i: NAT ← 0, i + 1 WHILE i < p.size DO-- Turn on Expects
p[i].d ← saveddrives[i];
ENDLOOP;
};
FOR i: NAT ← 0, i + 1 WHILE i < cycles DO { -- Do clock cycles
IF refreshcycle AND ~refreshhold THEN {
refreshhold ← TRUE;
refreshinprogress ← TRUE;
ClockMemory1[3, 2, 0, 0];
ClockMemory2[FALSE, FALSE];
ClockMemory3[0];
ClockMemory4[];
GoClock[3];
refreshcycle ← FALSE;
refreshhold ← FALSE;
refreshrq ← FALSE;
refreshinprogress ← FALSE;
};
ExpectsOff[];   -- checks off
IF extraEval THEN Eval[];  -- Setup Values
extraEval ← FALSE;
SetP[XCLOCK2,0];   -- clock 0
Eval[];    -- Setup Values
ExpectsOn[];   -- Turn on expects
SetP[XCLOCK2,1];   -- clock 1
Eval[];
oddclock ← ~oddclock;
IF refreshrq AND ~refreshcycle THEN refreshcycle ← TRUE;
IF (BitOps.WAND[lastrefresh, 8000H] # 0) AND ~oddclock THEN {
refreshcount ← refreshcount - 1;
IF refreshcount = 0 THEN {
refreshrq ← TRUE;
refreshcount ← BitOps.WAND[lastrefresh, 0FFFH] + 1;
};
};
};
ENDLOOP;
};
SyncClock: PROC = {
IF oddclock THEN GoClock[];
};
WriteLatch: PROC [addr, value: CARD] = {
-- Write value to the indicated MI latch
SetP[XA, addr];
SetP[XIOWbar, 1];
SetP[XD, value];
SetP[XIORDY, 1];
GoClock[1, addr = statuslatch];
SetP[XIOWbar, 0];
SetP[XCEbar, 0];
ChkP[XIORDY, 1];
GoClock[];
SetP[XIOWbar, 1];
SetP[XCEbar, 1];
ClrP[XIORDY];
GoClock[];
ClrP[XD];
ClrP[XA];
IF addr = statuslatch THEN laststatus ← value; -- save last status
IF addr = addrlatch THEN lastaddr ← value; -- save last addr
IF addr = refreshlatch THEN {
lastrefresh ← value;   -- save last refresh
refreshcount ← BitOps.WAND[lastrefresh, 0FFFH] + 1; -- init refresh counter
refreshrq ← BitOps.WAND[lastrefresh, 8000H] # 0;
};
};
ReadLatch: PROC [addr, value: CARD] = {
-- Read value from the indicated MI latch & compare with expected value
SetP[XA, addr];
SetP[XIORbar,1];
SetP[XIORDY,1];
GoClock[];
SetP[XIORbar,0];
SetP[XCEbar, 0];
ChkP[XD,value];
IF (addr = statuslatch) AND statusignore THEN
FOR i: NAT IN [14..15] DO p[XD].ls[i] ← X; ENDLOOP;
ChkP[XIORDY, 1];
GoClock[];
ClrP[XD];
ClrP[XA];
SetP[XIORbar,1];
SetP[XCEbar, 1];
ClrP[XIORDY];
GoClock[];
};
ClockMemory1: PROC [delay1, delay2, holddelay: NAT, casval: NAT ← 1] = {
-- Clock Through the sequencer of a memory operation
-- Get to Hold logic & delay HOLDA for holddelay
ChkP[XWENTbar, 1];
ChkP[XWENWbar, 1];
GoClock[delay1-1];
ChkP[XHOLD, 1];
GoClock[];
IF Basics.BITAND[laststatus, 8] = 0 THEN {
FOR i: NAT ← holddelay, i - 1 WHILE i > 0 DO GoClock[]; ENDLOOP;
SetP[XHOLDA, 1];
};
GoClock[delay2-1];
ChkP[XCASbar, casval];
GoClock[];
};
CasPA: PROC RETURNS[CARD] = {
RETURN[
Basics.DoubleOr[
Basics.DoubleAnd[
Basics.DoubleShiftRight[[lc[curriopaddr]], 2],
[li[01FFH]]],
Basics.DoubleAnd[
Basics.DoubleShiftLeft[[lc[lastaddr]], 9],
[li[0200H]]]
].lc];
};
RasPA: PROC RETURNS[CARD] = {
RETURN[
Basics.DoubleAnd[
Basics.DoubleShiftRight[[lc[lastaddr]], 1],
[li[03FFH]]].lc];
};
ClockMemory2: PROC [checkwe: BOOLFALSE, do2ndclock: BOOLTRUE] = {
rasval: NAT ← Basics.DoubleAnd[Basics.DoubleShiftRight[[lc[lastaddr]], 11], [li[07H]]].lc;
rasdecodedval: NAT ← RasDecode[rasval];
-- Check for RAS & Ras Address
ChkP[XRASbar, rasdecodedval];
ChkP[XRASXbar, RasXDecode[rasval]];
ChkP[XPA, IF rasval = 7 THEN CasPA[] ELSE RasPA[]];
GoClock[];
ClrP[XPA];    -- PA only on 1st RAS'
IF checkwe THEN    -- Check WE on a write
{ ChkP[XWENTbar, 0]; ChkP[XWENWbar, 0]; };
IF do2ndclock THEN GoClock[];
};
ClockMemory3: PROC [memdelay: NAT] = {
Check for CAS & Cas Address
ChkP[XCASbar, 0];
ChkP[XPA, CasPA[]];
SetP[XMEMRDY, IF memdelay = 0 THEN 1 ELSE 0];
GoClock[];
IF p[XRASXbar].l = H THEN ClrP[XPA]; -- Only 1 PA on CAS'
-- Test for MEMRDY delay
IF memdelay # 0 THEN {
FOR i: NAT ← memdelay, i - 1 WHILE i > 0 DO GoClock[]; ENDLOOP;
SetP[XMEMRDY, 1];
IF BitOps.WAND[memdelay, 1] = 1 THEN GoClock[];
};
-- Clear CAS' / RAS' / PA / RASX' / PD
ClrP[XIORDY];
ClrP[XCASbar];
ClrP[XRASbar];
ClrP[XRASXbar];
ClrP[XPD];
ClrP[XPDTAG];
ClrP[XPDHI];
ClrP[XPA];
ClrP[XPDTP];
ClrP[XPDWP];
ClrP[XWENTbar];
ClrP[XWENWbar];
ClrP[XHOLD];
GoClock[];
};
ClockMemory4: PROC = {
SetP[XIORDY, 1];
SetP[XIORbar, 1];
SetP[XIOWbar, 1];
SetP[XCEbar, 1];
ClrP[XD];
ClrP[XA];
SetP[XHOLDA, 0];
GoClock[];
ChkP[XWENTbar, 1];
ChkP[XWENWbar, 1];
ChkP[XIORDY, 1];
GoClock[];
ClrP[XIORDY];
ClrP[XWENTbar];
ClrP[XWENWbar];
};
ReadMemory: PROC [addr, memval, hival: CARD, hibyte, badhiparity, baddataparity: BOOLFALSE, holddelay, memdelay: NAT ← 0] = {
wordsel: CARD
Basics.DoubleAnd[Basics.DoubleShiftRight[[lc[addr]], 1],
[li[1]]].lc;
rsltval: CARD
IF hibyte THEN hival
ELSE
Basics.DoubleAnd[
Basics.DoubleShiftRight[[lc[memval]], IF wordsel = 1 THEN 16 ELSE 0],
[lc[0FFFFH]]].lc;
tagval: CARD ← Basics.DoubleAnd[[lc[hival]], [li[3]]].lc;
delay1: NAT ← 4 + Basics.BITAND[holddelay, 1];
delay2: NAT ← 2;
newaddr: CARD ← Basics.DoubleShiftRight[[lc[addr]], 11].lc;
hival ← Basics.DoubleShiftRight[[lc[hival]], 2].lc;
-- Set Latch with Upper part of address & Status Reg
IF lastaddr # newaddr THEN WriteLatch[addrlatch, newaddr];
IF hibyte THEN WriteLatch[statuslatch, Basics.DoubleOr[[lc[laststatus]], [lc[1]]].lc]
ELSE WriteLatch[statuslatch, Basics.DoubleAnd[[lc[laststatus]], [lc[0FFFEH]]].lc];
Sync Clock
SyncClock[];
-- Do Memory Read, Setup Chip Select & Address
SetP[XHOLDA, 0];
SetP[XCEbar, 0];
SetP[XA, Basics.DoubleAnd[[lc[addr]],[li[07FFH]]].lc];
GoClock[];
SetP[XIORbar, 0];
ChkP[XIORDY, 0];
refreshhold ← TRUE;
-- Get through 1st clocking sequence
ClockMemory1[delay1, delay2, holddelay];
ClockMemory2[];
Set up values to read
SetP[XPD, memval];
SetP[XPDTAG, tagval];
SetP[XPDHI, hival];
SetP[XPDTP, BitOps.WXOR[HiParity[hival], LOOPHOLE[badhiparity]]];
SetP[XPDWP, BitOps.WXOR[DataParity[memval, tagval], LOOPHOLE[baddataparity]]];
-- Get through Cas' clocking sequence
ClockMemory3[memdelay];
-- Check for returned data
ChkP[XD, rsltval];
GoClock[2];
ClockMemory4[];
refreshhold ← FALSE;
};
WriteMemory: PROC [addr, memval, hival, writeval: CARD, hibyte, badhiparity, baddataparity: BOOLFALSE, holddelay, memdelay: NAT ← 0] = {
wordsel: CARD
Basics.DoubleAnd[Basics.DoubleShiftRight[[lc[addr]], 1],
[li[1]]].lc;
newmemval: CARD;
newhival, newtagval: CARD;
ioop: BOOLFALSE;
tagval: CARD
Basics.DoubleAnd[[lc[hival]], [li[3]]].lc;
delay1: NAT ← 4 + Basics.BITAND[holddelay, 1];
delay2: NAT ← 2;
newaddr: CARD ← Basics.DoubleShiftRight[[lc[addr]], 11].lc;
hival ← Basics.DoubleShiftRight[[lc[hival]], 2].lc;
newhival ← hival;
newtagval ← tagval;
IF hibyte THEN {
newhival ← Basics.DoubleShiftRight[
Basics.DoubleAnd[ [lc[writeval]], [lc[0FCH]]], 2].lc;
newtagval ← Basics.DoubleAnd[ [lc[writeval]], [lc[3H]]].lc;
};
-- Set Latch with Upper part of address & Status Reg
IF lastaddr # newaddr THEN WriteLatch[addrlatch, newaddr];
IF hibyte THEN WriteLatch[statuslatch, Basics.DoubleOr[[lc[laststatus]], [lc[1]]].lc]
ELSE WriteLatch[statuslatch, Basics.DoubleAnd[[lc[laststatus]], [lc[0FFFEH]]].lc];
ioop ← RasXDecode[Basics.DoubleAnd[Basics.DoubleShiftRight[[lc[lastaddr]], 11], [li[07H]]].lc] # 1;
Sync Clock
SyncClock[];
-- Do Memory Read
SetP[XCEbar, 0];
SetP[XHOLDA, 0];
SetP[XA, Basics.DoubleAnd[[lc[addr]],[li[07FFH]]].lc];
GoClock[];
ChkP[XIORDY, 0];
SetP[XIOWbar,0];
SetP[XD, writeval];
refreshhold ← TRUE;
ClockMemory1[delay1, delay2, holddelay];
IF~ ioop THEN {
-- Read Word Before Writing, unless an IO operation
ClockMemory2[];
-- Set Values to Read
SetP[XPD, memval];
SetP[XPDTAG, tagval];
SetP[XPDHI, hival];
SetP[XPDTP, BitOps.WXOR[HiParity[hival], LOOPHOLE[badhiparity]]];
SetP[XPDWP, BitOps.WXOR[DataParity[memval, tagval], LOOPHOLE[baddataparity]]];
-- Check for CAS & Cas Address
ClockMemory3[memdelay];
GoClock[2];
};
-- 3. WRITE Merged word ------------------------------------
-- Check for RAS & Ras Address
ClockMemory2[TRUE];
-- Check for CAS & Cas Address, data written
newmemval ←
IF hibyte THEN lastpd
ELSE
Basics.DoubleOr[
Basics.DoubleAnd[ [lc[lastpd]],
Basics.DoubleShiftLeft[[lc[0FFFFH]], IF wordsel = 1 THEN 0 ELSE 16]],
Basics.DoubleShiftLeft[[lc[writeval]], IF wordsel = 1 THEN 16 ELSE 0]].lc;
ChkP[XPD, newmemval];
IF ~ ioop THEN {
ChkP[XPDTAG, newtagval];
ChkP[XPDHI, newhival];
ChkP[XPDTP, HiParity[newhival]];
ChkP[XPDWP, DataParity[newmemval, newtagval]];
};
ClockMemory3[memdelay];
4. Clear time ---------------------------------------------
ClockMemory4[];
GoClock[3];
refreshhold ← FALSE;
};
ChipReady: PROC = {
-- Set all pads of the chip so it is ready for input
& remove x's from the chip.
oddclock ← FALSE;
statusignore ← TRUE;
refreshcycle ← FALSE;
refreshhold ← FALSE;
refreshrq ← FALSE;
refreshinprogress ← FALSE;
lastrefresh ← 0;
refreshcount ← 0;
SetP[Gnd, 0];
SetP[Vdd, 1];
SetP[PadGnd, 0];
SetP[PadVdd, 1];
p[Vdd].b ← TRUE;
p[PadVdd].b ← TRUE;
-- Set IOP side 1st
SetP[XA, 0];
SetP[XD, 0];
SetP[XIOWbar, 1];
SetP[XIORbar, 1];
SetP[XCEbar, 1];
ClrP[XIORDY];
SetP[XHOSTRESET, 1];
ClrP[XHINT];
-- Set MI to LP pins
ClrP[XLPRESET];
ClrP[XHOLD];
SetP[XHOLDA, 0];
SetP[XPIRQ, 0];
ClrP[XXIRQ0];
-- Set Memory Pins
ClrP[XPDWP];
ClrP[XPDTP];
ClrP[XPDTAG];
ClrP[XPDHI];
ClrP[XPD];
-- Set Memory Control Pins
ClrP[XCASbar];
ClrP[XRASbar];
ClrP[XRASXbar];
ClrP[XPA];
SetP[XMEMRDY, 1];
ClrP[XWENTbar];
ClrP[XWENWbar];
-- Clock Pins
GoClock[4];
clear reset
Set the Latches
WriteLatch[statuslatch, 0800H];
GoClock[2];
SetP[XHOSTRESET, 0];
GoClock[12, TRUE];
ChkP[XLPRESET, 1];   -- Check for LPRESET = 1
WriteLatch[refreshlatch, 0];  -- Clear refresh counter
WriteLatch[addrlatch, 0];   -- Clear address latch
ClrP[XLPRESET];   -- Don't for LPRESET
WriteLatch[statuslatch, 1000H];  -- Clear LPRESET
GoClock[4];
ChkP[XLPRESET, 0];   -- Check for LPRESET = 0
WriteLatch[statuslatch, statusregreset];
ClrP[XLPRESET];   -- Don't for LPRESET
statusignore ← FALSE;
ReadLatch[statuslatch, statusregreset];  -- Read Status Reg
ReadLatch[refreshlatch, 0];  -- Read refreshcounter
ReadLatch[addrlatch, 0];   -- Read address latch
ReadMemory[0, 0, 0];   -- Clear Parity Errors
ReadMemory[1C00010H, 0, 0];  -- Read IO port
WriteMemory[1C00010H, 0, 0, 0];  -- Write IO port
WriteLatch[statuslatch, statusregreset]; -- Write Status Reg
};
ChkNClk: PROC [port, value: CARD] = {
ChkP[port, value];
GoClock[];
ClrP[port];
};
TestStatReg: PROC = {
-- Test Bits in Status Regs
bits: 0 - Tag Parity Error
 1 - Data Parity Error
 2 - PIRQ
 3 - Reset LPRESET
 4 - Set LPRESET
 5 - Enable Parity IRQ
 6 - Reset PIRQ
 7 - Reset Parity Error
 8 - Enable PIRQ
 12- Hold Ignore
 13- Dint2 (XIRQ1)
 14- XIRQ0
 15- Hi Byte Select
-- Test XIRQ0
WriteLatch[statuslatch, statusregreset];
WriteLatch[statuslatch, 2];  -- Set XIRQ0
ChkP[XXIRQ0, 1];   -- Check for XIRQ0 = 1
GoClock[];
ClrP[XXIRQ0];
WriteLatch[statuslatch, statusregreset];
ChkP[XXIRQ0, 0];   -- Check for XIRQ0 = 0
GoClock[];
ClrP[XXIRQ0];
Test PIRQ logic
SetP[XPIRQ, 0];
WriteLatch[statuslatch, 0200H];  -- Clr PIRQ bit
ReadLatch[statuslatch, 0200H];  -- Latch should be clear
WriteLatch[statuslatch, 0080H];  -- Enable PIRQ
SetP[XPIRQ, 1];   -- Set PIRQ
GoClock[];
ChkP[XHINT, 1];
ReadLatch[statuslatch, 2080H];  -- Should have PIRQ & HINT
ClrP[XHINT];
SetP[XPIRQ, 0];
GoClock[];
ReadLatch[statuslatch, 2080H];  -- Should Still have PIRQ & HINT
WriteLatch[statuslatch, 0200H];  -- Clr PIRQ bit
ChkP[XHINT, 0];
GoClock[];
ReadLatch[statuslatch, 0200H];  -- Latch & HINT should be clear
WriteLatch[statuslatch, 0000H];  -- Clr Latch
SetP[XPIRQ, 1];   -- Set PIRQ
GoClock[];
ReadLatch[statuslatch, 2000H];  -- Should have PIRQ but no HINT
SetP[XPIRQ, 0];
ClrP[XHINT];
WriteLatch[statuslatch, statusregreset];
};
TestRefresh: PROC = {
-- Refresh Count Register:
Bit: 0 - Enale Refresh Counter
 4-15 Refresh Counter
Test Refresh Cycles
WriteLatch[refreshlatch, 8010H];
GoClock[100];
WriteLatch[refreshlatch, 0000H];
WriteLatch[refreshlatch, 8040H];
FOR i: NAT ← 0, i+1 WHILE i < 10 DO {
ReadMemory[0, 0, 0];
GoClock[30];
};
ENDLOOP;
-- WriteLatch[refreshlatch, 0000H];
};
TestLatches: PROC = {
-- Test Ability to Read / Write Internal Latches
ReadMemory[0, 0, 0];
WriteLatch[statuslatch, statusregreset];
-- Test Status Reg
FOR val: ILISTLIST [0, 1, 2, 4, 8, 16, 32, 64, 128,
100H, 200H, 400H,
statusregreset], val.rest
WHILE val # NIL DO
WriteLatch[statuslatch, val.first];
ReadLatch[statuslatch, val.first];
ENDLOOP;
-- Test Refresh Count Reg
FOR val: ILISTLIST[0, 1, 2, 4, 8, 16, 32, 64, 128, 255, 100H, 200H, 400H, 800H], val.rest WHILE val # NIL DO
WriteLatch[refreshlatch, val.first];
ReadLatch[refreshlatch, val.first];
ENDLOOP;
-- Test Address Latch
FOR val: ILISTLIST[0, 1, 2, 4, 8, 16, 32, 64, 128, 255,
100H, 200H, 400H, 800H, 1000H, 2000H, 4000H, 8000H, 0FF00H, 0FFFFH], val.rest WHILE val # NIL DO
WriteLatch[addrlatch, val.first];
ReadLatch[addrlatch, val.first];
ENDLOOP;
Test Bits in Status Regs
TestStatReg[];
WriteLatch[statuslatch, statusregreset];
ReadMemory[0, 0, 0];
WriteLatch[statuslatch, statusregreset];
TestRefresh[];
WriteLatch[statuslatch, statusregreset];
WriteLatch[statuslatch, statusregnorm];
WriteLatch[refreshlatch, 0];
};
RandomMemoryTest: PROC = {
addr: CARD;
RandomBool: PROC RETURNS [BOOL] = {
RETURN[IF Random.ChooseInt[rs, 0, 1] = 0 THEN FALSE ELSE TRUE]};
RandomCard: PROC [hi: CARD, alt: CARD ← 0] RETURNS [CARD] = {
IF (alt # 0) AND (Random.ChooseInt[rs, 0, 15] = 15) THEN RETURN[alt]
ELSE
RETURN[
Basics.DoubleOr[
Basics.DoubleShiftLeft[
[lc[Random.ChooseInt[rs, 0, Basics.DoubleShiftRight[ [lc[hi]], 16].lc ] ]],
16],
Basics.DoubleAnd[
[lc[Random.ChooseInt[rs, 0, Basics.DoubleAnd[ [lc[hi]], [lc[0FFFFH]] ].lc] ]],
[lc[0FFFFH]] ]
].lc
]
};
rs ← Random.Create[];
FOR i: CARD ← 0, i + 1
WHILE i < 100 DO
addr ← RandomCard[08FFFFFH, 1C00000H];
IF RandomBool[] THEN
ReadMemory[
addr,
RandomCard[0FFFFFFFFH],
RandomCard[0FFH],
IF addr = 1C00000H THEN FALSE ELSE RandomBool[],
FALSE,
FALSE,
RandomCard[10],
RandomCard[10]]
ELSE
WriteMemory[
addr,
RandomCard[0FFFFFFFFH],
RandomCard[0FFH],
RandomCard[0FFFFH],
IF addr = 1C00000H THEN FALSE ELSE RandomBool[],
FALSE,
FALSE,
RandomCard[10],
RandomCard[10]];
ENDLOOP;
};
TestMemory: PROC = {
MemoryReadTest: PROC = {
Test Memory Reads
ReadMemory[0, 0, 0, FALSE, FALSE, FALSE, 6, 9];
Go through some specific locations
FOR addr: ILISTLIST [1C00000H, 0, 1, 2, 4, 8, 16, 32, 64, 128,
100H, 200H, 400H, 800H, 1000H, 2000H, 4000H, 8000H,
10000H, 20000H, 40000H, 80000H, 100000H, 200000H, 400000H, 800000H, 100000H, 200000H, 400000H, 800000H, 7FFFFFH
], addr.rest
WHILE addr # NIL DO
ReadMemory[addr.first ,0, 0, FALSE];
ReadMemory[addr.first ,0FFFFH, 0, FALSE];
ReadMemory[addr.first ,0, 3, FALSE, FALSE, FALSE, 7];
ReadMemory[addr.first ,0, 003FH, FALSE];
ReadMemory[addr.first ,0FFFFH, 003FH, FALSE];
ReadMemory[addr.first , 0, 0FFH, TRUE];
ReadMemory[addr.first , 0, 0AAH, TRUE];
ENDLOOP;
};
MemoryWriteTest: PROC = {
-- Write Memroy Test
WriteMemory[0, 0, 0, 0, FALSE];
WriteMemory[0, 0, 0, 0, FALSE, FALSE, FALSE, 6];
Go through some specific locations
FOR addr: ILISTLIST [1C00000H, 0, 1, 2, 4, 8, 16, 32, 64, 128,
100H, 200H, 400H, 800H, 1000H, 2000H, 4000H, 8000H,
10000H, 20000H, 40000H, 80000H, 100000H, 200000H, 400000H, 800000H, 100000H, 200000H, 400000H, 800000H, 7FFFFFH
], addr.rest
WHILE addr # NIL DO
WriteMemory[addr.first ,0, 0, 0FFFFH, FALSE];
WriteMemory[addr.first ,0FFFFH, 0, 0AAAAH, FALSE];
WriteMemory[addr.first ,0, 3, 5555H, FALSE, FALSE, FALSE, 2];
WriteMemory[addr.first ,0, 003FH, 055AA, FALSE];
WriteMemory[addr.first ,0FFFFH, 003FH, 0AA55H, FALSE];
IF addr.first # 1C00000H THEN {
WriteMemory[addr.first , 0, 0FFH, 55H, TRUE];
WriteMemory[addr.first , 0, 0AAH, 0FFH, TRUE];
};
ENDLOOP;
};
ReadMemory[0 ,0, 0, FALSE, FALSE, FALSE, 6];
ReadMemory[0 ,0, 0, FALSE, FALSE, FALSE, 7];
ReadMemory[0 ,0, 0, FALSE, FALSE, FALSE, 0, 3];
ReadMemory[0 ,0, 0, FALSE, FALSE, FALSE, 0, 4];
ReadMemory[0 ,0, 0, FALSE, FALSE, FALSE, 3, 4];
ReadMemory[1C00000H ,0, 0, FALSE, FALSE, FALSE, 4, 5];
WriteMemory[0 ,0, 0, 0, FALSE, FALSE, FALSE, 4, 0];
WriteMemory[0 ,0, 0, 0, FALSE, FALSE, FALSE, 5, 0];
WriteMemory[0 ,0, 0, 0, FALSE, FALSE, FALSE, 0, 6];
WriteMemory[0 ,0, 0, 0, FALSE, FALSE, FALSE, 0, 7];
WriteMemory[0 ,0, 0, 0, FALSE, FALSE, FALSE, 5, 6];
WriteMemory[1C00000H ,0, 0, 0, FALSE, FALSE, FALSE, 6, 7];
MemoryWriteTest[];
MemoryReadTest[];
};
ParityTest: PROC = {
-- Test the parity error detection & interrupt lines
-- Setup / clear status reg
WriteLatch[statuslatch, statusregreset];
WriteLatch[statuslatch, statusregnorm];
ChkP[XHINT, 0];
ReadLatch[statuslatch, statusregnorm];
-- Read with Tag Parity Error
ReadMemory[0,0,0, FALSE, TRUE, FALSE];
ReadLatch[statuslatch, statusregnorm + 8000H];
-- Turn on Interrupt Enable & check HINT
ClrP[XHINT];
WriteLatch[statuslatch, statusregnorm + 0400H];
ChkP[XHINT, 1];
ReadLatch[statuslatch, statusregnorm + 8400H];
-- Clear Interrupt Enable & check HINT cleared
ClrP[XHINT];
WriteLatch[statuslatch, statusregnorm];
ChkP[XHINT, 0];
GoClock[];
-- Clear Tag Parity Error
ReadMemory[0,0,0];
WriteLatch[statuslatch, statusregnorm + 0100H];
ReadLatch[statuslatch, laststatus];
WriteLatch[statuslatch, statusregnorm];
-- Read with Data Parity Error
ReadMemory[0,0,0, FALSE, FALSE, TRUE];
ReadLatch[statuslatch, statusregnorm + 4000H];
-- Turn on Interrupt Enable & check HINT
ClrP[XHINT];
WriteLatch[statuslatch, statusregnorm + 0400H];
ChkP[XHINT, 1];
ReadLatch[statuslatch, statusregnorm + 4400H];
-- Clear Interrupt Enable & check HINT cleared
ClrP[XHINT];
WriteLatch[statuslatch, statusregnorm];
ChkP[XHINT, 0];
GoClock[];
-- Clear Data Parity Error
ReadMemory[0,0,0];
WriteLatch[statuslatch, statusregnorm + 0100H];
ReadLatch[statuslatch, laststatus];
WriteLatch[statuslatch, statusregnorm];
ClrP[XHINT];
};
MISetupInit[cellType.public];
ChipReady[];
RandomMemoryTest[];
TestMemory[];
TestLatches[];
ParityTest[];
};

Belongs in Ports
ITDList: PROC [public: CoreCreate.Wire, indicies: LIST OF NAT, initDrive: Ports.Drive] ~ {
FOR l: LIST OF NAT ← indicies, l.rest WHILE l#NIL DO
[] ← Ports.InitTesterDrive[wire: public[l.first], initDrive: initDrive];
ENDLOOP;
};
IPList: PROC [public: CoreCreate.Wire, indicies: LIST OF NAT, levelType: Ports.LevelType, initDrive: Ports.Drive ← none] ~ {
FOR l: LIST OF NAT ← indicies, l.rest WHILE l#NIL DO
[] ← Ports.InitPort[wire: public[l.first], levelType: levelType, initDrive: initDrive];
ENDLOOP;
};
Start Code
InitializeTest[];
END.