DIRECTORY AMBridge, AMTypes, Ascii, BitTwiddling, Cucumber, IO, OrderedSymbolTableRef, PrincOps, PrincOpsUtils, Rope, RoseClocks, RoseCreate, RoseRun, RoseStateIO, RoseTypes;

RoseTestingImpl: CEDAR PROGRAM
IMPORTS AMBridge, AMTypes, Ascii, BitTwiddling, Cucumber, IO, OrderedSymbolTableRef, PrincOpsUtils, Rope, RoseClocks, RoseCreate, RoseRun, RoseStateIO, RoseTypes
EXPORTS RoseCreate, RoseRun, RoseTypes =

BEGIN OPEN RoseTypes, RoseRun, RoseCreate;

InterfaceMismatch: PUBLIC ERROR [cell: Cell,
index: CARDINAL,
expected, got: NodeType] = CODE;

TV: TYPE = AMTypes.TV;
Type: TYPE = AMTypes.Type;

WrapTop: PUBLIC PROC [rootName, typeName: ROPE, decider: ExpandDeciderClosure, clocks: ROPE _ NIL, sim: Simulation] =
BEGIN
rootType: CellType;
rootType _ GetWrappingType[typeName, clocks];
CreateTopCell[instanceName: rootName, typeName: rootType.name, decider: decider, sim: sim];
END;

GetWrappingType: PROC [subName, clocks: ROPE] RETURNS [wrappingType: CellType] =
BEGIN
wrappingName: ROPE = subName.Cat["-wrap-", clocks];
subType: CellType;
IF (wrappingType _ GetCellType[wrappingName]) # NIL THEN RETURN;
IF (subType _ GetCellType[subName]) = NIL THEN ERROR Error[msg: "No such type", data: subName];
wrappingType _ RegisterCellType[
name: wrappingName,
expandProc: ExpandWrapper,
evals: [],
ports: NEW [PortsRep[0]],
typeData: NEW [WrapTypeRep _ [subType, clocks]]];
END;

WrapType: TYPE = REF WrapTypeRep; WrapTypeRep: TYPE = RECORD [
subType: CellType,
clocks: ROPE];

ExpandWrapper: PROC [thisCell: Cell, to: ExpansionReceiver] --ExpandProc-- =
BEGIN
wc: WrapType _ NARROW[thisCell.type.typeData];
IF wc.clocks # NIL THEN {
clockType: CellType _ RoseClocks.ClockGen[[]];
PerClock: PROC [key: Key, nodeName: ROPE] = {
portIndex: PortIndex _ nilPortIndex;
WITH key SELECT FROM
x: Key.position => portIndex _ x.index;
x: Key.keyword => portIndex _ GetIndex[clockType.ports, x.name];
ENDCASE => ERROR;
[] _ to.class.NodeInstance[erInstance: to.instance, name: nodeName, type: clockType.ports[portIndex].type];
};
EnumerateConnections[wc.clocks, PerClock];
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: "clockGen", typeName: clockType.name, interfaceNodes: wc.clocks];
};
EnsureEnvironment[in: thisCell, forType: wc.subType, to: to];
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: LowerFirst[wc.subType.name], typeName: wc.subType.name, interfaceNodes: ""];
END;

LowerFirst: PROC [u: ROPE] RETURNS [l: ROPE] = {
IF u.Length[] = 0 THEN RETURN [u];
l _ Rope.FromChar[Ascii.Lower[u.Fetch[0]]].Concat[u.Substr[start: 1]]};

EnsureEnvironment: PUBLIC PROC [in: Cell, forType: CellType, to: ExpansionReceiver] =
BEGIN
FOR portIndex: CARDINAL IN [0 .. forType.ports.length) DO
port: Port = forType.ports[portIndex];
node: Node _ NARROW[in.internalNodes.Lookup[port.name]];
s: Strength _ charge;
iv: ROPE _ NIL;
IF node # NIL THEN LOOP;
IF port.name.Equal["gnd", FALSE] THEN {s _ input; iv _ "gnd"} ELSE
IF port.name.Equal["vdd", FALSE] THEN {s _ input; iv _ "vdd"} ELSE
IF port.input AND NOT port.output THEN s _ input ELSE
IF port.output AND NOT port.input THEN s _ chargeWeak;
[] _ to.class.NodeInstance[erInstance: to.instance, name: port.name, type: port.type, initialValue: iv, initialValueFormat: IF iv # NIL THEN "init" ELSE NIL, initData: NEW [Strength _ s]];
ENDLOOP;
END;

ProcToInt: PROC [p: PROC ANY RETURNS ANY] RETURNS [i: INT] =
TRUSTED {i _ LOOPHOLE[p, INTEGER]};

MakeTesterPorts: PROC [testee: Ports, alwaysOutput, alwaysInput: BOOL _ FALSE] RETURNS [tester: Ports] =
BEGIN
tester _ NEW [PortsRep[testee.length]];
FOR i: CARDINAL IN [0 .. testee.length) DO
tester[i] _ testee[i];
IF testee[i].instructionsSimple # testee[i].type.simple THEN {
IF testee[i].type.simple THEN ERROR;
tester[i].type _ testee[i].type.procs.SimpleEquivalent[testee[i].type];
};
tester[i].input _ alwaysInput OR testee[i].output;
tester[i].output _ alwaysOutput OR testee[i].input;
ENDLOOP;
END;

