DIRECTORY Basics, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, HashTable, Ports, Process, Rope, Rosemary, SymTab; RosemaryImpl: CEDAR PROGRAM IMPORTS Basics, CoreClasses, CoreFlat, CoreIO, 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; roseBehaveProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseBehave]; roseCutSetProp: ATOM = CoreProperties.RegisterProperty[prop: $RoseCutSet]; roseWireDataProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $RoseWireData], write: RoseWireDataWrite, read: RoseWireDataRead]; RoseWireDataWrite: CoreIO.PropWriteProc = { roseWireData: RoseWireData _ NARROW[value]; CoreIO.WriteID[h, Ports.levelNames[roseWireData.value]]; CoreIO.WriteID[h, Ports.driveNames[roseWireData.size]]; }; RoseWireDataRead: CoreIO.PropReadProc = { roseWireData: RoseWireData _ NEW[RoseWireDataRec]; roseWireData.value _ Ports.FindLevel[CoreIO.ReadID[h]]; roseWireData.size _ Ports.FindDrive[CoreIO.ReadID[h]]; value _ roseWireData; }; roseFixedWireProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $RoseFixedWire], write: RoseFixedWireWrite, read: RoseFixedWireRead]; RoseFixedWireWrite: CoreIO.PropWriteProc = { level: REF Ports.Level _ NARROW[value]; CoreIO.WriteID[h, Ports.levelNames[level^]]; }; RoseFixedWireRead: CoreIO.PropReadProc = { level: REF Ports.Level _ NEW[Ports.Level]; level^ _ Ports.FindLevel[CoreIO.ReadID[h]]; value _ level; }; roseTransistorSizeProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $RoseTransistorSize], write: RoseTransistorSizeWrite, read: RoseTransistorSizeRead]; RoseTransistorSizeWrite: CoreIO.PropWriteProc = { size: REF Ports.Drive _ NARROW[value]; CoreIO.WriteID[h, Ports.driveNames[size^]]; }; RoseTransistorSizeRead: CoreIO.PropReadProc = { size: REF Ports.Drive _ NEW[Ports.Drive]; size^ _ Ports.FindDrive[CoreIO.ReadID[h]]; value _ size; }; roseClassTable: SymTab.Ref _ SymTab.Create[]; Stop: PUBLIC SIGNAL [msg: ROPE, data: REF ANY _ NIL] = CODE; 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; }; 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 _ L] RETURNS [sameWire: Core.Wire] = { CoreProperties.PutWireProp[on: wire, prop: roseFixedWireProp, value: NEW[Ports.Level _ level]]; sameWire _ wire; }; SetWire: PUBLIC PROC [wire: Core.Wire, level: Ports.Level _ L, size: WireSize _ charge] RETURNS [sameWire: Core.Wire] = { CoreProperties.PutWireProp[on: wire, prop: roseWireDataProp, value: NEW[RoseWireDataRec _ [level, 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: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; simulation _ NEW[SimulationRec]; simulation.coreToValues _ HashTable.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; 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; wireSize: NAT; fixed: BOOL; [fixed, wireSize, roseWire] _ InitWire[public]; roseWire.connections _ NEW[FieldSeq[2]]; IF NOT HashTable.Insert[table: wireToRoseWire, key: roseWire, value: roseWire] THEN ERROR; IF wireSize>1 THEN maxComposite _ wireSize; IF port.type=b OR port.type=bs OR port.type=c OR port.type=lc THEN boolWires _ CONS[roseWire, boolWires]; }; }; InitWire: PROC [coreWire: Core.Wire] RETURNS [fixed: BOOL, wireSize: NAT, roseWire: RoseWire] = { FetchValue: PROC [wire: Core.Wire] RETURNS [wireDrive: Ports.Drive _ charge, wireLevel: Ports.Level _ L] = { wireData: RoseWireData _ NARROW[CoreProperties.GetWireProp[from: coreWire, prop: roseWireDataProp]]; wireFixedRef: REF Ports.Level _ NARROW[CoreProperties.GetWireProp[from: coreWire, prop: roseFixedWireProp]]; fixed _ wireFixedRef#NIL; IF wireData#NIL THEN { wireDrive _ wireData.size; wireLevel _ wireData.value; }; IF fixed THEN { wireDrive _ infinite; wireLevel _ wireFixedRef^ }; }; GetValue: PROC [wire: Core.Wire] = { roseWire.currentValue[bit] _ FetchValue[wire].wireLevel; bit _ bit + 1; }; bit: NAT _ 0; roseWire _ NEW[RoseWireRec]; wireSize _ CoreOps.WireBits[coreWire]; IF wireSize>1 THEN { roseWire.currentValue _ AllocateLevelSequence[wireSize]; CoreOps.VisitAtomicWires[coreWire, GetValue]; } ELSE { [roseWire.wireDrive, roseWire.wireLevel] _ FetchValue[coreWire]; roseWire.switchDrive _ roseWire.wireDrive; }; roseWire.wire.wire _ coreWire; }; InstantiateInstances: PUBLIC PROC [cellType: Core.CellType, testPort: Ports.Port, cutSets: LIST OF 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: public].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: public, 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, 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, cutSets]; 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; wireSize: NAT; fixed: BOOL; [fixed, wireSize, roseWire] _ InitWire[wire]; 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 AND NOT fixed THEN { roseWire.channels _ AllocateTransistorPointers[wireData.channels]; roseWire.gates _ AllocateTransistorPointers[wireData.gates]; }; roseWire.wire.path _ path; 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, cutSets]; 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.instance.path _ path; roseInstance.instance.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: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; simulation _ NEW[SimulationRec]; simulation.coreCellType _ cellType; 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]; simulation.coreToValues _ HashTable.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash]; 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] = { SetX: HashTable.EachPairAction = { roseWire: RoseWire _ NARROW[value]; IF roseWire.wireDrive=infinite THEN RETURN; IF roseWire.currentValue=NIL THEN roseWire.wireLevel _ X ELSE FOR bit: NAT IN [0..roseWire.currentValue.size) DO roseWire.currentValue[bit] _ X; ENDLOOP; }; IF steady THEN ERROR; -- not implemented [] _ HashTable.Pairs[table: simulation.coreToRoseWires, action: SetX]; EstablishInvariants[simulation]; }; 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; { noMore: BOOL _ FALSE; 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 SIGNAL Stop["Wire with bool port settled to an X", $BoolWireHasX]; } ELSE FOR bit: CARDINAL IN [0..roseWire.currentValue.size) DO IF roseWire.currentValue[bit]=X THEN SIGNAL Stop["Wire with bool port settled to an X", $BoolWireHasX]; IF noMore THEN EXIT; ENDLOOP; IF noMore THEN EXIT; 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 ERROR; ENDLOOP; FOR fieldIndex: NAT IN [0..binding.fields.size) DO roseWire: RoseWire _ binding.fields[fieldIndex].roseWire; fieldForce: BOOL _ FALSE; IF roseWire.currentValue=NIL THEN { IF roseWire.switchDrive>=force THEN fieldForce _ TRUE; } ELSE { connections: Fields _ roseWire.connections; FOR connectionIndex: NAT IN [0..connections.size) DO IF connections[connectionIndex].portBinding.currentDrive>=force THEN { fieldForce _ TRUE; EXIT; }; ENDLOOP; }; someForce _ someForce OR fieldForce; someNotForce _ someNotForce OR NOT fieldForce; ENDLOOP; IF someForce AND someNotForce THEN ERROR; anotherPort.d _ IF someForce THEN force ELSE expect; }; }; }; roseInstance: RoseCellInstance _ NARROW[HashTable.Fetch[table: simulation.coreToRoseInstances, key: instance].value]; settled: Ports.Port _ roseInstance.publicPort; settledPortBindings: PortBindings _ roseInstance.portBindings; Ports.CopyPortValue[from: settled, to: test]; IF Ports.VisitPortPair[onePort: settled, anotherPort: test, eachPortPair: SetDrive] THEN ERROR; }; RawRoseWire: PUBLIC PROC [simulation: Simulation, flatWire: CoreFlat.FlatWire] RETURNS [roseWire: RoseWire] = { roseWire _ NARROW[HashTable.Fetch[table: simulation.coreToRoseWires, key: flatWire].value]; }; FindRoseWire: PROC [simulation: Simulation, bindings: HashTable.Table, wire: Core.Wire, wireKey: CoreFlat.FlatWire] 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 [flat: CoreFlat.FlatWireRec] = { WITH key SELECT FROM wireKey: CoreFlat.FlatWire => flat _ wireKey^; wireKey: RoseWire => flat _ wireKey.wire; 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]]; }; RoseInstanceHashNarrow: PROC [key: REF ANY] RETURNS [flat: CoreFlat.FlatInstanceRec] = { WITH key SELECT FROM instanceKey: CoreFlat.FlatInstance => flat _ instanceKey^; instanceKey: RoseCellInstance => flat _ instanceKey.instance; ENDCASE => ERROR; }; RoseInstanceHash: PROC [key: REF ANY] RETURNS [hash: CARDINAL] = { hash _ CoreFlat.FlatInstanceHashRec[RoseInstanceHashNarrow[key]]; }; RoseInstanceEqual: PROC [key1, key2: REF ANY] RETURNS [equal: BOOL] = { equal _ CoreFlat.FlatInstanceEqualRec[RoseInstanceHashNarrow[key1], RoseInstanceHashNarrow[key2]]; }; END. ÚRosemaryImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Barth, June 16, 1986 5:06:41 pm PDT Louis Monier May 22, 1986 10:43:02 am PDT Behaviour Instantiation Relaxation State Access Ê6é– "cedar" style˜codešœ™Kšœ Ïmœ1™žœ/˜š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šœžœ˜7Kšœ žœ˜ Kšœg˜gKšœ#˜#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šœžœ˜7Kšœ žœ˜ Kšœ#˜#Kšœ˜Kšœžœ-˜LKšœc˜cKšœd˜dKšœg˜gKšœ©˜©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˜šŸœ˜"Kšœžœ˜#Kšžœžœžœ˜+Kšžœžœžœ˜8š žœžœžœžœ!ž˜7Kšœ˜Kšžœ˜—K˜K˜—Kšžœž œÏc˜)KšœF˜FKšœ ˜ 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šžœ˜—šœ˜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šœ;˜;šœ˜Kšžœ žœžœ-˜Bš žœžœžœžœž˜+Kšœ1˜1Kšžœ˜—K˜—šœ˜Kšžœ žœžœR˜gš žœžœžœžœž˜+KšœZ˜ZKšžœ˜—K˜—šœ˜Kšœžœ˜-Kšžœ žœžœC˜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˜——™ š  œžœžœžœ%˜ZKšœ˜Kšœ˜K™—š  œžœžœžœ žœžœ˜VK˜šŸœ˜&Kšœ!žœ˜/Kš žœžœžœžœžœ˜AK˜—Kšœ!žœ˜%KšœN˜NKšœ˜Kšœ˜K™—š œžœžœ;žœ žœžœžœ˜}Kšœ!žœN˜uKšœ˜Kšœ˜K™—š  œžœžœ3žœ!˜qKšœžœ˜KšœžœC˜Zšžœžœžœ˜K˜š œžœ!˜6KšœO˜Ošžœ žœžœ˜š žœ žœž œžœž˜5Kšœ1˜1Kšžœ˜—K˜—šžœ žœ˜Kšœ˜Kš œžœžœžœžœ&˜T—K˜K˜—š  œžœžœ žœžœ žœžœ žœ ˜wKšžœžœ ž˜+š žœžœ žœžœž˜/KšœA˜Ašžœ žœžœ žœ˜%Kšœ&˜&Kšœžœ;˜[Kšœ˜šžœžœžœ˜Kšœ˜Kšœ˜K˜—šžœ žœžœž˜$Kšœ9˜9Kšžœ˜—KšœD˜Dšžœ žœžœ˜šœ žœ˜Kšœ˜Kšœ˜Kšœ,˜,—Kšœ žœ˜K˜—Kšžœ˜K˜—Kšžœ˜—Kšœ˜K˜—Kšœ˜Kšœžœ˜7K˜KšœU˜UKšœ˜Kšžœžœžœžœžœ žœ@žœžœ˜uKšœ˜KšžœžœOžœžœ˜`K˜—Kšœžœ6˜Ašžœžœžœž˜4KšœG˜Gšžœžœžœ˜Kšœ6˜6Kšœ ˜ K˜—šžœ˜Kšœ žœ˜&šžœžœžœž˜)Kšœ7˜7Kšžœ˜—Kšœ0˜0K˜—Kšžœ˜—Kšœ˜K˜—š  œžœžœ1žœžœžœ žœžœ˜€Kšœ˜Kšœžœ˜4KšœM˜MKšœH˜HK˜K˜—š  œžœPžœžœžœžœ žœžœžœžœ˜¿K˜š  œžœžœžœžœžœžœžœ˜Kš žœžœžœžœžœžœž˜9š žœžœžœžœžœžœž˜;šžœ:žœ˜BKšœ žœ˜Kšœžœ˜ Kšžœ˜K˜—Kšžœ˜—Kšžœ˜—Kšœ˜K˜—Kš œ žœžœžœžœK˜iKšœ˜Kšžœžœžœ˜,šž˜š žœžœžœžœžœ&žœ˜cKšœ žœ˜Kšžœ˜K˜—šžœ*žœ˜2Kšœ žœ˜Kšœ žœ˜Kšžœ˜Kšœ˜—Kšœ žœA˜QKšžœžœžœ˜,Kšžœ(žœžœ˜4Kšœžœ ˜Kšžœ˜—Kšœ˜K˜—š œžœžœ'žœ˜OK˜šŸ œ˜+Kšœ!žœ˜/šžœžœžœ˜ Kšœžœ˜4šžœžœžœž˜!Kšœ|˜|Kšžœ˜—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˜—š  œžœžœP˜iK˜š œ˜$šžœžœ˜ šžœžœžœ˜4Kšœ˜Kšœ žœžœ˜Kšœžœžœ˜šžœžœžœž˜1Kšœ$˜$Kšžœžœžœ˜(Kšžœžœžœ˜Kšžœ˜—šžœ žœžœž˜2Kšœ9˜9Kšœ žœžœ˜šžœžœžœ˜#Kšžœžœžœ˜6Kšœ˜—šžœ˜Kšœ+˜+šžœžœžœž˜4šžœ>žœ˜FKšœ žœ˜Kšžœ˜K˜—Kšžœ˜—K˜—Kšœžœ ˜$Kšœžœžœ ˜.Kšžœ˜—Kšžœ žœžœžœ˜)Kšœžœ žœžœ˜4Kšœ˜—K˜—K˜K˜—Kšœ!žœN˜uKšœ.˜.Kšœ>˜>Jšœ-˜-KšžœRžœžœ˜_Kšœ˜K™—š  œžœžœ7žœ˜oKšœ žœK˜\Kšœ˜K˜—š  œžœbžœžœ˜šKšœžœ4˜TKšœ˜Kšœ˜Kšœ žœJ˜[Kšœ˜K˜—š  œžœžœžœžœ!˜Pšžœžœž˜Kšœ.˜.Kšœ)˜)Kšžœžœ˜—Kšœ˜K˜—š   œžœžœžœžœžœ˜>Jšœ9˜9Kšœ˜K˜—š   œžœžœžœžœ žœ˜CKšœV˜VKšœ˜K˜—š  œžœžœžœžœ%˜Xšžœžœž˜Kšœ:˜:Kšœ=˜=Kšžœžœ˜—Kšœ˜K˜—š  œžœžœžœžœžœ˜BJšœA˜AKšœ˜K˜—š  œžœžœžœžœ žœ˜GKšœb˜bKšœ˜K˜——Kšžœ˜—…—Ê ã