DIRECTORY AMBridge, AMTypes, Ascii, Asserting, Cucumber, IO, OrderedSymbolTableRef, Rope, RoseClocks, RoseCreate, RoseIOHacks, RoseRun, RoseStateIO, RoseTypes; RoseTestingImpl: CEDAR PROGRAM IMPORTS AMBridge, AMTypes, Ascii, Asserting, Cucumber, IO, OrderedSymbolTableRef, Rope, RoseClocks, RoseCreate, RoseRun, RoseStateIO, RoseTypes EXPORTS RoseCreate, RoseIOHacks, RoseRun, RoseTypes = BEGIN OPEN RoseTypes, RoseIOHacks, RoseRun, RoseCreate; InterfaceMismatch: PUBLIC ERROR [cell: Cell, index: CARDINAL, expected, got: NodeType] = CODE; TV: TYPE = AMTypes.TV; Type: TYPE = AMTypes.Type; MirrorPorts: PUBLIC PROC [fwd: Ports, alwaysOutput, alwaysInput: BOOL _ FALSE] RETURNS [bkwd: Ports] = BEGIN bkwd _ NEW [PortsRep[fwd.length]]; FOR i: CARDINAL IN [0 .. fwd.length) DO bkwd[i] _ fwd[i]; bkwd[i].input _ alwaysInput OR fwd[i].output; bkwd[i].output _ alwaysOutput OR fwd[i].input; ENDLOOP; END; MakeMoreIO: PUBLIC PROC [cell: Cell, bToo: BOOL] RETURNS [a, b: REF ANY] = TRUSTED BEGIN a _ cell.type.ioCreator[cell.type]; IF bToo THEN b _ cell.type.ioCreator[cell.type]; END; WrapTop: PUBLIC PROC [rootName, typeName: ROPE, decider: ExpandDeciderClosure, clocks: ROPE _ NIL, sim: Simulation] RETURNS [root: Cell] = BEGIN rootType: CellType; rootType _ GetWrappingType[typeName, clocks]; root _ 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]; EnsureEnvironment[in: thisCell, forType: wc.subType, to: to]; [] _ to.class.CellInstance[erInstance: to.instance, instanceName: LowerFirst[wc.subType.name], typeName: wc.subType.name, interfaceNodes: ""]; IF wc.clocks # NIL THEN [] _ to.class.CellInstance[erInstance: to.instance, instanceName: "clockGen", typeName: RoseClocks.ClockGen[[]].name, interfaceNodes: wc.clocks]; 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]]; id: REF ANY _ NIL; IF node # NIL THEN LOOP; IF port.name.Equal["gnd", FALSE] THEN id _ $ZeroPower ELSE IF port.name.Equal["vdd", FALSE] THEN id _ $PlusPower ELSE IF port.input AND NOT port.output THEN id _ $Input ELSE IF port.output AND NOT port.input THEN id _ $Output; [] _ to.class.NodeInstance[erInstance: to.instance, name: port.name, type: port.type, initData: id]; ENDLOOP; END; ProcToInt: PROC [p: PROC ANY RETURNS ANY] RETURNS [i: INT] = TRUSTED {i _ LOOPHOLE[p, INTEGER]}; CreateTest: PUBLIC PROC [rootName, typeName, testName: ROPE, decider: ExpandDeciderClosure, sim: Simulation] RETURNS [root: Cell, cth: CellTestHandle] = BEGIN testeeType: CellType _ GetCellType[typeName]; test: CellTest; testerName: ROPE = "tester"; testeeName: ROPE = "testee"; rootType, testerType: CellType; rootTypeName: ROPE; rd: RootData; td: TesterData; IF testeeType = NIL THEN ERROR Error[msg: "No such type", data: typeName]; test _ GetTest[name: testName, from: testeeType]; rd _ NEW [RootDataRep _ [ 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]]; rootTypeName _ IO.PutFR["%g-%g-%g-TesterRoot[%g, %g]", IO.rope[testerName], IO.rope[testeeName], IO.rope[typeName], IO.rope[testName]]; IF (testerType _ GetCellType[rd.testerTypeName]) = NIL THEN testerType _ RegisterCellType[ name: rd.testerTypeName, ioCreator: CreateTesterIO, initializer: InitTester, evals: testerEvals, ports: RoseCreate.MirrorPorts[fwd: testeeType.ports, alwaysOutput: TRUE], driveCreator: testeeType.driveCreator, typeData: td]; IF (rootType _ GetCellType[rootTypeName]) = NIL THEN rootType _ RegisterCellType[ name: rootTypeName, expandProc: ExpandTestRoot, evals: [], ports: NEW [PortsRep[0]], typeData: rd]; cth _ NEW [CellTestHandleRep _ [sim: sim, test: test]]; sim.other _ Asserting.AssertFn1[fn: cthKey, val: cth, inAdditionTo: sim.other]; root _ CreateTopCell[instanceName: rootName, typeName: rootType.name, decider: decider, sim: sim]; cth.testee _ LookupCell[path: LIST[testeeName], from: root]; cth.tester _ LookupCell[path: LIST[testerName], from: root]; END; cthKey: ATOM _ $cthKey; TesterData: TYPE = REF TesterDataRep; TesterDataRep: TYPE = RECORD [ testeeType: CellType, test: CellTest]; RootData: TYPE = REF RootDataRep; RootDataRep: TYPE = RECORD [ testeeType: CellType, testerTypeName, testeeTypeName, testerName, testeeName: ROPE]; ExpandTestRoot: PROC [thisCell: Cell, to: ExpansionReceiver] --ExpandProc-- = BEGIN rd: RootData _ NARROW[thisCell.type.typeData]; FOR i: INT IN [0 .. rd.testeeType.ports.length) DO p: Port _ rd.testeeType.ports[i]; [] _ to.class.NodeInstance[erInstance: to.instance, name: p.name, type: p.type]; ENDLOOP; [] _ to.class.CellInstance[erInstance: to.instance, instanceName: rd.testeeName, typeName: rd.testeeTypeName, interfaceNodes: ""]; [] _ to.class.CellInstance[erInstance: to.instance, instanceName: rd.testerName, typeName: rd.testerTypeName, interfaceNodes: ""]; END; testerEvals: EvalProcs _ [ PropQ: PropTesterQUD, PropUD: PropTesterQUD, ValsChanged: TesterValsChanged, EvalSimple: TesterSimple]; CellTestHandle: TYPE = REF CellTestHandleRep; CellTestHandleRep: PUBLIC TYPE = RECORD [ sim: Simulation, tester, testee: Cell _ NIL, parms: RoseRun.TestParms _ NIL, instructionsAsAny: REF ANY _ NIL, instructionsAsWP: LONG POINTER TO CARDINAL _ NIL, driveAsAny: REF ANY _ NIL, driveAsDrive: Drive _ NIL, first: BOOLEAN _ FALSE, test: CellTest ]; 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, $instructionsAsAny, $driveAsDrive => NULL; $parms => Cucumber.Transfer[what: cth.parms, where: where, direction: direction]; $instructionsAsWP => RoseStateIO.TransferWords[cth.instructionsAsWP, cth.tester.type.ioWordCount, where, direction]; $driveAsAny => Cucumber.Transfer[what: cth.driveAsAny, where: where, direction: direction]; ENDCASE => ERROR; END; CreateTesterIO: PROC [ct: CellType] RETURNS [ioAsAny: REF ANY] --IOCreator-- = BEGIN td: TesterData _ NARROW[ct.typeData]; ioAsAny _ td.testeeType.ioCreator[td.testeeType]; END; InitTester: PROC [cell: Cell, leafily: BOOLEAN] --Initializer-- = BEGIN IF leafily THEN BEGIN td: TesterData _ NARROW[cell.type.typeData]; cth: CellTestHandle _ NARROW[Asserting.FnVal[fn: cthKey, from: cell.sim.other]]; cth.instructionsAsAny _ MakeMoreIO[cell: cell, bToo: FALSE].a; cth.instructionsAsWP _ LOOPHOLE[cth.instructionsAsAny]; 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 Drive; ENDLOOP; }; }; cell.realCellStuff.state _ cth; END; END; PropTesterQUD: CellProc--PROC [cell: Cell]-- = BEGIN cth: CellTestHandle _ NARROW[cell.realCellStuff.state]; CopyIO[from: cth.instructionsAsWP, to: cell.realCellStuff.switchIOAsWP, by: cell.type.ports, what: forward, specials: FALSE, generals: TRUE, simples: FALSE, drive: NIL]; END; CopyIO: PUBLIC PROC [from, to: WordPtr, by: Ports, what: DirectionInstruction, specials, generals, simples: BOOLEAN, drive: Drive] = BEGIN FOR portIndex: CARDINAL IN [0 .. by.length) DO port: Port _ by[portIndex]; afterLast: CARDINAL; di: DirectionInstruction; IF NOT (IF port.type.simple THEN simples ELSE IF port.special THEN specials ELSE generals) THEN LOOP; SELECT what FROM firstFoo, restFoo => IF port.type.simple THEN { di _ SELECT drive.drives[portIndex] FROM Drive => IF what = firstFoo THEN forward ELSE IF what = restFoo THEN check ELSE ERROR, Ignore, Test => none, ENDCASE => ERROR; } ELSE IF port.special THEN { di _ udFwdLBack; } ELSE ERROR; none, forward, backward, check, udFwdLBack => di _ what; ENDCASE => ERROR; afterLast _ port.firstWord + port.wordCount; SELECT di FROM none => NULL; forward => FOR c: CARDINAL IN [port.firstWord .. afterLast) DO TRUSTED {(to + c)^ _ (from + c)^}; ENDLOOP; backward => FOR c: CARDINAL IN [port.firstWord .. afterLast) DO TRUSTED {(from + c)^ _ (to + c)^}; ENDLOOP; udFwdLBack => TRUSTED { port.type.procs.CopyUD[nt: port.type, from: from+port.firstWord, to: to+port.firstWord]; port.type.procs.CopyVal[nt: port.type, from: to+port.firstWord, to: from+port.firstWord]; }; check => FOR c: CARDINAL IN [port.firstWord .. afterLast) DO TRUSTED {IF (from + c)^ # (to + c)^ THEN SIGNAL Warning[IO.PutFR["Port %g has an error", IO.rope[port.name]]]}; ENDLOOP; ENDCASE => ERROR; ENDLOOP; END; TesterValsChanged: PROC [cell: Cell] --CellProc-- = BEGIN cth: CellTestHandle _ NARROW[cell.realCellStuff.state]; FOR portIndex: NAT IN [0 .. cell.type.ports.length) DO port: Port _ cell.type.ports[portIndex]; IF (NOT port.type.simple) AND (NOT port.special) THEN TRUSTED { port.type.procs.ValFromNode[cell.interfaceNodes[portIndex], cth.instructionsAsWP + port.firstWord]}; ENDLOOP; END; TesterSimple: PROC [cell: Cell] --CellProc-- = BEGIN cth: CellTestHandle _ NARROW[cell.realCellStuff.state]; bw: DirectionInstruction _ restFoo; IF cth.first THEN {bw _ firstFoo; cth.first _ FALSE}; CopyIO[from: cth.instructionsAsWP, to: cell.realCellStuff.newIOAsWP, by: cell.type.ports, what: bw, specials: TRUE, generals: FALSE, simples: TRUE, drive: cth.driveAsDrive]; END; Eval: PUBLIC PROC [handle: CellTestHandle, returnAfter: ReturnAfter _ returnWhenSettled] RETURNS [happened: StepType] = BEGIN ScheduleCell[handle.tester]; PerturbDifferences[handle]; handle.first _ TRUE; IF handle.parms.stopBefore THEN SIGNAL Stop["About to eval", handle.testee]; DO happened _ StepSim[handle.sim]; IF (IF happened IN MaskableStepType THEN returnAfter[happened] ELSE TRUE) THEN EXIT; ENDLOOP; FOR portIndex: CARDINAL IN [0 .. handle.tester.type.ports.length) DO port: Port _ handle.tester.type.ports[portIndex]; diff: BOOLEAN _ FALSE; newWP: WordPtr; oldWP: WordPtr; IF (NOT port.type.simple) OR handle.driveAsDrive.drives[portIndex]=Ignore THEN LOOP; TRUSTED BEGIN newWP _ handle.instructionsAsWP + port.firstWord; oldWP _ handle.tester.realCellStuff.newIOAsWP + port.firstWord; END; FOR i: CARDINAL IN [0 .. port.wordCount) DO TRUSTED BEGIN IF newWP^ # oldWP^ THEN {diff _ TRUE; EXIT}; newWP _ newWP + 1; oldWP _ oldWP + 1; END; ENDLOOP; IF diff THEN SIGNAL Stop[IO.PutFR["Port %g failed", IO.rope[port.name]], handle.testee]; ENDLOOP; IF handle.parms.stopAfter THEN SIGNAL Stop["Just eval'd", handle.testee]; END; PerturbDifferences: PROC [cth: CellTestHandle] = BEGIN FOR portIndex: CARDINAL IN [0 .. cth.tester.type.ports.length) DO port: Port _ cth.tester.type.ports[portIndex]; different: BOOLEAN _ FALSE; IF port.type.simple OR port.special THEN LOOP; TRUSTED {different _ port.type.procs.CompareUD[nt: port.type, wp1: cth.instructionsAsWP + port.firstWord, wp2: cth.tester.realCellStuff.switchIOAsWP + port.firstWord]}; IF different THEN PerturbPort[cell: cth.tester, index: portIndex, evenIfInput: TRUE]; ENDLOOP; END; Test: PUBLIC PROC [sim: Simulation, cth: CellTestHandle, parms: TestParms, testData: REF ANY _ NIL] = BEGIN test: CellTest _ NARROW[cth.testee.type.testers.Lookup[cth.test.name]]; IF test = NIL THEN ERROR Error["Type has no such test proc", cth]; cth.parms _ parms; test.proc[handle: cth, testeeType: cth.testee.type, testData: testData, io: cth.instructionsAsAny, driveAsAny: cth.driveAsAny, stateAsAny: IF test.stateToo THEN cth.testee.realCellStuff.state ELSE NIL]; WHILE StepSim[sim] # noStep DO NULL ENDLOOP; END; cthHandler: Cucumber.Handler _ NEW [Cucumber.HandlerRep _ [TransferCellTestHandle]]; cthHandler.Register[CODE[CellTestHandleRep]]; END. [Indigo]2.8>Rosemary.DF=>RoseTestingImpl.Mesa Last Edited by: Spreitzer, February 12, 1985 6:18:01 pm PST Last Edited by: Barth, April 23, 1985 4:59:54 pm PST Last Edited by: Gasbarro, July 17, 1984 3:52:04 pm PDT Last Edited by: Monier, April 23, 1985 6:24:07 pm PST Κ– "cedar" style˜J™7J™K˜Kšœœ˜—K˜š  œœ)Οcœ˜LKš˜Kšœœ˜.Kšœ=˜=K˜ŽKšœ œœ’˜©Kšœ˜—K˜š   œœœœœ˜0Kšœœœ˜"K˜G—K˜š œœœ7˜UKš˜šœ œœ˜9K˜&Kšœ œ%˜8Kšœœœœ˜Kšœœœœ˜Kšœœœ˜:Kšœœœ˜:Kš œ œœ œ ˜7Kšœ œœ œ˜4K˜dKšœ˜—Kšœ˜—K˜š  œœœœœœœœ˜—K˜š œœ)‘œ˜MKš˜Kšœœ˜.šœœœ#˜2K˜!KšœP˜PKšœ˜—Kšœ‚˜‚Kšœ‚˜‚Kšœ˜—K˜šœ˜Kšœ˜Kšœ˜K˜K˜—K˜Kšœœœ˜-šœœœœ˜)K˜Kšœœ˜Kšœœ˜Kšœœœœ˜!Kš œœœœœœ˜1Kšœ œœœ˜Kšœœ˜Kšœœœ˜K˜Kšœ˜—K˜Kšœ œ˜!K˜Kš œœœœœœ œ˜gK˜Kš œœœœ%˜oK˜š œœ œœœœ'œœ‘œ˜ͺKš˜Kšœœ˜$šœ ˜KšœNœ˜SKšœQ˜QKšœt˜tKšœ[˜[Kšœœ˜—Kšœ˜—K˜š  œœœ œœ‘ œ˜NKš˜Kšœœ˜%Kšœ1˜1Kšœ˜—K˜š  œœœ‘œ˜AKš˜šœ ˜Kš˜Kšœœ˜,Kšœœ4˜PKšœ5œ˜>Kšœœ˜7Kšœœ˜Kšœœ˜šœœœ˜&Kšœ œœ-˜@šœœœ˜Kšœ œ˜Kšœ œ˜ Kšœ œœ#˜9Kšœ2˜9Kšœ$˜$Kš œœœœ?œ$˜Kšœ˜Kšœœ˜2šœœœ˜/Kšœœœœ˜IKšœ˜—K˜—K˜—Kšœ˜Kšœ˜—Kšœ˜—K˜š  œ ‘œ˜.Kš˜Kšœœ˜7Kš œvœ œ œ œ˜©Kšœ˜—K˜š œœœYœ˜„Kš˜šœ œœ˜.Kšœ˜Kšœ œ˜Kšœ˜Kšœœœœ œœœ œ œœ˜ešœ˜šœœ˜(šœ˜šœœ˜(šœ œœ ˜-Kšœœ˜!Kšœ˜—Kšœ˜Kšœœ˜—K˜—šœœœ˜Kšœ˜K˜—Kšœœ˜ —Kšœ8˜8Kšœœ˜—Kšœ,˜,šœ˜Kšœœ˜ šœ œœœ˜>Kšœ˜"Kšœ˜—šœ œœœ˜?Kšœ˜"Kšœ˜—šœœ˜KšœX˜XKšœY˜YK˜—šœ œœœ˜œ˜UKšœ˜—Kšœ˜—K˜š  œœœDœœœ˜eKš˜Kšœœ0˜GKšœœœœ*˜BK˜Kš œ‹œœ œœ˜ΚKšœœœœ˜,Kšœ˜—K˜Kšœœ2˜TK˜Kšœœ˜-K˜Kšœ˜—…—4’E?