DIRECTORY BitOps, Core, CoreFlat, CoreOps, IO, Logic, Ports, Random, Rosemary, RosemaryUser; TestLogicImpl: CEDAR PROGRAM IMPORTS BitOps, CoreFlat, Logic, Ports, Random, Rosemary, RosemaryUser ~ BEGIN CheckSameSize: PROC [ct: Core.CellType, i0, i1, i2, i3, i4, i5: NAT _ LAST[NAT]] ~ { IF i0=LAST[NAT] THEN RETURN; IF i1#LAST[NAT] THEN {IF ct.public[i0].size # ct.public[i1].size THEN ERROR}; IF i2#LAST[NAT] THEN {IF ct.public[i0].size # ct.public[i2].size THEN ERROR}; IF i3#LAST[NAT] THEN {IF ct.public[i0].size # ct.public[i3].size THEN ERROR}; IF i4#LAST[NAT] THEN {IF ct.public[i0].size # ct.public[i4].size THEN ERROR}; IF i5#LAST[NAT] THEN {IF ct.public[i0].size # ct.public[i5].size THEN ERROR}; }; AdderTester: RosemaryUser.TestProc = { Add: PROC [a, b, carry: INT] ~ { s: INT _ a+b+carry; IF s>=max THEN {s _ s-max; p[carryOut].l _ H} ELSE p[carryOut].l _ L; Ports.LCToLS[a, p[inA].ls]; Ports.LCToLS[b, p[inB].ls]; p[carryIn].l _ SELECT carry FROM 0 => L, 1 => H, ENDCASE => ERROR; Ports.LCToLS[s, p[sum].ls]; Eval[]; }; max, b: INT; rs: Random.RandomStream; inA, inB, sum, carryIn, carryOut, vdd, gnd: NAT _ LAST[NAT]; [inA, inB, sum, carryIn, carryOut, vdd, gnd] _ Ports.PortIndexes[cellType.public, "A", "B", "Sum", "carryIn", "carryOut", "Vdd", "Gnd"]; b _ p[sum].ls.size; IF b>31 THEN RETURN; max _ BitOps.TwoToThe[b]; rs _ Random.Create[max]; Add[0, 0, 0]; Add[max-1, 0, 0]; Add[max-1, 0, 1]; Add[max-1, 1, 0]; Add[0, 1, 1]; Add[Random.NextInt[rs], Random.NextInt[rs], 0]; Add[Random.NextInt[rs], Random.NextInt[rs], 1]; }; TestAdder: PROC [ct: Core.CellType] RETURNS [ok: BOOLEAN] ~ { inA, inB, sum, carryIn, carryOut, vdd, gnd: NAT _ LAST[NAT]; tester: RosemaryUser.Tester; [inA, inB, sum, carryIn, carryOut, vdd, gnd] _ Ports.PortIndexes[ct.public, "A", "B", "Sum", "carryIn", "carryOut", "Vdd", "Gnd"]; CheckSameSize[ct, inA, inB, sum]; CheckSameSize[ct, carryIn, carryOut]; Ports.InitTesterDrive[wire: ct.public[inA], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[inB], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[carryIn], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[sum], initDrive: expect]; Ports.InitTesterDrive[wire: ct.public[carryOut], initDrive: expect]; [] _ Rosemary.SetFixedWire[ct.public[vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[gnd], L]; RosemaryUser.RegisterTestProc["TestAdder", AdderTester]; tester _ RosemaryUser.TestProcedureViewer[ cellType: ct, testButtons: LIST["TestAdder"], name: "TestAdder", displayWires: RosemaryUser.DisplayPortLeafWires[ct], cutSet: CoreFlat.CreateCutSet[cellTypes: LIST["Logic"]], -- sc gates level steady: FALSE]; RosemaryUser.StartTest[tester]; }; [] _ TestAdder[Logic.Adder[4]]; END. -- Registers: enable, reset, complementary output -- Constant: b>32; b=32, v=-1; v=0 (no Vdd); v=1 (no Gnd) -- eqConstant: same as constant -- Comparator -- Muxes: select -> which input; no select; several selects TestRegister: PROC [ct: Core.CellType, n: NAT _ 2 ] RETURNS [ok: BOOLEAN] ~ { ck, en, input, output, noutput, Vdd, Gnd: NAT; adInput, adMaster, adSlave, adOutput, adnOutput, adOmaster, adOslave, nInputs, nOutputs: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; state: LogicRegsImpl.RegRef; adInput _ 3; adMaster _ adInput+n; adSlave _ adMaster+n; nInputs _ adSlave+n; adOutput _ 1; adnOutput _ adOutput+n; adOmaster _ adnOutput+n; adOslave _ adOmaster+n; nOutputs _ adOslave+n; [ck, en, input, output, noutput, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "CK", "en", "Input", "Output", "nOutput", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[ck], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[en], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; Ports.InitTesterDrive[wire: ct.public[noutput], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; state _ NARROW[Rosemary.GetState[simulation, flatRoot]]; table _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicRegisterR: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[ck].l _ in[0]; tp[en].l _ in[1]; tp[r].l _ in[2]; state.prevCK _ in[3]; FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[adInput+i]; state.master[i] _ in[adMaster+i]; state.slave[i] _ in[adSlave+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[nOutputs]]; out[0] _ state.prevCK; FOR i: NAT IN [0..n) DO out[adOutput+i] _ tp[output].ls[i]; out[adnOutput+i] _ tp[noutput].ls[i]; out[adOmaster+i] _ state.master[i]; out[adOslave+i] _ state.slave[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; ck, en, r, input, output, noutput, Vdd, Gnd: NAT; adInput, adMaster, adSlave, adOutput, adnOutput, adOmaster, adOslave, nInputs, nOutputs: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; state: LogicRegsImpl.RegRef; adInput _ 4; adMaster _ adInput+n; adSlave _ adMaster+n; nInputs _ adSlave+n; adOutput _ 1; adnOutput _ adOutput+n; adOmaster _ adnOutput+n; adOslave _ adOmaster+n; nOutputs _ adOslave+n; [ck, en, r, input, output, noutput, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "CK", "en", "r", "Input", "Output", "nOutput", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[ck], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[en], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[r], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; Ports.InitTesterDrive[wire: ct.public[noutput], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; state _ NARROW[Rosemary.GetState[simulation, flatRoot]]; table _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicRegisterSimple: PROC [ct: Core.CellType, n: NAT _2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[ck].l _ in[0]; state.prevCK _ in[1]; FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[adInput+i]; state.master[i] _ in[adMaster+i]; state.slave[i] _ in[adSlave+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[nOutputs]]; out[0] _ state.prevCK; FOR i: NAT IN [0..n) DO out[adOutput+i] _ tp[output].ls[i]; out[adnOutput+i] _ tp[noutput].ls[i]; out[adOmaster+i] _ state.master[i]; out[adOslave+i] _ state.slave[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; ck, input, output, noutput, Vdd, Gnd: NAT; adInput, adMaster, adSlave, adOutput, adnOutput, adOmaster, adOslave, nInputs, nOutputs: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; state: LogicRegsImpl.RegRef; adInput _ 1; adMaster _ adInput+n; adSlave _ adMaster+n; nInputs _ adSlave+n; adOutput _ 1; adnOutput _ adOutput+n; adOmaster _ adnOutput+n; adOslave _ adOmaster+n; nOutputs _ adOslave+n; [ck, input, output, noutput, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "CK", "Input", "Output", "nOutput", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[ck], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; Ports.InitTesterDrive[wire: ct.public[noutput], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; state _ NARROW[Rosemary.GetState[simulation, flatRoot]]; table _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[nInputs, nOutputs, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicTristateBuffer: PROC [ct: Core.CellType, n: NAT _2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[enable].l _ in[0]; FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[1+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[n]]; FOR i: NAT IN [0..n) DO out[i] _ tp[output].ls[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; input, output, enable, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [input, output, enable, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "Input", "Output", "enable", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[enable], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; table _ TruthTables.BuildTable[n+1, n, Settle, withX]; tableNoX _ TruthTables.BuildTable[n+1, n, Settle, withX]; withX _ FALSE; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicLatch: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[ck].l _ in[0]; FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[1+i]; state.master[i] _ in[n+1+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[n]]; FOR i: NAT IN [0..n) DO out[i] _ tp[output].ls[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; ck, input, output, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; state: LogicRegsImpl.RegRef; [ck, input, output, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "CK", "Input", "Output", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[ck], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; state _ NARROW[Rosemary.GetState[simulation, flatRoot]]; table _ TruthTables.BuildTable[2*n+1, n, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[2*n+1, n, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicAdder: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { T: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[carryin].l _ in[0]; FOR i: NAT IN [0..n) DO tp[a].ls[i] _ in[1+i]; tp[b].ls[i] _ in[n+1+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[n+1]]; out[0] _ tp[carryout].l; FOR i: NAT IN [0..n) DO out[i+1] _ tp[sum].ls[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; a, b, sum, carryin, carryout, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [a, b, sum, carryin, carryout, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "A", "B", "Sum", "carryIn", "carryOut", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[a], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[b], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[carryin], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[sum], initDrive: none]; Ports.InitTesterDrive[wire: ct.public[carryout], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; table _ TruthTables.BuildTable[2*n+1, n+1, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[2*n+1, n+1, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; LoopTest: RosemaryUser.TestProc = { Initialize[p, cellType.public]; FromPtoK[p, Eval,000000000H]; FromPtoK[p, Eval,0FFFFFFFFH]; }; RosemaryUser.RegisterTestProc["LoopTest", LoopTest]; }; END. TestLogicConstant: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[n]]; FOR i: NAT IN [0..n) DO out[i] _ tp[output].ls[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; output, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [output, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "Output", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; table _ TruthTables.BuildTable[0, n, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[0, n, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicComparator: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { FOR i: NAT IN [0..n) DO tp[a].ls[i] _ in[i]; tp[b].ls[i] _ in[n+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[1]]; out[0] _ tp[aeqb].l; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; a, b, aeqb, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [a, b, aeqb, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "A", "B", "AEqB", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[a], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[b], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[aeqb], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; table _ TruthTables.BuildTable[2*n, 1, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[2*n, 1, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; TestLogicEqConstant: PROC [ct: Core.CellType, n: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[1]]; out[0] _ tp[output].l; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; input, output, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [input, output, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "In", "out", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; table _ TruthTables.BuildTable[n, 1, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[n, 1, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; MsgDone[ct, worst]; }; MsgBadX: PROC [ct: Core.CellType] ~ { TerminalIO.WriteRopes["The cell ", CoreOps.GetCellTypeName[ct], " has bad X responses\n"]; }; MsgDone: PROC [ct: Core.CellType, worst: ARRAY BOOLEAN OF REAL] ~ { TerminalIO.WriteRopes[CoreOps.GetCellTypeName[ct], IO.PutFR[" rise time:%4.1f, fall time:%4.1f\n\n", IO.real[worst[TRUE]/1000.0], IO.real[worst[FALSE]/1000.0]]]; }; MsgMismatch: PROC [ct: Core.CellType, in: TruthLine, out: TruthLine] ~ { TerminalIO.WriteRopes[CoreOps.GetCellTypeName[ct], " mismatch for "]; }; LevelFromBool: PROC [b: BOOLEAN] RETURNS [l: Ports.Level] ~ { l _ IF b THEN H ELSE L; }; BoolFromLevel: PROC [l: Ports.Level] RETURNS [b: BOOLEAN] ~ { IF l=X THEN ERROR; b _ l=H; }; MintInput: PROC [ct: Core.CellType] RETURNS [circuit: Mint.Circuit] ~ { fixedV: Mint.NodeList; WriteCapa.WriteWireCapa[ct]; circuit _ Mint.InputData[ct, FALSE]; fixedV _ Mint.BuildNodeList["public.Vdd", NIL, circuit]; Mint.SetNode[fixedV.first, TRUE]; fixedV _ Mint.BuildNodeList["public.Gnd", fixedV, circuit]; Mint.SetNode[fixedV.first, FALSE]; Mint.PrepareSets[circuit, fixedV]; }; LogicRegisterTests: PROC ~ { register, registerR, registerSimple, triStateBuffer, triStateBufferInv, latch: Core.CellType; -- LogicRegsImpl cells register _ Logic.Register[2]; IF ~TestLogicRegister[register, 2].ok THEN MsgBadX[register]; registerR _ Logic.RegisterR[2]; IF ~TestLogicRegisterR[registerR, 2].ok THEN MsgBadX[registerR]; registerSimple _ Logic.RegisterSimple[2]; IF ~TestLogicRegisterSimple[registerSimple, 2].ok THEN MsgBadX[registerSimple]; triStateBuffer _ Logic.TristateBuffer[2]; IF ~TestLogicTristateBuffer[triStateBuffer, 2].ok THEN MsgBadX[triStateBuffer]; triStateBufferInv _ Logic.TristateBufferInv[2]; IF ~TestLogicTristateBuffer[triStateBufferInv, 2].ok THEN MsgBadX[triStateBufferInv]; latch _ Logic.Latch[2]; IF ~TestLogicLatch[latch, 2].ok THEN MsgBadX[latch]; }; LogicArithTests: PROC ~ { adder, constant, comparator, eqconstant: Core.CellType; -- LogicArithImpl cells adder _ Logic.Adder[2]; IF ~TestLogicAdder[adder, 2].ok THEN MsgBadX[adder]; constant _ Logic.Constant[2, 1]; IF ~TestLogicConstant[constant, 2].ok THEN MsgBadX[constant]; comparator _ Logic.Comparator[2]; IF ~TestLogicComparator[comparator, 2].ok THEN MsgBadX[comparator]; eqconstant _ Logic.EqConstant[2, 1]; IF ~TestLogicEqConstant[eqconstant, 2].ok THEN MsgBadX[eqconstant]; }; END. TestLogicImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by: Louis Monier December 19, 1986 10:05:37 pm PST An attempt to test every macro in Logic; the librarian must write one test proc per cell. Utilities Test of Adder -- Logic.Adder[b] is defined for b>1; both operands and sum are numbers on b bits, interpreted as 2's complement numbers; we choose to test only with values fitting on 32 bits. -- find port indexes -- check sizes -- prepares tester ports -- simulate Things to add to the checks TestLogicMuxD: PROC [ct: Core.CellType, n, b: NAT _ 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REAL _ ALL[0.0]] ~ { Settle: PUBLIC PROC [in: TruthLine] RETURNS [out: TruthLine] ~ { tp[ck].l _ in[0]; FOR i: NAT IN [0..n) DO tp[input].ls[i] _ in[1+i]; state.master[i] _ in[n+1+i]; ENDLOOP; Rosemary.Settle[simulation]; out _ NEW[TruthElmtRec.value[n]]; FOR i: NAT IN [0..n) DO out[i] _ tp[output].ls[i]; ENDLOOP; }; tableNoX: TruthTables.TruthTable; withX: BOOLEAN _ TRUE; select, input, output, Vdd, Gnd: NAT; tp: Ports.Port; simulation: Rosemary.Simulation; [select, input, output, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "Select", "In", "Output", "Vdd", "Gnd"]; Ports.InitTesterDrive[wire: ct.public[select], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[input], initDrive: force]; Ports.InitTesterDrive[wire: ct.public[output], initDrive: none]; [] _ Rosemary.SetFixedWire[ct.public[Vdd], H]; [] _ Rosemary.SetFixedWire[ct.public[Gnd], L]; tp _ Ports.CreatePort[ct, TRUE]; simulation _ Rosemary.Instantiate[ct, tp, CoreFlat.CreateCutSet[cellTypes: LIST[CoreOps.GetCellTypeName[ct]]]]; Rosemary.Initialize[simulation]; state _ NARROW[Rosemary.GetState[simulation, flatRoot]]; table _ TruthTables.BuildTable[2*n+1, n, Settle, withX]; withX _ FALSE; tableNoX _ TruthTables.BuildTable[2*n+1, n, Settle, withX]; TruthTables.FillXValues[tableNoX]; ok _ TruthTables.Equal[tableNoX, table]; }; Heading Heading LogicMuxesTests: PROC [n: NAT _ 2] ~ { muxD, muxD2, muxD4, mux, mux2, mux4, decoderS, decoder: Core.CellType; -- LogicMuxesImpl cells muxD _ Logic.MuxD[2, 2]; IF ~TestLogicMuxD[muxD, 2, 2].ok THEN MsgBadX[muxD]; muxD2 _ Logic.MuxD2[2]; IF ~TestLogicMuxD2[muxD2, 2].ok THEN MsgBadX[muxD2]; muxD4 _ Logic.MuxD4[2]; IF ~TestLogicMuxD4[muxD4, 2].ok THEN MsgBadX[muxD4]; mux _ Logic.Mux[2, 2]; IF ~TestLogicMux[mux, 2, 2].ok THEN MsgBadX[mux]; mux2 _ Logic.Mux2[2]; IF ~TestLogicMux2[mux2, 2].ok THEN MsgBadX[mux2]; mux4 _ Logic.Mux4[2]; IF ~TestLogicMux4[mux4, 2].ok THEN MsgBadX[mux4]; decoderS _ Logic.DecoderS[2, 0]; IF ~TestLogicDecoderS[constant, 2, 0].ok THEN MsgBadX[decoderS]; decoder _ Logic.Decoder[2, 0]; IF ~TestLogicDecoder[decoder, 2].ok THEN MsgBadX[decoder]; }; LogicCounterTests: PROC [n: NAT _ 2] ~ { counter, shiftReg: Core.CellType; -- LogicArithImpl cells counter _ Logic.Counter[2]; IF ~TestLogicCounter[counter, 2].ok THEN MsgBadX[counter]; shiftReg _ Logic.ShiftReg[2]; IF ~TestLogicShiftReg[shiftReg, 2].ok THEN MsgBadX[shiftReg]; }; LogicMemTests: PROC [n: NAT _ 2] ~ { fifo, latch: Core.CellType; -- LogicArithImpl cells fifo _ Logic.Fifo[2, ]; IF ~TestLogicFifo[counter, 2].ok THEN MsgBadX[counter]; shiftReg _ Logic.ShiftReg[2]; IF ~TestLogicShiftReg[shiftReg, 2].ok THEN MsgBadX[shiftReg]; }; ΚΑ˜codešœ™Kšœ Οmœ1™™>—K™K™YK™šΟk ˜ Kšœ!žœ/˜R—K˜KšΡbln œžœž˜Kšžœ?˜FKšœž˜head™ š Οn œžœ-žœžœžœ˜TKš žœžœžœžœžœ˜Kšžœžœžœžœžœ)žœžœ˜MKšžœžœžœžœžœ)žœžœ˜MKšžœžœžœžœžœ)žœžœ˜MKšžœžœžœžœžœ)žœžœ˜MKšžœžœžœžœžœ)žœžœ˜MK˜——™ Kšœ°™°š  œ˜&š œžœžœ˜ Kšœžœ ˜Kšžœžœ žœ˜EKšœ˜Kšœ˜šœžœž˜ Kšœ˜K˜Kšžœžœ˜—Kšœ˜Kšœ˜K˜—Kšœžœ˜ Kšœ˜Kšœ,žœžœžœ˜˜>Kšœ>˜>KšœB˜BKšœ?˜?KšœD˜DKšœ.˜.Kšœ.˜.J™ Kšœ8˜8šœ*˜*Kšœ˜Kšœ žœ˜ Kšœ˜Kšœ5˜5Kšœ)žœ Οc˜JJšœžœ˜—Kšœ˜K˜K˜—Kšœ˜—Kšžœ˜™K˜1K˜9K˜K˜ K˜;K˜š   œžœžœžœžœ˜NKšœ% œžœ˜.KšœYžœ˜]Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ‚˜‚Kšœ=˜=Kšœ=˜=Kšœ@˜@Kšœ@˜@KšœA˜AKšœ.˜.Kšœ.˜.Kšœžœ˜ KšœKžœ ˜oKšœ ˜ Kšœžœ*˜8KšœA˜AKšœžœ˜KšœD˜DKšœ"˜"Kšœ(˜(Kšœ˜K˜K˜—š œžœžœžœžœ(žœžœžœžœžœ ˜šš œžœžœžœ˜@Kšœ˜Kšœ˜Kšœ˜Kšœ˜šžœžœžœž˜Kšœ ˜ Kšœ!˜!Kšœ˜Kšžœ˜—Kšœ˜Kšœžœ˜(Kšœ˜šžœžœžœž˜Kšœ#˜#Kšœ%˜%Kšœ#˜#Kšœ!˜!Kšžœ˜—K˜K™—Kšœ!˜!Kšœžœžœ˜Kšœ( œžœ˜1KšœYžœ˜]Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœŠ˜ŠKšœ=˜=Kšœ=˜=Kšœ<˜˜>Kšœ.˜.Kšœ.˜.Kšœžœ˜ KšœKžœ ˜oKšœ ˜ Kšœ6˜6Kšœžœ˜Kšœ9˜9Kšœ"˜"Kšœ(˜(Kšœ˜K˜K˜—š œžœžœžœžœ(žœžœžœžœžœ ˜›š œžœžœžœ˜@šžœžœžœž˜Kšœ˜Kšžœ˜—Kšœ˜Kšœžœ˜!Kšœ˜K˜K™—Kšœ!˜!Kšœžœžœ˜Kšœ œžœ˜Kšœ˜Kšœ ˜ KšœT˜TKšœ@˜@Kšœ@˜@Kšœ.˜.Kšœ.˜.Kšœžœ˜ KšœKžœ ˜oKšœ ˜ Kšœ4˜4Kšœžœ˜Kšœ7˜7Kšœ"˜"Kšœ(˜(Kšœ˜K˜K˜—š  œžœžœžœžœ(žœžœžœžœžœ ™˜š œžœžœžœ™@Kšœ™šžœžœžœž™Kšœ™Kšœ™Kšžœ™—Kšœ™Kšœžœ™!šžœžœžœž™Kšœ™Kšžœ™—K™K™—Kšœ!™!Kšœžœžœ™Kšœ œžœ™%Kšœ™Kšœ ™ Kšœi™iKšœA™AKšœ@™@Kšœ@™@Kšœ.™.Kšœ.™.Kšœžœ™ KšœKžœ ™oKšœ ™ Kšœžœ*™8Kšœ8™8Kšœžœ™Kšœ;™;Kšœ"™"Kšœ(™(K™K™—K˜—šΠrtœ£™ š œžœ˜%KšœZ˜ZK˜K˜—š  œžœžœžœžœžœ˜CKš œ3žœ0žœ žœ žœ žœ ˜‘K˜K˜—š  œžœ7˜HKšœE˜EK˜K˜—š  œžœžœžœ˜=Kšœžœžœžœ˜K˜K˜—š  œžœžœžœ˜=Jšžœžœžœ˜J˜K˜K˜—š  œžœžœ˜GKšœ˜Kšœ˜Kšœžœ˜$Jšœ*žœ ˜8Jšœžœ˜!Jšœ;˜;Jšœžœ˜"Jšœ"˜"K˜——š£œ£™ š œžœ˜Kšœ^‘˜tKšœ˜Kšžœ$žœ˜=Kšœ˜Kšžœ&žœ˜@Kšœ)˜)Kšžœ0žœ˜OKšœ)˜)Kšžœ0žœ˜OKšœ/˜/Kšžœ3žœ˜UKšœ˜Kšžœžœ˜4K˜K˜—š œžœ˜Kšœ8‘˜OKšœ˜Kšžœžœ˜4Kšœ ˜ Kšžœ$žœ˜=Kšœ!˜!Kšžœ(žœ˜CKšœ$˜$Kšžœ(žœ˜CK˜K˜—š œžœžœ ™&KšœG‘™^Kšœ™Kšžœžœ™4Kšœ™Kšžœžœ™4Kšœ™Kšžœžœ™4Kšœ™Kšžœžœ™1Kšœ™Kšžœžœ™1Kšœ™Kšžœžœ™1Kšœ ™ Kšžœ'žœ™@Kšœ™Kšžœ"žœ™:K™K™—š Πbn œžœžœ ™(Kšœ"‘™9Kšœ™Kšžœ"žœ™:Kšœ™Kšžœ$žœ™=K™K™—š € œžœžœ ™$Kšœ‘™3Kšœ™Kšžœžœ™7Kšœ™Kšžœ$žœ™=K™K™—K˜K˜—Kšžœ˜—…—KΖn‹