Instantiate:
PUBLIC
PROC [cellType: Core.CellType, testPort: Ports.Port, cutSet: CoreFlat.CutSet ←
NIL, statePoints:
NAT ← 0]
RETURNS [simulation: Simulation] = {
ComputeInDegree:
PROC [wire: Core.Wire, bindings: RefTab.Ref ←
NIL] = {
key: Core.Wire;
wireData: WireData;
[key, wireData] ← FindBind[wire, bindings];
IF wireData=
NIL
THEN {
IF EUWireTrap.wire=key THEN SIGNAL HackStop; -- Hack
wireData ← NEW[WireDataRec];
IF NOT RefTab.Insert[x: wireTable, key: key, val: wireData] THEN ERROR;
};
IF wireData.valid THEN wireData.multiInPointers ← TRUE
ELSE {
IF EUWireTrap.wire=key THEN SIGNAL HackStop; -- Hack
wireData.valid ← TRUE;
wireData.multiInPointers ← FALSE;
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], bindings];
ENDLOOP;
};
IF EUWireTrap.wire=wire THEN TrapEnable ← TRUE; -- Hack
};
MarkPortLeavesCountConnections:
PROC [cellType: Core.CellType, bindings: RefTab.Ref, wire: Core.Wire, checkPort:
BOOL, type: Ports.LevelType, visited: RefTab.Ref] = {
wireData: WireData ← FindPublicBind[wire, bindings];
IF
NOT RefTab.Fetch[x: visited, key: wire].found
THEN {
IF NOT RefTab.Insert[x: visited, key: wire, val: $Visited] THEN ERROR;
wireData.connections ← wireData.connections + 1;
IF checkPort
THEN {
type ← Ports.WirePortType[cellType, wire].levelType;
IF type # composite
THEN {
wireData.portLeaf ← TRUE;
checkPort ← FALSE;
};
};
FOR sub:
NAT
IN [0..wire.size)
DO
MarkPortLeavesCountConnections[cellType, bindings, wire[sub], checkPort, type, visited];
ENDLOOP;
};
IF type=b OR type=bs OR type=c OR type=lc OR type=q THEN wireData.boolPort ← TRUE;
};
FindPublicBind:
PROC [wire: Core.Wire, bindings: RefTab.Ref]
RETURNS [wireData: WireData] = {
IF bindings=NIL THEN wireData ← NARROW[RefTab.Fetch[x: wireTable, key: wire].val]
ELSE {
flatWire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x: bindings, key: wire].val];
IF flatWire=NIL THEN ERROR;
wireData ← NARROW[RefTab.Fetch[x: wireTable, key: flatWire.wire].val];
IF wire=EUGndWireTrap.wire THEN {
hackWireData ← wireData;
hackChannels ← wireData.channels;
maxHackChannels ← MAX[wireData.channels, maxHackChannels];
}; -- Hack
IF TrapEnable AND Rope.Equal[CoreOps.GetShortWireName[wire], "Gnd"] THEN {
IF flatWire.wire#EUWireTrap.wire THEN SIGNAL HackStop;
}; -- Hack
};
};
FindBind:
PROC [wire: Core.Wire, bindings: RefTab.Ref]
RETURNS [leftUpper: Core.Wire, wireData: WireData] = {
flatWire: CoreFlat.FlatWire ← IF bindings=NIL THEN NIL ELSE NARROW[RefTab.Fetch[x: bindings, key: wire].val];
leftUpper ← IF flatWire=NIL THEN wire ELSE flatWire.wire;
wireData ← NARROW[RefTab.Fetch[x: wireTable, key: leftUpper].val];
};
GatherDataAllocateWires: CoreFlat.BoundFlatCellProc = {
Process.CheckForAbort[];
SELECT
TRUE
FROM
cell.class=CoreClasses.transistorCellClass => {
public: Core.Wire ← cell.public;
wireData: WireData ← FindPublicBind[public[gate], bindings];
IF enableHack THEN IF CoreFlat.InstancePathEqual[flatCell.path, hackWireCellPath] THEN SIGNAL HackStop[]; -- Hack
wireData.gates ← wireData.gates + 1;
wireData.portLeaf ← TRUE;
wireData ← FindPublicBind[public[ch1], bindings];
wireData.channels ← wireData.channels + 1;
wireData.portLeaf ← TRUE;
wireData ← FindPublicBind[public[ch2], bindings];
wireData.channels ← wireData.channels + 1;
wireData.portLeaf ← TRUE;
};
CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => {
public: Core.Wire ← cell.public;
visited: RefTab.Ref ← RefTab.Create[];
FOR i:
NAT
IN [0..public.size)
DO
MarkPortLeavesCountConnections[cell, bindings, public[i], TRUE, composite, visited]
ENDLOOP;
};
cell.class=CoreClasses.recordCellClass => {
ActualInDegree:
PROC [wire: Core.Wire] = {
wireData: WireData ← FindBind[wire, bindings].wireData;
IF wireData=
NIL
THEN
FOR sub:
NAT
IN [0..wire.size)
DO
ActualInDegree[wire[sub]];
ENDLOOP
ELSE wireData.multiInPointers ← TRUE;
};
cellTypeRCT: CoreClasses.RecordCellType ← NARROW[cell.data];
internal: Core.Wire ← cellTypeRCT.internal;
FOR i:
NAT
IN [0..internal.size)
DO
ComputeInDegree[internal[i], bindings];
ENDLOOP;
FOR i:
NAT
IN [0..cellTypeRCT.size)
DO
actual: Core.Wire ← cellTypeRCT[i].actual;
FOR a:
NAT
IN [0..actual.size)
DO
ActualInDegree[actual[a]];
ENDLOOP;
ENDLOOP;
CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, GatherDataAllocateWires];
IF enableHack THEN IF CoreFlat.FlatCellTypeEqualRec[flatCell, hackCell] THEN SIGNAL HackStop[]; -- Hack
FOR i:
NAT
IN [0..internal.size)
DO
[] ← AllocateRoseWires[internal[i], flatCell, bindings];
ENDLOOP;
};
ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, GatherDataAllocateWires];
Process.CheckForAbort[];
};
AllocateRoseWires:
PROC [wire: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, bindings: RefTab.Ref, publicWireRoots:
BOOL ←
FALSE]
RETURNS [public:
BOOL ←
FALSE, allocated:
BOOL ←
FALSE] = {
flatWire: CoreFlat.FlatWire ← IF bindings=NIL THEN NIL ELSE NARROW[RefTab.Fetch[x: bindings, key: wire].val];
IF
NOT (public ← flatWire#
NIL)
THEN {
wireData: WireData ← NARROW[RefTab.Fetch[x: wireTable, key: wire].val];
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], flatCell, bindings, publicWireRoots];
allocated ← allocated OR subAllocated;
somePublic ← somePublic OR subPublic;
ENDLOOP;
IF allocated
OR somePublic
THEN {
FOR sub:
NAT
IN [0..wire.size)
DO
subFlat: CoreFlat.FlatWire ← IF bindings=NIL THEN NIL ELSE NARROW[RefTab.Fetch[x: bindings, key: wire[sub]].val];
IF subFlat=
NIL
THEN {
subWireData: WireData ← NARROW[RefTab.Fetch[x: wireTable, key: wire[sub]].val];
IF NOT subWireData.allocated THEN AllocateWire[wire[sub], subWireData, flatCell, publicWireRoots];
};
ENDLOOP;
wireData.allocated ← TRUE;
allocated ← TRUE;
}
ELSE {
IF wireData.multiInPointers
OR wireData.portLeaf
THEN {
AllocateWire[wire, wireData, flatCell, publicWireRoots];
allocated ← TRUE;
};
};
};
IF EUWireTrap.wire=wire THEN SIGNAL HackStop; -- Hack
wireData.valid ← FALSE;
};
};
AllocateWire:
PROC [wire: Core.Wire, wireData: WireData, flatCell: CoreFlat.FlatCellTypeRec, publicWireRoots:
BOOL] = {
roseWire: RoseWire;
wireSize: NAT;
fixed: BOOL;
[fixed, wireSize, roseWire] ← InitWire[wire, publicWireRoots];
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.notOffChannels ← AllocateTransistorPointers[wireData.channels];
roseWire.gates ← AllocateTransistorPointers[wireData.gates];
};
roseWire.wire.flatCell ← flatCell;
IF NOT RefTab.Insert[x: simulation.coreToRoseWires, key: roseWire, val: roseWire] THEN ERROR;
maxRoseWireSize ← MAX[maxRoseWireSize, wireSize];
IF wireData.boolPort THEN simulation.roseBoolWires ← CONS[roseWire, simulation.roseBoolWires];
wireData.allocated ← TRUE;
};
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;
};
};
ComputeBindings:
PROC [bindings: RefTab.Ref, port: Ports.Port, wire: Core.Wire, binds: PortBindings, firstFreeBinding:
CARDINAL, instance: RoseCellInstance ←
NIL, visited: RefTab.Ref]
RETURNS [newFirstFreeBinding:
CARDINAL] = {
newFirstFreeBinding ← firstFreeBinding;
IF port.levelType=composite
THEN {
FOR subPort:
NAT
IN [0..port.size)
DO
newFirstFreeBinding ← ComputeBindings[bindings, port[subPort], wire[subPort], binds, newFirstFreeBinding, instance, visited];
ENDLOOP;
}
ELSE {
IF
NOT RefTab.Fetch[x: visited, key: port].found
THEN {
portBinding: PortBinding ←
NEW[PortBindingRec ← [
clientPort: port,
currentDrive: port.d,
instance: instance]];
portBinding.fields ← NEW[FieldSeq[CountFields[bindings: bindings, wire: wire, bound: RefTab.Create[]]]];
[] ← ComputeFields[bindings: bindings, wire: wire, portBinding: portBinding, valueStart: 0, bound: RefTab.Create[], firstFreeField: 0];
binds[newFirstFreeBinding] ← portBinding;
newFirstFreeBinding ← newFirstFreeBinding + 1;
IF NOT RefTab.Insert[x: visited, key: port, val: $Visited] THEN ERROR;
};
};
};
CountFields:
PROC [bindings: RefTab.Ref, wire: Core.Wire, bound: RefTab.Ref]
RETURNS [fieldCount:
CARDINAL ← 0] = {
IF LookUpRoseWire[wire, bindings]=
NIL
THEN {
FOR subWire:
NAT
IN [0..wire.size)
DO
fieldCount ← fieldCount + CountFields[bindings, 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 [bindings: RefTab.Ref, wire: Core.Wire, portBinding: PortBinding, valueStart:
NAT, bound: RefTab.Ref, firstFreeField:
CARDINAL]
RETURNS [newFirstFreeField:
CARDINAL, newValueStart:
NAT] = {
roseWire: RoseWire ← LookUpRoseWire[wire, bindings];
newValueStart ← valueStart;
newFirstFreeField ← firstFreeField;
IF roseWire =
NIL
THEN {
FOR subWire:
NAT
IN [0..wire.size)
DO
[newFirstFreeField, newValueStart] ← ComputeFields[bindings, wire[subWire], portBinding, newValueStart, bound, newFirstFreeField];
ENDLOOP;
}
ELSE {
IF
NOT RefTab.Fetch[x: bound, key: wire].found
THEN {
size: NAT ← IF roseWire.currentValue=NIL THEN 1 ELSE roseWire.currentValue.size;
field: Field ←
NEW[FieldRec ← [
portBinding: portBinding,
portStartBit: valueStart,
roseWire: roseWire,
currentValue: AllocateLevelSequence[size]]];
IF portBinding.clientPort.driveType=separate THEN field.currentDrive ← AllocateDriveSequence[size, portBinding.clientPort.ds];
portBinding.fields[firstFreeField] ← field;
newFirstFreeField ← newFirstFreeField + 1;
newValueStart ← newValueStart + field.currentValue.size;
roseWire.connections[roseWire.firstFreeConnection] ← field;
roseWire.firstFreeConnection ← roseWire.firstFreeConnection + 1;
IF NOT RefTab.Insert[x: bound, key: wire, val: $Bound] THEN ERROR;
};
};
};
AllocateInstances: CoreFlat.BoundFlatCellProc = {
Process.CheckForAbort[];
SELECT
TRUE
FROM
cell.class=CoreClasses.transistorCellClass => {
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;
};
public: Core.Wire ← cell.public;
coreTransistor: CoreClasses.Transistor ← NARROW[cell.data];
roseTransistor: RoseTransistor ← NEW[RoseTransistorRec];
transistorSizeRef: REF Ports.Drive ← NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: roseTransistorSizeProp]];
roseTransistor.gate ← LookUpRoseWire[public[gate], bindings];
InsertTransistor[roseTransistor.gate.gates];
roseTransistor.ch1 ← LookUpRoseWire[public[ch1], bindings];
InsertTransistor[roseTransistor.ch1.channels];
roseTransistor.ch2 ← LookUpRoseWire[public[ch2], bindings];
InsertTransistor[roseTransistor.ch2.channels];
IF transistorSizeRef=NIL THEN transistorSizeRef ← NARROW[CoreProperties.GetCellTypeProp[from: cell, prop: roseTransistorSizeProp]];
IF transistorSizeRef#NIL THEN roseTransistor.conductivity ← transistorSizeRef^;
IF sizeHackEnable
THEN {
name: ROPE ← CoreClasses.GetCellInstanceName[instance];
IF name#
NIL
THEN
FOR drv: Ports.Drive
IN Ports.Drive
DO
IF Rope.Equal[Ports.driveNames[drv], name]
THEN {
roseTransistor.conductivity ← drv;
EXIT;
};
REPEAT
FINISHED =>
FOR drv: Ports.Drive
IN sizeHackType
DO
IF Rope.Equal[sizeHackNames[drv], name]
THEN {
roseTransistor.conductivity ← drv;
EXIT;
};
ENDLOOP;
ENDLOOP;
};
roseTransistor.type ← coreTransistor.type;
roseTransistor.instance ← flatCell;
transistorCount ← transistorCount + 1;
};
CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => {
public: Core.Wire ← cell.public;
roseInstance: RoseCellInstance ← NEW[RoseCellInstanceRec];
roseInstance.roseCellType ← FindRoseCellTypeOrComplain[cell];
roseInstance.publicPort ← Ports.CreatePort[cell];
roseInstance.portBindings ← NEW[PortBindingSeq[Ports.PortLeaves[ roseInstance.publicPort]]];
IF roseInstance.portBindings.size#ComputeBindings[bindings: bindings, port: roseInstance.publicPort, wire: public, binds: roseInstance.portBindings, firstFreeBinding: 0, instance: roseInstance, visited: RefTab.Create[]] THEN ERROR;
IF roseInstance.roseCellType.init#
NIL
THEN
roseInstance.state ← roseInstance.roseCellType.init[cellType: cell, p: roseInstance.publicPort].stateAny;
roseInstance.instance ← flatCell;
IF NOT RefTab.Insert[x: simulation.coreToRoseInstances, key: roseInstance, val: roseInstance] THEN ERROR;
instanceCount ← instanceCount + 1;
};
ENDCASE => CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, AllocateInstances];
Process.CheckForAbort[];
};
LookUpRoseWire:
PROC [wire: Core.Wire, bindings: RefTab.Ref]
RETURNS [roseWire: RoseWire] = {
IF bindings=
NIL
THEN {
wireKey.flatCell ← CoreFlat.rootCellType;
wireKey.wire ← wire;
roseWire ← NARROW[RefTab.Fetch[x: simulation.coreToRoseWires, key: wireKey].val];
}
ELSE {
leftUpper: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x: bindings, key: wire].val];
roseWire ← NARROW[RefTab.Fetch[x: simulation.coreToRoseWires, key: leftUpper].val];
};
};
ComputeMaxVicinity: RefTab.EachPairAction = {
roseWire: RoseWire ← NARROW[val];
IF roseWire.wireDrive=infinite THEN UpdateReaders[simulation, roseWire, NIL]
ELSE IF NOT roseWire.mark THEN maxVicinity ← MAX[maxVicinity, CountVicinity[roseWire]];
};
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;
};
WireData: TYPE = REF WireDataRec;
WireDataRec:
TYPE =
RECORD [
valid: BOOL ← FALSE,
multiInPointers: BOOL ← FALSE,
connections: CARDINAL ← 0,
channels: CARDINAL ← 0,
gates: CARDINAL ← 0,
portLeaf: BOOL ← FALSE,
boolPort: BOOL ← FALSE,
allocated:
BOOL ←
FALSE];
time: BasicTime.GMT ← BasicTime.Now[];
transistorCount: INT ← 0;
instanceCount: INT ← 0;
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];
wireTable: RefTab.Ref ← RefTab.Create[mod: 1019];
enableHack: BOOL ← Rope.Equal[CoreOps.GetCellTypeName[cellType], "EU"]; -- Hack
hackCell: CoreFlat.FlatCellTypeRec ← IF enableHack THEN CoreFlat.ParseCellTypePath[cellType, "/140/0"] ELSE []; -- Hack
hackWireCellPath: CoreFlat.InstancePath ← [];
IF enableHack THEN CoreFlat.ParseWirePath[cellType, "/140/0(Inner)/0(Control)/0(BothAlps)/0(DPControl)/0(UpsideDownDPControl)/28/80(OutputDriver)/0(Inverter)/0.public.ch2"] ELSE []; -- Hack
hackWireCellPath.length ← 31; -- Hack
hackWireCellPath.bits[0] ← TRUE; -- Hack
hackWireCellPath.bits[4] ← TRUE; -- Hack
hackWireCellPath.bits[5] ← TRUE; -- Hack
hackWireCellPath.bits[15] ← TRUE; -- Hack
hackWireCellPath.bits[16] ← TRUE; -- Hack
hackWireCellPath.bits[17] ← TRUE; -- Hack
hackWireCellPath.bits[20] ← TRUE; -- Hack
hackWireCellPath.bits[22] ← TRUE; -- Hack
priority: Process.Priority ← Process.GetPriority[];
Process.SetPriority[Process.priorityBackground];
TerminalIO.PutF["Rosemary expanding cell %g\n", IO.rope[CoreOps.GetCellTypeName[cellType]]];
simulation ← NewSimulation[];
simulation.cellType ← cellType;
simulation.testPort ← testPort;
simulation.publicBindings ← NEW[PortBindingSeq[Ports.PortLeaves[testPort]]];
simulation.coreToRoseWires ← RefTab.Create[mod: 1019, equal: RoseWireEqual, hash: RoseWireHash];
simulation.coreToRoseInstances ← RefTab.Create[mod: 1019, equal: RoseInstanceEqual, hash: RoseInstanceHash];
simulation.coreToRoseValues ← RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash];
{
public: Core.Wire ← cellType.public;
visited: RefTab.Ref ← RefTab.Create[];
FOR i:
NAT
IN [0..public.size)
DO
ComputeInDegree[public[i]];
ENDLOOP;
FOR i:
NAT
IN [0..public.size)
DO
MarkPortLeavesCountConnections[cellType, NIL, public[i], TRUE, composite, visited];
ENDLOOP;
GatherDataAllocateWires[cellType];
FOR i:
NAT
IN [0..public.size)
DO
[] ← AllocateRoseWires[public[i], CoreFlat.rootCellType, NIL, TRUE];
ENDLOOP;
};
IF simulation.publicBindings.size#ComputeBindings[bindings: NIL, port: testPort, wire: cellType.public, binds: simulation.publicBindings, firstFreeBinding: 0, visited: RefTab.Create[]] THEN ERROR;
AllocateInstances[cellType];
simulation.scratchValue ← NEW[Ports.LevelSequenceRec[maxRoseWireSize]];
simulation.scratchDrive ← NEW[Ports.DriveSequenceRec[maxRoseWireSize]];
[] ← RefTab.Pairs[x: 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];
Process.SetPriority[priority];
PrintPeriod[IO.PutFR["Rosemary expanded %g transistors and %g instances in", IO.int[transistorCount], IO.int[instanceCount]], time, BasicTime.Now[]];