<> <> 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: BOOL _ FALSE] = { 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: BOOL _ TRUE]] = { 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: BOOL _ TRUE]] = { data _ Basics.BITAND[Basics.LowHalf[BitOps.TwoToThe[CRProcs.dataBits]-1], data]; p[Address].c _ address; <<>> <> p[nPrecharge].b _ FALSE; Eval[]; p[nPrecharge].b _ TRUE; Eval[]; <<>> <> p[Access].b _ TRUE; <<>> <> 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[]]; <<>> <> 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: 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 _ BitOps.TwoToThe[BitOps.NBits[Size]]; InitPortIndicies[cellType.public]; InitRAM[p, Eval]; <> <> 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.