CreateTest: PUBLIC PROC [rootName, typeName, testName: ROPE, decider: ExpandDeciderClosure, sim: Simulation, dual: BOOL _ FALSE] =
BEGIN
testeeType: CellType _ GetCellType[typeName];
test: CellTest;
testerName: ROPE = "tester";
testeeName: ROPE = "testee";
singleType, testerType: CellType;
singleTypeName, topTypeName: ROPE;
sd: SingleData;
td: TesterData;
cth: CellTestHandle;
IF testeeType = NIL THEN ERROR Error[msg: "No such type", data: typeName];
test _ GetTest[name: testName, from: testeeType];
sd _ NEW [SingleDataRep _ [
testeeType: testeeType,
testerTypeName: IO.PutFR["%g-Tester(%g)", IO.rope[typeName], IO.rope[testName]],
testeeTypeName: typeName,
testerName: testerName,
testeeName: testeeName]];
td _ NEW [TesterDataRep _ [
testeeType: testeeType,
test: test]];
singleTypeName _ IO.PutFR["%g-TesterSingle(%g)", IO.rope[typeName], IO.rope[testName]];
IF (testerType _ GetCellType[sd.testerTypeName]) = NIL
THEN testerType _ RegisterCellType[
name: sd.testerTypeName,
ioCreator: CreateTesterIO,
initializer: InitTester,
evals: testerEvals,
ports: MakeTesterPorts[testee: testeeType.ports, alwaysOutput: TRUE],
driveCreator: CreateTesterDrive,
typeData: td];
IF (singleType _ GetCellType[singleTypeName]) = NIL
THEN singleType _ RegisterCellType[
name: singleTypeName,
expandProc: ExpandTestSingle,
evals: [],
ports: NEW [PortsRep[0]],
typeData: sd];
IF dual THEN {
dualTypeName: ROPE _ Rope.Cat[singleTypeName, "-Dual"];
dualType: CellType _ GetCellType[dualTypeName];
dd: DualData _ NEW [DualDataRep _ [singleTypeName]];
IF dualType = NIL THEN dualType _ RegisterCellType[
name: dualTypeName,
expandProc: ExpandDualTester,
evals: [],
ports: NEW [PortsRep[0]],
typeData: dd];
topTypeName _ dualTypeName;
cth _ NEW [CellTestHandleRep.dual _ [sim: sim, test: test, testerType: testerType, testeeType: testeeType, variant: dual[]]];
}
ELSE {
topTypeName _ singleTypeName;
cth _ NEW [CellTestHandleRep.single _ [sim: sim, test: test, testerType: testerType, testeeType: testeeType, variant: single[]]];
};
sim.cth _ cth;
CreateTopCell[instanceName: rootName, typeName: topTypeName, decider: decider, sim: sim];
WITH cth SELECT FROM
scth: SingleCTH => {
scth.testee _ LookupCell[path: LIST[testeeName], from: sim.root];
scth.tester _ LookupCell[path: LIST[testerName], from: sim.root];
};
dcth: DualCTH => {
dcth.testee[1] _ LookupCell[path: LIST["1", testeeName], from: sim.root];
dcth.tester[1] _ LookupCell[path: LIST["1", testerName], from: sim.root];
dcth.testee[2] _ LookupCell[path: LIST["2", testeeName], from: sim.root];
dcth.tester[2] _ LookupCell[path: LIST["2", testerName], from: sim.root];
};
ENDCASE => ERROR;
END;

TesterData: TYPE = REF TesterDataRep;
TesterDataRep: TYPE = RECORD [
testeeType: CellType,
test: CellTest];

