Instantiation
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];
};
Relaxation
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<infinite
THEN {
currentHead: RoseWire ← simulation.perturbed;
wire.nextPerturbedWire ← currentHead;
IF currentHead#NIL THEN currentHead.previousPerturbedWire ← wire;
simulation.perturbed ← wire;
};
};
State Access
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]];
};