TestLogicImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier December 19, 1986 10:05:37 pm PST
Bertrand Serlet March 30, 1987 10:37:03 pm PST
An attempt to test every macro in Logic; the librarian must write one test proc per cell.
DIRECTORY
BitOps, Core, CoreFlat, CoreOps, IO, Logic, Ports, Random, Rosemary, RosemaryUser;
TestLogicImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreFlat, Logic, Ports, Random, Rosemary, RosemaryUser
~ BEGIN
Utilities
CheckSameSize: PROC [ct: Core.CellType, i0, i1, i2, i3, i4, i5: NATLAST[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};
};
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.
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: NATLAST[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: NATLAST[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.
Things to add to the checks
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 REALALL[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: BOOLEANTRUE;
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 𡤂] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REALALL[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: BOOLEANTRUE;
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 𡤂] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REALALL[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: BOOLEANTRUE;
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 REALALL[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: BOOLEANTRUE;
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 REALALL[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: BOOLEANTRUE;
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 REALALL[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: BOOLEANTRUE;
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 REALALL[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: BOOLEANTRUE;
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 REALALL[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: BOOLEANTRUE;
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];
};
TestLogicMuxD: PROC [ct: Core.CellType, n, b: NAT ← 2] RETURNS [ok: BOOLEAN, table: TruthTables.TruthTable, worst: ARRAY BOOLEAN OF REALALL[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: BOOLEANTRUE;
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
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];
};
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];
};
END.