SingleData: TYPE = REF SingleDataRep;
SingleDataRep: TYPE = RECORD [
testeeType: CellType,
testerTypeName, testeeTypeName, testerName, testeeName: ROPE];

DualData: TYPE = REF DualDataRep;
DualDataRep: TYPE = RECORD [
singleTypeName: ROPE];

ExpandTestSingle: PROC [thisCell: Cell, to: ExpansionReceiver] --ExpandProc-- =
BEGIN
sd: SingleData _ NARROW[thisCell.type.typeData];
FOR i: INT IN [0 .. sd.testeeType.ports.length) DO
p: Port _ sd.testeeType.ports[i];
[] _ to.class.NodeInstance[erInstance: to.instance, name: p.name, type: p.type];
ENDLOOP;
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: sd.testeeName, typeName: sd.testeeTypeName, interfaceNodes: ""];
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: sd.testerName, typeName: sd.testerTypeName, interfaceNodes: ""];
END;

ExpandDualTester: PROC [thisCell: Cell, to: ExpansionReceiver] --ExpandProc-- =
BEGIN
dd: DualData _ NARROW[thisCell.type.typeData];
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: "1", typeName: dd.singleTypeName, interfaceNodes: ""];
[] _ to.class.CellInstance[erInstance: to.instance, instanceName: "2", typeName: dd.singleTypeName, interfaceNodes: ""];
END;

testerEvals: EvalProcs _ [
PropQ: PropTesterQUD,
PropUD: PropTesterQUD,
ValsChanged: TesterValsChanged,
EvalSimple: TesterSimple];

CellTestHandle: TYPE = REF CellTestHandleRep;
CellTestHandleRep: PUBLIC TYPE = RECORD [
sim: Simulation,
parms: RoseRun.TestParms _ NIL,
switchInstructionsAsAny: REF ANY _ NIL,
switchInstructionsAsWP: WordPtr _ NIL,
simpleInstructionsAsAny: REF ANY _ NIL,
simpleInstructionsAsWP: WordPtr _ NIL,
driveAsAny: REF ANY _ NIL,
driveAsDrive: Drive _ NIL,
test: CellTest,
testerType, testeeType: CellType,
variant: SELECT kind: * FROM
single => [tester, testee: Cell _ NIL],
dual => [
tester, testee: ARRAY [1 .. 2] OF Cell _ ALL[NIL],
altSwitchInstructionsAsAny: REF ANY _ NIL,
altSwitchInstructionsAsWP: WordPtr _ NIL,
altSimpleInstructionsAsAny: REF ANY _ NIL,
altSimpleInstructionsAsWP: WordPtr _ NIL
],
ENDCASE
];

SingleCTH: TYPE = REF CellTestHandleRep.single;
DualCTH: TYPE = REF CellTestHandleRep.dual;

Waiting: TYPE = {Tester, Testee};

NarrowToCellTestHandle: PUBLIC PROC [any: REF ANY] RETURNS [cth: CellTestHandle] = {cth _ NARROW[any]};

GetSimulationFromCellTestHandle: PUBLIC PROC [cth: CellTestHandle] RETURNS [sim: Simulation] = {sim _ cth.sim};

TransferCellTestHandle: PROC [whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY] --Cucumber.PartTransferProc-- = TRUSTED
BEGIN
cth: CellTestHandle _ NARROW[whole];
SELECT part.first FROM
$sim, $tester, $testee, $testeeInitData, $switchInstructionsAsAny, $simpleInstructionsAsAny, $driveAsDrive => NULL;
$parms => Cucumber.Transfer[what: cth.parms, where: where, direction: direction];
$switchInstructionsAsWP => RoseStateIO.TransferWords[cth.switchInstructionsAsWP, cth.testerType.switchWordCount, where, direction];
$simpleInstructionsAsWP => RoseStateIO.TransferWords[cth.simpleInstructionsAsWP, cth.testerType.simpleWordCount, where, direction];
$driveAsAny => Cucumber.Transfer[what: cth.driveAsAny, where: where, direction: direction];
ENDCASE => ERROR;
END;

CreateTesterIO: PROC [ct: CellType, switch: BOOL] RETURNS [ioAsAny: REF ANY] --IOCreator-- =
BEGIN
td: TesterData _ NARROW[ct.typeData];
ioAsAny _ td.testeeType.ioCreator[td.testeeType, switch];
END;

CreateTesterDrive: PROC [ct: CellType] RETURNS [ioAsAny: REF ANY] --DriveCreator-- =
BEGIN
td: TesterData _ NARROW[ct.typeData];
ioAsAny _ td.testeeType.driveCreator[td.testeeType];
END;

