Properties hanging on the resulting Core
layoutProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[PWCore.layoutProp, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
coreProp: PUBLIC ATOM ← PWCore.coreProp;
extractedCoreProp: PUBLIC ATOM ← PW.RegisterProp[$SinixExtractedCore, TRUE];
pinsProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$SinixPins];
wireGeometryProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$SinixWireGeometry, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
instanceProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$SinixInstance];
errorsProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$SinixErrors, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy]]];
Operations for an easy management of those properties
AddPinPropOnWire:
PUBLIC
PROC [wire: Wire, pin:
CD.Instance] = {
pins: LIST OF CD.Instance ← CONS [pin, NARROW [CoreProperties.GetWireProp[wire, pinsProp]]];
CoreProperties.PutWireProp[wire, pinsProp, pins];
};
AppendWireGeometryPropOnWire:
PUBLIC
PROC [wire: Wire, geometry:
LIST
OF
CD.Instance] = {
WHILE geometry#
NIL
DO
AddWireGeometryPropOnWire[wire, geometry.first];
geometry ← geometry.rest;
ENDLOOP;
};
AddWireGeometryPropOnWire:
PUBLIC
PROC [wire: Wire, cdInstance:
CD.Instance] = {
PutWireGeometryPropOnWire[wire, CONS [cdInstance, GetWireGeometryPropFromWire[wire]]];
};
PutWireGeometryPropOnWire:
PUBLIC
PROC [wire: Wire, geometry:
LIST
OF
CD.Instance] = {
CoreProperties.PutWireProp[wire, wireGeometryProp, geometry];
};
GetWireGeometryPropFromWire:
PUBLIC
PROC [wire: Wire]
RETURNS [geometry:
LIST
OF
CD.Instance] = {
geometry ← NARROW [CoreProperties.GetWireProp[wire, wireGeometryProp]];
};
HighLighting errors utilities
Cellize:
PROC [obj:
CD.Object]
RETURNS [cell:
CD.Object]= {
cellPtr: CD.CellPtr;
cell ← CDCells.CreateEmptyCell[];
cellPtr ← NARROW [cell.specificRef];
cellPtr.contents ← LIST [PWPins.NewInstance[obj]];
cell.size ← obj.size;
};
HighLightWires:
PROC [fusionData: FusionData, cell:
CD.Object, wires:
LIST
OF Wire] = {
WHILE wires#NIL DO HighLightWire[fusionData, cell, wires.first]; wires ← wires.rest ENDLOOP;
};
HighLightWire:
PROC [fusionData: FusionData, cell:
CD.Object, wire: Wire] = {
HighLightInstances[cell, FindRootGeometry[fusionData, wire]];
};
HighLightInstances:
PROC [cell:
CD.Object, geometry:
LIST
OF
CD.Instance] = {
WHILE geometry#NIL DO HighLightInstance[cell, geometry.first]; geometry ← geometry.rest ENDLOOP;
};
HighLightInstance:
PROC [cell:
CD.Object, inst:
CD.Instance] = {
cellPtr: CD.CellPtr ← NARROW [cell.specificRef];
hinst:
CD.Instance ← PWPins.NewInstance[
ob: CDRects.CreateRect[inst.ob.size, CD.highLightShade],
location: inst.location, orientation: inst.orientation];
cellPtr.contents ← CONS [hinst, cellPtr.contents];
};
Fusion data structure and internal manipulation
FusionData: TYPE = REF FusionDataRec;
FusionDataRec:
TYPE =
RECORD [
fusioned: RefTab.Ref, -- Association [fusioned -> root] [Wire -> Wire]
geometry: RefTab.Ref, -- Association [root -> geometry] [Wire -> LIST OF CD.Instances]
intervals: Intervals.Table -- Association [interval -> instance and root] [Intervals.Interval -> IW]
];
Geometry can be attached at all levels of a structured wire.
IW: TYPE = REF IWRec;
IWRec: TYPE = RECORD [instance: CD.Instance, wire: Wire];
EqualIW:
PROC [value1, value2: Intervals.Value]
RETURNS [
BOOL] = {
iw1: IW ← NARROW [value1]; iw2: IW ← NARROW [value2];
RETURN [iw1^=iw2^];
};
InstanceToInterval:
PROC [instance:
CD.Instance]
RETURNS [interval: Intervals.Interval] = {
interval ← RectToInterval[CDInstances.InstRectO[instance]];
};
RectToInterval:
PROC [rect:
CD.Rect]
RETURNS [interval: Intervals.Interval] = {
interval ← [rect.x1+rect.y1, rect.x2+rect.y2];
};
InsertInstance:
PROC [fusionData: FusionData, instance:
CD.Instance, wire: Wire] = {
newInstances: LIST OF CD.Instance ← CONS [instance, FindRootGeometry[fusionData, wire]];
[] ← RefTab.Store[fusionData.geometry, wire, newInstances];
Intervals.Insert[fusionData.intervals, InstanceToInterval[instance], NEW [IWRec ← [instance: instance, wire: wire]]];
};
Fusion external manipulation
Enforces the invariant: all roots have all their sub-wires which are roots
DagIfy:
PROC [fusionData: FusionData] = {
WireDagIfy:
PROC [wire: Wire] = {
FOR i:
NAT
IN [0 .. wire.size)
DO
WireDagIfy[wire[i]];
wire[i] ← RootWire[fusionData, wire[i]];
ENDLOOP;
};
InternalDagIfy: RefTab.EachPairAction = {
wire: Wire ← NARROW [key];
quit ← FALSE;
WireDagIfy[wire];
};
[] ← RefTab.Pairs[fusionData.geometry, InternalDagIfy];
};
CreateFusionData:
PROC [rect:
CD.Rect]
RETURNS [fusionData: FusionData] = {
fusionData ←
NEW [FusionDataRec ← [
fusioned: RefTab.Create[],
geometry: RefTab.Create[],
intervals: Intervals.Create[RectToInterval[rect]]
]];
};
The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity
RootWire:
PROC [fusionData: FusionData, wire: Wire]
RETURNS [rootWire: Wire] = {
rootWire ← NARROW [RefTab.Fetch[fusionData.fusioned, wire].val];
IF rootWire=NIL THEN RETURN [wire];
rootWire ← RootWire[fusionData, rootWire];
[] ← RefTab.Replace[fusionData.fusioned, wire, rootWire];
};
FindRootGeometry:
PROC [fusionData: FusionData, wire: Wire]
RETURNS [geometry:
LIST
OF
CD.Instance] = {
geometry ← NARROW [RefTab.Fetch[fusionData.geometry, wire].val];
};
InsertInstances:
PROC [fusionData: FusionData, instances:
LIST
OF
CD.Instance, wire: Wire] = {
WHILE instances#
NIL
DO
InsertInstance[fusionData, instances.first, wire]; instances ← instances.rest;
ENDLOOP;
};
This proc really does the fusion of fusioned and root, by wiping fusioned of some tables, and adding interesting properties of fusioned to root.
DeleteFusioned:
PROC [fusionData: FusionData, fusioned, root: Wire] = {
fusionedGeometry: LIST OF CD.Instance ← FindRootGeometry[fusionData, fusioned];
IF fusioned=root THEN RETURN; -- might occur when called from InsureStructure
root.properties ← CoreProperties.AppendProps[root.properties, fusioned.properties];
[] ← RefTab.Store[fusionData.fusioned, fusioned, root];
IF ~RefTab.Delete[fusionData.geometry, fusioned] THEN ERROR;
FOR instances:
LIST
OF
CD.Instance ← fusionedGeometry, instances.rest
WHILE instances#
NIL
DO
IF ~Intervals.Delete[fusionData.intervals, InstanceToInterval[instances.first], NEW [IWRec ← [instance: instances.first, wire: fusioned]], EqualIW] THEN ERROR;
InsertInstance[fusionData, instances.first, root];
ENDLOOP;
};
FindTouchingWires:
PROC [fusionData: FusionData, geometry:
LIST
OF
CD.Instance, compareLayers:
BOOL ←
TRUE]
RETURNS [touchingWires:
LIST
OF Wire ←
NIL] = {
FOR insts:
LIST
OF
CD.Instance ← geometry, insts.rest
WHILE insts#
NIL
DO
interval: Intervals.Interval ← InstanceToInterval[insts.first];
InternalFindTouchingWires: Intervals.EachIntervalValueProc = {
iw: IW ← NARROW [value];
IF Touch[iw.instance, insts.first, compareLayers]
AND ~CoreOps.Member[touchingWires, iw.wire]
THEN touchingWires ← CONS [iw.wire, touchingWires];
};
[] ← Intervals.Enumerate[fusionData.intervals, InternalFindTouchingWires, interval];
ENDLOOP;
};
Conceptually same as the previous one that uses the intervals but faster for getting all wires (or nearly all).
AllMatchingWires:
PROC [fusionData: FusionData, match:
PROC [Wire,
LIST
OF
CD.Instance]
RETURNS [
BOOL]]
RETURNS [matchingWires:
LIST
OF Wire ←
NIL] = {
InternalEnumerate: RefTab.EachPairAction = {
wire: Wire ← NARROW [key]; geometry: LIST OF CD.Instance ← NARROW [val];
quit ← FALSE;
IF ~match[wire, geometry] THEN RETURN;
matchingWires ← CONS [wire, matchingWires];
};
[] ← RefTab.Pairs[fusionData.geometry, InternalEnumerate];
};
Other Internal utilities
MatchOnlyIfPinsProp:
PROC [wire: Wire, geometry:
LIST
OF
CD.Instance]
RETURNS [
BOOL] = {
RETURN [CoreProperties.GetWireProp[wire, pinsProp]#NIL];
};
decorates the wire on the way
MatchAlways:
PROC [wire: Wire, geometry:
LIST
OF
CD.Instance]
RETURNS [
BOOL] = {
PutWireGeometryPropOnWire[wire, geometry];
RETURN [TRUE];
};
wire (at the moment of the call) is a non fusioned wire (a root wire appearing in fusionData.geometry)
InsureStructure:
PROC [fusionData: FusionData, wire, structure: Wire, copyProps:
BOOL]
RETURNS [newWire, newStructure: Wire] = {
SELECT
TRUE
FROM
wire.size=0
AND structure.size=0 => {
newWire ← wire; newStructure ← structure;
};
wire.size=0 => {
newWire ← CoreOps.CreateWires[structure.size];
[] ← RefTab.Store[fusionData.geometry, newWire, NIL]; -- so that enumerations do not forget this new wire
newStructure ← CoreOps.CopyWire[structure];
DeleteFusioned[fusionData, wire, newWire];
FOR i:
NAT
IN [0 .. structure.size)
DO
newWire[i] ← CoreOps.CreateWire[props: IF copyProps THEN CoreProperties.CopyProps[structure[i].properties] ELSE NIL];
[] ← RefTab.Store[fusionData.geometry, newWire[i], NIL]; -- so that enumerations do not forget this new wire
[newWire[i], newStructure[i]] ← InsureStructure[fusionData, newWire[i], structure[i], copyProps];
ENDLOOP;
};
structure.size=0 => {
newWire ← wire; newStructure ← wire;
};
wire.size=structure.size => {
newWire ← CoreOps.CreateWires[structure.size];
[] ← RefTab.Store[fusionData.geometry, newWire, NIL]; -- so that enumerations do not forget this new wire
newStructure ← CoreOps.CopyWire[structure];
DeleteFusioned[fusionData, wire, newWire];
FOR i:
NAT
IN [0 .. wire.size)
DO
[newWire[i], newStructure[i]] ← InsureStructure[fusionData, wire[i], structure[i], copyProps];
DeleteFusioned[fusionData, wire[i], newWire[i]];
ENDLOOP;
};
ENDCASE => ERROR; -- structure mismatch
IF copyProps THEN newWire.properties ← CoreProperties.AppendProps[newWire.properties, structure.properties];
};
FusionStructureGeometryAndName:
PROC [fusionData: FusionData, structure: Wire, geometry:
LIST
OF
CD.Instance, name:
ROPE, copyProps:
BOOL]
RETURNS [wire: Wire ←
NIL] = {
touchingWires: LIST OF Wire ← FindTouchingWires[fusionData, geometry];
IF name#
NIL
THEN {
MatchName:
PROC [wire: Wire, geometry:
LIST
OF
CD.Instance]
RETURNS [
BOOL] = {
RETURN [Rope.Equal[CoreOps.GetShortWireName[wire], name]];
};
sameNameWires: LIST OF Wire ← AllMatchingWires[fusionData, MatchName];
we add the wires that make a connection by name
WHILE sameNameWires#
NIL
DO
IF ~CoreOps.Member[touchingWires, sameNameWires.first]
THEN {
TerminalIO.WriteF["Fusion by name of %g\n", IO.rope[name]];
touchingWires ← CONS [sameNameWires.first, touchingWires];
};
sameNameWires ← sameNameWires.rest;
ENDLOOP;
};
Check that touchingWires only contains unnamed wires or wires named name
FOR list:
LIST
OF Wire ← touchingWires, list.rest
WHILE list#
NIL
DO
touchingWireName: ROPE ← CoreOps.GetShortWireName[list.first];
SELECT
TRUE
FROM
touchingWireName=NIL => {};
name=NIL => name ← touchingWireName;
Rope.Equal[touchingWireName, name] => {};
ENDCASE => {
TerminalIO.WriteF["Two wires that do not have the same name are touching: %g and %g.\n", IO.rope[name], IO.rope[touchingWireName]];
ERROR;
};
ENDLOOP;
IF touchingWires=
NIL
THEN {
wire ← CoreOps.CreateWire[];
InsertInstances[fusionData, geometry, wire];
[] ← CoreOps.SetShortWireName[wire, name];
[wire, structure] ← InsureStructure[fusionData, wire, structure, copyProps];
RETURN;
};
wire ← touchingWires.first;
InsertInstances[fusionData, geometry, wire];
[] ← CoreOps.SetShortWireName[wire, name];
[wire, structure] ← InsureStructure[fusionData, wire, structure, copyProps];
touchingWires ← touchingWires.rest;
WHILE touchingWires#
NIL
DO
fusioned: Wire ← touchingWires.first;
DeleteFusioned[fusionData, fusioned, wire];
[wire, structure] ← InsureStructure[fusionData, wire, fusioned, copyProps];
touchingWires ← touchingWires.rest;
ENDLOOP;
};
FusionWire:
PROC [fusionData: FusionData, public: Wire, transformation:
CD.Instance, copyProps:
BOOL]
RETURNS [actual: Wire] = {
actual ← FusionStructureGeometryAndName[
fusionData,
public,
TransformList[transformation, NARROW [CoreProperties.GetWireProp[public, pinsProp]]],
IF copyProps THEN CoreOps.GetShortWireName[public] ELSE NIL,
copyProps
];
IF copyProps THEN actual.properties ← CoreProperties.AppendProps[actual.properties, public.properties];
FOR i:
NAT
IN [0 .. public.size)
DO
subActual: Wire ← FusionWire[fusionData, public[i], transformation, copyProps];
DeleteFusioned[fusionData, subActual, actual[i]];
IF ~CoreOps.Conform[subActual, actual[i]] THEN ERROR;
ENDLOOP;
};
FusionWires:
PROC [fusionData: FusionData, public: Wire, transformation:
CD.Instance]
RETURNS [actual: Wire] = {
actual ← CoreOps.CreateWires[public.size];
FOR i:
NAT
IN [0 .. actual.size)
DO
actual[i] ← FusionWire[fusionData, public[i], transformation, FALSE];
ENDLOOP;
};
Extraction
extractProcProp: PUBLIC ATOM ← PW.RegisterProp[$SinixExtractProc, TRUE];
Extract:
PUBLIC ExtractProc = {
refProc: REF ExtractProc ← NIL;
cellType ← NARROW [CDProperties.GetPropFromObject[obj, extractedCoreProp]];
IF cellType#NIL THEN RETURN;
refProc ← NARROW [CDProperties.GetPropFromList[properties, extractProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDProperties.GetPropFromObject[obj, extractProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDProperties.GetProp[obj.class, extractProcProp]];
[cellType, wire, category] ← (IF refProc=NIL THEN ExtractExpand ELSE refProc^)[obj, properties, userData];
};
ExtractExpand:
PUBLIC ExtractProc = {
newObj: CD.Object ← CDDirectory.Expand[obj, NIL, NIL];
TerminalIO.Write[IO.rope["Using ExpandProc for object of class "], IO.atom[obj.class.objectType], IO.rope[" \n"]];
IF newObj=NIL THEN ERROR;
RETURN Extract[newObj, CDProperties.DangerousAppendProps[obj.properties, properties], userData];
};
ExtractWire:
PUBLIC ExtractProc = {
category ← $Wire;
wire ← CoreOps.CreateWire[];
AddPinPropOnWire[wire, PWPins.NewInstance[obj]];
};
ExtractPin:
PUBLIC ExtractProc = {
instance: CD.Instance ← PWPins.NewInstance[ob: obj, properties: properties];
pinName: ROPE ← CDSymbolicObjects.GetName[instance];
category ← $Wire;
wire ← CoreOps.CreateWire[name: pinName];
AddPinPropOnWire[wire, instance];
};
ExtractCell:
PUBLIC ExtractProc = {
cellPtr: CD.CellPtr ← NARROW [obj.specificRef];
cdInstances: LIST OF CD.Instance ← cellPtr.contents;
fusionData: FusionData ← CreateFusionData[CDBasics.RectAt[[0, 0], obj.size]];
currentInstances: LIST OF CoreClasses.CellInstance ← NIL;
count: NAT ← 0;
Process.SetPriority[Process.priorityBackground];
FOR list: LIST OF CD.Instance ← cdInstances, list.rest WHILE list#NIL DO count ← count+1 ENDLOOP;
TerminalIO.WriteF["Extracting cell %g (size: [%g, %g], instances: %g)\n", IO.rope[CDDirectory.Name[obj]], IO.int[obj.size.x], IO.int[obj.size.y], IO.int[count]];
WHILE cdInstances#
NIL
DO
cdInstance: CD.Instance ← cdInstances.first;
subCellType: Core.CellType; subWire: Wire; subCategory: ATOM;
[subCellType, subWire, subCategory] ← Extract[cdInstance.ob, CDProperties.DangerousAppendProps[cdInstance.properties, properties], userData];
SELECT
TRUE
FROM
subCategory=$Null => {};
subCategory=$Wire => {
wire: Wire ← FusionWire[fusionData, subWire, cdInstance, TRUE];
};
subCategory=$Device => {
instance: CoreClasses.CellInstance ← NEW [CoreClasses.CellInstanceRec ← [actual: FusionWires[fusionData, subCellType.public, cdInstance], type: subCellType]];
CoreProperties.PutCellInstanceProp[instance, instanceProp, cdInstance];
currentInstances ← CONS [instance, currentInstances];
};
ENDCASE => ERROR;
cdInstances ← cdInstances.rest;
ENDLOOP;
Enumerate all the internals, and add as a pin property all the geometry that crosses the interestRect
BEGIN
RectToInst:
PROC [rect:
CD.Rect]
RETURNS [inst:
CD.Instance] = {
inst ← PWPins.NewInstance[CDRects.CreateRect[CDBasics.SizeOfRect[rect], CD.combined], CDBasics.BaseOfRect[rect]];
};
ir: CD.Rect ← CD.InterestRect[obj]; -- the interestRect
ir1: CD.Rect ← [ir.x1, ir.y1-1, ir.x2, ir.y1+1];
ir2: CD.Rect ← [ir.x1-1, ir.y1, ir.x1+1, ir.y2];
ir3: CD.Rect ← [ir.x1, ir.y2-1, ir.x2, ir.y2+1];
ir4: CD.Rect ← [ir.x2-1, ir.y1, ir.x2+1, ir.y2];
irGeometry: LIST OF CD.Instance ← LIST [RectToInst[ir1], RectToInst[ir2], RectToInst[ir3], RectToInst[ir4]];
mightBePublic: LIST OF Wire ← FindTouchingWires[fusionData, irGeometry, FALSE];
WHILE mightBePublic#
NIL
DO
wire: Wire ← mightBePublic.first;
geometry: LIST OF CD.Instance ← FindRootGeometry[fusionData, wire];
IF geometry=NIL THEN ERROR;
FOR instances:
LIST
OF
CD.Instance ← geometry, instances.rest
WHILE instances#
NIL
DO
IF TouchList[irGeometry, instances.first, FALSE] THEN AddPinPropOnWire[wire, instances.first];
ENDLOOP;
mightBePublic ← mightBePublic.rest;
ENDLOOP;
END ;
We replace in all instances wires by their roots
FOR list:
LIST
OF CoreClasses.CellInstance ← currentInstances, list.rest
WHILE list#
NIL
DO
instance: CoreClasses.CellInstance ← list.first;
actual: Wire ← instance.actual;
FOR i:
NAT
IN [0 .. actual.size)
DO
wire: Wire ← RootWire[fusionData, actual[i]];
IF FindRootGeometry[fusionData, wire]=NIL THEN ERROR; -- non connected actual
actual[i] ← wire;
ENDLOOP;
ENDLOOP;
We build the CellType
DagIfy[fusionData];
cellType ← CoreClasses.CreateRecordCell[
public: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchOnlyIfPinsProp]],
internal: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchAlways]],
instances: currentInstances,
name: CDDirectory.Name[obj]
];
CoreProperties.PutCellTypeProp[cellType, layoutProp, obj];
CDProperties.PutPropOnObject[obj, extractedCoreProp, cellType];
};
ExtractAbut:
PUBLIC ExtractProc = {
newObj: CD.Object ← CDDirectory.Expand[obj, NIL, NIL];
IF newObj=NIL THEN ERROR;
[cellType, wire, category] ← Extract[newObj, CDProperties.DangerousAppendProps[obj.properties, properties], userData];
IF cellType=NIL OR category#$Device THEN RETURN;
CoreProperties.PutCellTypeProp[cellType, layoutProp, newObj];
CDProperties.PutPropOnObject[newObj, extractedCoreProp, cellType];
};
ExtractIndirect:
PUBLIC ExtractProc = {
nets: RefTab.Ref ← NARROW [CDProperties.GetPropFromObject[obj, PWCore.netsProp]];
sourceObject: CD.Object ← NARROW [obj.specificRef];
subCellType: Core.CellType; subWire: Wire; subCategory: ATOM;
fusionData: FusionData ← CreateFusionData[CDBasics.RectAt[[0, 0], obj.size]];
subInstance: CoreClasses.CellInstance;
fakeInstance: CD.Instance ← PWPins.NewInstance[obj];
TerminalIO.WriteF["Extracting indirect %g (size: [%g, %g])\n", IO.rope[CDDirectory.Name[obj]], IO.int[obj.size.x], IO.int[obj.size.y]];
[subCellType, subWire, subCategory] ← Extract[sourceObject, CDProperties.DangerousAppendProps[obj.properties, properties], userData];
IF nets=NIL THEN RETURN [subCellType, subWire, subCategory];
IF subCategory#$Device THEN ERROR;
subInstance ← NEW [CoreClasses.CellInstanceRec ← [actual: FusionWires[fusionData, subCellType.public, fakeInstance], type: subCellType]];
CoreProperties.PutCellInstanceProp[subInstance, instanceProp, fakeInstance];
IF RefTab.GetSize[fusionData.fusioned]#0 THEN ERROR; -- we fusioned some wires!
We fusion using the nets property, and we put pin properties for future use
BEGIN
FusionEachNet: PWCore.EachNetProc = {
rootWire: Wire ← FusionStructureGeometryAndName[fusionData, wire, pins, NIL, FALSE];
rootWire.properties ← CoreProperties.AppendProps[rootWire.properties, wire.properties]; -- so to have a decent name, for example
CoreProperties.PutWireProp[rootWire, pinsProp, pins];
};
[] ← PWCore.EnumerateNets[nets, FusionEachNet];
END;
Test provisoire pour debug
IF RefTab.GetSize[fusionData.fusioned]#0 THEN {
Net connecting 2 subinternals not connected in layout
cell: CD.Object ← Cellize[obj];
AddInCell: RefTab.EachPairAction = {
wire: Wire ← NARROW [key];
geometry: LIST OF CD.Instance ← FindRootGeometry[RootWire[wire]];
quit ← FALSE;
HighLightInstances[cell, geometry];
};
[] ← RefTab.Pairs[fusionData.fusioned, AddInCell];
ERROR;
};
We build the CellType
DagIfy[fusionData];
cellType ← CoreClasses.CreateRecordCell[
public: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchOnlyIfPinsProp]],
internal: CoreOps.CreateWire[AllMatchingWires[fusionData, MatchAlways]],
instances: LIST [subInstance],
name: CDDirectory.Name[obj]
];
IF CDProperties.GetPropFromObject[obj, coreProp]#NIL AND CoreOps.WireBits[NARROW [CDProperties.GetPropFromObject[obj, coreProp], Core.CellType].public]#CoreOps.WireBits[cellType.public] THEN ERROR; -- mismatch between the original core and the extracted core
};
Geometry Primitives
touchProcProp: PUBLIC ATOM ← PW.RegisterProp[$TouchProc];
Touch:
PUBLIC TouchProc = {
refProc: REF TouchProc;
IF ~CDBasics.Intersect[CDInstances.InstRectO[instance1], CDInstances.InstRectO[instance2]] THEN RETURN;
IF instance1.ob.class=CDSymbolicObjects.pinObjectsClass AND instance2.ob.class=CDSymbolicObjects.pinObjectsClass AND compareLayers THEN RETURN [CDLayers.AbstractToPaint[CDSymbolicObjects.GetLayer[instance1]]=CDLayers.AbstractToPaint[CDSymbolicObjects.GetLayer[instance2]]]; -- Speed up Hack
refProc ← NARROW [CDProperties.GetPropFromObject[instance1.ob, touchProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDProperties.GetProp[instance1.ob.class, touchProcProp]];
yes ← (IF refProc=NIL THEN TouchExpand ELSE refProc^)[instance1, instance2, compareLayers];
};
TouchExpand:
PUBLIC TouchProc = {
instance1 ← PWPins.NewInstance[
ob: CDDirectory.Expand[instance1.ob, NIL, NIL],
location: instance1.location, orientation: instance1.orientation
];
IF instance1.ob=NIL THEN ERROR;
RETURN [Touch[instance1, instance2, compareLayers]];
};
TouchPin:
PUBLIC TouchProc = {
RETURN [TouchRectObject[instance2, CDInstances.InstRectO[instance1], CDSymbolicObjects.GetLayer[instance1], compareLayers]];
};
TouchRect:
PUBLIC TouchProc = {
RETURN [TouchRectObject[instance2, CDInstances.InstRectO[instance1], instance1.ob.layer, compareLayers]];
};
TouchCell:
PUBLIC TouchProc = {
cellPtr: CD.CellPtr ← NARROW [instance1.ob.specificRef];
RETURN [TouchList[TransformList[instance1, cellPtr.contents], instance2, compareLayers]];
};
TouchAtomic:
PUBLIC TouchProc = {
FOR rList: CDAtomicObjects.DrawList ←
NARROW [instance1.ob.specificRef, CDAtomicObjects.AtomicObsPtr].rList, rList.rest
WHILE rList#
NIL
DO
IF TouchRectObject[instance2, CDOrient.MapRect[rList.first.r, instance1.ob.size, instance1.orientation, instance1.location], rList.first.lev, compareLayers] THEN RETURN [TRUE];
ENDLOOP;
};
Geometry Utilities
TouchSomeLayer:
PROC [instances:
LIST
OF
CD.Instance, bound:
CD.Rect]
RETURNS [yes:
BOOL ←
FALSE] = {
FOR list:
LIST
OF
CD.Instance ← instances, list.rest
WHILE list#
NIL
DO
IF TouchSomeLayer1[list.first, bound] THEN RETURN [TRUE];
ENDLOOP;
};
TouchSomeLayer1:
PROC [instance:
CD.Instance, bound:
CD.Rect]
RETURNS [yes:
BOOL ←
FALSE] = {
IF ~CDBasics.Intersect[CDInstances.InstRectO[instance], bound] THEN RETURN;
SELECT instance.ob.class
FROM
CDCells.cellClass => {
cellPtr: CD.CellPtr ← NARROW [instance.ob.specificRef];
FOR instances:
LIST
OF
CD.Instance ← cellPtr.contents, instances.rest
WHILE instances#
NIL
DO
IF TouchSomeLayer1[Transform[instance, instances.first], bound] THEN RETURN [TRUE];
ENDLOOP;
};
ENDCASE => RETURN [TRUE];
};
TouchRectObject:
PUBLIC
PROC [instance:
CD.Instance, rect:
CD.Rect, layer:
CD.Layer, compareLayers:
BOOL ←
TRUE]
RETURNS [yes:
BOOL ←
FALSE] = {
rectInstance: CD.Instance;
IF ~CDBasics.Intersect[CDInstances.InstRectO[instance], rect] THEN RETURN;
IF instance.ob.class=CDRects.bareRectClass THEN RETURN [~compareLayers OR CDLayers.AbstractToPaint[instance.ob.layer]=CDLayers.AbstractToPaint[layer]];
rectInstance ← PWPins.NewInstance[
ob: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer],
location: CDBasics.BaseOfRect[rect]
];
yes ← Touch[instance, rectInstance, compareLayers];
};
Transform:
PUBLIC
PROC [transformation, instance:
CD.Instance]
RETURNS [result:
CD.Instance] = {
RETURN [PWPins.TransformInstance[instance, transformation.ob.size, transformation.location, transformation.orientation]];
};
TransformList:
PUBLIC
PROC [transformation:
CD.Instance, instances:
LIST
OF
CD.Instance]
RETURNS [result:
LIST
OF
CD.Instance ←
NIL] = {
WHILE instances#
NIL
DO
result ← CONS [Transform[transformation, instances.first], result];
instances ← instances.rest;
ENDLOOP;
};
TouchList:
PUBLIC
PROC [instances:
LIST
OF
CD.Instance, instance:
CD.Instance, compareLayers:
BOOL ←
TRUE]
RETURNS [yes:
BOOL ←
FALSE] = {
FOR list:
LIST
OF
CD.Instance ← instances, list.rest
WHILE list#
NIL
DO
IF Touch[list.first, instance, compareLayers] THEN RETURN [TRUE];
ENDLOOP;
};
TouchListList:
PUBLIC
PROC [instances1, instances2:
LIST
OF
CD.Instance, compareLayers:
BOOL ←
TRUE]
RETURNS [yes:
BOOL ←
FALSE] = {
FOR list:
LIST
OF
CD.Instance ← instances1, list.rest
WHILE list#
NIL
DO
IF TouchList[instances2, list.first, compareLayers] THEN RETURN [TRUE];
ENDLOOP;
};