CRTest.mesa
Barth, March 13, 1987 11:47:37 am PST
DIRECTORY Basics, BitOps, Core, CoreFlat, CRProcs, Ports, Rosemary, RosemaryUser;
CRTest: CEDAR PROGRAM
IMPORTS Basics, BitOps, CoreFlat, Ports, Rosemary, RosemaryUser =
BEGIN OPEN CRProcs;
Vdd: NAT;
Gnd: NAT;
PadVdd: NAT;
PadGnd: NAT;
nPrecharge: NAT;
Access: NAT;
Write: NAT;
Read: NAT;
Address: NAT;
Data: NAT;
Size: NAT = 4*rowQuads*8;
InitPortIndicies: PROC [p: Core.Wire] ~ {
Vdd ← Ports.PortIndex[p, "Vdd"];
Gnd ← Ports.PortIndex[p, "Gnd"];
PadVdd ← Ports.PortIndex[p, "PadVdd"];
PadGnd ← Ports.PortIndex[p, "PadGnd"];
nPrecharge ← Ports.PortIndex[p, "nPrecharge"];
Access ← Ports.PortIndex[p, "Access"];
Write ← Ports.PortIndex[p, "Write"];
Read ← Ports.PortIndex[p, "Read"];
Address ← Ports.PortIndex[p, "Address"];
Data ← Ports.PortIndex[p, "Data"];
};
Init: PROC [ct: Core.CellType, flatten: BOOLFALSE] = {
InitPortIndicies[ct.public];
[] ← Rosemary.SetFixedWire[ct.public[Vdd], H];
[] ← Rosemary.SetFixedWire[ct.public[Gnd], L];
[] ← Rosemary.SetFixedWire[ct.public[PadVdd], H];
[] ← Rosemary.SetFixedWire[ct.public[PadGnd], L];
[] ← Ports.InitTesterDrive[wire: ct.public[nPrecharge], initDrive: force];
[] ← Ports.InitTesterDrive[wire: ct.public[Access], initDrive: force];
[] ← Ports.InitTesterDrive[wire: ct.public[Write], initDrive: force];
[] ← Ports.InitTesterDrive[wire: ct.public[Read], initDrive: force];
[] ← Ports.InitTesterDrive[wire: ct.public[Address], initDrive: force];
[] ← Ports.InitTesterDrive[wire: ct.public[Data], initDrive: none];
[] ← RosemaryUser.TestProcedureViewer[name: "CrossRAM Tester", cellType: ct, testButtons: LIST["Write2Read2", "Illinois"], displayWires: RosemaryUser.DisplayPortLeafWires[ct], steady: FALSE, cutSet: CoreFlat.CreateCutSet[cellTypes: IF flatten THEN NIL ELSE LIST["CrossRAM"]], recordDeltas: FALSE];
};
InitRAM: PROC [p: Ports.Port, Eval: PROC [memory: BOOLTRUE]] = {
p[Vdd].b ← TRUE; p[Gnd].b ← FALSE;
p[PadVdd].b ← TRUE; p[PadGnd].b ← FALSE;
p[nPrecharge].b ← TRUE; p[Access].b ← FALSE;
p[Write].b ← FALSE; p[Read].b ← FALSE;
p[Data].d ← force;
Eval[! Rosemary.Stop => RESUME];
p[Data].d ← none;
};
AccessRAM: PROC [address: CARDINAL, data: CARDINAL, write: BOOL, p: Ports.Port, Eval: PROC [memory: BOOLTRUE]] = {
data ← Basics.BITAND[Basics.LowHalf[BitOps.TwoToThe[CRProcs.dataBits]-1], data];
p[Address].c ← address;
precharge
p[nPrecharge].b ← FALSE;
Eval[];
p[nPrecharge].b ← TRUE;
Eval[];
enable select line
p[Access].b ← TRUE;
if write then enable write drivers
IF write THEN {
p[Data].d ← force;
p[Write].b ← TRUE;
} ELSE {
p[Data].d ← expect;
p[Read].b ← TRUE;
};
p[Data].c ← data;
Eval[ ! Rosemary.Stop => IF reason = $BoolWireHasX THEN SIGNAL FindX[]];
disable select line
p[Access].b ← p[Write].b ← p[Read].b ← FALSE;
p[Data].d ← none;
Eval[];
};
Write2Read2: RosemaryUser.TestProc = {
InitPortIndicies[cellType.public];
InitRAM[p, Eval];
AccessRAM[write: TRUE, address: 0, data: 0, p: p, Eval: Eval];
AccessRAM[write: TRUE, address: 1, data: 0FFH, p: p, Eval: Eval];
AccessRAM[write: FALSE, address: 0, data: 0, p: p, Eval: Eval];
AccessRAM[write: FALSE, address: 1, data: 0FFH, p: p, Eval: Eval];
};
Illinois: RosemaryUser.TestProc = {
CycleRAM: PROC [address: CARDINAL, data: CARDINAL, write: BOOL] = {
AccessRAM[write: write, address: address, data: data, p: p, Eval: Eval];
};
HalfStep: PROC [upper: BOOL, data: BOOL, write: BOOL] = {
address: CARDINALIF upper THEN halfBit ELSE 0;
addressMod: CARDINAL;
DO
CycleRAM[address, IF data THEN LAST[CARDINAL] ELSE 0, write];
address ← address + 1;
addressMod ← address MOD (2*halfBit);
IF (upper AND addressMod=0) OR (NOT upper AND addressMod=halfBit) THEN address ← address + halfBit;
IF address>=Size THEN EXIT;
ENDLOOP;
};
StepIndex: TYPE = [0..8);
complementUpper: ARRAY StepIndex OF BOOL = [TRUE,TRUE,FALSE,TRUE,FALSE,FALSE,TRUE,FALSE];
writeData: ARRAY StepIndex OF BOOL = [TRUE,FALSE,TRUE,TRUE,FALSE,TRUE,FALSE,FALSE];
readData: ARRAY StepIndex OF BOOL = [FALSE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,FALSE];
halfBit: CARDINAL ← BitOps.TwoToThe[BitOps.NBits[Size]];
InitPortIndicies[cellType.public];
InitRAM[p, Eval];
write zero to all locations
divide RAM by columns instead of rows
FOR address: CARDINAL IN [0..Size) DO
CycleRAM[address, 0, TRUE];
ENDLOOP;
UNTIL (halfBit ← halfBit/2) = 4 DO
FOR step: StepIndex IN StepIndex DO
HalfStep[upper: complementUpper[step], data: writeData[step], write: TRUE];
HalfStep[upper: NOT complementUpper[step], data: readData[step], write: FALSE];
ENDLOOP;
ENDLOOP;
};
FindX: SIGNAL = CODE;
CrossRAMInit: Rosemary.InitProc = {
stateAny ← NEW[CrossRAMStateRec[Size]];
IF dataBits>16 OR addressBits>16 THEN ERROR;
};
CrossRAMSimple: Rosemary.EvalProc = {
state: CrossRAMState ← NARROW[stateAny];
IF NOT p[Vdd].b OR p[Gnd].b OR NOT p[PadVdd].b OR p[PadGnd].b THEN SIGNAL Rosemary.Stop[];
IF (NOT p[nPrecharge].b AND p[Access].b) OR (p[Write].b AND p[Read].b) OR (NOT p[nPrecharge].b AND p[Write].b) THEN SIGNAL Rosemary.Stop[];
IF NOT p[nPrecharge].b THEN state.precharged ← TRUE;
p[Data].d ← none;
IF p[Access].b THEN {
IF NOT state.precharged THEN SIGNAL Rosemary.Stop[];
IF state.accessOccured AND state.address#p[Address].c THEN SIGNAL Rosemary.Stop[];
state.accessOccured ← TRUE;
state.address ← p[Address].c;
IF p[Read].b THEN {
p[Data].c ← state.memory[state.address].data;
p[Data].d ← drive;
};
IF p[Write].b THEN state.memory[state.address].data ← p[Data].c;
};
IF NOT p[Access].b AND state.accessOccured THEN {
state.accessOccured ← FALSE;
state.precharged ← FALSE;
};
};
[] ← Rosemary.Register[roseClassName: "CrossRAM", init: CrossRAMInit, evalSimple: CrossRAMSimple];
RosemaryUser.RegisterTestProc["Write2Read2", Write2Read2];
RosemaryUser.RegisterTestProc["Illinois", Illinois];
END.