<> <> <> <> 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]; <> 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]; <> 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.