<> <> <> <> <<>> 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> GetWirePath: PUBLIC PROC [roseWire: RoseWire] RETURNS [coreWire: CoreFlat.FlatWireRec] = { coreWire _ roseWire.wire; }; <<>> GetCellTypeState: PUBLIC PROC [simulation: Simulation] RETURNS [stateAny: REF ANY] = { Instance: HashTable.EachPairAction = { roseInstance: RoseCellInstance _ NARROW[value]; IF cellInstance=NIL THEN cellInstance _ roseInstance ELSE ERROR}; cellInstance: RoseCellInstance _ NIL; [] _ HashTable.Pairs[table: simulation.coreToRoseInstances, action: Instance]; stateAny _ cellInstance.state; }; <<>> GetInstanceState: PUBLIC PROC [simulation: Simulation, instance: CoreFlat.FlatInstance] RETURNS [stateAny: REF ANY _ NIL] = { roseInstance: RoseCellInstance _ NARROW[HashTable.Fetch[table: simulation.coreToRoseInstances, key: instance].value]; stateAny _ roseInstance.state; }; <<>> WireValue: PUBLIC PROC [simulation: Simulation, wire: CoreFlat.FlatWire] RETURNS [value: Ports.LevelSequence] = { firstFreeBit: NAT _ 0; values: Values _ NARROW[HashTable.Fetch[table: simulation.coreToValues, key: wire].value]; IF values=NIL THEN { FindHereOrBelow: PROC [wire: CoreFlat.FlatWireRec] = { roseWire: RoseWire _ FindRoseWire[simulation, wireBindTab, wire.wire, wireKey]; IF roseWire=NIL THEN { FOR subWire: NAT DECREASING IN [0..wire.wire.size) DO FindHereOrBelow[[wire.path, wire.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.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 _ wire.path; 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, internal, wireKey]; IF roseWire#NIL THEN { values _ CONS[[ roseWire: roseWire, firstBit: firstBit, size: CoreOps.WireBits[wire.wire]], values]; foundRose _ TRUE; }; EXIT; }; ENDLOOP; }; wireBindTab: HashTable.Table; wireKey: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; cellType: Core.CellType; [wireBindTab, cellType] _ CoreFlat.BoundCellType[simulation.coreCellType, wire.path]; FindHereOrBelow[wire^]; IF values=NIL THEN IF NOT FindAbove[NARROW[cellType.data, CoreClasses.RecordCellType].internal].foundRose THEN ERROR; wireKey^ _ wire^; IF NOT HashTable.Insert[table: simulation.coreToValues, key: wireKey, value: values] THEN ERROR; }; value _ NEW[Ports.LevelSequenceRec[CoreOps.WireBits[wire.wire]]]; FOR values _ 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; }; WireValueRope: PUBLIC PROC [simulation: Rosemary.Simulation, wirePathRope: ROPE, base: NAT _ 16] RETURNS [value: ROPE _ NIL] = { wireRoot: CoreFlat.WireRoot; wire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec]; [wire^, wireRoot] _ CoreFlat.FindWire[simulation.coreCellType, wirePathRope]; value _ Ports.LevelSequenceToRope[WireValue[simulation, wire], 0, base]; }; CutSetMember: PROC [packedPath: CoreFlat.PackedPath, instance: CoreClasses.CellInstance, cutSets: LIST OF ROPE] RETURNS [member: BOOL _ FALSE, transistor: BOOL _ FALSE, ct: Core.CellType] = { OneInOther: PROC [one, other: LIST OF ROPE] RETURNS [yes: BOOL _ FALSE] = { FOR this: LIST OF ROPE _ one, this.rest UNTIL this=NIL DO FOR that: LIST OF ROPE _ other, that.rest UNTIL that=NIL DO IF Rope.Equal[CoreOps.FixStupidRef[this.first], that.first] THEN { member _ TRUE; yes _ TRUE; RETURN; }; ENDLOOP; ENDLOOP; }; thisSet: LIST OF ROPE _ NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: roseCutSetProp]]; ct _ instance.type; IF OneInOther[cutSets, thisSet] THEN RETURN; 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; }; thisSet _ NARROW[CoreProperties.GetCellTypeProp[from: ct, prop: roseCutSetProp]]; IF OneInOther[cutSets, thisSet] THEN RETURN; 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.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]; }; SettleToTest: PUBLIC PROC [simulation: Simulation, instance: CoreFlat.FlatInstance, test: Ports.Port] = { SetDrive: Ports.EachPortPairProc = { IF onePort.type#composite THEN { IF onePort.d#none THEN anotherPort.d _ expect ELSE { binding: PortBinding; someForce: BOOL _ FALSE; someNotForce: BOOL _ FALSE; FOR bind: NAT IN [0..settledPortBindings.size) DO binding _ settledPortBindings[bind]; IF binding.clientPort=onePort THEN EXIT; REPEAT FINISHED => 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.