InitTester: PROC [cell: Cell] --Initializer-- =
BEGIN
td: TesterData _ NARROW[cell.type.typeData];
cth: CellTestHandle _ cell.sim.cth;
cth.switchInstructionsAsAny _ td.testeeType.ioCreator[td.testeeType, TRUE];
cth.switchInstructionsAsWP _ LOOPHOLE[cth.switchInstructionsAsAny];
cth.simpleInstructionsAsAny _ td.testeeType.ioCreator[td.testeeType, FALSE];
cth.simpleInstructionsAsWP _ LOOPHOLE[cth.simpleInstructionsAsAny];
cth.driveAsAny _ NIL;
cth.driveAsDrive _ NIL;
IF cell.type.driveCreator # NIL THEN {
driveAsAny: REF ANY _ td.testeeType.driveCreator[td.testeeType];
IF driveAsAny # NIL THEN {
driveAsTV: TV;
gotSize: INT;
neededSize: INT _ SIZE[DriveRep[cell.type.ports.length]];
TRUSTED {driveAsTV _ AMBridge.TVForReferent[driveAsAny]};
gotSize _ AMTypes.TVSize[driveAsTV];
IF gotSize < neededSize THEN ERROR Error[IO.PutFR["DriveCreator for cell type %g returned one too small", IO.rope[cell.type.name]], driveAsAny];
cth.driveAsAny _ driveAsAny;
TRUSTED {cth.driveAsDrive _ LOOPHOLE[driveAsAny]};
FOR pi: NAT IN [0 .. cell.type.ports.length) DO
cth.driveAsDrive[pi] _ IF cell.type.ports[pi].input THEN test ELSE IF cell.type.ports[pi].name.Equal["vdd", FALSE] OR cell.type.ports[pi].name.Equal["gnd", FALSE] THEN input ELSE drive;
ENDLOOP;
};
};
cell.realCellStuff.state _ cth;
END;

PropTesterQUD: CellProc--PROC [cell: Cell]-- =
BEGIN
cth: CellTestHandle _ NARROW[cell.realCellStuff.state];
CopyIO[from: cth.switchInstructionsAsWP, to: cell.realCellStuff.switchIOAsWP, by: cell.type.ports, what: forward, simple: FALSE, drive: NIL];
END;

DirectionInstruction: TYPE = {none, forward, backward, check, moveByDrive, checkTests, checkIns};

CopyIO: PROC [from, to: WordPtr, by: Ports, what: DirectionInstruction, simple: BOOLEAN, drive: Drive, cell: Cell _ NIL] =
BEGIN OPEN BitTwiddling;
bbTableSpace: PrincOps.BBTableSpace;
bbTable: PrincOps.BitBltTablePtr;
TRUSTED {bbTable _ PrincOpsUtils.AlignedBBTable[@bbTableSpace]};
FOR portIndex: CARDINAL IN [0 .. by.length) DO
port: Port _ by[portIndex];
di: DirectionInstruction;
bitCount, leftPad: INTEGER;
IF port.type.simple # simple THEN LOOP;
[data: bitCount, leftPad: leftPad] _ port.type.procs.Bits[port.type];
{
field: Field _ IF port.type.simple THEN port.simple ELSE port.switch;
fromPtr: Ptr _ OffsetPtr[WPField[from, field], leftPad];
toPtr: Ptr _ OffsetPtr[WPField[to, field], leftPad];
SELECT what FROM
moveByDrive => IF port.type.simple
THEN {
di _ SELECT drive.drives[portIndex] FROM
test => none,
see => backward,
ignore => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => forward,
ENDCASE => ERROR;
}
ELSE ERROR;
checkTests => IF port.type.simple
THEN {
di _ SELECT drive.drives[portIndex] FROM
test => check,
see => none,
ignore => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => none,
ENDCASE => ERROR;
}
ELSE ERROR;
checkIns => IF port.type.simple
THEN {
di _ SELECT drive.drives[portIndex] FROM
test => check,
see => check,
ignore => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => none,
ENDCASE => ERROR;
}
ELSE ERROR;
none, forward, backward, check => di _ what;
ENDCASE => ERROR;
SELECT di FROM
none => NULL;
forward => Copy[fromPtr, toPtr, bitCount, bbTable];
backward => Copy[toPtr, fromPtr, bitCount, bbTable];
check => IF NOT Equal[fromPtr, toPtr, bitCount] THEN SIGNAL Warning[IO.PutFR["test failed on %g", IO.rope[RoseCreate.LongPortName[cell, portIndex]]]];
moveByDrive, checkTests => ERROR;
ENDCASE => ERROR;
}
ENDLOOP;
END;

