RoseTestingImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Barth, August 1, 1985 2:31:39 pm PDT
Spreitzer, November 18, 1985 10:13:54 pm PST
DIRECTORY Asserting, BasicTime, Core, CoreClasses, CoreFlatten, CoreOps, CoreProperties, GetMe, IO, PrincOps, PrincOpsUtils, Rope, RoseBehavior, RoseBind, RoseBindPrivate, RoseControl, RoseEngine, RosePrivates, RoseSimTypes, RoseWireTwiddling, RoseWireTypes, TimeStamp;
RoseTestingImpl: CEDAR PROGRAM
IMPORTS Asserting, BasicTime, CoreClasses, CoreOps, CoreProperties, GetMe, PrincOpsUtils, Rope, RoseBind, RoseBindPrivate, RoseControl, RoseEngine, RoseWireTwiddling
EXPORTS RoseBind, RoseControl
=
BEGIN OPEN CP: CoreProperties, RoseWireTypes, RoseSimTypes, RoseEngine, RWTg: RoseWireTwiddling;
BehaviorClass: TYPE = REF BehaviorClassRec;
BehaviorClassRec: PUBLIC TYPE = RoseBindPrivate.BehaviorClassRec;
SimulationRec: PUBLIC TYPE = RoseSimTypes.SimulationRec;
CellTestHandleRep: PUBLIC TYPE = RoseSimTypes.CellTestHandleRep;
TestType: TYPE = REF TestTypeRec;
TestTypeRec: TYPE = RECORD [
testerCT, testeeCT: CellType,
testerRCT, testeeRCT: RoseCellType
];
TestRootType: TYPE = REF TestRootTypeRec;
TestRootTypeRec: TYPE = RECORD [
testerCI, testeeCI: CellInstance,
tt: TestType
];
testeeTypeToRootType: ARRAY --expand--BOOL OF ATOM = [
FALSE: CP.RegisterProperty[$RoseTesteeTypeToPairingRootType],
TRUE: CP.RegisterProperty[$RoseTesteeTypeToExpandingRootType]
];
testeeTypeToTesterType: ATOM = CP.RegisterProperty[$RoseTesteeTypeToTesterType];
testeeBehaviorClassToTesterBehaviorClass: ATOM = $RoseTesteeBehaviorClassToTesterBehaviorClass;
testerRootTypeToTesterInstance: ATOM = CP.RegisterProperty[$RoseTesterRootTypeToTesterInstance];
trtKey: ATOM = CP.RegisterProperty[$RoseTestRootTypeKey];
myStamp: TimeStamp.Stamp ← GetMe.GetVersion[];
GetTestSimulation
: PUBLIC PROC [cth: CellTestHandle] RETURNS [simulation: Simulation]
= {simulation ← cth.sim};
InstantiateForTest: PUBLIC PROC [cellType: Core.CellType, expand: BOOLTRUE] RETURNS [cth: CellTestHandle] = {
rootType: CellType ← GetTestRootType[cellType, expand];
simulation: Simulation ← RoseControl.Instantiate[rootType];
cth ← FinishTestInstantiation[simulation, expand, rootType];
};
GetTestRootType: PUBLIC PROC [testeeType: CellType, expand: BOOL] RETURNS [rootType: CellType] = {
testerType: CellType;
tt: TestType;
trt: TestRootType;
rootType ← NARROW[CP.GetCellTypeProp[testeeType, testeeTypeToRootType[expand]]];
IF rootType # NIL THEN RETURN;
testerType ← NARROW[CP.GetCellTypeProp[testeeType, testeeTypeToTesterType]];
IF testerType = NIL THEN {
testeeBehaviorClass, testerBehaviorClass: BehaviorClass;
testerPW: Wire;
goodPrivate: BOOL;
[class: testeeBehaviorClass, goodPrivate: goodPrivate] ← RoseBindPrivate.GetBehaviorClass[testeeType, FALSE, TRUE, TRUE];
IF NOT goodPrivate THEN ERROR;
testerBehaviorClass ← NARROW[Asserting.FnVal[
testeeBehaviorClassToTesterBehaviorClass,
testeeBehaviorClass.other]];
testerPW ← CoreOps.CopyWire[testeeType.public];
IF testerBehaviorClass = NIL THEN {
testerBehaviorClass ← RoseBind.EnsureBehaviorClass[
name: testeeBehaviorClass.name.Cat["Tester"],
publicWirePrototype: Convert[testeeBehaviorClass.publicWirePrototype]
];
testerBehaviorClass.detailsStamp ← myStamp;
testerBehaviorClass.detailsTime ← BasicTime.Now[];
testerBehaviorClass.details ← testerBehaviorDetails;
testerBehaviorClass.unusualDerivation ← [details: TRUE];
[] ← RoseBindPrivate.EnsureBCParts[testerBehaviorClass, FALSE, FALSE, TRUE];
testeeBehaviorClass.other ← Asserting.AssertFn1[
testeeBehaviorClassToTesterBehaviorClass,
testerBehaviorClass,
testeeBehaviorClass.other,
NIL,
TRUE];
};
testerType ← NEW [Core.CellTypeRec ← [
name: testeeType.name.Cat["Tester"],
public: testerPW,
class: CoreClasses.unspecifiedCellClass,
data: NIL,
properties: CP.Props[[RoseBind.classKey, testerBehaviorClass]]
]];
CP.PutCellTypeProp[testeeType, testeeTypeToTesterType, testerType];
CP.PutCellTypeProp[
testerType,
RoseBind.argsKey,
tt ← NEW [TestTypeRec ← [
testerCT: testerType,
testeeCT: testeeType,
testerRCT: GetRoseCellType[testerType, FALSE, TRUE],
testeeRCT: GetRoseCellType[testeeType, FALSE, FALSE]
]]
];
}
ELSE tt ← NARROW[CP.GetCellTypeProp[testerType, RoseBind.argsKey]];
SELECT expand FROM
FALSE => {
iw: Wire ← CoreOps.CopyWire[testeeType.public];
trt ← NEW [TestRootTypeRec ← [
testerCI: NEW [CoreClasses.CellInstanceRec ← [
name: testerName,
actual: iw,
type: testerType
]],
testeeCI: NEW [CoreClasses.CellInstanceRec ← [
name: testeeName,
actual: iw,
type: testeeType
]],
tt: tt
]];
rootType ← NEW [Core.CellTypeRec ← [
name: testeeType.name.Cat[" Test Root"],
class: CoreClasses.recordCellClass,
public: CoreOps.CreateSequenceWire["public wire", NIL],
data: NEW [CoreClasses.RecordCellTypeRec ← [
internal: iw,
instances: LIST[trt.testerCI, trt.testeeCI]
]],
properties: CP.Props[[trtKey, trt]]
]];
};
TRUE => {
testeeRecord, rootRecord: CoreClasses.RecordCellType;
trt ← NEW [TestRootTypeRec ← [
testerCI: NEW [CoreClasses.CellInstanceRec ← [
name: testerName,
actual: testeeType.public,
type: testerType
]],
testeeCI: NIL,
tt: tt
]];
testeeRecord ← NARROW[testeeType.data];
rootRecord ← NEW [CoreClasses.RecordCellTypeRec ← testeeRecord^];
rootRecord.instances ← CONS[
trt.testerCI,
rootRecord.instances
];
rootType ← NEW [Core.CellTypeRec ← testeeType^];
rootType.name ← Rope.Cat["Testing ", testeeType.name];
rootType.data ← rootRecord;
CP.PutCellTypeProp[rootType, trtKey, trt];
};
ENDCASE => ERROR;
CP.PutCellTypeProp[testeeType, testeeTypeToRootType[expand], rootType];
};
testerName: ROPE = "tester";
testeeName: ROPE = "testee";
Convert: PROC [testeePWP: Wire] RETURNS [testerPWP: Wire] = {
ConvertProps: PROC [wire: Wire] RETURNS [subWires: BOOLTRUE, quit: BOOLFALSE] = {
Do: PROC [to, from: ATOM] = {
CP.PutWireProp[wire, to, CP.GetWireProp[wire, from]];
};
Do[RoseBind.switchWire, RoseBind.testerSwitchWire];
Do[RoseBind.complexDrive, RoseBind.testerComplexDrive];
Do[RoseBind.simpleDrive, RoseBind.testerSimpleDrive];
};
testerPWP ← CoreOps.CopyWire[testeePWP];
[] ← CoreOps.VisitWire[testerPWP, ConvertProps];
};
FinishTestInstantiation: PUBLIC PROC [sim: Simulation, expanded: BOOL, rootCellType: CellType] RETURNS [cth: CellTestHandle] = {
trt: TestRootType = NARROW[CP.GetCellTypeProp[rootCellType, trtKey]];
testerRCI: RoseCellInstance = GetRoseCell[sim, trt.testerCI];
cth ← NARROW[testerRCI.state];
cth.sim ← sim;
cth.expanded ← expanded;
cth.testerCI ← trt.testerCI;
cth.testeeCI ← trt.testeeCI;
cth.testerRCI ← testerRCI;
cth.testeeRCI ← IF expanded THEN NIL ELSE GetRoseCell[sim, trt.testeeCI];
cth.instructionFields ← NEW [EffectivePortSeq[cth.testerRCI.effectivePorts.length]];
FOR epi: EffectivePortIndex IN [0 .. cth.instructionFields.length) DO
cep: EffectivePort = cth.testerRCI.effectivePorts[epi];
cth.instructionFields[epi] ← [
switch: Subscript[
RWTg.RefToPtr[cth.switchInstructions, cth.testerRCT.wireTypes[switch]],
cth.testerRCT.wireTypes[switch],
cep.path],
newSimple: Subscript[
RWTg.RefToPtr[cth.simpleInstructions, cth.testerRCT.wireTypes[simple]],
cth.testerRCT.wireTypes[simple],
cep.path],
oldSimple: nilPtr,
newDrive: Subscript[
RWTg.RefToPtr[cth.driveInstructions, cth.testerRCT.wireTypes[drive]],
cth.testerRCT.wireTypes[drive],
cep.path,
TRUE],
oldDrive: nilPtr,
type: cep.type,
implType: cep.implType,
path: cep.path,
input: cep.input,
output: cep.output,
XPhobic: cep.XPhobic,
transduced: cep.transduced
];
ENDLOOP;
sim ← sim;
};
testerBehaviorDetails: RoseBehavior.Details ← NEW [RoseBehavior.DetailsRec ← [
EvalSimple: EvalTesterSimple,
ValsChanged: TesterValsChanged,
InitQ: NIL,
PropQ: PropTesterQUD,
InitUD: NIL,
PropUD: PropTesterQUD,
FinalUD: NIL,
EnumerateVicinity: NIL,
CreateState: CreateTesterState
]];
EvalTesterSimple: PROC [argsAny, switchAny, simpleAny, strengthAny, stateAny: REF ANY, perturb: PROC [portPath: PortPath]] --EvalProc-- = {
cth: CellTestHandle = NARROW[stateAny];
driveType: RoseWireType = cth.testerRCT.wireTypes[drive];
RWTg.CopyAndLimitDrive[
type: driveType,
fromP: cth.driveInstructionsAsPtr,
toP: RWTg.RefToPtr[cth.testerRCI.newDrive, driveType],
min: FIRST[Strength]
];
CopyIO[from: cth.instructionFields, to: cth.testerRCI.effectivePorts, what: moveByDrive, flavor: simple];
argsAny ← argsAny;
};
TesterValsChanged: PROC [argsAny, switchAny, simpleAny, strengthAny, stateAny: REF ANY, perturb: PROC [portPath: PortPath]] --EvalProc-- = {
cth: CellTestHandle = NARROW[stateAny];
CopyIO[from: cth.testerRCI.effectivePorts, to: cth.instructionFields, what: levelForward, flavor: switch];
argsAny ← argsAny;
};
PropTesterQUD: PROC [argsAny, switchAny, simpleAny, strengthAny, stateAny: REF ANY, perturb: PROC [portPath: PortPath]] --EvalProc-- = {
cth: CellTestHandle ← NARROW[stateAny];
CopyIO[from: cth.instructionFields, to: cth.testerRCI.effectivePorts, what: forward, flavor: switch];
argsAny ← argsAny;
};
DirectionInstruction: TYPE = {none, forward, backward, check, moveByDrive, checkTests, checkIns, levelForward};
CopyIO: PROC [from, to: EffectivePortS, what: DirectionInstruction, flavor: WireFlavor] = {
bbTableSpace: PrincOps.BBTableSpace;
bbTable: PrincOps.BitBltTablePtr;
TRUSTED {bbTable ← PrincOpsUtils.AlignedBBTable[@bbTableSpace]};
IF from.length # to.length THEN ERROR;
FOR epi: EffectivePortIndex IN [0 .. to.length) DO
rwt: RoseWireType ← to[epi].type;
di: DirectionInstruction;
IF rwt.class.super.flavor # flavor THEN LOOP;
{
fromPtr: Ptr ← SELECT rwt.class.super.flavor FROM
simple => from[epi].newSimple,
switch => from[epi].switch,
ENDCASE => ERROR;
toPtr: Ptr ← SELECT rwt.class.super.flavor FROM
simple => to[epi].newSimple,
switch => to[epi].switch,
ENDCASE => ERROR;
fromDrivePtr: Ptr = from[epi].newDrive;
SELECT what FROM
moveByDrive => SELECT rwt.class.super.flavor FROM
simple => {
di ← SELECT RWTg.ReadDrive[fromDrivePtr] FROM
test => none,
see => backward,
none => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => forward,
ENDCASE => ERROR;
};
ENDCASE => ERROR;
checkTests => SELECT rwt.class.super.flavor FROM
simple => {
di ← SELECT RWTg.ReadDrive[fromDrivePtr] FROM
test => check,
see => none,
none => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => none,
ENDCASE => ERROR;
};
ENDCASE => ERROR;
checkIns => SELECT rwt.class.super.flavor FROM
simple => {
di ← SELECT RWTg.ReadDrive[fromDrivePtr] FROM
test => check,
see => check,
none => none,
chargeWeak, chargeMediumWeak, charge, chargeMediumStrong, chargeStrong, chargeVeryStrong, driveWeak, driveMediumWeak, drive, driveMediumStrong, driveStrong, driveVeryStrong, input => none,
ENDCASE => ERROR;
};
ENDCASE => ERROR;
none, forward, backward, check, levelForward => di ← what;
ENDCASE => ERROR;
SELECT di FROM
none => NULL;
forward => RWTg.CopyVal[rwt, rwt, fromPtr, toPtr, bbTable];
levelForward => RWTg.CopyLevel[rwt, rwt, fromPtr, toPtr];
backward => RWTg.CopyVal[rwt, rwt, toPtr, fromPtr, bbTable];
check => IF NOT RWTg.EqualVal[rwt, rwt, fromPtr, toPtr] THEN SIGNAL RoseControl.Warning["test failed"];
moveByDrive, checkTests, checkIns => ERROR;
ENDCASE => ERROR;
}
ENDLOOP;
what ← what;
};
CreateTesterState: PROC [argsAny: REF ANYNIL] RETURNS [stateAny: REF ANYNIL] = {
tt: TestType = NARROW[argsAny];
cth: CellTestHandle = NEW [CellTestHandleRep ← [
sim: NIL,
expanded: FALSE--not necessarily ... real value set later--,
testerCT: tt.testerCT,
testeeCT: tt.testeeCT,
switchInstructions: tt.testerRCT.behaviorClass.private.createSwitch[tt.testeeCT.public],
simpleInstructions: tt.testerRCT.behaviorClass.private.createSimple[tt.testeeCT.public],
driveInstructions: tt.testerRCT.behaviorClass.private.createDrive[tt.testeeCT.public],
testerRCT: tt.testerRCT,
testeeRCT: tt.testeeRCT
]];
cth.driveInstructionsAsPtr ← RWTg.RefToPtr[cth.driveInstructions, tt.testerRCT.wireTypes[drive]];
stateAny ← cth;
};
Subscript: PROC [p: Ptr, rwt: RoseWireType, path: PortPath, driveHack: BOOLFALSE] RETURNS [q: Ptr] = {
IF path = NIL THEN RETURN [p];
{
q ← Subscript[
RWTg.SubPtr[rwt, p, path.first, driveHack],
RWTg.SubType[rwt, path.first, driveHack],
path.rest,
driveHack
];
};
};
Test: PUBLIC PROC [cth: CellTestHandle, testProc: RoseControl.TestProc, testData: REF ANYNIL, stateToo: BOOLFALSE, steady: BOOLTRUE] =
BEGIN
sim: Simulation = cth.sim;
test: CellTest = NEW [CellTestRec ← [testProc, testData, stateToo]];
ctl: TestControl = NEW [TestControlRec ← []];
Eval: PROC = {
tester: RoseCellInstance ← cth.testerRCI;
ScheduleCell[tester];
PerturbDifferences[cth, tester];
IF cth.ctl.stopBefore THEN SIGNAL RoseControl.Stop["About to eval"];
RoseControl.Settle[sim];
CopyIO[from: cth.instructionFields, to: tester.effectivePorts, what: checkTests, flavor: simple];
IF cth.ctl.stopAfter THEN SIGNAL RoseControl.Stop["Just eval'd"];
};
state: REF ANYIF stateToo THEN IF cth.testeeRCI # NIL THEN cth.testeeRCI.state ELSE ERROR ELSE NIL;
cth.test ← test;
cth.ctl ← ctl;
RoseControl.Initialize[sim, steady];
test.testProc[
testeeType: cth.testeeCT,
testData: test.testData,
switchInstructions: cth.switchInstructions,
simpleInstructions: cth.simpleInstructions,
driveInstructions: cth.driveInstructions,
stateAny: state,
Eval: Eval
];
RoseControl.Settle[sim];
cth.test ← NIL;
cth.ctl ← NIL;
END;
PerturbDifferences: PROC [cth: CellTestHandle, cell: RoseCellInstance] = {
cell ← cell;
FOR epi: EffectivePortIndex IN [0 .. cell.effectivePorts.length) DO
rwt: RoseWireType ← cell.effectivePorts[epi].type;
different: BOOLFALSE;
SELECT rwt.class.super.flavor FROM
simple => LOOP;
switch => NULL;
drive => ERROR;
ENDCASE => ERROR;
different ← NOT RWTg.EqualUD[
rwt,
rwt,
cell.effectivePorts[epi].switch,
cth.instructionFields[epi].switch];
IF different THEN PerturbWire[rw: cell.connectedWires[epi], agitator: [cell, cell.effectivePorts[epi].path], evenIfInput: TRUE];
ENDLOOP;
cth ← cth;
};
END.