<> <> <> <<>> <> <<>> 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}; }; <> <<-- 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.>> 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; <<-- find port indexes>> [inA, inB, sum, carryIn, carryOut, vdd, gnd] _ Ports.PortIndexes[ct.public, "A", "B", "Sum", "carryIn", "carryOut", "Vdd", "Gnd"]; <<-- check sizes>> CheckSameSize[ct, inA, inB, sum]; CheckSameSize[ct, carryIn, carryOut]; <<-- prepares tester ports>> 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]; <<-- simulate>> 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]; }; <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <<[select, input, output, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "Select", "In", "Output", "Vdd", "Gnd"];>> <> <> <> <<[] _ Rosemary.SetFixedWire[ct.public[Vdd], H];>> <<[] _ Rosemary.SetFixedWire[ct.public[Gnd], L];>> <> <> <> <> <> <> <> <> <> <<};>> <<>> <<Heading>> 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]; }; <<Heading>> 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.