Fmt: PROC [n: Node, p: Ptr] RETURNS [rope: ROPE] = {
fmt: Format _ n.type.procs.GetFormat[n.type, ""];
rope _ fmt.FormatValue[n, fmt, p];
};

TesterValsChanged: PROC [cell: Cell, perturb: PROC [portIndex: PortIndex]] --SimpleEval-- =
BEGIN OPEN BitTwiddling;
cth: CellTestHandle _ NARROW[cell.realCellStuff.state];
swp: WordPtr _ WITH cth SELECT FROM
dcth: DualCTH => SELECT cell FROM
dcth.tester[1] => dcth.switchInstructionsAsWP,
dcth.tester[2] => dcth.altSwitchInstructionsAsWP,
ENDCASE => ERROR,
scth: SingleCTH => scth.switchInstructionsAsWP,
ENDCASE => ERROR;
FOR portIndex: NAT IN [0 .. cell.type.ports.length) DO
port: Port _ cell.type.ports[portIndex];
IF (NOT port.type.simple) THEN {
leftPad, bits: INT;
[data: bits, leftPad: leftPad] _ port.type.procs.Bits[port.type];
port.type.procs.CopyVal[
nt: port.type,
from: OffsetPtr[WPField[cell.realCellStuff.switchIOAsWP, port.switch], leftPad],
to: OffsetPtr[WPField[swp, port.switch], leftPad]
];
};
ENDLOOP;
END;

TesterSimple: PROC [cell: Cell, perturb: PROC [portIndex: PortIndex]] --SimpleEval-- =
BEGIN
cth: CellTestHandle _ NARROW[cell.realCellStuff.state];
swp: WordPtr _ cth.simpleInstructionsAsWP;
cellDrive: Drive _ cell.realCellStuff.newDrive;
WITH cth SELECT FROM
dcth: DualCTH => SELECT cell FROM
dcth.tester[1] => NULL;
dcth.tester[2] => {
swp _ dcth.altSimpleInstructionsAsWP;
};
ENDCASE => ERROR;
scth: SingleCTH => NULL;
ENDCASE => ERROR;
FOR pi: PortIndex IN [0 .. cell.type.ports.length) DO
cellDrive[pi] _ MAX[cth.driveAsDrive[pi], FIRST[Strength]];
ENDLOOP;
CopyIO[from: swp, to: cell.realCellStuff.newIOAsWP, by: cell.type.ports, what: moveByDrive, simple: TRUE, drive: cth.driveAsDrive];
cell _ cell;
END;

Eval: PUBLIC PROC [handle: CellTestHandle, returnAfter: ReturnAfter _ returnWhenSettled] RETURNS [happened: StepType] =
BEGIN
iowp: WordPtr _ NIL;
tester: Cell _ NIL;
WITH handle SELECT FROM
dcth: DualCTH => {
ScheduleCell[dcth.tester[1]];
ScheduleCell[dcth.tester[2]];
PerturbDifferences[dcth, dcth.tester[1]];
PerturbDifferences[dcth, dcth.tester[2]];
CopyIO[from: dcth.simpleInstructionsAsWP, to: dcth.altSimpleInstructionsAsWP, by: dcth.testerType.ports, what: forward, simple: TRUE, drive: dcth.driveAsDrive];
CopyIO[from: dcth.switchInstructionsAsWP, to: dcth.altSwitchInstructionsAsWP, by: dcth.testerType.ports, what: forward, simple: FALSE, drive: dcth.driveAsDrive];
};
scth: SingleCTH => {
ScheduleCell[scth.tester];
PerturbDifferences[scth, scth.tester];
};
ENDCASE => ERROR;
IF handle.parms.stopBefore THEN SIGNAL Stop["About to eval"];
DO
happened _ StepSim[handle.sim];
IF (IF happened IN MaskableStepType THEN returnAfter[happened] ELSE TRUE) THEN EXIT;
ENDLOOP;
WITH handle SELECT FROM
dcth: DualCTH => {
tester _ dcth.tester[1];
CopyIO[from: dcth.simpleInstructionsAsWP, to: dcth.altSimpleInstructionsAsWP, by: dcth.testerType.ports, what: checkIns, simple: TRUE, drive: dcth.driveAsDrive, cell: tester];
CopyIO[from: dcth.switchInstructionsAsWP, to: dcth.altSwitchInstructionsAsWP, by: dcth.testerType.ports, what: check, simple: FALSE, drive: dcth.driveAsDrive, cell: tester];
};
scth: SingleCTH => {
tester _ scth.tester;
};
ENDCASE => ERROR;
iowp _ tester.realCellStuff.newIOAsWP;
CopyIO[from: handle.simpleInstructionsAsWP, to: iowp, by: handle.testerType.ports, what: checkTests, simple: TRUE, drive: handle.driveAsDrive, cell: tester];
IF handle.parms.stopAfter THEN SIGNAL Stop["Just eval'd"];
END;

