DIRECTORY Basics, Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, Ports, Process, Rope, Rosemary, SymTab; RosemaryImpl: CEDAR PROGRAM IMPORTS Basics, CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, Ports, Process, Rope, SymTab EXPORTS Rosemary = BEGIN OPEN Rosemary; ROPE: TYPE = Core.ROPE; WordAsBits: TYPE = PACKED ARRAY [0..16) OF BOOL; DWordAsBits: TYPE = PACKED ARRAY [0..32) OF BOOL; RoseWireList: TYPE = LIST OF RoseWire; roseBehaveProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseBehave]; roseWireSizeProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseWireSize]; roseFixedWireProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseFixedWire]; roseTransistorSizeProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseTransistorSize]; roseCutSetProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseCutSet]; roseClassTable: SymTab.Ref _ SymTab.Create[]; BindCellType: PUBLIC PROC [cellType: Core.CellType, roseClassName: ROPE] RETURNS [sameCellType: Core.CellType] = { CoreProperties.PutCellTypeProp[on: cellType, prop: roseBehaveProp, value: roseClassName]; sameCellType _ cellType; }; BindCellClass: PUBLIC PROC [cellClass: Core.CellClass, roseClassName: ROPE] RETURNS [sameCellClass: Core.CellClass] = { CoreProperties.PutCellClassProp[on: cellClass, prop: roseBehaveProp, value: roseClassName]; sameCellClass _ cellClass; }; Register: PUBLIC PROC [roseClassName: ROPE, init: InitProc _ NIL, evalSimple: EvalProc _ NIL] RETURNS [sameRoseClassName: ROPE] = { found: BOOL; val: REF ANY; [found, val] _ SymTab.Fetch[x: roseClassTable, key: roseClassName]; IF found THEN { rct: RoseCellType _ NARROW[val]; rct.init _ init; rct.evalSimple _ evalSimple; } ELSE [] _ SymTab.Store[x: roseClassTable, key: roseClassName, val: NEW[RoseCellTypeRec _ [init: init, evalSimple: evalSimple]]]; sameRoseClassName _ roseClassName; }; Stop: PUBLIC SIGNAL [msg: ROPE, data: REF ANY _ NIL] = CODE; AddCutSets: PUBLIC PROC [cellType: Core.CellType, cs1, cs2, cs3, cs4, cs5, cs6: ROPE _ NIL] RETURNS [sameCellType: Core.CellType] = { cutSetList: LIST OF ROPE _ NARROW[CoreProperties.GetCellTypeProp[from: cellType, prop: roseCutSetProp]]; IF cs1#NIL THEN cutSetList _ CONS[cs1, cutSetList]; IF cs2#NIL THEN cutSetList _ CONS[cs2, cutSetList]; IF cs3#NIL THEN cutSetList _ CONS[cs3, cutSetList]; IF cs4#NIL THEN cutSetList _ CONS[cs4, cutSetList]; IF cs5#NIL THEN cutSetList _ CONS[cs5, cutSetList]; IF cs6#NIL THEN cutSetList _ CONS[cs6, cutSetList]; CoreProperties.PutCellTypeProp[on: cellType, prop: roseCutSetProp, value: cutSetList]; sameCellType _ cellType; }; SetFixedWire: PUBLIC PROC [wire: Core.Wire, level: Ports.Level] RETURNS [sameWire: Core.Wire] = { CoreProperties.PutWireProp[on: wire, prop: roseFixedWireProp, value: NEW[Ports.Level _ level]]; sameWire _ wire; }; SetWireSize: PUBLIC PROC [wire: Core.Wire, size: WireSize] RETURNS [sameWire: Core.Wire] = { CoreProperties.PutWireProp[on: wire, prop: roseWireSizeProp, value: NEW[Ports.Drive _ size]]; sameWire _ wire; }; SetTransistorCellTypeSize: PUBLIC PROC [transistor: Core.CellType, size: TransistorSize] RETURNS [sameTransistor: Core.CellType] = { CoreProperties.PutCellTypeProp[on: transistor, prop: roseTransistorSizeProp, value: NEW[Ports.Drive _ size]]; sameTransistor _ transistor; }; SetTransistorInstanceSize: PUBLIC PROC [transistor: CoreClasses.CellInstance, size: TransistorSize] RETURNS [sameTransistor: CoreClasses.CellInstance] = { CoreProperties.PutCellInstanceProp[on: transistor, prop: roseTransistorSizeProp, value: NEW[Ports.Drive _ size]]; sameTransistor _ transistor; }; InstantiateCellType: PUBLIC PROC [cellType: Core.CellType, testPort: Ports.Port, statePoints: NAT _ 0] RETURNS [simulation: Simulation] = { Wire: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; IF roseWire.wireDrive=infinite THEN UpdateReaders[simulation, roseWire, NIL]; }; ComputeCellTypeBindings: PROC [port: Ports.Port, wire: Core.Wire, wireToRoseWire: HashTable.Table, binds: PortBindings, firstFreeBinding: CARDINAL, instance: RoseCellInstance _ NIL] RETURNS [newFirstFreeBinding: CARDINAL] = { wireKey.wire _ wire; newFirstFreeBinding _ firstFreeBinding; IF port.type=composite THEN { FOR subPort: NAT IN [0..port.size) DO newFirstFreeBinding _ ComputeCellTypeBindings[port[subPort], wire[subPort], wireToRoseWire, binds, newFirstFreeBinding, instance]; ENDLOOP; } ELSE { thisRoseWire: RoseWire _ NARROW[HashTable.Fetch[table: wireToRoseWire, key: wireKey].value]; portBinding: PortBinding _ NEW[PortBindingRec _ [ instance: instance, clientPort: port, fields: NEW[FieldSeq[1]], currentDrive: port.d]]; field: Field _ NEW[FieldRec _ [ portBinding: portBinding, roseWire: thisRoseWire]]; portBinding.fields[0] _ field; field.currentValue _ AllocateLevelSequence[IF thisRoseWire.currentValue=NIL THEN 1 ELSE thisRoseWire.currentValue.size]; binds[newFirstFreeBinding] _ portBinding; newFirstFreeBinding _ newFirstFreeBinding + 1; IF thisRoseWire.connections[0]=NIL THEN thisRoseWire.connections[0] _ field ELSE thisRoseWire.connections[1] _ field; }; }; roseInstance: RoseCellInstance _ NEW[RoseCellInstanceRec]; max: CARDINAL; wireToRoseWire: HashTable.Table; wireKey: RoseWireHashKey _ NEW[RoseWireHashKeyRec]; simulation _ NEW[SimulationRec]; simulation.coreCellType _ cellType; wireToRoseWire _ simulation.coreToRoseWires _ HashTable.Create[equal: RoseWireEqual, hash: RoseWireHash]; simulation.coreToRoseInstances _ HashTable.Create[equal: RoseInstanceEqual, hash: RoseInstanceHash]; IF NOT HashTable.Insert[table: simulation.coreToRoseInstances, key: roseInstance, value: roseInstance] THEN ERROR; simulation.instanceNeedEval _ roseInstance; FOR strength: Ports.Drive IN Ports.Drive DO simulation.vicinityByStrength[strength].wires _ NEW[RoseWireSeq[1]]; ENDLOOP; roseInstance.publicPort _ Ports.CreatePort[cellType.public]; [max, simulation.roseBoolWires] _ AllocateCellTypeRoseWires[simulation, roseInstance.publicPort, cellType.public, wireToRoseWire]; simulation.scratchValue _ NEW[Ports.LevelSequenceRec[max]]; simulation.scratchDrive _ NEW[DriveRec[max]]; roseInstance.roseCellType _ FindRoseCellType[cellType]; IF roseInstance.roseCellType.init#NIL THEN roseInstance.state _ roseInstance.roseCellType.init[cellType: cellType, p: roseInstance.publicPort]; roseInstance.portBindings _ NEW[PortBindingSeq[Ports.PortLeaves[ roseInstance.publicPort]]]; IF roseInstance.portBindings.size#ComputeCellTypeBindings[instance: roseInstance, port: roseInstance.publicPort, wire: cellType.public, wireToRoseWire: wireToRoseWire, binds: roseInstance.portBindings, firstFreeBinding: 0] THEN ERROR; simulation.publicBindings _ NEW[PortBindingSeq[Ports.PortLeaves[testPort]]]; IF simulation.publicBindings.size#ComputeCellTypeBindings[port: testPort, wire: cellType.public, wireToRoseWire: wireToRoseWire, binds: simulation.publicBindings, firstFreeBinding: 0] THEN ERROR; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: Wire]; simulation.testPort _ testPort; AllocateStatePoints[simulation, statePoints]; EstablishInvariants[simulation]; }; AllocateCellTypeRoseWires: PROC [simulation: Simulation, port: Ports.Port, public: Core.Wire, wireToRoseWire: HashTable.Table] RETURNS [maxComposite: CARDINAL _ 0, boolWires: RoseWireList _ NIL] = { IF port.type=composite THEN { subBools: RoseWireList; subMax: CARDINAL; FOR sub: NAT IN [0..port.size) DO [subMax, subBools] _ AllocateCellTypeRoseWires[simulation, port[sub], public[sub], wireToRoseWire]; maxComposite _ MAX[subMax, maxComposite]; FOR bools: RoseWireList _ subBools, bools.rest UNTIL bools=NIL DO boolWires _ CONS[bools.first, boolWires]; ENDLOOP; ENDLOOP; } ELSE { roseWire: RoseWire _ NEW[RoseWireRec]; [] _ InitWire[public, roseWire]; roseWire.connections _ NEW[FieldSeq[2]]; IF NOT HashTable.Insert[table: wireToRoseWire, key: roseWire, value: roseWire] THEN ERROR; IF NOT (port.type=l OR port.type=b) THEN { maxComposite _ CoreOps.WireBits[public]; roseWire.currentValue _ AllocateLevelSequence[maxComposite]; }; IF port.type=b OR port.type=bs OR port.type=c OR port.type=lc THEN boolWires _ CONS[roseWire, boolWires]; roseWire.wire _ public; }; }; InitWire: PROC [coreWire: Core.Wire, roseWire: RoseWire] RETURNS [fixed: BOOL] = { wireSizeRef: REF Ports.Drive _ NARROW[CoreProperties.GetWireProp[from: coreWire, prop: roseWireSizeProp]]; wireFixedRef: REF Ports.Level _ NARROW[CoreProperties.GetWireProp[from: coreWire, prop: roseFixedWireProp]]; IF wireSizeRef#NIL THEN roseWire.wireDrive _ wireSizeRef^; IF wireFixedRef#NIL THEN { roseWire.wireDrive _ infinite; roseWire.switchDrive _ infinite; roseWire.wireLevel _ wireFixedRef^ }; }; InstantiateInstances: PUBLIC PROC [cellType: Core.CellType, testPort: Ports.Port, cutSet: ROPE _ NIL, statePoints: NAT _ 0] RETURNS [simulation: Simulation] = { ComputeInDegree: PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, wire: Core.Wire] = { bind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: wire].value]; wireData: WireData _ NARROW[bind.data]; IF wireData=NIL THEN { wireData _ NEW[WireDataRec]; bind.data _ wireData; }; IF wireData.indegree=0 THEN { wireData.indegree _ 1; wireData.connections _ 0; wireData.channels _ 0; wireData.gates _ 0; wireData.portLeaf _ FALSE; wireData.boolPort _ FALSE; wireData.allocated _ FALSE; FOR sub: NAT IN [0..wire.size) DO ComputeInDegree[bindings, path, wire[sub]]; ENDLOOP; } ELSE wireData.indegree _ wireData.indegree + 1; }; MarkPortLeavesCountConnections: PROC [bindings: HashTable.Table, actual: Core.Wire, public: Core.Wire, checkPort: BOOL, visited: HashTable.Table, type: Ports.PortType _ composite] = { actualBind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: actual].value]; actualData: WireData _ NARROW[actualBind.data]; IF NOT HashTable.Fetch[table: visited, key: actual].found THEN { actualData.connections _ actualData.connections + 1; IF checkPort THEN { type _ Ports.WirePortType[public]; IF type # composite THEN { actualData.portLeaf _ TRUE; checkPort _ FALSE; }; }; FOR sub: NAT IN [0..actual.size) DO MarkPortLeavesCountConnections[bindings, actual[sub], public[sub], checkPort, visited, type]; ENDLOOP; IF NOT HashTable.Insert[table: visited, key: actual, value: $Visited] THEN ERROR; }; IF type=b OR type=bs OR type=c OR type=lc THEN actualData.boolPort _ TRUE; }; ComputeBindings: PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, port: Ports.Port, wire: Core.Wire, binds: PortBindings, firstFreeBinding: CARDINAL, instance: RoseCellInstance _ NIL] RETURNS [newFirstFreeBinding: CARDINAL] = { newFirstFreeBinding _ firstFreeBinding; IF port.type=composite THEN { FOR subPort: NAT IN [0..port.size) DO newFirstFreeBinding _ ComputeBindings[bindings, path, port[subPort], wire[subPort], binds, newFirstFreeBinding, instance]; ENDLOOP; } ELSE { portBinding: PortBinding _ NEW[PortBindingRec _ [ clientPort: port, currentDrive: port.d, instance: instance]]; portBinding.fields _ NEW[FieldSeq[CountFields[bindings: bindings, path: path, wire: wire, bound: HashTable.Create[]]]]; [] _ ComputeFields[bindings: bindings, path: path, wire: wire, portBinding: portBinding, valueStart: 0, bound: HashTable.Create[], firstFreeField: 0]; binds[newFirstFreeBinding] _ portBinding; newFirstFreeBinding _ newFirstFreeBinding + 1; }; }; CountFields: PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, wire: Core.Wire, bound: HashTable.Table] RETURNS [fieldCount: CARDINAL _ 0] = { IF LookUpRoseWire[bindings, path, wire]=NIL THEN { FOR subWire: NAT IN [0..wire.size) DO fieldCount _ fieldCount + CountFields[bindings, path, wire[subWire], bound]; ENDLOOP; } ELSE { IF NOT HashTable.Fetch[table: bound, key: wire].found THEN { fieldCount _ 1; IF NOT HashTable.Insert[table: bound, key: wire, value: $Bound] THEN ERROR; }; }; }; ComputeFields: PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, wire: Core.Wire, portBinding: PortBinding, valueStart: NAT, bound: HashTable.Table, firstFreeField: CARDINAL] RETURNS [newFirstFreeField: CARDINAL, newValueStart: NAT] = { roseWire: RoseWire _ LookUpRoseWire[bindings, path, wire]; newValueStart _ valueStart; newFirstFreeField _ firstFreeField; IF roseWire = NIL THEN { FOR subWire: NAT IN [0..wire.size) DO [newFirstFreeField, newValueStart] _ ComputeFields[bindings, path, wire[subWire], portBinding, newValueStart, bound, newFirstFreeField]; ENDLOOP; } ELSE { IF NOT HashTable.Fetch[table: bound, key: wire].found THEN { field: Field _ NEW[FieldRec _ [ portBinding: portBinding, portStartBit: valueStart, roseWire: roseWire, currentValue: AllocateLevelSequence[IF roseWire.currentValue=NIL THEN 1 ELSE roseWire.currentValue.size]]]; FOR bit: NAT IN [0..field.currentValue.size) DO field.currentValue[bit] _ L; ENDLOOP; portBinding.fields[firstFreeField] _ field; newFirstFreeField _ newFirstFreeField + 1; newValueStart _ newValueStart + field.currentValue.size; FOR f: NAT IN [0..roseWire.connections.size) DO IF roseWire.connections[f]=NIL THEN { roseWire.connections[f] _ field; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; IF NOT HashTable.Insert[table: bound, key: wire, value: $Bound] THEN ERROR; }; }; }; CountVicinity: PROC [wire: RoseWire, currentCount: NAT _ 0] RETURNS [newCount: NAT] = { channels: RoseTransistors _ wire.channels; wire.mark _ TRUE; newCount _ currentCount + 1; IF channels#NIL THEN FOR t: CARDINAL IN [0..channels.size) DO tran: RoseTransistor _ channels[t]; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; IF otherWire.wireDrive#infinite AND NOT otherWire.mark THEN newCount _ CountVicinity[otherWire, newCount]; ENDLOOP; }; LookUpRoseWire: PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, wire: Core.Wire] RETURNS [roseWire: RoseWire] = { roseWire _ FindRoseWire[simulation, bindings, path, wire, wireKey]; }; InsertRootPublics: CoreFlat.EachCellTypeProc = { public: Core.Wire _ cellType.public; visited: HashTable.Table _ HashTable.Create[]; FOR i: NAT IN [0..public.size) DO ComputeInDegree[bindings, path, public[i]]; ENDLOOP; FOR i: NAT IN [0..public.size) DO MarkPortLeavesCountConnections[bindings, public[i], public[i], TRUE, visited]; ENDLOOP; }; InsertInternals: CoreFlat.EachCellTypeProc = { cellTypeRCT: CoreClasses.RecordCellType _ NARROW[cellType.data]; internal: Core.Wire _ cellTypeRCT.internal; FOR i:NAT IN [0..internal.size) DO ComputeInDegree[bindings, path, internal[i]]; ENDLOOP; }; GatherWireData: CoreFlat.EachInstanceProc = { LookupBind: PROC [wire: Core.Wire] RETURNS [wireData: WireData] = { bind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: wire].value]; wireData _ NARROW[bind.data]; wireData.portLeaf _ TRUE; }; member, transistor: BOOL; subType: Core.CellType; [member, transistor, subType] _ CutSetMember[path, instance, cutSet]; flatten _ NOT member; IF member THEN { actual: Core.Wire _ instance.actual; IF transistor THEN { wireData: WireData _ LookupBind[actual[gate]]; wireData.gates _ wireData.gates + 1; wireData _ LookupBind[actual[ch1]]; wireData.channels _ wireData.channels + 1; wireData _ LookupBind[actual[ch2]]; wireData.channels _ wireData.channels + 1; } ELSE { visited: HashTable.Table _ HashTable.Create[]; FOR i: NAT IN [0..actual.size) DO MarkPortLeavesCountConnections[bindings: bindings, actual: actual[i], public: instance.type.public[i], checkPort: TRUE, visited: visited] ENDLOOP; }; } }; AllocateWires: CoreFlat.EachCellTypeProc = { AllocateRoseWires: PROC [wire: Core.Wire] RETURNS [public: BOOL _ FALSE, allocated: BOOL _ FALSE] = { AllocateWire: PROC [wire: Core.Wire, wireData: WireData] = { AllocateTransistorPointers: PROC [count: CARDINAL] RETURNS [transistors: RoseTransistors _ NIL] = { IF count>0 THEN { transistors _ NEW[RoseTransistorSeq[count]]; FOR i: CARDINAL IN [0..transistors.size) DO transistors[i] _ NIL; ENDLOOP; }; }; roseWire: RoseWire _ NEW[RoseWireRec]; wireSize: NAT _ CoreOps.WireBits[wire]; fixed: BOOL _ InitWire[wire, roseWire]; IF wireData.connections>0 THEN { roseWire.connections _ NEW[FieldSeq[wireData.connections]]; FOR i: CARDINAL IN [0..roseWire.connections.size) DO roseWire.connections[i] _ NIL; ENDLOOP; }; IF wireSize>1 THEN roseWire.currentValue _ AllocateLevelSequence[wireSize] ELSE IF NOT fixed THEN { roseWire.channels _ AllocateTransistorPointers[wireData.channels]; roseWire.gates _ AllocateTransistorPointers[wireData.gates]; }; roseWire.path _ path; roseWire.wire _ wire; IF NOT HashTable.Insert[table: simulation.coreToRoseWires, key: roseWire, value: roseWire] THEN ERROR; maxRoseWireSize _ MAX[maxRoseWireSize, wireSize]; IF wireData.boolPort THEN simulation.roseBoolWires _ CONS[roseWire, simulation.roseBoolWires]; wireData.allocated _ TRUE; }; bind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: wire].value]; wireData: WireData _ NARROW[bind.data]; IF NOT (public _ NOT CoreFlat.PathEqual[bind.path, path]) THEN { IF wireData.allocated THEN allocated _ TRUE ELSE { somePublic: BOOL _ FALSE; FOR sub: NAT IN [0..wire.size) DO subPublic, subAllocated: BOOL; [subPublic, subAllocated] _ AllocateRoseWires[wire[sub]]; allocated _ allocated OR subAllocated; somePublic _ somePublic OR subPublic; ENDLOOP; IF allocated OR somePublic THEN { FOR sub: NAT IN [0..wire.size) DO subBind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: wire[sub]].value]; subWireData: WireData _ NARROW[subBind.data]; IF (NOT subWireData.allocated) AND CoreFlat.PathEqual[subBind.path, path] THEN AllocateWire[wire[sub], subWireData]; ENDLOOP; wireData.allocated _ TRUE; } ELSE { IF wireData.indegree>1 OR wireData.portLeaf THEN { AllocateWire[wire, wireData]; allocated _ TRUE; }; }; }; wireData.indegree _ 0; }; }; cellTypeRCT: CoreClasses.RecordCellType _ NARROW[cellType.data]; internal: Core.Wire _ cellTypeRCT.internal; FOR i: NAT IN [0..internal.size) DO [] _ AllocateRoseWires[internal[i]]; ENDLOOP; }; CreateRootBindings: CoreFlat.EachCellTypeProc = { IF simulation.publicBindings.size#ComputeBindings[bindings: bindings, path: path, port: testPort, wire: cellType.public, binds: simulation.publicBindings, firstFreeBinding: 0] THEN ERROR; }; AllocateInstances: CoreFlat.EachInstanceProc = { member, transistor: BOOL; subType: Core.CellType; [member, transistor, subType] _ CutSetMember[path, instance, cutSet]; flatten _ NOT member; IF member THEN { actual: Core.Wire _ instance.actual; IF transistor THEN { InsertTransistor: PROC [transistors: RoseTransistors] = { IF transistors#NIL THEN FOR t: NAT IN [0..transistors.size) DO IF transistors[t]=NIL THEN { transistors[t] _ roseTransistor; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; }; coreTransistor: CoreClasses.Transistor _ NARROW[subType.data]; roseTransistor: RoseTransistor _ NEW[RoseTransistorRec]; transistorSizeRef: REF Ports.Drive _ NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: roseTransistorSizeProp]]; roseTransistor.gate _ LookUpRoseWire[bindings, path, actual[gate]]; InsertTransistor[roseTransistor.gate.gates]; roseTransistor.ch1 _ LookUpRoseWire[bindings, path, actual[ch1]]; InsertTransistor[roseTransistor.ch1.channels]; roseTransistor.ch2 _ LookUpRoseWire[bindings, path, actual[ch2]]; InsertTransistor[roseTransistor.ch2.channels]; IF transistorSizeRef=NIL THEN transistorSizeRef _ NARROW[CoreProperties.GetCellTypeProp[from: subType, prop: roseTransistorSizeProp]]; IF transistorSizeRef#NIL THEN roseTransistor.conductivity _ transistorSizeRef^; roseTransistor.type _ coreTransistor.type; } ELSE { roseInstance: RoseCellInstance _ NEW[RoseCellInstanceRec]; roseInstance.nextNeedEval _ simulation.instanceNeedEval; simulation.instanceNeedEval _ roseInstance; roseInstance.roseCellType _ FindRoseCellType[subType]; roseInstance.publicPort _ Ports.CreatePort[wire: subType.public]; roseInstance.portBindings _ NEW[PortBindingSeq[Ports.PortLeaves[ roseInstance.publicPort]]]; IF roseInstance.portBindings.size#ComputeBindings[bindings: bindings, path: path, port: roseInstance.publicPort, wire: actual, binds: roseInstance.portBindings, firstFreeBinding: 0, instance: roseInstance] THEN ERROR; IF roseInstance.roseCellType.init#NIL THEN roseInstance.state _ roseInstance.roseCellType.init[cellType: subType, p: roseInstance.publicPort]; roseInstance.path _ path; roseInstance.instance _ instance; IF NOT HashTable.Insert[table: simulation.coreToRoseInstances, key: roseInstance, value: roseInstance] THEN ERROR; }; }; }; ComputeMaxVicinity: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; IF roseWire.wireDrive=infinite THEN UpdateReaders[simulation, roseWire, NIL] ELSE IF NOT roseWire.mark THEN maxVicinity _ MAX[maxVicinity, CountVicinity[roseWire]]; }; WireData: TYPE = REF WireDataRec; WireDataRec: TYPE = RECORD [ indegree: CARDINAL _ 0, connections: CARDINAL _ 0, channels: CARDINAL _ 0, gates: CARDINAL _ 0, portLeaf: BOOL _ FALSE, boolPort: BOOL _ FALSE, allocated: BOOL _ FALSE]; gate: NAT = CoreClasses.TransistorPort.gate.ORD; ch1: NAT = CoreClasses.TransistorPort.ch1.ORD; ch2: NAT = CoreClasses.TransistorPort.ch2.ORD; maxRoseWireSize: NAT _ 0; maxVicinity: NAT _ 0; wireKey: RoseWireHashKey _ NEW[RoseWireHashKeyRec]; simulation _ NEW[SimulationRec]; simulation.coreCellType _ cellType; simulation.cutSet _ cutSet; simulation.testPort _ testPort; simulation.publicBindings _ NEW[PortBindingSeq[Ports.PortLeaves[testPort]]]; simulation.coreToRoseWires _ HashTable.Create[mod: 1024, equal: RoseWireEqual, hash: RoseWireHash]; simulation.coreToRoseInstances _ HashTable.Create[equal: RoseInstanceEqual, hash: RoseInstanceHash]; CoreFlat.EnumerateLeaves[root: cellType, rootCellType: InsertRootPublics, beforeInstances: InsertInternals, eachInstance: GatherWireData, afterInstances: AllocateWires]; CoreFlat.EnumerateLeaves[root: cellType, rootCellType: CreateRootBindings, eachInstance: AllocateInstances]; simulation.scratchValue _ NEW[Ports.LevelSequenceRec[maxRoseWireSize]]; simulation.scratchDrive _ NEW[DriveRec[maxRoseWireSize]]; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: ComputeMaxVicinity]; FOR strength: Ports.Drive IN Ports.Drive DO simulation.vicinityByStrength[strength].wires _ NEW[RoseWireSeq[maxVicinity]]; ENDLOOP; AllocateStatePoints[simulation, statePoints]; EstablishInvariants[simulation]; }; EstablishInvariants: PROC [simulation: Simulation] = { Instance: HashTable.EachPairAction = { roseInstance: RoseCellInstance _ NARROW[value]; CleanUp[simulation: simulation, bindings: roseInstance.portBindings, forceUpdate: TRUE, updateProc: NIL]; }; Wire: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; roseWire.mark _ FALSE; IF roseWire.connections#NIL THEN RecomputeValue[simulation: simulation, wire: roseWire, forceReaderUpdate: TRUE, updateProc: NIL]; Perturb[simulation, roseWire]; }; CleanUp[simulation: simulation, bindings: simulation.publicBindings, forceUpdate: TRUE, updateProc: NIL]; [] _ HashTable.Pairs[table: simulation.coreToRoseInstances, action: Instance]; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: Wire]; }; FindRoseCellType: PROC [cellType: Core.CellType] RETURNS [roseCellType: RoseCellType] = { roseClassName: ROPE _ NARROW[CoreProperties.GetCellTypeProp[from: cellType, prop: roseBehaveProp]]; found: BOOL; val: REF ANY; IF roseClassName=NIL THEN roseClassName _ NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: roseBehaveProp]]; [found, val] _ SymTab.Fetch[roseClassTable, roseClassName]; roseCellType _ NARROW[val]; }; AllocateLevelSequence: PROC [count: NAT] RETURNS [ls: Ports.LevelSequence] = { ls _ NEW[Ports.LevelSequenceRec[count]]; FOR bit: NAT IN [0..count) DO ls[bit] _ L; ENDLOOP; }; Initialize: PUBLIC PROC [simulation: Simulation, steady: BOOL _ TRUE] = { ERROR; -- not implemented }; Settle: PUBLIC PROC [simulation: Simulation, updateProc: UpdateProc _ NIL] = { priority: Process.Priority _ Process.GetPriority[]; Process.SetPriority[Process.priorityBackground]; { ENABLE UNWIND => Process.SetPriority[priority]; CleanUp[simulation: simulation, bindings: simulation.publicBindings, updateProc: updateProc]; UNTIL simulation.instanceNeedEval=NIL AND simulation.perturbed=NIL DO UNTIL simulation.instanceNeedEval=NIL DO instance: RoseCellInstance _ simulation.instanceNeedEval; simulation.instanceNeedEval _ instance.nextNeedEval; instance.nextNeedEval _ NIL; instance.roseCellType.evalSimple[p: instance.publicPort, stateAny: instance.state]; CleanUp[simulation: simulation, bindings: instance.portBindings, updateProc: updateProc]; Process.CheckForAbort[]; ENDLOOP; UpdatePerturbed[simulation: simulation, updateProc: updateProc]; Process.CheckForAbort[]; ENDLOOP; FOR roseWires: LIST OF RoseWire _ simulation.roseBoolWires, roseWires.rest UNTIL roseWires=NIL DO roseWire: RoseWire _ roseWires.first; IF roseWire.currentValue=NIL THEN { IF roseWire.wireLevel=X THEN ERROR; } ELSE FOR bit: CARDINAL IN [0..roseWire.currentValue.size) DO IF roseWire.currentValue[bit]=X THEN ERROR; ENDLOOP; ENDLOOP; }; Process.SetPriority[priority]; }; CleanUp: PROC [simulation: Simulation, bindings: PortBindings, forceUpdate: BOOL _ FALSE, updateProc: UpdateProc] = { FOR binds: CARDINAL IN [0..bindings.size) DO bind: PortBinding _ bindings[binds]; client: Ports.Port _ bind.clientPort; changeDrive: BOOL _ bind.currentDrive#client.d; IF changeDrive THEN bind.currentDrive _ client.d; SELECT client.type FROM l, b => { field: Field _ bind.fields[0]; changeValue: BOOL _ FALSE; clientLevel: Ports.Level _ IF client.type=l THEN client.l ELSE IF client.b THEN H ELSE L; IF field.currentValue[0]#clientLevel THEN { changeValue _ TRUE; field.currentValue[0] _ clientLevel; }; UpdateReader[simulation, field]; IF changeDrive OR changeValue OR forceUpdate THEN RecomputeValue[simulation, field.roseWire, forceUpdate, updateProc]; }; ls, bs, c, lc => { FOR fields: CARDINAL IN [0..bind.fields.size) DO field: Field _ bind.fields[fields]; fieldValue: Ports.LevelSequence _ field.currentValue; changeValue: BOOL _ FALSE; fieldStart: NAT _ field.portStartBit+client.fieldStart; FOR bit: NAT IN [0..fieldValue.size) DO thisBit: NAT _ bit+fieldStart; clientLevel: Ports.Level _ SELECT client.type FROM ls => client.ls[thisBit], bs => IF client.bs[thisBit] THEN H ELSE L, c => IF LOOPHOLE[client.c, WordAsBits][thisBit] THEN H ELSE L, lc => IF (IF thisBit < 16 THEN LOOPHOLE[Basics.HighHalf[client.lc], WordAsBits][thisBit] ELSE LOOPHOLE[Basics.LowHalf[client.lc], WordAsBits][thisBit - 16]) THEN H ELSE L, ENDCASE => ERROR; IF fieldValue[bit]#clientLevel THEN { changeValue _ TRUE; fieldValue[bit] _ clientLevel; }; ENDLOOP; UpdateReader[simulation, field]; IF changeDrive OR changeValue OR forceUpdate THEN RecomputeValue[simulation, field.roseWire, forceUpdate, updateProc]; ENDLOOP; }; ENDCASE => ERROR; ENDLOOP; }; RecomputeValue: PROC [simulation: Simulation, wire: RoseWire, forceReaderUpdate: BOOL, updateProc: UpdateProc] = { wireValue: Ports.LevelSequence _ wire.currentValue; IF wireValue=NIL THEN { scratchLevel: Ports.Level _ wire.wireLevel; scratchDrive: Ports.Drive _ wire.wireDrive; FOR writers: CARDINAL IN [0..wire.connections.size) DO writer: Field _ wire.connections[writers]; writerLevel: Ports.Level _ writer.currentValue[0]; writerDrive: Ports.Drive _ writer.portBinding.currentDrive; IF writerDrive > scratchDrive THEN { scratchLevel _ writerLevel; scratchDrive _ writerDrive; } ELSE IF writerDrive = scratchDrive AND scratchLevel # writerLevel AND writerDrive > none THEN scratchLevel _ X; ENDLOOP; IF scratchLevel#wire.connectionLevel OR scratchDrive#wire.connectionDrive OR forceReaderUpdate THEN { wire.connectionLevel _ scratchLevel; wire.connectionDrive _ scratchDrive; Perturb[simulation, wire]; }; } ELSE { scratchValue: Ports.LevelSequence _ simulation.scratchValue; scratchDrive: DriveSequence _ simulation.scratchDrive; changeWire: BOOL _ FALSE; FOR bit: NAT IN [0..wireValue.size) DO scratchValue[bit] _ wireValue[bit]; scratchDrive[bit] _ wire.wireDrive; ENDLOOP; FOR writers: CARDINAL IN [0..wire.connections.size) DO writer: Field _ wire.connections[writers]; writerValue: Ports.LevelSequence _ writer.currentValue; writerDrive: Ports.Drive _ writer.portBinding.currentDrive; FOR bit: NAT IN [0..writerValue.size) DO sd: Ports.Drive _ scratchDrive[bit]; IF writerDrive > sd THEN { scratchValue[bit] _ writerValue[bit]; scratchDrive[bit] _ writerDrive; } ELSE IF writerDrive = sd AND scratchValue[bit] # writerValue[bit] AND writerDrive > none THEN scratchValue[bit] _ X; ENDLOOP; ENDLOOP; FOR bit: NAT IN [0..wireValue.size) DO IF wireValue[bit] # scratchValue[bit] THEN { wireValue[bit] _ scratchValue[bit]; changeWire _ TRUE; }; ENDLOOP; IF changeWire OR forceReaderUpdate THEN UpdateReaders[simulation, wire, updateProc]; }; }; UpdateReaders: PROC [simulation: Simulation, wire: RoseWire, updateProc: UpdateProc] = { IF updateProc#NIL THEN updateProc[wire]; IF wire.connections#NIL THEN FOR readers: CARDINAL IN [0..wire.connections.size) DO reader: Field _ wire.connections[readers]; instance: RoseCellInstance _ reader.portBinding.instance; IF instance#NIL THEN IF instance.nextNeedEval=NIL THEN { instance.nextNeedEval _ simulation.instanceNeedEval; simulation.instanceNeedEval _ instance; }; UpdateReader[simulation, reader]; ENDLOOP; }; UpdateReader: PROC [simulation: Simulation, reader: Field] = { ToBool: PROC [level: Ports.Level, old: BOOL] RETURNS [new: BOOL] = { new _ SELECT level FROM L => FALSE, X => old, H => TRUE, ENDCASE => ERROR; }; wire: RoseWire _ reader.roseWire; wireValue: Ports.LevelSequence _ wire.currentValue; readerValue: Ports.Port _ reader.portBinding.clientPort; readerStart: NAT _ reader.portStartBit+readerValue.fieldStart; SELECT readerValue.type FROM l => readerValue.l _ wire.wireLevel; b => readerValue.b _ ToBool[wire.wireLevel, readerValue.b]; ls => IF wireValue=NIL THEN readerValue.ls[readerStart] _ wire.wireLevel ELSE FOR bit: NAT IN [0..wireValue.size) DO readerValue.ls[bit+readerStart] _ wireValue[bit]; ENDLOOP; bs => IF wireValue=NIL THEN readerValue.bs[readerStart] _ ToBool[wire.wireLevel, readerValue.bs[readerStart]] ELSE FOR bit: NAT IN [0..wireValue.size) DO readerValue.bs[bit+readerStart] _ ToBool[wireValue[bit], readerValue.bs[bit+readerStart]]; ENDLOOP; c => { asBits: WordAsBits _ LOOPHOLE[readerValue.c]; IF wireValue=NIL THEN asBits[readerStart] _ ToBool[wire.wireLevel, asBits[readerStart]] ELSE FOR bit: NAT IN [0..wireValue.size) DO thisBit: NAT _ bit+readerStart; asBits[thisBit] _ ToBool[wireValue[bit], asBits[thisBit]]; ENDLOOP; readerValue.c _ LOOPHOLE[asBits]; }; lc => { asBits: DWordAsBits _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[readerValue.lc]]]; IF wireValue=NIL THEN asBits[readerStart] _ ToBool[wire.wireLevel, asBits[readerStart]] ELSE FOR bit: NAT IN [0..wireValue.size) DO thisBit: NAT _ bit+readerStart; asBits[thisBit] _ ToBool[wireValue[bit], asBits[thisBit]]; ENDLOOP; readerValue.lc _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[asBits]]]; }; ENDCASE => ERROR; }; UpdatePerturbed: PROC [simulation: Simulation, updateProc: UpdateProc] = { Conductance: TYPE = {on, off, unknown}; TranOn: PROC [tran: RoseTransistor] RETURNS [cond: Conductance] = { gateValue: Ports.Level _ tran.gate.wireLevel; cond _ SELECT tran.type 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; }; PushWireByStrength: PROC [wire: RoseWire, thisDrive: Ports.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: Ports.Level] RETURNS [strength: Ports.Drive] = { level: Ports.Level; IF wire.wireDrive>wire.connectionDrive THEN { level _ wire.wireLevel; strength _ wire.wireDrive; } ELSE { level _ wire.connectionLevel; strength _ wire.connectionDrive; }; IF level=notLevel THEN strength _ none; }; wireDrive: Ports.Drive _ SELECT what FROM switch => IF wire.wireDrive>wire.connectionDrive THEN wire.wireDrive ELSE wire.connectionDrive, up => UpDownStrength[L], down => UpDownStrength[H], ENDCASE => ERROR; channels: RoseTransistors _ wire.channels; wire.mark _ TRUE; IF channels#NIL THEN FOR t: CARDINAL IN [0..channels.size) DO tran: RoseTransistor _ channels[t]; tranCond: Conductance _ TranOn[tran]; otherWire: RoseWire _ tran.ch1; IF otherWire=wire THEN otherWire _ tran.ch2; IF tranCond=off THEN LOOP; IF otherWire.wireDrive=infinite THEN { IF ((what=switch AND tranCond=on) OR (what=up AND otherWire.wireLevel#L) OR (what=down AND otherWire.wireLevel#H)) AND wireDrive < tran.conductivity THEN wireDrive _ tran.conductivity; } ELSE IF NOT otherWire.mark THEN FindVicinity[otherWire, what]; ENDLOOP; IF what#switch AND wireDrive < wire.switchDrive THEN wireDrive _ none; PushWireByStrength[wire, wireDrive]; SELECT what FROM switch => { 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.switchDrive _ wireDrive; }; up => wire.upDrive _ wireDrive; down => wire.downDrive _ wireDrive; ENDCASE => ERROR; }; PushStrength: PROC [what: PushWhat] = { FOR thisDrive: Ports.Drive DECREASING IN [none..infinite) DO firstFreeWire: CARDINAL; UNTIL (firstFreeWire _ simulation.vicinityByStrength[thisDrive].firstFree)=0 DO wire: RoseWire _ simulation.vicinityByStrength[thisDrive].wires[ firstFreeWire-1]; channels: RoseTransistors _ wire.channels; 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; IF channels#NIL THEN FOR t: CARDINAL IN [0..channels.size) DO tran: RoseTransistor _ channels[t]; tranCond: Conductance _ TranOn[tran]; driveThrough: Ports.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 tranCond#off AND driveThrough >= otherWire.switchDrive AND driveThrough > otherWire.upDrive THEN { otherWire.upDrive _ driveThrough; PushWireByStrength[otherWire, driveThrough]; }; down => IF tranCond#off AND driveThrough >= otherWire.switchDrive AND driveThrough > otherWire.downDrive THEN { otherWire.downDrive _ driveThrough; PushWireByStrength[otherWire, driveThrough]; }; ENDCASE => ERROR; ENDLOOP; ENDLOOP; ENDLOOP; }; recomputed: RoseWire _ NIL; UNTIL simulation.perturbed=NIL DO wire: RoseWire _ simulation.perturbed; FindVicinity[wire, switch]; PushStrength[switch]; FindVicinity[wire, up]; PushStrength[up]; FindVicinity[wire, down]; PushStrength[down]; ENDLOOP; FOR recomputed _ recomputed, recomputed.nextRecomputed UNTIL recomputed=NIL DO wireLevel: Ports.Level _ SELECT TRUE FROM recomputed.upDrive=none => L, recomputed.downDrive=none => H, ENDCASE => X; IF recomputed.wireLevel#wireLevel THEN { gates: RoseTransistors _ recomputed.gates; IF gates#NIL THEN FOR t: CARDINAL IN [0..gates.size) DO tran: RoseTransistor _ gates[t]; Perturb[simulation, tran.ch1]; Perturb[simulation, tran.ch2]; ENDLOOP; recomputed.wireLevel _ wireLevel; UpdateReaders[simulation, recomputed, updateProc]; }; ENDLOOP; }; Perturb: PROC [simulation: Simulation, wire: RoseWire] = { IF wire.nextPerturbedWire=NIL AND wire.previousPerturbedWire=NIL AND simulation.perturbed#wire AND wire.wireDrive { FindHereOrBelow: PROC [path: CoreFlat.PackedPath, wire: Core.Wire] = { roseWire: RoseWire _ FindRoseWire[simulation, wireBindTab, path, wire, wireKey]; IF roseWire=NIL THEN { FOR subWire: NAT DECREASING IN [0..wire.size) DO FindHereOrBelow[path, wire[subWire]]; ENDLOOP; } ELSE values _ CONS[[ roseWire: roseWire, size: IF roseWire.currentValue=NIL THEN 1 ELSE roseWire.currentValue.size], values]; }; FindAbove: PROC [internal: Core.Wire] RETURNS [foundCore: BOOL _ FALSE, foundRose: BOOL _ FALSE, firstBit: NAT _ 0] = { IF internal=wire THEN foundCore _ TRUE ELSE FOR thisWire: NAT IN [0..internal.size) DO [foundCore, foundRose, firstBit] _ FindAbove[internal[thisWire]]; IF foundCore AND NOT foundRose THEN { path: CoreFlat.PackedPath _ packedPath; bind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: wireBindTab, key: internal].value]; roseWire: RoseWire; IF bind#NIL THEN { path _ bind.path; internal _ bind.wire; }; FOR subWire: NAT IN [0..thisWire) DO firstBit _ firstBit + CoreOps.WireBits[internal[subWire]] ENDLOOP; roseWire _ FindRoseWire[simulation, wireBindTab, path, internal, wireKey]; IF roseWire#NIL THEN { values _ CONS[[ roseWire: roseWire, firstBit: firstBit, size: CoreOps.WireBits[wire]], values]; foundRose _ TRUE; }; EXIT; }; ENDLOOP; }; values: Values _ NIL; wireBindTab: HashTable.Table; wireKey: RoseWireHashKey _ NEW[RoseWireHashKeyRec]; cellType: Core.CellType; [wireBindTab, cellType] _ CoreFlat.BoundCellType[simulation.coreCellType, packedPath]; FindHereOrBelow[packedPath, wire]; IF values=NIL THEN IF NOT FindAbove[NARROW[cellType.data, CoreClasses.RecordCellType].internal].foundRose THEN ERROR; binds _ simulation.coreToValues _ CONS[[ path: packedPath, wire: wire, values: values], simulation.coreToValues]; }; ENDLOOP; value _ NEW[Ports.LevelSequenceRec[CoreOps.WireBits[wire]]]; FOR values: Values _ binds.first.values, values.rest UNTIL values=NIL DO currentValue: Ports.LevelSequence _ values.first.roseWire.currentValue; IF currentValue=NIL THEN { value[firstFreeBit] _ values.first.roseWire.wireLevel; firstFreeBit _ firstFreeBit + 1; } ELSE { firstBit: NAT _ values.first.firstBit; FOR bit: NAT IN [0..values.first.size) DO value[firstFreeBit + bit] _ currentValue[firstBit+bit]; ENDLOOP; firstFreeBit _ firstFreeBit + values.first.size; }; ENDLOOP; }; CutSetMember: PROC [packedPath: CoreFlat.PackedPath, instance: CoreClasses.CellInstance, cutSet: ROPE] RETURNS [member: BOOL _ FALSE, transistor: BOOL _ FALSE, ct: Core.CellType] = { FixStupidRef: PROC [ref: REF ANY] RETURNS [rope: ROPE] = { rope _ WITH ref SELECT FROM r: REF TEXT => Rope.FromRefText[r], r: ROPE => r, ENDCASE => ERROR; }; cutSets: LIST OF ROPE _ NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: roseCutSetProp]]; ct _ instance.type; FOR csl: LIST OF ROPE _ cutSets, csl.rest UNTIL csl=NIL DO IF Rope.Equal[FixStupidRef[csl.first], cutSet] THEN { member _ TRUE; RETURN; }; ENDLOOP; DO IF ct.class.recast=NIL AND FindRoseCellType[ct]#NIL AND ct.class#CoreClasses.recordCellClass THEN { member _ TRUE; RETURN; }; IF ct.class=CoreClasses.transistorCellClass THEN { member _ TRUE; transistor _ TRUE; RETURN; }; cutSets _ NARROW[CoreProperties.GetCellTypeProp[from: ct, prop: roseCutSetProp]]; FOR csl: LIST OF ROPE _ cutSets, csl.rest UNTIL csl=NIL DO IF Rope.Equal[FixStupidRef[csl.first], cutSet] THEN { member _ TRUE; RETURN; }; ENDLOOP; IF ct.class#CoreClasses.identityCellClass THEN EXIT; ct _ NARROW[ct.data]; ENDLOOP; }; AllocateStatePoints: PUBLIC PROC [simulation: Simulation, statePoints: NAT] = { InstanceState: HashTable.EachPairAction = { roseInstance: RoseCellInstance _ NARROW[value]; IF roseInstance.state#NIL THEN { roseInstance.statePoints _ NEW[SRASeq[statePoints]]; FOR s: NAT IN [0..statePoints) DO roseInstance.statePoints[s] _ roseInstance.roseCellType.init[roseInstance.instance.type, roseInstance.publicPort]; ENDLOOP; }; AllocatePortBindings[roseInstance.portBindings]; }; WireState: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; roseWire.statePoints _ IF roseWire.currentValue=NIL THEN NEW[Ports.LevelSequenceRec[statePoints]] ELSE AllocateLevelSequenceSeq[roseWire.currentValue.size]; }; AllocateLevelSequenceSeq: PROC [size: NAT] RETURNS [seq: LevelSequenceSeq] = { seq _ NEW[LevelSequenceSeqRec[statePoints]]; FOR s: NAT IN [0..statePoints) DO seq[s] _ NEW[Ports.LevelSequenceRec[size]]; ENDLOOP; }; AllocatePortBindings: PROC [binds: PortBindings] = { FOR b: NAT IN [0..binds.size) DO bind: PortBinding _ binds[b]; bind.statePoints _ NEW[DriveRec[statePoints]]; FOR f: NAT IN [0..bind.fields.size) DO field: Field _ bind.fields[f]; field.statePoints _ AllocateLevelSequenceSeq[field.currentValue.size]; ENDLOOP; ENDLOOP; }; IF statePoints=0 THEN RETURN; [] _ HashTable.Pairs[table: simulation.coreToRoseInstances, action: InstanceState]; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: WireState]; simulation.statePoints _ NEW[PortSequenceRec[statePoints]]; FOR sp: NAT IN [0..statePoints) DO simulation.statePoints[sp] _ Ports.CreatePort[simulation.coreCellType.public]; ENDLOOP; AllocatePortBindings[simulation.publicBindings]; }; StatePoint: PUBLIC PROC [simulation: Simulation, point: NAT] = { InstanceState: HashTable.EachPairAction = { roseInstance: RoseCellInstance _ NARROW[value]; IF roseInstance.state#NIL THEN roseInstance.roseCellType.copy[from: roseInstance.state, to: roseInstance.statePoints[point]]; SavePortBindings[roseInstance.portBindings]; }; WireState: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; IF roseWire.currentValue=NIL THEN { ls: Ports.LevelSequence _ NARROW[roseWire.statePoints]; ls[point] _ roseWire.wireLevel; } ELSE { sp: LevelSequenceSeq _ NARROW[roseWire.statePoints]; ls: Ports.LevelSequence _ sp[point]; FOR bit: NAT IN [0..roseWire.currentValue.size) DO ls[bit] _ roseWire.currentValue[bit]; ENDLOOP; }; }; SavePortBindings: PROC [binds: PortBindings] = { FOR b: NAT IN [0..binds.size) DO bind: PortBinding _ binds[b]; bind.statePoints[point] _ bind.currentDrive; FOR f: NAT IN [0..bind.fields.size) DO field: Field _ bind.fields[f]; source: Ports.LevelSequence _ field.currentValue; dest: Ports.LevelSequence _ field.statePoints[point]; FOR bit: NAT IN [0..field.currentValue.size) DO dest[bit] _ source[bit]; ENDLOOP; ENDLOOP; ENDLOOP; }; [] _ HashTable.Pairs[table: simulation.coreToRoseInstances, action: InstanceState]; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: WireState]; Ports.CopyPortValue[from: simulation.testPort, to: simulation.statePoints[point]]; SavePortBindings[simulation.publicBindings]; }; RestoreState: PUBLIC PROC [simulation: Simulation, point: NAT] = { InstanceState: HashTable.EachPairAction = { roseInstance: RoseCellInstance _ NARROW[value]; IF roseInstance.state#NIL THEN roseInstance.roseCellType.copy[from: roseInstance.statePoints[point], to: roseInstance.state]; RestorePortBindings[roseInstance.portBindings]; roseInstance.nextNeedEval _ simulation.instanceNeedEval; simulation.instanceNeedEval _ roseInstance; }; WireState: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; IF roseWire.currentValue=NIL THEN { ls: Ports.LevelSequence _ NARROW[roseWire.statePoints]; roseWire.wireLevel _ ls[point]; roseWire.nextPerturbedWire _ simulation.perturbed; roseWire.previousPerturbedWire _ NIL; IF simulation.perturbed#NIL THEN simulation.perturbed.previousPerturbedWire _ roseWire; simulation.perturbed _ roseWire; RecomputeValue[simulation, roseWire, FALSE, NIL]; } ELSE { sp: LevelSequenceSeq _ NARROW[roseWire.statePoints]; ls: Ports.LevelSequence _ sp[point]; FOR bit: NAT IN [0..roseWire.currentValue.size) DO roseWire.currentValue[bit] _ ls[bit]; ENDLOOP; }; UpdateReaders[simulation, roseWire, NIL]; }; RestorePortBindings: PROC [binds: PortBindings] = { FOR b: NAT IN [0..binds.size) DO bind: PortBinding _ binds[b]; bind.currentDrive _ bind.statePoints[point]; FOR f: NAT IN [0..bind.fields.size) DO field: Field _ bind.fields[f]; dest: Ports.LevelSequence _ field.currentValue; source: Ports.LevelSequence _ field.statePoints[point]; FOR bit: NAT IN [0..field.currentValue.size) DO dest[bit] _ source[bit]; ENDLOOP; ENDLOOP; ENDLOOP; }; Complain: UpdateProc = { ERROR Stop["State restoration failed, notify Rosemary wizard"]; }; simulation.instanceNeedEval _ NIL; [] _ HashTable.Pairs[table: simulation.coreToRoseInstances, action: InstanceState]; simulation.perturbed _ NIL; [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: WireState]; Ports.CopyPortValue[from: simulation.statePoints[point], to: simulation.testPort]; RestorePortBindings[simulation.publicBindings]; Settle[simulation, Complain]; }; FindRoseWire: PROC [simulation: Simulation, bindings: HashTable.Table, path: CoreFlat.PackedPath, wire: Core.Wire, wireKey: RoseWireHashKey] RETURNS [roseWire: RoseWire _ NIL] = { bind: CoreFlat.WireBind _ NARROW[HashTable.Fetch[table: bindings, key: wire].value]; wireKey.path _ bind.path; wireKey.wire _ bind.wire; roseWire _ NARROW[HashTable.Fetch[table: simulation.coreToRoseWires, key: wireKey].value]; }; RoseWireHashNarrow: PROC [key: REF ANY] RETURNS [path: CoreFlat.PackedPath, wire: Core.Wire] = { WITH key SELECT FROM wireKey: RoseWireHashKey => {path _ wireKey.path; wire _ wireKey.wire}; wireKey: RoseWire => {path _ wireKey.path; wire _ wireKey.wire}; ENDCASE => ERROR; }; RoseWireHash: PROC [key: REF ANY] RETURNS [hash: CARDINAL] = TRUSTED { path: CoreFlat.PackedPath; wire: Core.Wire; [path, wire] _ RoseWireHashNarrow[key]; hash _ CoreFlat.PathHash[path]; hash _ Basics.BITXOR[hash, Basics.LowHalf[LOOPHOLE[wire]]]; hash _ Basics.BITXOR[hash, Basics.HighHalf[LOOPHOLE[wire]]]; }; RoseWireEqual: PROC [key1, key2: REF ANY] RETURNS [equal: BOOL] = { path1, path2: CoreFlat.PackedPath; wire1, wire2: Core.Wire; [path1, wire1] _ RoseWireHashNarrow[key1]; [path2, wire2] _ RoseWireHashNarrow[key2]; equal _ CoreFlat.PathEqual[path1, path2] AND wire1=wire2; }; RoseInstanceHashNarrow: PROC [key: REF ANY] RETURNS [path: CoreFlat.PackedPath, instance: CoreClasses.CellInstance] = { WITH key SELECT FROM instanceKey: RoseInstanceHashKey => {path _ instanceKey.path; instance _ instanceKey.instance}; instanceKey: RoseCellInstance => {path _ instanceKey.path; instance _ instanceKey.instance}; ENDCASE => ERROR; }; RoseInstanceHash: PROC [key: REF ANY] RETURNS [hash: CARDINAL] = TRUSTED { path: CoreFlat.PackedPath; instance: CoreClasses.CellInstance; [path, instance] _ RoseInstanceHashNarrow[key]; hash _ CoreFlat.PathHash[path]; hash _ Basics.BITXOR[hash, Basics.LowHalf[LOOPHOLE[instance]]]; hash _ Basics.BITXOR[hash, Basics.HighHalf[LOOPHOLE[instance]]]; }; RoseInstanceEqual: PROC [key1, key2: REF ANY] RETURNS [equal: BOOL] = { path1, path2: CoreFlat.PackedPath; instance1, instance2: CoreClasses.CellInstance; [path1, instance1] _ RoseInstanceHashNarrow[key1]; [path2, instance2] _ RoseInstanceHashNarrow[key2]; equal _ CoreFlat.PathEqual[path1, path2] AND instance1=instance2; }; END. ŽRosemaryImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Barth, April 4, 1986 6:46:35 pm PST Behaviour Instantiation IF steady THEN ERROR; -- not implemented FOR hash: HashIndex IN HashIndex DO FOR roseWire: RoseWire _ simulation.coreToRoseWires[hash], roseWire.nextBucket UNTIL roseWire=NIL DO IF roseWire.wireDrive=infinite THEN LOOP; IF roseWire.currentValue=NIL THEN roseWire.wireLevel _ X ELSE FOR bit: NAT IN [0..roseWire.currentValue.size) DO roseWire.currentValue[bit] _ X; ENDLOOP; ENDLOOP; ENDLOOP; EstablishInvariants[simulation]; Relaxation State Access stateAny _ simulation.coreToRoseInstances[0].state; Ê3§– "cedar" style˜codešœ™Kšœ Ïmœ1™˜ZKšœžœ6˜JKšœ-˜-K˜head™ š Ïn œžœžœ*žœžœ"˜rKšœY˜YKšœ˜Kšœ˜K˜—š   œžœžœ,žœžœ$˜wKšœ[˜[Kšœ˜Kšœ˜K˜—š œžœžœžœžœžœžœžœ˜ƒKšœžœ˜ Kšœžœžœ˜ KšœD˜Dšžœžœ˜Kšœžœ˜ Kšœ˜Kšœ˜K˜—Kšžœ@žœ:˜Kšœ"˜"Kšœ˜K˜—šœžœžœžœžœžœžœžœ˜žœ/˜šKšœXžœ˜qKšœ˜Jšœ˜J˜—š  œžœžœ>žœžœ˜‹K˜šŸœ˜"Kšœžœ˜#Kšžœžœ%žœ˜MK˜K˜—š  œžœmžœžœžœžœ˜áKšœ˜Kšœ'˜'šžœžœ˜šžœ žœžœž˜%Kšœ‚˜‚Kšžœ˜—K˜—šžœ˜Kšœžœ=˜\šœžœ˜1K˜Kšœ˜Kšœžœ˜Kšœ˜—šœžœ ˜Kšœ˜Kšœ˜—Kšœ˜Kš œ+žœžœžœžœ!˜xKšœ)˜)Kšœ.˜.Kšžœžœžœ%žœ%˜uK˜—Kšœ˜K˜—Kšœ!žœ˜:Kšœžœ˜Kšœ ˜ Kšœžœ˜3Kšœ žœ˜ Kšœ#˜#Kšœi˜iKšœd˜dKšžœžœažœžœ˜rKšœ+˜+šžœžœ ž˜+Kšœ0žœ˜DKšžœ˜—Kšœ<˜šžœžœžœ˜Kšœ ˜ Kšžœ˜K˜—šž˜Kšžœžœ˜—Kšžœ˜—K˜K˜—Kšœ)žœ˜>Kšœ!žœ˜8KšœžœžœS˜~KšœC˜CKšœ,˜,KšœA˜AKšœ.˜.KšœA˜AKšœ.˜.KšžœžœžœžœN˜†Kšžœžœžœ2˜OKšœ*˜*K˜—šžœ˜Kšœ!žœ˜:Kšœ8˜8Kšœ+˜+Kšœ6˜6KšœA˜AKšœžœ=˜\KšžœÌžœžœ˜ÙKšžœ žœžœd˜ŽKšœ˜Kšœ!˜!Kšžœžœažœžœ˜rK˜—K˜—K˜K˜—šŸœ˜0Kšœžœ˜#Kšžœžœ%žœ˜LKš žœžœžœžœžœ'˜WK˜K˜—Kšœ žœžœ ˜!šœ žœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœ žœžœ˜Kšœ žœžœ˜šœ žœžœ˜K™——Kšœžœ#žœ˜0Kšœžœ"žœ˜.Kšœžœ"žœ˜.Kšœžœ˜Kšœ žœ˜Kšœžœ˜3Kšœ žœ˜ Kšœ#˜#Kšœ˜Kšœ˜Kšœžœ-˜LKšœc˜cKšœd˜dKšœ©˜©Kšœl˜lKšœžœ*˜GKšœžœ˜9KšœT˜Tšžœžœ ž˜+Kšœ0žœ˜NKšžœ˜—K˜-K˜ ˜K™——š œžœ˜6K˜šŸœ˜&Kšœ!žœ˜/KšœRžœžœ˜iK˜K˜—šŸœ˜"Kšœžœ˜#Kšœ žœ˜Kš žœžœžœKžœžœ˜‚K˜K˜K˜—KšœRžœžœ˜iKšœN˜NKšœF˜FK˜K˜—š œžœžœ!˜YKšœžœžœG˜cKšœžœ˜ Kšœžœžœ˜ KšžœžœžœžœN˜~Kšœ;˜;Kšœžœ˜K˜K˜—š œžœ žœžœ˜NKšœžœ ˜(šžœžœžœ žœ˜Kšœ ˜ Kšžœ˜—Kšœ˜K˜—š   œžœžœ"žœžœ˜IKšžœÏc˜Kšžœž œ¡™)šžœžœ ž™#šžœLžœ žœž™dKšžœžœžœ™)Kšžœžœžœ™8š žœžœžœžœ!ž™7Kšœ™Kšžœ™—Kšžœ™—Kšžœ™—Kšœ ™ Kšœ˜K˜——šœ ™ š œžœžœ3žœ˜NKšœ3˜3Kšœ0˜0˜Kšžœžœ"˜/Kšœ]˜]š žœžœžœžœž˜Ešžœžœž˜(Kšœ9˜9Kšœ4˜4Kšœžœ˜KšœS˜SKšœY˜YK˜Kšžœ˜—Kšœ@˜@K˜Kšžœ˜—š žœ žœžœ5žœ žœž˜aKšœ%˜%šžœžœžœ˜#Kšžœžœžœ˜#K˜—š žœžœžœžœ!ž˜Kšœžœžœžœ2žœžœ7žœžœ˜«Kšžœžœ˜—šžœžœ˜%Kšœžœ˜Kšœ˜K˜—Kšžœ˜—K˜ Kšžœ žœ žœ žœE˜vKšžœ˜—K˜—Kšžœžœ˜—Kšžœ˜—J˜J˜—š œžœ=žœ˜rKšœ3˜3šžœ žœžœ˜Kšœ+˜+Kšœ+˜+šžœ žœžœž˜6Kšœ*˜*Kšœ2˜2Kšœ;˜;šžœžœ˜$Kšœ˜Kšœ˜K˜—Kš žœžœžœžœžœ˜oKšžœ˜—šžœ#žœ#žœžœ˜eKšœ$˜$Kšœ$˜$Kšœ˜K˜—K˜—šžœ˜Kšœ<˜K˜š  œžœžœžœžœ˜Dšœž œž˜Kšœžœ˜ Kšœ ˜ Kšœžœ˜ Kšžœžœ˜—K˜K˜—K˜!Kšœ3˜3Kšœ8˜8Kšœ žœ.˜>šžœž˜Kšœ%˜%Kšœ<˜<šœžœ žœžœ-˜HKš žœžœžœžœž˜+Kšœ1˜1Kšžœ˜—šœžœ žœžœR˜mš žœžœžœžœž˜+KšœZ˜ZKšžœ˜——šœ˜Kšœžœ˜-Kšžœ žœžœBž˜Xš žœžœžœžœž˜+Kšœ žœ˜Kšœ:˜:Kšžœ˜—Kšœžœ ˜!K˜—šœ˜Kšœžœžœ˜LKšžœ žœžœC˜Xš žœžœžœžœž˜+Kšœ žœ˜Kšœ:˜:Kšžœ˜—Kšœžœžœ ˜?K˜—Kšžœžœ˜—K˜K˜—š œžœ6˜KK˜Kšœ žœ˜'K˜š œžœžœ˜CKšœ-˜-šœžœ žœ˜šœžœ ž˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšžœžœ˜—šœžœ ž˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšžœžœ˜—Kšœ ˜ Kšžœžœ˜—K˜K˜—š œžœ-˜EKšœk˜kKšœj˜jK˜K˜—šœ žœ˜$K˜—š  œžœ%˜7K˜š œžœžœ˜PKšœ˜šžœ%žœ˜-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šžœ žœžœ˜FKšœ$˜$šžœž˜šœ ˜ Kšœ(˜(Kšœ0˜0Kšžœžœžœ'˜7Kšžœ žœžœ#˜7Kšžœžœ˜>Kšœžœ˜Kšœžœ˜!Kšœ!˜!Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ#˜#Kšžœžœ˜—K˜K˜—š  œžœ˜'šžœž œžœž˜K˜Kšžœžœ˜,šžœž˜šœ žœ žœ$žœ˜HKšœ%˜%Kšœ,˜,K˜—š œžœžœ&žœ"žœ˜kKšœ!˜!Kšœ,˜,K˜—š œžœžœ&žœ$žœ˜oKšœ#˜#Kšœ,˜,K˜—Kšžœžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ˜—K˜K˜—Kšœžœ˜šžœžœž˜!Kšœ&˜&Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—šžœ4žœ žœž˜Nšœžœžœž˜)Kšœ˜Kšœ˜Kšžœ˜ —šžœ žœ˜(Kšœ*˜*š žœžœžœžœžœžœž˜7Kšœ ˜ Kšœ˜Kšœ˜Kšžœ˜—Kšœ!˜!Kšœ2˜2K˜—Kšžœ˜—K˜K˜—š œžœ-˜:š žœžœžœžœžœžœ˜Kšœ-˜-Kšœ%˜%Kšžœ žœžœ*˜AKšœ˜Kšœ˜—Kšœ˜K˜——™ š  œžœžœžœ5˜fKšœ˜Kšœ˜Kšœ˜K™—š  œžœžœžœ žœžœ˜VKšœ3™3Kšœ˜K™—š œžœžœmžœ žœžœžœ˜¯Kšœi˜išœ#žœ˜AKšœ˜Kšœ˜—Kšœ!žœQ˜xKšœ˜Kšœ˜K™—š  œžœžœZžœ!˜˜Kšœi˜iKšœžœ˜Kšœžœ˜šžœ-žœžœž˜BKšžœ2žœžœžœ˜Xšž˜šžœ˜ K˜š œžœ1˜FKšœP˜Pšžœ žœžœ˜š žœ žœž œžœž˜0Kšœ%˜%Kšžœ˜—K˜—šžœ žœ˜Kšœ˜Kš œžœžœžœžœ&˜T—K˜K˜—š  œžœžœ žœžœ žœžœ žœ ˜wKšžœžœ ž˜&š žœžœ žœžœž˜/KšœA˜Ašžœ žœžœ žœ˜%Kšœ'˜'Kšœžœ;˜[Kšœ˜šžœžœžœ˜Kšœ˜Kšœ˜K˜—šžœ žœžœž˜$Kšœ9˜9Kšžœ˜—KšœJ˜Jšžœ žœžœ˜šœ žœ˜Kšœ˜Kšœ˜Kšœ'˜'—Kšœ žœ˜K˜—Kšžœ˜K˜—Kšžœ˜—Kšœ˜K˜—Kšœžœ˜Kšœ˜Kšœžœ˜3K˜KšœV˜VKšœ"˜"Kšžœžœžœžœžœ žœ@žœžœ˜ušœ"žœ˜(Kšœ˜Kšœ ˜ Kšœ*˜*—K˜——Kšžœ˜—Kšœžœ1˜<šžœ2žœžœž˜HKšœG˜Gšžœžœžœ˜Kšœ6˜6Kšœ ˜ K˜—šžœ˜Kšœ žœ˜&šžœžœžœž˜)Kšœ7˜7Kšžœ˜—Kšœ0˜0K˜—Kšžœ˜—Kšœ˜K˜—š  œžœOžœžœ žœžœžœžœ˜¶K˜š   œžœžœžœžœžœ˜:šœžœžœž˜Kšœžœžœ˜#Kšœžœ˜ Kšžœžœ˜—Kšœ˜K˜—Kš œ žœžœžœžœK˜iKšœ˜š žœžœžœžœžœžœž˜:šžœ-žœ˜5Kšœ žœ˜Kšžœ˜K˜—Kšžœ˜—šž˜š žœžœžœžœžœ&žœ˜cKšœ žœ˜Kšžœ˜K˜—šžœ*žœ˜2Kšœ žœ˜Kšœ žœ˜Kšžœ˜Kšœ˜—Kšœ žœA˜Qš žœžœžœžœžœžœž˜:šžœ-žœ˜5Kšœ žœ˜Kšžœ˜K˜—Kšžœ˜—Kšžœ(žœžœ˜4Kšœžœ ˜Kšžœ˜—Kšœ˜K˜——š œžœžœ'žœ˜OK˜šŸ œ˜+Kšœ!žœ˜/šžœžœžœ˜ Kšœžœ˜4šžœžœžœž˜!Kšœr˜rKšžœ˜—K˜—Kšœ0˜0K˜K˜—šŸ œ˜'Kšœžœ˜#Kš œžœžœžœžœ&žœ6˜œK˜K˜—š œžœžœžœ˜NKšœžœ#˜,šžœžœžœž˜!Kšœ žœ˜+Kšžœ˜—K˜K˜—š œžœ˜4šžœžœžœž˜ Kšœ˜Kšœžœ˜.šžœžœžœž˜&K˜KšœF˜FKšžœ˜—Kšžœ˜—K˜K˜—Kšžœžœžœ˜KšœS˜SKšœK˜KKšœžœ˜;šžœžœžœž˜"KšœN˜NKšžœ˜—Kšœ0˜0K˜K˜—š  œžœžœ!žœ˜@K˜šŸ œ˜+Kšœ!žœ˜/Kšžœžœžœ_˜}Kšœ,˜,K˜K˜—šŸ œ˜'Kšœžœ˜#šžœžœžœ˜#Kšœžœ˜7Kšœ˜K˜—šžœ˜Kšœžœ˜4Kšœ$˜$šžœžœžœ!ž˜2Kšœ%˜%Kšžœ˜—K˜—K˜K˜—š œžœ˜0šžœžœžœž˜ Kšœ˜Kšœ,˜,šžœžœžœž˜&K˜Kšœ1˜1Kšœ5˜5šžœžœžœž˜/Kšœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜—K˜K˜—KšœS˜SKšœK˜KKšœR˜RKšœ,˜,K˜K˜—š  œžœžœ!žœ˜BK˜šŸ œ˜+Kšœ!žœ˜/Kšžœžœžœ_˜}Kšœ/˜/Kšœ8˜8Kšœ+˜+K˜K˜—šŸ œ˜'Kšœžœ˜#šžœžœžœ˜#Kšœžœ˜7Kšœ˜Kšœ2˜2Kšœ!žœ˜%Kšžœžœžœ7˜WKšœ ˜ Kšœ%žœžœ˜1K˜—šžœ˜Kšœžœ˜4Kšœ$˜$šžœžœžœ!ž˜2Kšœ%˜%Kšžœ˜—K˜—Kšœ$žœ˜)K˜K˜—š œžœ˜3šžœžœžœž˜ Kšœ˜Kšœ,˜,šžœžœžœž˜&K˜Kšœ/˜/Kšœ7˜7šžœžœžœž˜/Kšœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜—K˜K˜—š œ˜Kšžœ:˜?K˜K˜—Kšœžœ˜"KšœS˜SKšœžœ˜KšœK˜KKšœR˜RKšœ/˜/K˜K˜K˜—š  œžœ{žœžœ˜³Kšœžœ4˜TKšœ˜Kšœ˜Kšœ žœJ˜[Kšœ˜K˜—š  œžœžœžœžœ1˜`šžœžœž˜KšœG˜GKšœ@˜@Kšžœžœ˜—Kšœ˜K˜—š  œžœžœžœžœžœžœ˜FKšœ˜K˜Kšœ'˜'Jšœ˜Jšœžœžœ ˜;Jšœžœžœ ˜