<> <> <> <<>> 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^; IF wireFixedRef#NIL THEN { roseWire.switchDrive _ 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; EstablishInvariants[simulation]; }; EstablishInvariants: PROC [simulation: RoseSimulation] = { Wire: RefTab.EachPairAction = { roseWire: RoseWire _ NARROW[val]; roseWire.mark _ FALSE; Perturb[simulation, roseWire]; roseWire.notOffChannels _ NIL; FOR rts: RoseTransistors _ roseWire.channels, rts.rest UNTIL rts=NIL DO roseTransistor: RoseTransistor _ rts.first; IF TranOn[roseTransistor, roseTransistor.gate.wireLevel]#off THEN roseWire.notOffChannels _ CONS[roseTransistor, roseWire.notOffChannels]; ENDLOOP; }; [] _ RefTab.Pairs[x: simulation.coreToRoseWires, action: Wire]; }; Initialize: PUBLIC PROC [simulation: RoseSimulation] = { SetWire: RefTab.EachPairAction = { roseWire: RoseWire _ NARROW[val]; IF roseWire.wireSize#infinite THEN roseWire.wireLevel _ X; }; [] _ RefTab.Pairs[x: simulation.coreToRoseWires, action: SetWire]; EstablishInvariants[simulation]; }; 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> <> CreateProbe: PUBLIC PROC [simulation: RoseSimulation, flatWire: CoreFlat.FlatWireRec] RETURNS [probe: RoseProbe] = { fw: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; fw^ _ flatWire; <> probe _ NEW[RoseProbeRec[1]]; probe[0] _ NEW[RoseProbePrimitiveRec]; probe[0].wire _ NARROW[RefTab.Fetch[x: simulation.coreToRoseWires, key: fw].val]; IF probe[0].wire=NIL THEN ERROR; probe[0].wire.probes _ CONS[probe[0], probe[0].wire.probes]; probe.simulation _ simulation; }; <<>> BindProbe: PUBLIC PROC [simulation: RoseSimulation, cellType: Core.CellType, name: Rope.ROPE, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] RETURNS [probe: RoseProbe] = { probe _ CreateProbe[simulation, [flatCell: flatCell, wire: CoreOps.FindWire[cellType.public, name]]]; }; BindProbes: PUBLIC PROC [simulation: RoseSimulation, cellType: Core.CellType, n0, n1, n2, n3, n4: Rope.ROPE _ NIL, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType] RETURNS [p0, p1, p2, p3, p4: RoseProbe _ NIL] = { IF n0#NIL THEN p0 _ BindProbe[simulation, cellType, n0, flatCell]; IF n1#NIL THEN p1 _ BindProbe[simulation, cellType, n1, flatCell]; IF n2#NIL THEN p2 _ BindProbe[simulation, cellType, n2, flatCell]; IF n3#NIL THEN p3 _ BindProbe[simulation, cellType, n3, flatCell]; IF n4#NIL THEN p4 _ BindProbe[simulation, cellType, n4, flatCell]; }; <<>> <> GetLevel, GL: PUBLIC PROC [p: RoseProbe] RETURNS [v: Level] = { IF p.size#1 THEN ERROR; v _ p[0].wire.wireLevel; }; GetBool, GB: PUBLIC PROC [p: RoseProbe] RETURNS [v: BOOL] = { ERROR; }; GetInt, GI: PUBLIC PROC [p: RoseProbe] RETURNS [v: INT32] = { ERROR; }; GetCardinal, GC: PUBLIC PROC [p: RoseProbe] RETURNS [v: CARD32] = { ERROR; }; <> PutLevel, PL: PUBLIC PROC [p: RoseProbe, v: Level, d: Drive _ drive] = { FOR i: NAT IN [0..p.size) DO p[i].level _ v; p[i].drive _ d; Perturb[p.simulation, p[i].wire] ENDLOOP; }; PutBool, PB: PUBLIC PROC [p: RoseProbe, v: BOOL, d: Drive _ drive] = { ERROR; }; PutInt, PI: PUBLIC PROC [p: RoseProbe, v: INT32, d: Drive _ drive] = { ERROR; }; PutCardinal, PC: PUBLIC PROC [p: RoseProbe, v: CARD32, d: Drive _ drive] = { ERROR; }; <> GetProbeDrive, GPD: PUBLIC PROC [p: RoseProbe, index: NAT _ 0] RETURNS [d: Drive] = { ERROR; }; GetProbeLevel, GPL: PUBLIC PROC [p: RoseProbe] RETURNS [v: Level] = { ERROR; }; GetProbeBool, GPB: PUBLIC PROC [p: RoseProbe] RETURNS [v: BOOL] = { ERROR; }; GetProbeInt, GPI: PUBLIC PROC [p: RoseProbe] RETURNS [v: INT32] = { ERROR; }; GetProbeCardinal, GPC: PUBLIC PROC [p: RoseProbe] RETURNS [v: CARD32] = { ERROR; }; <> FindLevel: PUBLIC PROC [levelID: Rope.ROPE] RETURNS [level: Level] = { FOR lev: Level IN Level DO IF Rope.Equal[levelNames[lev], levelID] THEN {level _ lev; EXIT}; REPEAT FINISHED => 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.