PerturbDifferences: PROC [cth: CellTestHandle, cell: Cell] =
BEGIN OPEN BitTwiddling;
FOR portIndex: PortIndex IN [0 .. cell.type.ports.length) DO
port: Port _ cell.type.ports[portIndex];
different: BOOL _ FALSE;
leftPad: INT;
IF port.type.simple THEN LOOP;
leftPad _ port.type.procs.Bits[port.type].leftPad;
TRUSTED {different _ port.type.procs.CompareUD[
port.type,
OffsetPtr[WPField[cth.switchInstructionsAsWP, port.switch], leftPad],
OffsetPtr[WPField[cell.realCellStuff.switchIOAsWP, port.switch], leftPad]
]};
IF different THEN PerturbNode[node: cell.interfaceNodes[portIndex], agitator: nilSlot, evenIfInput: TRUE];
ENDLOOP;
END;

Test: PUBLIC PROC [sim: Simulation, parms: TestParms, testData: REF ANY _ NIL] =
BEGIN
cth: CellTestHandle _ sim.cth;
test: CellTest _ cth.test;
state: REF ANY _ NIL;
IF test = NIL THEN ERROR Error["Type has no such test proc", cth];
cth.parms _ parms;
IF test.stateToo THEN state _ WITH cth SELECT FROM
scth: SingleCTH => scth.testee.realCellStuff.state,
dcth: DualCTH =>
IF dcth.testee[1].realCellStuff # NIL THEN dcth.testee[1].realCellStuff.state ELSE
IF dcth.testee[2].realCellStuff # NIL THEN dcth.testee[2].realCellStuff.state ELSE ERROR,
ENDCASE => ERROR;
test.proc[handle: cth, testeeType: cth.testeeType, testData: testData, switchInstructions: cth.switchInstructionsAsAny, simpleInstructions: cth.simpleInstructionsAsAny, driveAsAny: cth.driveAsAny, stateAsAny: state];
WHILE StepSim[sim] # noStep DO NULL ENDLOOP;
END;

cthHandler: Cucumber.Handler _ NEW [Cucumber.HandlerRep _ [TransferCellTestHandle]];

cthHandler.Register[CODE[CellTestHandleRep]];

