CRTest.mesa
Barth, July 17, 1986 2:23:32 pm PDT
DIRECTORY Basics, BitHacks, Core, CRProcs, Ports, Rosemary, RosemaryUser;
CRTest:
CEDAR
PROGRAM
IMPORTS Basics, BitHacks, 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;
Init:
PROC [ct: Core.CellType, flatten:
BOOL ←
FALSE] = {
sim: Rosemary.Simulation;
Vdd ← Ports.PortIndex[ct.public, "Vdd"];
Gnd ← Ports.PortIndex[ct.public, "Gnd"];
PadVdd ← Ports.PortIndex[ct.public, "PadVdd"];
PadGnd ← Ports.PortIndex[ct.public, "PadGnd"];
nPrecharge ← Ports.PortIndex[ct.public, "nPrecharge"];
Access ← Ports.PortIndex[ct.public, "Access"];
Write ← Ports.PortIndex[ct.public, "Write"];
Read ← Ports.PortIndex[ct.public, "Read"];
Address ← Ports.PortIndex[ct.public, "Address"];
Data ← Ports.PortIndex[ct.public, "Data"];
[] ← 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];
sim ← RosemaryUser.TestProcedureViewer[name: "CrossRAM Tester", cellType: ct, testButtons: LIST["Write2Read2", "Illinois"], displayWires: RosemaryUser.DisplayCellTypePortLeafWires[ct], flatten: flatten];
Rosemary.Initialize[simulation: sim, steady: FALSE];
};
InitRAM:
PROC [p: Ports.Port,
Eval:
PROC] = {
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] = {
data ← Basics.BITAND[Basics.LowHalf[BitHacks.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[];
disable select line
p[Access].b ← p[Write].b ← p[Read].b ← FALSE;
p[Data].d ← none;
Eval[];
};
Write2Read2: RosemaryUser.TestProc = {
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: CARDINAL ← IF 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 ← BitHacks.TwoToThe[addressBits];
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;
};
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.