DIRECTORY BrineIO, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, IO, NewBasicRosemary, RefTab, Rope; NewBasicRosemaryImpl: CEDAR PROGRAM IMPORTS BrineIO, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, IO, RefTab, Rope EXPORTS NewBasicRosemary = BEGIN OPEN NewBasicRosemary; roseFixedWireProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $RoseFixedWire, properties: CoreProperties.Props[[CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc _ RoseFixedWirePrint]]]], write: RoseFixedWireWrite, read: RoseFixedWireRead]; RoseFixedWirePrint: CoreProperties.PropPrintProc = { lev: REF Level _ NARROW[val]; CoreOps.PrintIndent[indent, to]; IO.PutF[to, "%g: ", IO.atom[roseFixedWireProp]]; IO.PutRope[to, levelNames[lev^]]; }; RoseFixedWireWrite: CoreIO.PropWriteProc = { level: REF Level _ NARROW[value]; BrineIO.WriteID[stream, levelNames[level^]]; }; RoseFixedWireRead: CoreIO.PropReadProc = { level: REF Level _ NEW[Level]; level^ _ FindLevel[BrineIO.ReadID[stream]]; value _ level; }; SetFixedWire: PUBLIC PROC [wire: Core.Wire, level: Level _ L] RETURNS [sameWire: Core.Wire] = { CoreProperties.PutWireProp[on: wire, prop: roseFixedWireProp, value: NEW[Level _ level]]; sameWire _ wire; }; SetNamedFixedWire: PUBLIC PROC [cellType: Core.CellType, name: Rope.ROPE, level: Level _ L] RETURNS [sameWire: Core.Wire] = { sameWire _ SetFixedWire[CoreOps.FindWire[cellType.public, name], level]; }; Instantiate: PUBLIC PROC [cellType: Core.CellType] RETURNS [simulation: RoseSimulation] = { FlattenCell: CoreFlat.BoundFlatCellProc = { SELECT TRUE FROM cell.class=CoreClasses.transistorCellClass => { public: Core.Wire _ cell.public; coreTransistor: CoreClasses.Transistor _ NARROW[cell.data]; roseTransistor: RoseTransistor _ NEW[RoseTransistorRec]; roseTransistor.gate _ LookUpRoseWire[public[gate], bindings]; roseTransistor.gate.gates _ CONS[roseTransistor, roseTransistor.gate.gates]; roseTransistor.ch1 _ LookUpRoseWire[public[ch1], bindings]; roseTransistor.ch1.channels _ CONS[roseTransistor, roseTransistor.ch1.channels]; roseTransistor.ch1.notOffChannels _ CONS[roseTransistor, roseTransistor.ch1.notOffChannels]; roseTransistor.ch2 _ LookUpRoseWire[public[ch2], bindings]; roseTransistor.ch2.channels _ CONS[roseTransistor, roseTransistor.ch2.channels]; roseTransistor.ch2.notOffChannels _ CONS[roseTransistor, roseTransistor.ch2.notOffChannels]; roseTransistor.transistorType _ coreTransistor.type; roseTransistor.flatCellType _ flatCell; }; cell.class=CoreClasses.recordCellClass => { AllocateWire: PROC [coreWire: Core.Wire] = { flatWire: CoreFlat.FlatWire _ IF bindings=NIL THEN NIL ELSE NARROW[RefTab.Fetch[x: bindings, key: coreWire].val]; IF flatWire=NIL THEN { wireKey.flatCell _ flatCell; wireKey.wire _ coreWire; IF RefTab.Fetch[x: simulation.coreToRoseWires, key: wireKey].val=NIL THEN { wireFixedRef: REF Level _ NARROW[CoreProperties.GetWireProp[from: coreWire, prop: roseFixedWireProp]]; roseWire: RoseWire _ NEW[RoseWireRec]; roseWire.flatWire _ wireKey^; Perturb[simulation, roseWire]; IF wireFixedRef#NIL THEN { roseWire.wireSize _ infinite; roseWire.wireLevel _ wireFixedRef^ }; IF NOT RefTab.Insert[x: simulation.coreToRoseWires, key: roseWire, val: roseWire] THEN ERROR; }; }; }; cellTypeRCT: CoreClasses.RecordCellType _ NARROW[cell.data]; CoreOps.VisitRootAtomics[cellTypeRCT.internal, AllocateWire]; CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCell]; }; ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCell]; }; LookUpRoseWire: PROC [wire: Core.Wire, bindings: RefTab.Ref] RETURNS [roseWire: RoseWire _ NIL] = { leftUpper: CoreFlat.FlatWire _ NARROW[RefTab.Fetch[x: bindings, key: wire].val]; roseWire _ NARROW[RefTab.Fetch[x: simulation.coreToRoseWires, key: leftUpper].val]; }; ComputeMaxVicinity: RefTab.EachPairAction = { roseWire: RoseWire _ NARROW[val]; IF roseWire.wireSize#infinite AND NOT roseWire.mark THEN maxVicinity _ MAX[maxVicinity, CountVicinity[roseWire]]; }; CountVicinity: PROC [wire: RoseWire, currentCount: NAT _ 0] RETURNS [newCount: NAT] = { wire.mark _ TRUE; newCount _ currentCount + 1; FOR rts: RoseTransistors _ wire.channels, rts.rest UNTIL rts=NIL DO tran: RoseTransistor _ rts.first; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; IF otherWire.wireSize#infinite AND NOT otherWire.mark THEN newCount _ CountVicinity[otherWire, newCount]; ENDLOOP; }; gate: NAT = CoreClasses.TransistorPort.gate.ORD; ch1: NAT = CoreClasses.TransistorPort.ch1.ORD; ch2: NAT = CoreClasses.TransistorPort.ch2.ORD; wireKey: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; maxVicinity: NAT _ 0; simulation _ NEW[RoseSimulationRec]; simulation.cellType _ cellType; simulation.coreToRoseWires _ RefTab.Create[mod: 1019, equal: RoseWireEqual, hash: RoseWireHash]; FlattenCell[cell: cellType]; [] _ RefTab.Pairs[x: simulation.coreToRoseWires, action: ComputeMaxVicinity]; FOR strength: Drive IN Drive DO simulation.vicinityByStrength[strength].wires _ NEW[RoseWireSeq[maxVicinity]]; ENDLOOP; }; Settle: PUBLIC PROC [simulation: RoseSimulation] = { simulation.settle _ simulation.settle+1; UNTIL simulation.perturbed=NIL DO simulation.step _ simulation.step+1; UpdatePerturbed[simulation: simulation]; ENDLOOP; }; UpdatePerturbed: PROC [simulation: RoseSimulation] = { PushWireByStrength: PROC [wire: RoseWire, thisDrive: Drive] = { simulation.vicinityByStrength[thisDrive].wires[ simulation.vicinityByStrength[thisDrive].firstFree] _ wire; simulation.vicinityByStrength[thisDrive].firstFree _ simulation.vicinityByStrength[thisDrive].firstFree+1; }; PushWhat: TYPE = {switch, up, down}; FindVicinity: PROC [wire: RoseWire, what: PushWhat] = { UpDownStrength: PROC [notLevel: Level] RETURNS [strength: Drive] = { strength _ IF wire.wireLevel=notLevel THEN none ELSE wire.wireSize; }; wireSize: Drive _ SELECT what FROM switch => wire.wireSize, up => UpDownStrength[L], down => UpDownStrength[H], ENDCASE => ERROR; wire.mark _ TRUE; FOR rts: RoseTransistors _ wire.notOffChannels, rts.rest UNTIL rts=NIL DO tran: RoseTransistor _ rts.first; tranCond: Conductance _ TranOn[tran, tran.gate.wireLevel]; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; IF otherWire.wireSize=infinite THEN { IF ((what=switch AND tranCond=on) OR (what=up AND otherWire.wireLevel#L) OR (what=down AND otherWire.wireLevel#H)) AND wireSize < tran.conductivity THEN wireSize _ tran.conductivity; } ELSE IF NOT otherWire.mark THEN FindVicinity[otherWire, what]; ENDLOOP; FOR rps: RoseProbePrimitives _ wire.probes, rps.rest UNTIL rps=NIL DO probe: RoseProbePrimitive _ rps.first; IF ((what=switch AND probe.drive>none) OR (what=up AND probe.level#L) OR (what=down AND probe.level#H)) AND wireSize < probe.drive THEN wireSize _ probe.drive; ENDLOOP; IF what#switch AND wireSize < wire.switchDrive THEN wireSize _ none; PushWireByStrength[wire, wireSize]; SELECT what FROM switch => wire.switchDrive _ wireSize; up => wire.upDrive _ wireSize; down => wire.downDrive _ wireSize; ENDCASE => ERROR; }; PushStrength: PROC [what: PushWhat] = { FOR thisDrive: Drive DECREASING IN [none..infinite) DO firstFreeWire: CARDINAL; UNTIL (firstFreeWire _ simulation.vicinityByStrength[thisDrive].firstFree)=0 DO wire: RoseWire _ simulation.vicinityByStrength[thisDrive].wires[ firstFreeWire-1]; wire.mark _ FALSE; simulation.vicinityByStrength[thisDrive].firstFree _ firstFreeWire-1; IF thisDrive=none OR thisDrive < (SELECT what FROM switch => wire.switchDrive, up => wire.upDrive, down => wire.downDrive, ENDCASE => ERROR) THEN LOOP; FOR rts: RoseTransistors _ wire.notOffChannels, rts.rest UNTIL rts=NIL DO tran: RoseTransistor _ rts.first; tranCond: Conductance _ TranOn[tran, tran.gate.wireLevel]; driveThrough: Drive _ MIN[thisDrive, tran.conductivity]; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; SELECT what FROM switch => IF tranCond=on AND driveThrough > otherWire.switchDrive THEN { otherWire.switchDrive _ driveThrough; PushWireByStrength[otherWire, driveThrough]; }; up => IF driveThrough >= otherWire.switchDrive AND driveThrough > otherWire.upDrive THEN { otherWire.upDrive _ driveThrough; PushWireByStrength[otherWire, driveThrough]; }; down => IF driveThrough >= otherWire.switchDrive AND driveThrough > otherWire.downDrive THEN { otherWire.downDrive _ driveThrough; PushWireByStrength[otherWire, driveThrough]; }; ENDCASE => ERROR; ENDLOOP; ENDLOOP; ENDLOOP; }; UpdateRecomputed: PROC = { FOR thisWire: RoseWire _ recomputed, thisWire.nextRecomputed UNTIL thisWire=NIL DO wireLevel: Level _ SELECT TRUE FROM thisWire.upDrive=none AND thisWire.downDrive>=force => L, thisWire.downDrive=none AND thisWire.upDrive>=force => H, ENDCASE => X; IF thisWire.wireLevel#wireLevel THEN { FOR rts: RoseTransistors _ thisWire.gates, rts.rest UNTIL rts=NIL DO CheckAddOrRemove: PROC [channel: RoseWire] = { IF channel.channels#NIL THEN SELECT TRUE FROM wasNotOff AND NOT isNotOff => { trail: RoseTransistors _ NIL; FOR rts: RoseTransistors _ channel.notOffChannels, rts.rest UNTIL rts=NIL DO IF rts.first=tran THEN { IF trail=NIL THEN channel.notOffChannels _ rts.rest ELSE trail.rest _ rts.rest; EXIT; }; trail _ rts; REPEAT FINISHED => ERROR; ENDLOOP; }; NOT wasNotOff AND isNotOff => channel.notOffChannels _ CONS[tran, channel.notOffChannels]; ENDCASE; }; tran: RoseTransistor _ rts.first; wasNotOff: BOOL _ TranOn[tran, thisWire.wireLevel]#off; isNotOff: BOOL _ TranOn[tran, wireLevel]#off; Perturb[simulation, tran.ch1]; Perturb[simulation, tran.ch2]; CheckAddOrRemove[tran.ch1]; CheckAddOrRemove[tran.ch2]; ENDLOOP; thisWire.wireLevel _ wireLevel; }; ENDLOOP; }; recomputed: RoseWire _ NIL; UNTIL simulation.perturbed=NIL DO FastFindVicinity: PROC [wire: RoseWire] = { wire.mark _ TRUE; IF wire.wireLevel#sameValue OR wire.probes#NIL THEN { allSameValue _ FALSE; singleInfiniteNoUnknownConductance _ FALSE; }; FOR rts: RoseTransistors _ wire.notOffChannels, rts.rest UNTIL rts=NIL DO tran: RoseTransistor _ rts.first; tranCond: Conductance _ TranOn[tran, tran.gate.wireLevel]; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; IF tranCond=unknown THEN singleInfiniteNoUnknownConductance _ FALSE; IF otherWire.wireSize=infinite THEN { IF infiniteFound AND infiniteValue#otherWire.wireLevel THEN singleInfiniteNoUnknownConductance _ FALSE; infiniteFound _ TRUE; infiniteValue _ otherWire.wireLevel; IF otherWire.wireLevel#sameValue THEN allSameValue _ FALSE; } ELSE IF NOT otherWire.mark THEN FastFindVicinity[otherWire]; ENDLOOP; { next: RoseWire _ wire.nextPerturbedWire; previous: RoseWire _ wire.previousPerturbedWire; IF next#NIL THEN next.previousPerturbedWire _ previous; IF previous#NIL THEN previous.nextPerturbedWire _ next; IF simulation.perturbed=wire THEN simulation.perturbed _ next; wire.nextPerturbedWire _ NIL; wire.previousPerturbedWire _ NIL; wire.nextRecomputed _ recomputed; recomputed _ wire; wire.nextVicinityWire _ vicinityWire; vicinityWire _ wire; }; }; ForceUpDown: PROC [up, down: Drive] = { FOR thisWire: RoseWire _ vicinityWire, thisWire.nextVicinityWire UNTIL thisWire=NIL DO thisWire.mark _ FALSE; thisWire.upDrive _ up; thisWire.downDrive _ down; ENDLOOP; }; wire: RoseWire _ simulation.perturbed; vicinityWire: RoseWire _ NIL; infiniteFound: BOOL _ FALSE; infiniteValue: Level _ X; singleInfiniteNoUnknownConductance: BOOL _ TRUE; allSameValue: BOOL _ TRUE; sameValue: Level _ wire.wireLevel; FastFindVicinity[wire]; SELECT TRUE FROM infiniteFound AND singleInfiniteNoUnknownConductance => { SELECT infiniteValue FROM L => ForceUpDown[none, infinite]; H => ForceUpDown[infinite, none]; ENDCASE => ERROR; }; allSameValue => { strength: Drive _ IF infiniteFound THEN infinite ELSE charge; SELECT sameValue FROM L => ForceUpDown[none, strength]; H => ForceUpDown[strength, none]; X => ForceUpDown[strength, strength]; ENDCASE => ERROR; } ENDCASE => { FOR thisWire: RoseWire _ vicinityWire, thisWire.nextVicinityWire UNTIL thisWire=NIL DO thisWire.mark _ FALSE; ENDLOOP; FindVicinity[wire, switch]; PushStrength[switch]; FindVicinity[wire, up]; PushStrength[up]; FindVicinity[wire, down]; PushStrength[down]; }; ENDLOOP; UpdateRecomputed[]; }; Conductance: TYPE = {on, off, unknown}; TranOn: PROC [tran: RoseTransistor, gateValue: Level] RETURNS [cond: Conductance] = { cond _ SELECT tran.transistorType FROM nE => SELECT gateValue FROM L => off, H => on, X => unknown, ENDCASE => ERROR, pE => SELECT gateValue FROM L => on, H => off, X => unknown, ENDCASE => ERROR, nD => on, ENDCASE => ERROR; }; Perturb: PROC [simulation: RoseSimulation, wire: RoseWire] = { IF wire.nextPerturbedWire=NIL AND wire.previousPerturbedWire=NIL AND simulation.perturbed#wire AND wire.wireSize ERROR; ENDLOOP; }; FindDrive: PUBLIC PROC [driveID: Rope.ROPE] RETURNS [drive: Drive] = { FOR drv: Drive IN Drive DO IF Rope.Equal[driveNames[drv], driveID] THEN {drive _ drv; EXIT}; REPEAT FINISHED => ERROR; ENDLOOP; }; levelNames: PUBLIC ARRAY Level OF Rope.ROPE _ ["L", "H", "X"]; driveNames: PUBLIC ARRAY Drive OF Rope.ROPE _ [ "inspect", "e", "n", "cw", "cmw", "c", "cms", "cs", "f", "dw", "dmw", "d", "dms", "ds", "i"]; RoseWireHashNarrow: PROC [key: REF ANY] RETURNS [flat: CoreFlat.FlatWireRec] = { WITH key SELECT FROM wireKey: CoreFlat.FlatWire => flat _ wireKey^; wireKey: RoseWire => flat _ wireKey.flatWire; ENDCASE => ERROR; }; RoseWireHash: PROC [key: REF ANY] RETURNS [hash: CARDINAL] = { hash _ CoreFlat.FlatWireHashRec[RoseWireHashNarrow[key]]; }; RoseWireEqual: PROC [key1, key2: REF ANY] RETURNS [equal: BOOL] = { equal _ CoreFlat.FlatWireEqualRec[RoseWireHashNarrow[key1], RoseWireHashNarrow[key2]]; }; END. HNewBasicRosemaryImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Barth, June 10, 1988 1:15:29 pm PDT Instantiation and Relaxation Probe Creation This is an interim hack that requires the argument to be an atomic, canonical wire. Sample Drive Access Utilities Data Structures Hash Table Utilities Κk– "cedar" style˜codešœ™Kšœ<™Kšœ˜—šœ2œœ˜EKšœ&˜&Kšœœœ œœ œœœ˜ŸKšœ˜—Kšœ œœ˜DKšœ#˜#šœ˜Kšœ&˜&Kšœ˜Kšœ"˜"Kšœœ˜—K˜K˜—šŸ œœ˜'šœ œœ˜6Kšœœ˜šœH˜OKšœR˜RKšœ œ˜KšœE˜Ešœœœ˜2Kšœ˜Kšœ˜Kšœ˜Kšœœœœ˜—šœ6œœ˜IKšœ!˜!Kšœ:˜:Kšœœ˜8K˜Kšœœ˜,šœ˜šœ œ œ&œ˜HKšœ%˜%Kšœ,˜,K˜—šœœ'œ"œ˜ZKšœ!˜!Kšœ,˜,K˜—šœœ'œ$œ˜^Kšœ#˜#Kšœ,˜,K˜—Kšœœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜K˜—šŸœœ˜šœ:œ œ˜Ršœœœ˜#Kšœœ ˜9Kšœœ˜9Kšœ˜ —šœœ˜&šœ1œœ˜DK˜šŸœœ˜.š œœœœœ˜-šœ œœ˜Kšœœ˜šœ9œœ˜Lšœœ˜Kšœœœ"˜3Kšœ˜Kšœ˜K˜—K˜ Kšœœœ˜Kšœ˜—K˜—Kšœ œ&œ˜ZKšœ˜—K˜K˜—Kšœ!˜!Kšœ œ(˜7Kšœ œ˜-Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜—Kšœ˜—K˜K˜—Kšœœ˜šœœ˜!K˜šŸœœ˜+Kšœ œ˜šœœ œœ˜5Kšœœ˜Kšœ%œ˜+K˜—šœ6œœ˜IKšœ!˜!Kšœ:˜:K˜Kšœœ˜,Kšœœ&œ˜Dšœœ˜%Kšœœ#œ&œ˜gKšœœ˜Kšœ$˜$Kšœœœ˜;K˜—Kšœœœœ˜Kšœœ˜Kšœœ˜!Kšœ!˜!Kšœ˜Kšœ%˜%Kšœ˜K˜—K˜K˜—šŸ œœ˜'šœ>œ œ˜VKšœœ˜Kšœ˜Kšœ˜Kšœ˜—K˜K˜—Kšœ&˜&Kšœœ˜Kšœœœ˜K˜Kšœ$œœ˜0Kšœœœ˜K˜"Kšœ˜šœœ˜šœœ(˜9šœ˜Kšœ!˜!Kšœ!˜!Kšœœ˜—K˜—šœ˜Kšœœœ œ˜=šœ ˜Kšœ!˜!Kšœ!˜!Kšœ%˜%Kšœœ˜—K˜—šœ˜ šœ>œ œ˜VKšœœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜——Kšœ˜—Kšœ˜K˜K˜—Kšœ œ˜'K˜šŸœœ*œ˜Ušœœœ˜'šœœ ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœœ˜—šœœ ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœœ˜—Kšœ ˜ Kšœœ˜—K˜K˜—šŸœœ1˜>šœœœœœœœ˜€Kšœ-˜-Kšœ%˜%Kšœ œœ*˜AKšœ˜Kšœ˜—Kšœ˜K˜——™™šŸ œœœ>œ˜tKšœœ˜2K˜K™SKšœœ˜Kšœ œ˜&Kšœœ;˜QKšœœœœ˜ Kšœœ!˜œ˜ΈKšœe˜eK˜K˜—šŸ œœœPœœ>œ"œ˜ΰKšœœœ4˜BKšœœœ4˜BKšœœœ4˜BKšœœœ4˜BKšœœœ4˜BK˜K™——™š Οb Πbkœœœœ˜?Kšœ œœ˜K˜K˜K˜—š   ‘œœœœœ˜=Kšœ˜K˜K˜—š  ‘œœœœœ˜=Kšœ˜K˜K˜—š   ‘œœœœœ˜CKšœ˜K˜K˜——™š  ‘œœœ/˜Hšœœœ ˜K˜K˜Kšœ˜—K˜K˜—š   ‘œœœœ˜FKšœ˜K˜K˜—š  ‘œœœœ˜FKšœ˜K˜K˜—š   ‘œœœœ˜LKšœ˜K˜K˜——™š  ‘œœœœœ˜UKšœ˜K˜K˜—š  ‘œœœœ˜EKšœ˜K˜K˜—š  ‘œœœœœ˜CKšœ˜K˜K˜—š   ‘œœœœœ˜CKšœ˜K˜K˜—š  ‘œœœœœ˜IKšœ˜K˜K˜———™ š Ÿ œœœœœ˜Fšœ œ˜Kšœ&œœ˜AKšœœœ˜Kšœ˜—K˜K˜—š Ÿ œœœœœ˜Fšœ œ˜Kšœ&œœ˜AKšœœœ˜Kšœ˜—K˜K˜——™Kš œ œœœœ˜>J˜š œ œœœœ˜/Kšœ]˜]K˜J˜——™š Ÿœœœœœ!˜Pšœœ˜Kšœ.˜.Kšœ-˜-Kšœœ˜—Kšœ˜K˜—š Ÿ œœœœœœ˜>Jšœ9˜9Kšœ˜K˜—š Ÿ œœœœœ œ˜CKšœV˜VKšœ˜K˜——Kšœ˜—…—@μUŸ