END.
�����[Indigo]<Rosemary>r>Rosemary.DF=>RoseTestingImpl.Mesa
Last Edited by: Spreitzer, July 2, 1985 9:08:24 pm PDT 
Last Edited by: Barth, January 25, 1984 3:44 pm
Last Edited by: Gasbarro, July 17, 1984 3:52:04 pm PDT
�Ê ��–
"cedar" style˜�JšœÏmœ"™5J™7J™/J™6Icode˜�KšÏk	œ3žœp˜®K˜�šÐbxœžœž˜Kšžœ3žœe˜¡Kšžœ!˜(—K˜�Kšžœžœ ˜*K˜�šÐblœžœžœ
˜,Kšœžœ˜Kšœžœ˜ —K˜�Kšžœžœžœ˜Kšœžœ˜K˜�šÏnœžœžœžœ)žœžœ˜uKšž˜K˜Kšœ-˜-Kšœ[˜[Kšžœ˜—K˜�š¡œžœžœžœ˜PKšž˜Kšœžœ!˜3K˜Kšžœ.žœžœžœ˜@Kšžœ$žœžœžœ+˜_šœ ˜ Kšœ˜K˜K˜
Kšœžœ˜Kšœ
žœ$˜1—Kšžœ˜—K˜�š	œ
žœžœžœžœ˜>K˜Kšœžœ˜—K˜�š¡
œžœ)Ïcœ˜LKšž˜Kšœžœ˜.šžœ
žœžœ˜Kšœ.˜.š¡œžœžœ˜-K˜$šžœžœž˜Kšœ'˜'Kšœ@˜@Kšžœžœ˜—Kšœk˜kK˜—Kšœ*˜*Kšœƒ˜ƒK˜—Kšœ=˜=K˜ŽKšžœ˜—K˜�š
¡
œžœžœžœžœ˜0Kšžœžœžœ˜"K˜G—K˜�š¡œžœžœ7˜UKšž˜šžœžœžœž˜9K˜&Kšœ
žœ%˜8Kšœ˜Kšœžœžœ˜Kšžœžœžœžœ˜Kšžœžœžœž˜BKšžœžœžœž˜BKš	žœžœžœ
žœž˜5Kšžœ
žœžœžœ˜6Kš
œ|žœžœžœžœžœžœ˜¼Kšžœ˜—Kšžœ˜—K˜�š¡	œžœžœžœžœžœžœžœ˜<Kšžœžœžœ˜#—K˜�š
¡œžœ,žœžœžœ˜hKšž˜Kšœ	žœ˜'šžœžœžœž˜*K˜šžœ6žœ˜>Kšžœžœžœ˜$KšœG˜GKšœ˜—Kšœžœ˜2Kšœ žœ˜3Kšžœ˜—Kšžœ˜—K˜�š¡
œžœžœ žœ8žœžœ˜‚Kšž˜Kšœ-˜-Kšœ˜Kšœžœ˜Kšœžœ˜K˜!Kšœžœ˜"Kšœ˜Kšœ˜Kšœ˜Kšžœžœžœžœ,˜JKšœ1˜1šœžœ˜Kšœ˜Kšœžœžœžœ˜PKšœ˜Kšœ˜Kšœ˜—šœžœ˜Kšœ˜Kšœ
˜
—Kšœžœžœžœ˜Wšžœ1ž˜6šžœ˜#Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ?žœ˜EKšœ ˜ Kšœ˜——šžœ.ž˜3šžœ˜#Kšœ˜Kšœ˜Kšœ
˜
Kšœžœ˜Kšœ˜——šžœžœ˜Kšœžœ%˜7Kšœ/˜/Kšœžœ"˜4šžœžœžœ˜3Kšœ˜Kšœ˜Kšœ
˜
Kšœžœ˜Kšœ˜—Kšœ˜Kšœžœt˜}K˜—šžœ˜Kšœ˜Kšœžœx˜K˜—Kšœ˜KšœY˜Yšžœžœž˜˜Kšœžœ˜AKšœžœ˜AK˜—˜Kšœ"žœ#˜IKšœ"žœ#˜IKšœ"žœ#˜IKšœ"žœ#˜IK˜—Kšžœžœ˜—Kšžœ˜—K˜�Kšœžœžœ˜%šœžœžœ˜K˜Kšœ˜—K˜�Kšœžœžœ˜%šœžœžœ˜K˜Kšœ8žœ˜>—K˜�Kšœ
žœžœ
˜!šœ
žœžœ˜Kšœžœ˜—K˜�š¡œžœ)¢œ˜OKšž˜Kšœžœ˜0šžœžœžœ#ž˜2K˜!KšœP˜PKšžœ˜—Kšœ‚˜‚Kšœ‚˜‚Kšžœ˜—K˜�š¡œžœ)¢œ˜OKšž˜Kšœžœ˜.Kšœx˜xKšœx˜xKšžœ˜—K˜�šœ˜Kšœ˜Kšœ˜K˜K˜—K˜�Kšœžœžœ˜-šœžœžœžœ˜)K˜Kšœžœ˜Kšœžœžœžœ˜'Kšœ"žœ˜&Kšœžœžœžœ˜'Kšœ"žœ˜&Kšœžœžœžœ˜Kšœžœ˜K˜K˜!šœ	žœ	ž˜Kšœ"žœ˜'šœ	˜	Kš	œžœ
žœžœžœ˜2Kšœžœžœžœ˜*Kšœ%žœ˜)Kšœžœžœžœ˜*Kšœ%ž˜(Kšœ˜—Kšž˜—Kšœ˜—K˜�Kšœžœžœ˜/Kšœ	žœžœ˜+K˜�Kšœ	žœ˜!K˜�Kš¡œžœžœžœžœžœ žœ˜gK˜�Kš¡œžœžœžœ%˜oK˜�š¡œžœ	žœžœžœžœ'žœžœ¢œž˜ªKšž˜Kšœžœ˜$šžœž˜Kšœnžœ˜sKšœQ˜QKšœƒ˜ƒKšœƒ˜ƒKšœ[˜[Kšžœžœ˜—Kšžœ˜—K˜�š¡œžœžœžœžœžœ¢
œ˜\Kšž˜Kšœžœ˜%Kšœ9˜9Kšžœ˜—K˜�š¡œžœžœžœžœ¢œ˜TKšž˜Kšœžœ˜%Kšœ4˜4Kšžœ˜—K˜�š¡
œžœ¢œ˜/Kšž˜Kšœžœ˜,Kšœ#˜#KšœEžœ˜KKšœžœ˜CKšœEžœ˜LKšœžœ˜CKšœžœ˜Kšœžœ˜šžœžœžœ˜&Kšœžœžœ-˜@šžœžœžœ˜Kšœžœ˜Kšœ	žœ˜
Kšœžœžœ#˜9Kšžœ2˜9Kšœ$˜$Kš
žœžœžœžœ?žœ$˜Kšœ˜Kšžœžœ˜2šžœžœžœž˜/Kšœžœžœžœžœ'žœžœ'žœžœžœ˜¹Kšžœ˜—K˜—K˜—Kšœ˜Kšžœ˜—K˜�š¡
œ
¢œ˜.Kšž˜Kšœžœ˜7Kšœzžœ	žœ˜Kšžœ˜—K˜�KšœžœG˜aK˜�š¡œžœDžœžœ˜zKšžœžœ˜Kšœ$˜$Kšœ!˜!Kšžœ9˜@šžœžœžœž˜.Kšœ˜Kšœ˜Kšœžœ˜Kšžœžœžœ˜'K˜EK˜Kšœžœžœ
žœ
˜EK˜8K˜4šžœž˜šœžœ˜"šžœ˜šœžœž˜(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šœ3˜3Kšœ4˜4Kš
œ	žœžœ!žœžœ	žœžœ2˜–Kšœžœ˜!Kšžœžœ˜—K˜Kšžœ˜—Kšžœ˜—K˜�š¡œžœžœžœ˜4Kšœ1˜1Kšœ"˜"K˜—K˜�š¡œžœžœ¢œ˜[Kšžœžœ˜Kšœžœ˜7šœžœžœž˜#šœžœž˜!Kšœ.˜.Kšœ1˜1Kšžœžœ˜—Kšœ/˜/Kšžœžœ˜—šžœžœžœž˜6K˜(šžœžœžœ˜ Kšœžœ˜KšœA˜Ašœ˜Kšœ˜KšœP˜PKšœ1˜1K˜—K˜—Kšžœ˜—Kšžœ˜—K˜�š¡œžœžœ¢œ˜VKšž˜Kšœžœ˜7Kšœ*˜*Kšœ/˜/šžœžœž˜šœžœž˜!Kšœžœ˜šœ˜Kšœ%˜%K˜—Kšžœžœ˜—Kšœžœ˜Kšžœžœ˜—šžœžœž˜5Kšœžœžœ˜;Kšžœ˜—Kšœdžœ˜ƒK˜Kšžœ˜—K˜�š¡œžœžœHžœ˜wKšž˜Kšœžœ˜Kšœžœ˜šžœžœž˜˜Kšœ˜Kšœ˜Kšœ)˜)Kšœ)˜)Kšœ€žœ˜ Kšœ€žœ˜¡K˜—šœž˜Kšœ˜Kšœ&˜&Kšœ˜—Kšžœžœ˜—Kšžœžœžœ˜=šž˜K˜Kšžœžœ
žœžœžœžœžœžœ˜TKšžœ˜—šžœžœž˜˜Kšœ˜Kšœžœ*˜¯Kšœ~žœ*˜­K˜—šœ˜Kšœ˜Kšœ˜—Kšžœžœ˜—Kšœ&˜&Kšœmžœ,˜Kšžœžœžœ˜:Kšžœ˜—K˜�š¡œžœ$˜<Kšžœžœ˜šžœžœž˜<K˜(Kšœžœžœ˜Kšœ	žœ˜
Kšžœžœžœ˜K˜2šžœ(˜/Kšœ
˜
KšœE˜EKšœI˜IKšœ˜—KšžœžœSžœ˜jKšžœ˜—Kšžœ˜—K˜�š¡œžœžœ/žœžœžœ˜PKšž˜Kšœ˜Kšœ˜Kšœžœžœžœ˜Kšžœžœžœžœ*˜BK˜š	žœžœ	žœžœž˜2Kšœ3˜3˜Kšžœ žœžœ$ž˜RKš
žœ žœžœ$žœžœ˜Y—Kšžœžœ˜—KšœØ˜ØKšžœžœžœžœ˜,Kšžœ˜—K˜�Kšœžœ2˜TK˜�Kšœžœ˜-K˜�Kšžœ˜—�…—����JÂ��_¾��