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]
RETURNS [sameWire: Core.Wire] = {
CoreProperties.PutWireProp[on: wire, prop: roseFixedWireProp, value: NEW[Ports.Level ← level]];
sameWire ← wire;
};
SetWireSize:
PUBLIC
PROC [wire: Core.Wire, size: WireSize]
RETURNS [sameWire: Core.Wire] = {
CoreProperties.PutWireProp[on: wire, prop: roseWireSizeProp, value: NEW[Ports.Drive ← size]];
sameWire ← wire;
};
SetTransistorCellTypeSize:
PUBLIC
PROC [transistor: Core.CellType, size: TransistorSize]
RETURNS [sameTransistor: Core.CellType] = {
CoreProperties.PutCellTypeProp[on: transistor, prop: roseTransistorSizeProp, value: NEW[Ports.Drive ← size]];
sameTransistor ← transistor;
};
SetTransistorInstanceSize:
PUBLIC
PROC [transistor: CoreClasses.CellInstance, size: TransistorSize]
RETURNS [sameTransistor: CoreClasses.CellInstance] = {
CoreProperties.PutCellInstanceProp[on: transistor, prop: roseTransistorSizeProp, value: NEW[Ports.Drive ← size]];
sameTransistor ← transistor;
};
InstantiateCellType:
PUBLIC
PROC [cellType: Core.CellType, testPort: Ports.Port, statePoints:
NAT ← 0]
RETURNS [simulation: Simulation] = {
roseInstance: RoseCellInstance ← NEW[RoseCellInstanceRec];
max: CARDINAL;
wireToRoseWire: RefTab.Ref ← RefTab.Create[];
simulation ← NEW[SimulationRec];
simulation.coreCellType ← cellType;
simulation.coreToRoseInstances[0] ← roseInstance;
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;
FOR hash: HashIndex
IN HashIndex
DO
FOR roseWire: RoseWire ← simulation.coreToRoseWires[hash], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF roseWire.wireDrive=infinite THEN UpdateReaders[simulation, roseWire, NIL];
ENDLOOP;
ENDLOOP;
simulation.testPort ← testPort;
AllocateStatePoints[simulation, statePoints];
EstablishInvariants[simulation];
};
AllocateCellTypeRoseWires:
PROC [simulation: Simulation, port: Ports.Port, public: Core.Wire, wireToRoseWire: RefTab.Ref]
RETURNS [maxComposite:
CARDINAL ← 0, boolWires: RoseWireList ←
NIL] = {
IF port.type=composite
THEN {
subBools: RoseWireList;
subMax: CARDINAL;
FOR sub:
NAT
IN [0..port.size)
DO
[subMax, subBools] ← AllocateCellTypeRoseWires[simulation, port[sub], public[sub], wireToRoseWire];
maxComposite ← MAX[subMax, maxComposite];
FOR bools: RoseWireList ← subBools, bools.rest
UNTIL bools=
NIL
DO
boolWires ← CONS[bools.first, boolWires];
ENDLOOP;
ENDLOOP;
}
ELSE {
roseWire: RoseWire ← NEW[RoseWireRec];
hash: HashIndex ← PathHash[[0, ALL[FALSE]], public];
wireSizeRef: REF Ports.Drive ← NARROW[CoreProperties.GetWireProp[from: public, prop: roseWireSizeProp]];
wireFixedRef: REF Ports.Level ← NARROW[CoreProperties.GetWireProp[from: public, prop: roseFixedWireProp]];
IF wireSizeRef#NIL THEN roseWire.wireDrive ← wireSizeRef^;
IF wireFixedRef#
NIL
THEN {
roseWire.wireDrive ← infinite;
roseWire.switchDrive ← infinite;
roseWire.wireLevel ← wireFixedRef^
};
roseWire.connections ← NEW[FieldSeq[2]];
IF NOT RefTab.Insert[x: wireToRoseWire, key: public, val: roseWire] THEN ERROR;
IF port.type=l OR port.type=b THEN Perturb[simulation, roseWire]
ELSE {
maxComposite ← CoreOps.WireBits[public];
roseWire.currentValue ← AllocateLevelSequence[maxComposite];
};
IF port.type=b OR port.type=bs OR port.type=c OR port.type=lc THEN boolWires ← CONS[roseWire, boolWires];
roseWire.wire ← public;
roseWire.nextBucket ← simulation.coreToRoseWires[hash];
simulation.coreToRoseWires[hash] ← roseWire;
};
};
ComputeCellTypeBindings:
PROC [port: Ports.Port, wire: Core.Wire, wireToRoseWire: RefTab.Ref, 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 ← ComputeCellTypeBindings[port[subPort], wire[subPort], wireToRoseWire, binds, newFirstFreeBinding, instance];
ENDLOOP;
}
ELSE {
thisRoseWire: RoseWire ← NARROW[RefTab.Fetch[x: wireToRoseWire, key: wire].val];
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;
};
};
InstantiateInstances:
PUBLIC
PROC [cellType: Core.CellType, testPort: Ports.Port, cutSet:
ROPE ←
NIL, statePoints:
NAT ← 0]
RETURNS [simulation: Simulation] = {
FindRoseWires:
PROC [ct: Core.CellType] = {
AllocateRoseWires:
PROC [wire: Core.Wire]
RETURNS [public:
BOOL ←
FALSE, allocated:
BOOL ←
FALSE] = {
wireData: WireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: wire].val];
AllocateWire:
PROC [wire: Core.Wire, wireData: WireData] = {
AllocateTransistorPointers:
PROC [count:
CARDINAL]
RETURNS [transistors: RoseTransistors ←
NIL] = {
IF count>0
THEN {
transistors ← NEW[RoseTransistorSeq[count]];
FOR i:
CARDINAL
IN [0..transistors.size)
DO
transistors[i] ← NIL;
ENDLOOP;
};
};
roseWire: RoseWire ← NEW[RoseWireRec];
hash: HashIndex ← PathHash[packedPath, wire];
wireSize: NAT ← CoreOps.WireBits[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 THEN roseWire.currentValue ← AllocateLevelSequence[wireSize]
ELSE {
wireSizeRef: REF Ports.Drive ← NARROW[CoreProperties.GetWireProp[from: wire, prop: roseWireSizeProp]];
wireFixedRef: REF Ports.Level ← NARROW[CoreProperties.GetWireProp[from: wire, prop: roseFixedWireProp]];
roseWire.channels ← AllocateTransistorPointers[wireData.channels];
roseWire.gates ← AllocateTransistorPointers[wireData.gates];
IF wireSizeRef#NIL THEN roseWire.wireDrive ← wireSizeRef^;
IF wireFixedRef#
NIL
THEN {
roseWire.wireDrive ← infinite;
roseWire.switchDrive ← infinite;
roseWire.wireLevel ← wireFixedRef^
};
Perturb[simulation, roseWire];
};
roseWire.path ← packedPath;
roseWire.wire ← wire;
roseWire.nextBucket ← simulation.coreToRoseWires[hash];
simulation.coreToRoseWires[hash] ← roseWire;
maxRoseWireSize ← MAX[maxRoseWireSize, wireSize];
IF wireData.boolPort THEN simulation.roseBoolWires ← CONS[roseWire, simulation.roseBoolWires];
wireData.allocated ← TRUE;
};
IF
NOT (public ←
NOT PathEqual[wireData.path, packedPath])
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
subWireData: WireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: wire[sub]].val];
IF (NOT subWireData.allocated) AND PathEqual[subWireData.path, packedPath] 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;
};
};
rct: CoreClasses.RecordCellType ← NARROW[ct.data];
pathBits: NAT ← BitHacks.NBits[rct.size];
FOR i:
NAT
IN [0..rct.internal.size)
DO
ComputeInDegree[rct.internal[i]];
ENDLOOP;
FOR in:
NAT
IN [0..rct.size)
DO
member, transistor: BOOL;
subType: Core.CellType;
[member, transistor, subType] ← CutSetMember[packedPath, rct[in], cutSet];
IF member
THEN {
IF transistor
THEN {
actual: Core.Wire ← rct[in].actual;
wireData: WireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: actual[gate]].val];
wireData.gates ← wireData.gates + 1;
wireData.portLeaf ← TRUE;
wireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: actual[ch1]].val];
wireData.channels ← wireData.channels + 1;
wireData.portLeaf ← TRUE;
wireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: actual[ch2]].val];
wireData.portLeaf ← TRUE;
wireData.channels ← wireData.channels + 1;
}
ELSE {
visited: RefTab.Ref ← RefTab.Create[];
FOR i:
NAT
IN [0..rct[in].actual.size)
DO
MarkPortLeavesCountConnections[actual: rct[in].actual[i], public: rct[in].type.public[i], checkPort: TRUE, visited: visited]
ENDLOOP;
};
}
ELSE {
rc: Core.CellType ← Recordify[subType];
BindPublicToActual: CoreOps.EachWirePairProc = {
val: REF ANY ← RefTab.Fetch[x: wireDataTab, key: actualWire].val;
IF val=NIL THEN ERROR;
[] ← RefTab.Store[x: wireDataTab, key: publicWire, val: val];
};
FOR i:
NAT
IN [0..rct[in].actual.size)
DO
IF CoreOps.VisitBinding[actual: rct[in].actual[i], public: rc.public[i], eachWirePair: BindPublicToActual] THEN ERROR;
ENDLOOP;
FOR bit:
NAT
IN [0..pathBits)
DO
packedPath.bits[packedPath.length+bit] ← BitHacks.XthBitOfN[pathBits-bit-1, in];
ENDLOOP;
packedPath.length ← packedPath.length + pathBits;
FindRoseWires[ct: rc];
packedPath.length ← packedPath.length - pathBits;
};
ENDLOOP;
FOR i:
NAT
IN [0..rct.internal.size)
DO
[] ← AllocateRoseWires[rct.internal[i]];
ENDLOOP;
};
AllocateRoseInstances:
PROC [ct: Core.CellType] = {
MarkInvalid: CoreOps.EachWireProc = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: wire].val];
IF bind#NIL THEN bind.valid ← FALSE;
};
MarkValid: CoreOps.EachWireProc = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: wire].val];
IF bind#NIL THEN bind.valid ← TRUE;
};
rct: CoreClasses.RecordCellType ← NARROW[ct.data];
pathBits: NAT ← BitHacks.NBits[rct.size];
FOR in:
NAT
IN [0..rct.size)
DO
member, transistor: BOOL;
coreInstance: CoreClasses.CellInstance ← rct[in];
subType: Core.CellType;
[member, transistor, subType] ← CutSetMember[packedPath, coreInstance, cutSet];
IF member
THEN {
IF transistor
THEN {
InsertTransistor:
PROC [transistors: RoseTransistors] = {
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];
actual: Core.Wire ← coreInstance.actual;
transistorSizeRef: REF Ports.Drive ← NARROW[CoreProperties.GetCellInstanceProp[from: coreInstance, prop: roseTransistorSizeProp]];
roseTransistor.gate ← LookUpRoseWire[actual[gate]];
InsertTransistor[roseTransistor.gate.gates];
roseTransistor.ch1 ← LookUpRoseWire[actual[ch1]];
InsertTransistor[roseTransistor.ch1.channels];
roseTransistor.ch2 ← LookUpRoseWire[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];
hash: HashIndex ← PathHash[packedPath, coreInstance];
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[instance: roseInstance, port: roseInstance.publicPort, wire: coreInstance.actual, binds: roseInstance.portBindings, firstFreeBinding: 0] THEN ERROR;
IF roseInstance.roseCellType.init#NIL THEN roseInstance.state ← roseInstance.roseCellType.init[cellType: coreInstance.type, p: roseInstance.publicPort];
roseInstance.path ← packedPath;
roseInstance.instance ← coreInstance;
roseInstance.nextBucket ← simulation.coreToRoseInstances[hash];
simulation.coreToRoseInstances[hash] ← roseInstance;
};
}
ELSE {
rc: Core.CellType ← Recordify[subType];
BindPublicToActual: CoreOps.EachWirePairProc = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: actualWire].val];
IF bind=
NIL
THEN bind ←
NEW[WireBindRec ← [
path: packedPath,
wire: actualWire]]
ELSE IF NOT bind.valid THEN bind.path ← packedPath;
[] ← RefTab.Store[x: wireBindTab, key: publicWire, val: bind];
};
FOR i:
NAT
IN [0..rct[in].actual.size)
DO
IF CoreOps.VisitBinding[actual: rct[in].actual[i], public: rc.public[i], eachWirePair: BindPublicToActual] THEN ERROR;
ENDLOOP;
FOR bit:
NAT
IN [0..pathBits)
DO
packedPath.bits[packedPath.length+bit] ← BitHacks.XthBitOfN[pathBits-bit-1, in];
ENDLOOP;
packedPath.length ← packedPath.length + pathBits;
AllocateRoseInstances[ct: rc];
packedPath.length ← packedPath.length - pathBits;
};
ENDLOOP;
IF CoreOps.VisitWire[rct.internal, MarkInvalid] THEN ERROR;
IF CoreOps.VisitWire[ct.public, MarkValid] THEN ERROR;
};
ComputeInDegree:
PROC [wire: Core.Wire] = {
found: BOOL;
wireDataAny: REF;
wireData: WireData;
[found, wireDataAny] ← RefTab.Fetch[x: wireDataTab, key: wire];
IF found THEN wireData ← NARROW[wireDataAny]
ELSE {
wireData ← NEW[WireDataRec];
IF NOT RefTab.Insert[x: wireDataTab, key: wire, val: wireData] THEN ERROR;
};
IF wireData.indegree=0
THEN {
wireData.path ← packedPath;
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[wire[sub]];
ENDLOOP;
}
ELSE wireData.indegree ← wireData.indegree + 1;
};
MarkPortLeavesCountConnections:
PROC [actual: Core.Wire, public: Core.Wire, checkPort:
BOOL, visited: RefTab.Ref, type: Ports.PortType ← composite] = {
actualData: WireData ← NARROW[RefTab.Fetch[x: wireDataTab, key: actual].val];
IF
NOT RefTab.Fetch[x: visited, key: actual].found
THEN {
actualData.connections ← actualData.connections + 1;
IF checkPort
THEN {
type ← Ports.WirePortType[public];
IF type # composite
THEN {
actualData.portLeaf ← TRUE;
checkPort ← FALSE;
};
};
FOR sub:
NAT
IN [0..actual.size)
DO
MarkPortLeavesCountConnections[actual[sub], public[sub], checkPort, visited, type];
ENDLOOP;
IF NOT RefTab.Insert[x: visited, key: actual, val: $Visited] THEN ERROR;
};
IF type=b OR type=bs OR type=c OR type=lc THEN actualData.boolPort ← TRUE;
};
ComputeBindings:
PROC [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[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[wire: wire, bound: RefTab.Create[]]]];
[] ← ComputeFields[wire: wire, portBinding: portBinding, valueStart: 0, bound: RefTab.Create[], firstFreeField: 0];
binds[newFirstFreeBinding] ← portBinding;
newFirstFreeBinding ← newFirstFreeBinding + 1;
};
};
CountFields:
PROC [wire: Core.Wire, bound: RefTab.Ref]
RETURNS [fieldCount:
CARDINAL ← 0] = {
IF LookUpRoseWire[wire]=
NIL
THEN {
FOR subWire:
NAT
IN [0..wire.size)
DO
fieldCount ← fieldCount + CountFields[wire[subWire], bound];
ENDLOOP;
}
ELSE {
IF
NOT RefTab.Fetch[x: bound, key: wire].found
THEN {
fieldCount ← 1;
IF NOT RefTab.Insert[x: bound, key: wire, val: $Bound] THEN ERROR;
};
};
};
ComputeFields:
PROC [wire: Core.Wire, portBinding: PortBinding, valueStart:
NAT, bound: RefTab.Ref, firstFreeField:
CARDINAL]
RETURNS [newFirstFreeField:
CARDINAL, newValueStart:
NAT] = {
roseWire: RoseWire ← LookUpRoseWire[wire];
newValueStart ← valueStart;
newFirstFreeField ← firstFreeField;
IF roseWire =
NIL
THEN {
FOR subWire:
NAT
IN [0..wire.size)
DO
[newFirstFreeField, newValueStart] ← ComputeFields[wire[subWire], portBinding, newValueStart, bound, newFirstFreeField];
ENDLOOP;
}
ELSE {
IF
NOT RefTab.Fetch[x: 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 RefTab.Insert[x: bound, key: wire, val: $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 [wire: Core.Wire]
RETURNS [roseWire: RoseWire ←
NIL] = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: wire].val];
path: PackedPath;
IF bind=NIL THEN path ← packedPath
ELSE {
path ← bind.path;
wire ← bind.wire;
};
FOR roseWire: RoseWire ← simulation.coreToRoseWires[PathHash[path, wire]], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF PathEqual[roseWire.path, path] AND roseWire.wire=wire THEN RETURN[roseWire];
ENDLOOP;
};
WireData: TYPE = REF WireDataRec;
WireDataRec:
TYPE =
RECORD [
path: PackedPath,
indegree: CARDINAL ← 0,
connections: CARDINAL ← 0,
channels: CARDINAL ← 0,
gates: CARDINAL ← 0,
portLeaf: BOOL ← FALSE,
boolPort: BOOL ← FALSE,
allocated:
BOOL ←
FALSE];
gate: NAT = 0;
ch1: NAT = 1;
ch2: NAT = 2;
maxRoseWireSize: NAT ← 0;
maxVicinity: NAT ← 0;
packedPath: PackedPath ← [0, ALL[FALSE]];
wireDataTab: RefTab.Ref ← RefTab.Create[];
wireBindTab: RefTab.Ref ← RefTab.Create[];
publicRCT: Core.CellType ← Recordify[cellType];
simulation ← NEW[SimulationRec];
simulation.coreCellType ← cellType;
simulation.cutSet ← cutSet;
FOR i:
NAT
IN [0..publicRCT.public.size)
DO
ComputeInDegree[publicRCT.public[i]];
ENDLOOP;
{
visited: RefTab.Ref ← RefTab.Create[];
FOR i:
NAT
IN [0..publicRCT.public.size)
DO
MarkPortLeavesCountConnections[publicRCT.public[i], publicRCT.public[i], TRUE, visited];
ENDLOOP;
};
FindRoseWires[ct: publicRCT];
wireDataTab ← NIL;
simulation.publicBindings ← NEW[PortBindingSeq[Ports.PortLeaves[testPort]]];
IF simulation.publicBindings.size#ComputeBindings[port: testPort, wire: publicRCT.public, binds: simulation.publicBindings, firstFreeBinding: 0] THEN ERROR;
AllocateRoseInstances[ct: publicRCT];
simulation.scratchValue ← NEW[Ports.LevelSequenceRec[maxRoseWireSize]];
simulation.scratchDrive ← NEW[DriveRec[maxRoseWireSize]];
FOR hash: HashIndex
IN HashIndex
DO
FOR roseWire: RoseWire ← simulation.coreToRoseWires[hash], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF roseWire.wireDrive=infinite THEN UpdateReaders[simulation, roseWire, NIL]
ELSE IF NOT roseWire.mark THEN maxVicinity ← MAX[maxVicinity, CountVicinity[roseWire]];
ENDLOOP;
ENDLOOP;
FOR hash: HashIndex
IN HashIndex
DO
FOR roseWire: RoseWire ← simulation.coreToRoseWires[hash], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
roseWire.mark ← FALSE;
ENDLOOP;
ENDLOOP;
FOR strength: Ports.Drive
IN Ports.Drive
DO
simulation.vicinityByStrength[strength].wires ← NEW[RoseWireSeq[maxVicinity]];
ENDLOOP;
simulation.testPort ← testPort;
AllocateStatePoints[simulation, statePoints];
EstablishInvariants[simulation];
EstablishInvariants:
PROC [simulation: Simulation] = {
CleanUp[simulation: simulation, bindings: simulation.publicBindings, forceUpdate: TRUE, updateProc: NIL];
FOR hash: HashIndex
IN HashIndex
DO
FOR roseInstance: RoseCellInstance ← simulation.coreToRoseInstances[hash], roseInstance.nextBucket
UNTIL roseInstance=
NIL
DO
CleanUp[simulation: simulation, bindings: roseInstance.portBindings, forceUpdate: TRUE, updateProc: NIL];
ENDLOOP;
ENDLOOP;
FOR hash: HashIndex
IN HashIndex
DO
FOR roseWire: RoseWire ← simulation.coreToRoseWires[hash], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF roseWire.connections#NIL THEN RecomputeValue[simulation: simulation, wire: roseWire, forceReaderUpdate: TRUE, updateProc: NIL];
ENDLOOP;
ENDLOOP;
};
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];
};
Recordify:
PUBLIC
PROC [ct: Core.CellType]
RETURNS [rc: Core.CellType] = {
FOR rc ← ct, CoreOps.Recast[rc]
UNTIL rc.class.recast =
NIL
DO
rct.class.recast = NIL exactly when rct is a record or atomic.
NULL;
ENDLOOP;
};
AllocateLevelSequence:
PROC [count:
NAT]
RETURNS [ls: Ports.LevelSequence] = {
ls ← NEW[Ports.LevelSequenceRec[count]];
FOR bit:
NAT
IN [0..count)
DO
ls[bit] ← L;
ENDLOOP;
};
Initialize:
PUBLIC
PROC [simulation: Simulation, steady:
BOOL ←
TRUE] = {
ERROR; -- not implemented
};
Relaxation
Settle:
PUBLIC
PROC [simulation: Simulation, updateProc: UpdateProc ←
NIL] = {
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];
ENDLOOP;
FOR roseWires:
LIST
OF RoseWire ← simulation.roseBoolWires, roseWires.rest
UNTIL roseWires=
NIL
DO
roseWire: RoseWire ← roseWires.first;
IF roseWire.currentValue=
NIL
THEN {
IF roseWire.wireLevel=X THEN ERROR;
}
ELSE
FOR bit:
CARDINAL
IN [0..roseWire.currentValue.size)
DO
IF roseWire.currentValue[bit]=X THEN ERROR;
ENDLOOP;
ENDLOOP;
};
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] ← none;
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] = {
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 ←
SELECT wire.wireLevel
FROM
L => FALSE,
X => readerValue.b,
H => TRUE,
ENDCASE => ERROR;
ls =>
FOR bit:
NAT
IN [0..wireValue.size)
DO
readerValue.ls[bit+readerStart] ← wireValue[bit];
ENDLOOP;
bs =>
FOR bit:
NAT
IN [0..wireValue.size)
DO
readerValue.bs[bit+readerStart] ←
SELECT wireValue[bit]
FROM
L => FALSE,
X => readerValue.bs[bit+readerStart],
H => TRUE,
ENDCASE => ERROR;
ENDLOOP;
c => {
asBits: WordAsBits ← ALL[FALSE];
FOR bit:
NAT
IN [0..wireValue.size)
DO
asBits[bit+readerStart] ←
SELECT wireValue[bit]
FROM
L => FALSE,
X => LOOPHOLE[readerValue.c, WordAsBits][bit+readerStart],
H => TRUE,
ENDCASE => ERROR;
ENDLOOP;
readerValue.c ← LOOPHOLE[asBits];
};
lc => {
asBits: DWordAsBits ← ALL[FALSE];
FOR bit:
NAT
IN [0..wireValue.size)
DO
thisBit: NAT ← bit+readerStart;
asBits[thisBit] ←
SELECT wireValue[bit]
FROM
L => FALSE,
X => IF thisBit < 16 THEN LOOPHOLE[Basics.HighHalf[readerValue.lc], WordAsBits][thisBit] ELSE LOOPHOLE[Basics.LowHalf[readerValue.lc], WordAsBits][thisBit - 16],
H => TRUE,
ENDCASE => ERROR;
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
GetCellTypeState:
PUBLIC
PROC [simulation: Simulation]
RETURNS [stateAny:
REF
ANY] = {
stateAny ← simulation.coreToRoseInstances[0].state;
};
GetInstanceState:
PUBLIC
PROC [simulation: Simulation, instantiationPath: InstantiationPath, instance: CoreClasses.CellInstance]
RETURNS [stateAny:
REF
ANY ←
NIL] = {
packedPath: PackedPath ← ComputePackedPath[simulation, instantiationPath];
hash: HashIndex ← PathHash[packedPath, instance];
FOR roseInstance: RoseCellInstance ← simulation.coreToRoseInstances[hash], roseInstance.nextBucket
UNTIL roseInstance=
NIL
DO
IF PathEqual[roseInstance.path, packedPath] AND roseInstance.instance=instance THEN RETURN[roseInstance.state];
ENDLOOP;
};
GetWireValue:
PUBLIC
PROC [simulation: Simulation, instantiationPath: InstantiationPath, wire: Core.Wire, container: Ports.LevelSequence] = {
packedPath: PackedPath ← ComputePackedPath[simulation, instantiationPath];
binds: ValueBindings ← NIL;
firstFreeBit: NAT ← 0;
FOR binds ← simulation.coreToValues, binds.rest
UNTIL binds=
NIL
DO
IF PathEqual[packedPath, binds.first.path] AND wire=binds.first.wire THEN EXIT;
REPEAT
FINISHED => {
BindPublicToActual: CoreOps.EachWirePairProc = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: actualWire].val];
IF bind=
NIL
THEN bind ←
NEW[WireBindRec ← [
path: currentPath,
wire: actualWire]];
[] ← RefTab.Store[x: wireBindTab, key: publicWire, val: bind];
};
FindHereOrBelow:
PROC [path: PackedPath, wire: Core.Wire] = {
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: wire].val];
IF bind#
NIL
THEN {
path ← bind.path;
wire ← bind.wire;
};
FOR roseWire: RoseWire ← simulation.coreToRoseWires[PathHash[path, wire]], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF PathEqual[roseWire.path, path]
AND roseWire.wire=wire
THEN {
values ←
CONS[[
roseWire: roseWire,
size: IF roseWire.currentValue=NIL THEN 1 ELSE roseWire.currentValue.size], values];
EXIT;
};
REPEAT
FINISHED => {
FOR subWire:
NAT
IN [0..wire.size)
DO
FindHereOrBelow[path, wire[subWire]];
ENDLOOP;
};
ENDLOOP;
};
FindAbove:
PROC [internal: Core.Wire]
RETURNS [foundCore:
BOOL ←
FALSE, foundRose:
BOOL ←
FALSE, firstBit:
NAT ← 0] = {
IF internal=wire THEN foundCore ← TRUE
ELSE
FOR thisWire:
NAT
IN [0..internal.size)
DO
[foundCore, foundRose, firstBit] ← FindAbove[internal[thisWire]];
IF foundCore
AND
NOT foundRose
THEN {
path: PackedPath ← packedPath;
bind: WireBind ← NARROW[RefTab.Fetch[x: wireBindTab, key: internal].val];
IF bind#
NIL
THEN {
path ← bind.path;
internal ← bind.wire;
};
FOR subWire:
NAT
IN [0..thisWire)
DO
firstBit ← firstBit + CoreOps.WireBits[internal[subWire]]
ENDLOOP;
FOR roseWire: RoseWire ← simulation.coreToRoseWires[PathHash[path, internal]], roseWire.nextBucket
UNTIL roseWire=
NIL
DO
IF PathEqual[roseWire.path, path]
AND roseWire.wire=internal
THEN {
values ←
CONS[[
roseWire: roseWire,
firstBit: firstBit,
size: CoreOps.WireBits[wire]], values];
foundRose ← TRUE;
EXIT;
};
ENDLOOP;
EXIT;
};
ENDLOOP;
};
values: Values ← NIL;
wireBindTab: RefTab.Ref ← RefTab.Create[];
currentPath: PackedPath ← [0, ALL[FALSE]];
coreInstance: CoreClasses.CellInstance;
ct: Core.CellType ← simulation.coreCellType;
rc: Core.CellType ← Recordify[ct];
rct: CoreClasses.RecordCellType ← NARROW[rc.data];
UNTIL currentPath.length=packedPath.length
DO
boolWord: PACKED ARRAY [0..16) OF BOOL ← ALL[FALSE];
pathBits: NAT ← BitHacks.NBits[rct.size];
FOR bit:
NAT
IN [0..pathBits)
DO
thisBit: BOOL ← packedPath.bits[currentPath.length+bit];
boolWord[16-pathBits+bit] ← thisBit;
currentPath.bits[currentPath.length+bit] ← thisBit;
ENDLOOP;
coreInstance ← rct[LOOPHOLE[boolWord]];
IF CutSetMember[currentPath, coreInstance, simulation.cutSet].member THEN ERROR;
ct ← coreInstance.type;
rc ← Recordify[ct];
rct ← NARROW[rc.data];
IF CoreOps.VisitBinding[actual: coreInstance.actual, public: rc.public, eachWirePair: BindPublicToActual] THEN ERROR;
currentPath.length ← currentPath.length+pathBits;
ENDLOOP;
FindHereOrBelow[packedPath, wire];
IF values=NIL THEN IF NOT FindAbove[rct.internal].foundRose THEN ERROR;
binds ← simulation.coreToValues ←
CONS[[
path: packedPath,
wire: wire,
values: values], simulation.coreToValues];
};
ENDLOOP;
FOR values: Values ← binds.first.values, values.rest
UNTIL values=
NIL
DO
currentValue: Ports.LevelSequence ← values.first.roseWire.currentValue;
IF currentValue=
NIL
THEN {
container[firstFreeBit] ← values.first.roseWire.wireLevel;
firstFreeBit ← firstFreeBit + 1;
}
ELSE {
firstBit: NAT ← values.first.firstBit;
FOR bit:
NAT
IN [0..values.first.size)
DO
container[firstFreeBit + bit] ← currentValue[firstBit+bit];
ENDLOOP;
firstFreeBit ← firstFreeBit + values.first.size;
};
ENDLOOP;
};
ComputePackedPath:
PROC [simulation: Simulation, instantiationPath: InstantiationPath]
RETURNS [packedPath: PackedPath] = {
ct: Core.CellType ← simulation.coreCellType;
packedPath.length ← 0;
FOR path: InstantiationPath ← instantiationPath, path.rest
UNTIL path=
NIL
DO
rc: Core.CellType ← Recordify[ct];
rct: CoreClasses.RecordCellType ← NARROW[rc.data];
FOR in:
NAT
IN [0..rct.size)
DO
IF rct[in]=path.first
THEN {
pathBits: NAT ← BitHacks.NBits[rct.size];
FOR bit:
NAT
IN [0..pathBits)
DO
packedPath.bits[packedPath.length+bit] ← BitHacks.XthBitOfN[pathBits-bit-1, in];
ENDLOOP;
packedPath.length ← packedPath.length + pathBits;
ct ← rct[in].type;
EXIT;
};
REPEAT
FINISHED => ERROR;
ENDLOOP;
ENDLOOP;
};
GetCellType:
PUBLIC
PROC [rootCellType: Core.CellType, path: PackedPath]
RETURNS [cellType: Core.CellType ←
NIL] = {
startBit: NAT ← 0;
cellType ← Recordify[rootCellType];
UNTIL startBit=path.length
DO
rct: CoreClasses.RecordCellType ← NARROW[cellType.data];
pathBits: NAT ← BitHacks.NBits[rct.size];
instanceBits: PACKED ARRAY [0..16) OF BOOL ← ALL[FALSE];
FOR bit:
NAT
IN [0..pathBits)
DO
instanceBits[16-pathBits+bit] ← path.bits[startBit+bit];
ENDLOOP;
startBit ← startBit+pathBits;
cellType ← Recordify[rct[LOOPHOLE[instanceBits]].type];
ENDLOOP;
};
PathEqual:
PROC [one: PackedPath, other: PackedPath]
RETURNS [equal:
BOOL] = {
equal ← one.length=other.length;
IF equal
THEN
FOR bit:
NAT
IN [0..one.length)
DO
IF one.bits[bit]#other.bits[bit]
THEN {
equal ← FALSE;
EXIT;
};
ENDLOOP;
};
PathHash:
PROC [path: PackedPath, ref:
REF
ANY]
RETURNS [hi: HashIndex] =
TRUSTED {
pathAsLN: Basics.LongNumber ← Basics.SwapHalves[LOOPHOLE[path.bits]];
wideHI: CARDINAL;
pathAsLN ← Basics.DoubleShiftRight[pathAsLN, 32-path.length];
wideHI ← Basics.BITXOR[pathAsLN.lowbits, pathAsLN.highbits];
wideHI ← Basics.BITXOR[wideHI, Basics.LowHalf[LOOPHOLE[ref]]];
wideHI ← Basics.BITXOR[wideHI, Basics.HighHalf[LOOPHOLE[ref]]];
hi ← Basics.BITAND[wideHI, hashMask];
};
hashMask: NAT ← BitHacks.TwoToThe[BitHacks.NBits[LAST[HashIndex] + 1]] - 1;
CutSetMember:
PROC [packedPath: PackedPath, instance: CoreClasses.CellInstance, cutSet:
ROPE]
RETURNS [member:
BOOL ←
FALSE, transistor:
BOOL ←
FALSE, ct: Core.CellType] = {
FixStupidRef:
PROC [ref:
REF
ANY]
RETURNS [rope:
ROPE] = {
rope ←
WITH ref
SELECT
FROM
r: REF TEXT => Rope.FromRefText[r],
r: ROPE => r,
ENDCASE => ERROR;
};
cutSets: LIST OF ROPE ← NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: roseCutSetProp]];
ct ← instance.type;
FOR csl:
LIST
OF
ROPE ← cutSets, csl.rest
UNTIL csl=
NIL
DO
IF Rope.Equal[FixStupidRef[csl.first], cutSet]
THEN {
member ← TRUE;
RETURN;
};
ENDLOOP;
DO
IF ct.class.recast=
NIL
AND FindRoseCellType[ct]#
NIL
AND ct.class#CoreClasses.recordCellClass
THEN {
member ← TRUE;
RETURN;
};
IF ct.class=CoreClasses.transistorCellClass
THEN {
member ← TRUE;
transistor ← TRUE;
RETURN;
};
cutSets ← NARROW[CoreProperties.GetCellTypeProp[from: ct, prop: roseCutSetProp]];
FOR csl:
LIST
OF
ROPE ← cutSets, csl.rest
UNTIL csl=
NIL
DO
IF Rope.Equal[FixStupidRef[csl.first], cutSet]
THEN {
member ← TRUE;
RETURN;
};
ENDLOOP;
IF ct.class#CoreClasses.identityCellClass THEN EXIT;
ct ← NARROW[ct.data];
ENDLOOP;
};