CoreGeometryImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, August 6, 1986 0:38:23 am PDT
Bertrand Serlet September 14, 1987 11:23:38 pm PDT
Barth, February 18, 1987 8:19:50 pm PST
Jean-Marc Frailong January 17, 1988 5:41:55 pm PST
DIRECTORY
Basics,
CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts,
Convert,
CoreClasses, CoreFlat, CoreOps, CoreProperties,
CoreGeometry, CoreGeometryBackdoor,
GList,
InstanceTable,
PrincOps, PW, RefTab, Rope;
CoreGeometryImpl: CEDAR PROGRAM
IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts, Convert, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, GList, InstanceTable, PW, RefTab, Rope
EXPORTS CoreGeometry, CoreGeometryBackdoor
SHARES CDCells, CDRects ~ BEGIN OPEN CoreGeometry, CoreGeometryBackdoor;
Creating Decoration
CreateDecoration: PUBLIC PROC [name: ROPE] RETURNS [decoration: Decoration] ~ {
decoration ← NEW [DecorationRec ← [
name: name,
pinsProp: CoreProperties.RegisterProperty[
Convert.AtomFromRope[Rope.Cat[name, "Pins"]],
CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
],
objectProp: CoreProperties.RegisterProperty[
Convert.AtomFromRope[Rope.Cat[name, "Object"]],
CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
],
geometryProp: CoreProperties.RegisterProperty[
Convert.AtomFromRope[Rope.Cat[name, "Geometry"]],
CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
],
transProp: CoreProperties.RegisterProperty[
Convert.AtomFromRope[Rope.Cat[name, "Trans"]],
CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
]
]];
};
Pins
RawEnumeratePins: PUBLIC PROC [prop: ATOM, value: REF, eachInstance: EachInstanceProc] RETURNS [quit: BOOLFALSE] = {
IF value=NIL THEN RETURN;
WITH value SELECT FROM
instances: InstanceSeq => FOR i: NAT IN [0 .. instances.size)
DO IF eachInstance[instances[i]] THEN RETURN [TRUE] ENDLOOP;
instances: Instances => WHILE instances#NIL DO
IF eachInstance[instances.first] THEN RETURN [TRUE];
instances ← instances.rest;
ENDLOOP;
wire: Wire   => quit ← RawEnumeratePins[prop, CoreProperties.GetWireProp[wire, prop], eachInstance];
wires: LIST OF Wire => WHILE wires#NIL DO
IF RawEnumeratePins[prop, CoreProperties.GetWireProp[wires.first, prop], eachInstance] THEN RETURN [TRUE];
wires ← wires.rest;
ENDLOOP;
transWireIR: TransWireIR => {
ir: Rect ← transWireIR.ir;
FOR i: NAT IN [0 .. transWireIR.size) DO
TransEachPin: EachInstanceProc = {
IF TransfedNotAtEdge[trans, ir, instance] THEN RETURN;
quit ← eachInstance[Transform[trans, instance]];
};
trans: Transformation ← transWireIR[i].trans;
IF RawEnumeratePins[prop, CoreProperties.GetWireProp[transWireIR[i].wire, prop], TransEachPin]
THEN RETURN [TRUE];
ENDLOOP;
};
lazyEnumerate: LazyEnumerateData => quit ← lazyEnumerate.proc[eachInstance, lazyEnumerate.data1, lazyEnumerate.data2];
ENDCASE => ERROR; -- value unknown to this module. Pins were probably created without using the procedural interface.
};
EnumeratePins: PUBLIC PROC [decoration: Decoration, public: Wire, eachInstance: EachInstanceProc] RETURNS [quit: BOOL] = {
quit ← RawEnumeratePins[decoration.pinsProp, CoreProperties.GetWireProp[public, decoration.pinsProp], eachInstance];
};
CountPins: PUBLIC PROC [decoration: Decoration, public: Wire] RETURNS [count: INT ← 0] = {
CountEachInstance: EachInstanceProc = {count ← count + 1};
value: REF ← CoreProperties.GetWireProp[public, decoration.pinsProp];
IF value=NIL THEN RETURN;
WITH value SELECT FROM
instances: InstanceSeq => count ← instances.size;
instances: Instances  => count ← Length[instances];
ENDCASE     => [] ← RawEnumeratePins[decoration.pinsProp, value, CountEachInstance];
};
HasPins: PUBLIC PROC [decoration: Decoration, public: Wire] RETURNS [BOOL] = {
ReturnFirstPin: EachInstanceProc = {quit ← TRUE};
RETURN [EnumeratePins[decoration, public, ReturnFirstPin]];
};
GetPins: PUBLIC PROC [decoration: Decoration, public: Wire] RETURNS [pins: Instances ← NIL] = {
ConsEachPin: EachInstanceProc = {pins ← CONS [instance, pins]};
[] ← EnumeratePins[decoration, public, ConsEachPin];
};
PutPins: PUBLIC PROC [decoration: Decoration, public: Wire, pins: Instances] = {
size: NAT = Length[pins];
IF size#0 AND size<maxInstanceSeq THEN {
instances: InstanceSeq = NEW [InstanceSeqRec[size]];
FOR i: NAT IN [0 .. size) DO
instances[i] ← pins.first; pins ← pins.rest;
ENDLOOP;
CoreProperties.PutWireProp[public, decoration.pinsProp, instances];
} ELSE CoreProperties.PutWireProp[public, decoration.pinsProp, pins];
};
AddPins: PUBLIC PROC [decoration: Decoration, public: Wire, pins: Instances] = {
ConsEachPin: EachInstanceProc = {
FOR p: Instances ← pins, p.rest WHILE p#NIL DO
IF p.first=instance THEN RETURN ENDLOOP;
pins ← CONS [instance, pins]};
IF pins=NIL THEN RETURN;
[] ← EnumeratePins[decoration, public, ConsEachPin];
PutPins[decoration, public, pins]};
Object
HasObject: PUBLIC PROC [decoration: Decoration, cellType: CellType] RETURNS [BOOL] = {
RETURN [GetObject[decoration, cellType]#NIL];
};
GetObject: PUBLIC PROC [decoration: Decoration, cellType: CellType] RETURNS [object: Object] = {
object ← NARROW [CoreProperties.GetCellTypeProp[cellType, decoration.objectProp]];
};
PutObject: PUBLIC PROC [decoration: Decoration, cellType: CellType, object: Object] = {
CoreProperties.PutCellTypeProp[cellType, decoration.objectProp, object];
};
Geometry
EnumerateFlatGeometry: PUBLIC PROC [decoration: Decoration, root: CellType, target: FlatCellTypeRec ← CoreFlat.allFlatCells, leafProc: LeafProc, eachFlatWire: EachFlatWireProc ← NIL, eachFlatCell: EachFlatCellProc ← NIL] RETURNS [quit: BOOLFALSE] = {
We came from that one from a RecordCell [vertical move]
TransBoundFlat: CoreFlat.BoundFlatCellProc = {
trans: Transformation = GetTrans[decoration, instance];
refTrans: REF Transformation = NARROW [data];
currentTrans: Transformation = CDBasics.ComposeTransform[itemInCell: trans, cellInWorld: refTrans^];
BoundFlat[cell, target, flatCell, instance, index, parent, flatParent, NEW [Transformation ← currentTrans], bindings];
};
BoundFlat: CoreFlat.BoundFlatCellProc = {
refTrans: REF Transformation = NARROW [data];
IF CoreFlat.FlatCellTypeEqualRec[target, flatCell] THEN target ← CoreFlat.allFlatCells;
IF leafProc[cell, bindings] THEN {
IF target=CoreFlat.allFlatCells AND eachFlatCell#NIL THEN quit ← eachFlatCell[bindings: bindings, cell: cell, flatCell: flatCell, trans: refTrans^];
RETURN;
};
IF cell.class=CoreClasses.recordCellClass THEN {
RecordGeometry: CoreOps.EachWireProc = {
refBoundWire: FlatWire ← NARROW [RefTab.Fetch[bindings, wire].val];
IF NOT HasGeometry[decoration, wire] THEN RETURN;
quit ← eachFlatWire[wire, IF refBoundWire#NIL THEN refBoundWire^ ELSE [flatCell: flatCell, wire: wire], refTrans^];
};
rct: CoreClasses.RecordCellType = NARROW [cell.data];
IF target=CoreFlat.allFlatCells AND eachFlatWire#NIL THEN quit ← CoreOps.VisitWireSeq[rct.internal, RecordGeometry];
IF quit THEN RETURN;
CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, TransBoundFlat];
}
ELSE CoreFlat.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, BoundFlat];
};
BoundFlat[cell: root, target: target, bindings: CoreFlat.InitialBindingTable[root], data: NEW [Transformation ← []]];
};
RawEnumerateGeometry: PUBLIC PROC [prop: ATOM, value: REF, eachInstance: EachInstanceProc] RETURNS [quit: BOOLFALSE] = {
IF value=NIL THEN RETURN;
WITH value SELECT FROM
instances: Instances => WHILE instances#NIL DO
IF eachInstance[instances.first] THEN RETURN [TRUE];
instances ← instances.rest;
ENDLOOP;
instances: InstanceSeq => FOR i: NAT IN [0 .. instances.size)
DO IF eachInstance[instances[i]] THEN RETURN [TRUE] ENDLOOP;
lazyEnumerate: LazyEnumerateData => quit ← lazyEnumerate.proc[eachInstance, lazyEnumerate.data1, lazyEnumerate.data2];
ENDCASE => ERROR; -- decoration unknown to this module. Geometry was probably created without using the procedural interface.
};
EnumerateAllGeometry: PUBLIC PROC [decoration: Decoration, cell: CellType, wire: Wire, eachInstance: EachInstanceProc] RETURNS [quit: BOOLFALSE] = {
SELECT cell.class FROM
CoreClasses.recordCellClass => {
recordCell: CoreClasses.RecordCellType = NARROW [cell.data];
quit ← EnumerateGeometry[decoration: decoration, wire: wire, eachInstance: eachInstance];
FOR i: NAT IN [0 .. recordCell.size) UNTIL quit = TRUE DO
EnumerateSubInstances: CoreOps.EachWirePairProc = {
Enumerates next level instances.
EachTransSubInstance: EachInstanceProc = {
Applies eachInstance to the appropriate transformed subInstances.
RETURN [eachInstance[instance: Transform[trans: trans, instance: instance]]]
};
IF actualWire = wire THEN
quit ← EnumerateAllGeometry[decoration: decoration, cell: cellInstance.type, wire: publicWire, eachInstance: EachTransSubInstance]
};
cellInstance: CoreClasses.CellInstance = recordCell[i];
trans: Transformation = GetTrans[decoration: decoration, cellInstance: cellInstance];
quit ← CoreOps.VisitBinding[actual: cellInstance.actual, public: cellInstance.type.public, eachWirePair: EnumerateSubInstances].quit
ENDLOOP
};
CoreClasses.transistorCellClass =>
quit ← EnumerateGeometry[decoration: decoration, wire: wire, eachInstance: eachInstance];
ENDCASE => {
recastCell: CellType = CoreOps.Recast[me: cell];
wireTab: RefTab.Ref ← CoreOps.CreateBindingTable[wire1: cell.public, wire2: recastCell.public];
quit ← EnumerateAllGeometry[decoration: decoration, cell: recastCell, wire: NARROW [RefTab.Fetch[x: wireTab, key: wire].val], eachInstance: eachInstance]
};
};
EnumerateGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire, eachInstance: EachInstanceProc] RETURNS [quit: BOOL] = {
quit ← RawEnumerateGeometry[decoration.geometryProp, CoreProperties.GetWireProp[wire, decoration.geometryProp], eachInstance];
};
HasGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire] RETURNS [BOOL] = {
HasGeom: EachInstanceProc = {quit ← TRUE};
RETURN [EnumerateGeometry[decoration, wire, HasGeom]];
};
GetGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire] RETURNS [geometry: Instances ← NIL] = {
ConsEachGeom: EachInstanceProc = {geometry ← CONS [instance, geometry]};
[] ← EnumerateGeometry[decoration, wire, ConsEachGeom];
};
PutGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire, geometry: Instances] = {
size: INT = Length[geometry];
IF size#0 AND size<maxInstanceSeq THEN {
instances: InstanceSeq ← NEW [InstanceSeqRec[NAT[size]]];
FOR i: NAT IN [0 .. NAT[size]) DO
instances[i] ← geometry.first; geometry ← geometry.rest;
ENDLOOP;
CoreProperties.PutWireProp[wire, decoration.geometryProp, instances];
} ELSE CoreProperties.PutWireProp[wire, decoration.geometryProp, geometry];
};
AddGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire, geometry: Instances] = {
ConsEachGeom: EachInstanceProc = {geometry ← CONS [instance, geometry]};
IF geometry=NIL THEN RETURN;
[] ← EnumerateGeometry[decoration, wire, ConsEachGeom];
PutGeometry[decoration, wire, geometry];
};
Transformation
HasTrans: PUBLIC PROC [decoration: Decoration, cellInstance: CellInstance] RETURNS [BOOL] = {
RETURN [CoreProperties.GetCellInstanceProp[cellInstance, decoration.transProp]#NIL];
};
GetTrans: PUBLIC PROC [decoration: Decoration, cellInstance: CellInstance] RETURNS [trans: Transformation] = {
refTrans: REF Transformation ← NARROW [CoreProperties.GetCellInstanceProp[cellInstance, decoration.transProp]];
trans ← refTrans^;
};
PutTrans: PUBLIC PROC [decoration: Decoration, cellInstance: CellInstance, trans: Transformation] = {
CoreProperties.PutCellInstanceProp[cellInstance, decoration.transProp, NEW [Transformation ← trans]];
};
Enumeration of Sides for Routers
GetSides: PUBLIC PROC [ir: Rect, pin: Instance] RETURNS [sides: Sides ← noSide] = {
sides ← PinIRSides[ir, CDBasics.MoveRect[CDBasics.MapRect[CD.InterestRect[pin.obj], pin.trans], CDBasics.SubPoints[[0, 0], CDBasics.BaseOfRect[ir]]]];
};
pinIR is the rectangle expressing the InterestRect of the pin in the InterestRect coordinate system of the outer.
PinIRSides: PROC [ir, pinIR: Rect] RETURNS [sides: Sides ← noSide] = {
objSize: CD.Position = CDBasics.SizeOfRect[ir];
sides[top] ← CDBasics.Intersect[pinIR, [0, objSize.y-1, objSize.x, objSize.y]];
sides[bottom] ← CDBasics.Intersect[pinIR, [0, 0, objSize.x, 1]];
sides[left] ← CDBasics.Intersect[pinIR, [0, 0, 1, objSize.y]];
sides[right] ← CDBasics.Intersect[pinIR, [objSize.x-1, 0, objSize.x, objSize.y]];
};
EnumerateSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, wire: Wire, eachPin: EachPinProc] RETURNS [quit: BOOL] = {
EnumerateSeg: PROC [bbox: Rect, layer: CD.Layer] RETURNS [quit: BOOLFALSE]= {
pinIR: Rect = CDBasics.MoveRect[bbox, CDBasics.SubPoints[[0, 0], CDBasics.BaseOfRect[ir]]]; -- bbox of the pin in the obj coordinate system of the outer
sides: Sides = PinIRSides[ir, pinIR];
layer ← CDLayers.AbstractToPaint[layer];
IF CDProperties.GetLayerProp[layer, $RoutingLayer]=NIL THEN RETURN;
FOR side: Side IN Side DO
min, max: INT ← 0;
IF ~sides[side] THEN LOOP;
IF side=top OR side=bottom THEN {min ← pinIR.x1; max ← pinIR.x2};
IF side=left OR side=right THEN {min ← pinIR.y1; max ← pinIR.y2};
IF (quit ← eachPin[min, max, side, layer]) THEN RETURN;
ENDLOOP;
};
InternalEachPin: EachInstanceProc = {
SELECT TRUE FROM
instance.obj.class=CDRects.bareRectClass => quit ← EnumerateSeg[CDBasics.MapRect[CD.InterestRect[instance.obj], instance.trans], instance.obj.layer];
IsCoreGeometryPin[instance.obj] => quit ← EnumerateSeg[CDBasics.MapRect[CD.InterestRect[instance.obj], instance.trans], GetCoreGeometryPinLayer[instance]];
ENDCASE => quit ← FlattenInstance[instance, InternalEachPin];
};
ir: Rect = CD.InterestRect[GetObject[decoration, cellType]];
quit ← EnumeratePins[decoration, wire, InternalEachPin];
};
EnumerateWireSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, eachWirePin: EachWirePinProc] RETURNS [quit: BOOL] = {
EachWireSide: CoreOps.EachWireProc = {
EachPin: EachPinProc = {quit ← eachWirePin[wire, min, max, side, layer]};
IF ~RefTab.Store[visitOnceTab, wire, wire] THEN RETURN[FALSE, FALSE]; -- only once
quit ← EnumerateSides[decoration, cellType, wire, EachPin]};
visitOnceTab: RefTab.Ref ← RefTab.Create[];
quit ← CoreOps.VisitWireSeq[cellType.public, EachWireSide];
RefTab.Erase[visitOnceTab]; visitOnceTab ← NIL};
WMMSL: TYPE = RECORD [wire: Wire, min, max: INT, side: Side, layer: CD.Layer];
EnumerateNonOverlappingSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, eachWirePin: EachWirePinProc] RETURNS [quit: BOOL] = {
list: LIST OF REF WMMSLNIL;
CompareWMMSL: GList.CompareProc = {
wmmsl1: REF WMMSL = NARROW [ref1];
wmmsl2: REF WMMSL = NARROW [ref2];
RETURN [Basics.CompareInt[wmmsl1.min, wmmsl2.min]];
};
EachWirePin: EachWirePinProc = {
list ← CONS [NEW [WMMSL ← [wire, min, max, side, layer]], list];
};
[] ← EnumerateWireSides[decoration, cellType, EachWirePin];
list ← NARROW [GList.Sort[list, CompareWMMSL]]; -- modifies the list for good
FOR wmmsls: LIST OF REF WMMSL ← list, wmmsls.rest WHILE wmmsls#NIL DO
wmmsl1: REF WMMSL = wmmsls.first;
merge: BOOLTRUE;
WHILE merge DO
FOR aux: LIST OF REF WMMSL ← wmmsls, aux.rest WHILE aux#NIL AND aux.rest#NIL DO
wmmsl2: REF WMMSL = aux.rest.first;
IF wmmsl1.wire=wmmsl2.wire AND wmmsl1.side=wmmsl2.side AND wmmsl1.layer=wmmsl2.layer AND wmmsl2.min<=wmmsl1.max
THEN {wmmsl1.max ← MAX [wmmsl1.max, wmmsl2.max]; aux.rest ← aux.rest.rest; EXIT};
REPEAT FINISHED => merge ← FALSE;
ENDLOOP;
ENDLOOP;
ENDLOOP;
WHILE list#NIL DO
quit ← eachWirePin[list.first.wire, list.first.min, list.first.max, list.first.side, list.first.layer];
IF quit THEN EXIT;
list ← list.rest;
ENDLOOP;
};
WMML: TYPE = RECORD [wire: Wire, min, max: INT, layer: CD.Layer];
EnumerateSortedSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, side: Side, eachSortedPin: EachSortedPinProc] RETURNS [quit: BOOL] = {
list: LIST OF REF WMMLNIL;
sideFilter: Side = side;
CompareWMML: GList.CompareProc = {
wmml1: REF WMML = NARROW [ref1];
wmml2: REF WMML = NARROW [ref2];
RETURN [Basics.CompareInt[wmml1.min, wmml2.min]];
};
EachWirePin: EachWirePinProc = {
IF side=sideFilter THEN list ← CONS [NEW [WMML ← [wire, min, max, layer]], list];
};
[] ← EnumerateWireSides[decoration, cellType, EachWirePin];
list ← NARROW [GList.Sort[list, CompareWMML]]; -- modifies the list for good
WHILE list#NIL DO
quit ← eachSortedPin[list.first.wire, list.first.min, list.first.max, list.first.layer];
IF quit THEN EXIT;
list ← list.rest;
ENDLOOP;
};
Fabrication of Shells for Routers or for IO
font: CDTexts.CDFont ← CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica8", 4];
Font used for the text labels
CreateShell: PUBLIC PROC [decoration: Decoration, cellType: CellType, withCuteFonts: BOOLFALSE] RETURNS [shell: Object] = {
ConstructEachWire: CoreOps.EachWireProc = {
ConstructPins: EachInstanceProc = {
inst: CD.Instance ← IF IsCoreGeometryPin[instance.obj]
THEN CoreGeometryPinToCDPin[instance]
ELSE CDInstances.NewInst[instance.obj, instance.trans];
CDProperties.PutInstanceProp[inst, $SignalName, name];
instances ← CONS [inst, instances];
};
name: ROPE ← CoreOps.GetFullWireName[cellType.public, wire];
IF ~RefTab.Store[visitOnceTab, wire, wire] THEN RETURN[FALSE, FALSE]; -- only once
[] ← EnumeratePins[decoration, wire, ConstructPins];
IF withCuteFonts THEN {
ConstructFonts: EachPinProc = {
inst: CD.Instance ← CDInstances.NewInst[
text,
[off: SELECT side FROM
left => [-300, min], right => [iSize.x+10, min],
top => [min, iSize.y+10], bottom => [min, -300],
ENDCASE => ERROR,
orient: SELECT side FROM
left, right => original, top, bottom => rotate90, ENDCASE => ERROR]
];
instances ← CONS [inst, instances];
};
text: Object ← CDTexts.Create[name, font];
[] ← EnumerateSides[decoration, cellType, wire, ConstructFonts];
};
};
instances: LIST OF CD.Instance ← NIL;
ir: CD.Rect = CD.InterestRect[GetObject[decoration, cellType]];
iSize: CD.Position ← CDBasics.SizeOfRect[ir];
visitOnceTab: RefTab.Ref ← RefTab.Create[];
[] ← CoreOps.VisitWireSeq[cellType.public, ConstructEachWire];
RefTab.Erase[visitOnceTab]; visitOnceTab ← NIL;
shell ← PW.CreateCell[instances, ir, Rope.Cat[CoreOps.GetCellTypeName[cellType], "-Shell"]];
};
Checking of Decorations
CheckInterface: PUBLIC PROC [decoration: Decoration, cellType: CellType] RETURNS [ok: BOOL] = {
CheckPins: PROC [wire: Wire] = {IF NOT HasPins[decoration, wire] THEN ok ← FALSE};
ok ← HasObject[decoration, cellType];
CoreOps.VisitRootAtomics[cellType.public, CheckPins];
};
CheckInternal: PUBLIC PROC [decoration: Decoration, record: CellType] RETURNS [ok: BOOL] = {
data: CoreClasses.RecordCellType = NARROW [record.data];
IF NOT CheckInterface[decoration, record] THEN RETURN [FALSE];
FOR i: NAT IN [0 .. data.size)
DO [] ← GetTrans[decoration, data[i] ! ANY => ok ← FALSE] ENDLOOP;
};
Lazy Setting of Pins
Replaces lazy pins by the physical instances iff it is appropriate.
ExpandPins: PROC [decoration: Decoration, public: Wire] = {
count: INT ← CountPins[decoration, public];
SELECT TRUE FROM
count=0   => CoreProperties.PutWireProp[public, decoration.pinsProp, NIL];
count<=decoration.expandPinsCount AND count<maxInstanceSeq => {
pins: InstanceSeq ← NEW [InstanceSeqRec[count]];
SetEachPin: EachInstanceProc = {count ← count - 1; pins[count] ← instance};
[] ← EnumeratePins[decoration, public, SetEachPin];
IF count#0 THEN ERROR;
CoreProperties.PutWireProp[public, decoration.pinsProp, pins];
};
ENDCASE => {};
};
PutLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, lazyPinsEnumerate: LazyEnumerateProc, data1, data2: REFNIL] = {
CoreProperties.PutWireProp[public, decoration.pinsProp, NEW [LazyEnumerateDataRec ← [proc: lazyPinsEnumerate, data1: data1, data2: data2]]];
ExpandPins[decoration, public];
};
PutIndirectLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, indirect: Wire] = {
CoreProperties.PutWireProp[public, decoration.pinsProp, indirect];
ExpandPins[decoration, public];
};
PutIndirectsLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, indirects: LIST OF Wire] = {
CoreProperties.PutWireProp[public, decoration.pinsProp, indirects];
ExpandPins[decoration, public];
};
AddIndirectLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, indirect: Wire] = {
value: REF ← CoreProperties.GetWireProp[public, decoration.pinsProp];
SELECT TRUE FROM
CoreProperties.GetWireProp[indirect, decoration.pinsProp]=NIL => {};
value=NIL  => PutIndirectLazyPins[decoration, public, indirect];
value=indirect => {};
ENDCASE => WITH value SELECT FROM
wire: Wire => PutIndirectsLazyPins[decoration, public, LIST [wire, indirect]];
wires: LIST OF Wire => IF NOT CoreOps.Member[wires, indirect] THEN PutIndirectsLazyPins[decoration, public, CONS [indirect, wires]];
ENDCASE => {
pins: Instances ← NIL;
ConsEachPin: EachInstanceProc = {pins ← CONS [instance, pins]};
[] ← EnumeratePins[decoration, public, ConsEachPin];
[] ← EnumeratePins[decoration, indirect, ConsEachPin];
PutPins[decoration, public, pins];
};
};
PutTransWireIRsLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, transWires: LIST OF TransWire, ir: Rect] = {
count: NAT ← 0; -- number of TransWire in new list!
transWireIR: TransWireIR;
new: LIST OF TransWire ← NIL;
WHILE transWires#NIL DO
transWire: TransWire = transWires.first;
trans: Transformation = transWire.trans;
HasTransClipPin: EachInstanceProc = {quit ← NOT TransfedNotAtEdge[trans, ir, instance]};
IF EnumeratePins[decoration, transWire.wire, HasTransClipPin]
THEN {count ← count + 1; new ← CONS [transWire, new]};
transWires ← transWires.rest;
ENDLOOP;
transWireIR ← NEW [TransWireIRRec[count]];
transWireIR.ir ← ir;
FOR i: NAT IN [0 .. count) DO transWireIR[i] ← new.first; new ← new.rest ENDLOOP;
CoreProperties.PutWireProp[public, decoration.pinsProp, transWireIR];
ExpandPins[decoration, public];
};
PutTransWireIRLazyPins: PUBLIC PROC [decoration: Decoration, public: Wire, indirect: Wire, trans: Transformation, ir: Rect] = {
PutTransWireIRsLazyPins[decoration, public, LIST [[trans, indirect]], ir];
};
PutRecordLazyPins: PUBLIC PROC [decoration: Decoration, record: CellType, ir: Rect] = {
recData: CoreClasses.RecordCellType = NARROW [record.data];
table: RefTab.Ref ← RefTab.Create[record.public.size];
SetLazyPins: CoreOps.EachWireProc = {
list: LIST OF TransWire ← NARROW [RefTab.Fetch[table, wire].val];
PutTransWireIRsLazyPins[decoration, wire, list, ir];
};
FOR i: NAT IN [0 .. recData.size) DO
cellInstance: CoreClasses.CellInstance = recData[i];
trans: Transformation = GetTrans[decoration, cellInstance];
EachBind: CoreOps.EachWirePairProc = {
list: LIST OF TransWire ← NARROW [RefTab.Fetch[table, actualWire].val];
We avoid duplicates
FOR aux: LIST OF TransWire ← list, aux.rest WHILE aux#NIL DO
IF aux.first=[trans, publicWire] THEN RETURN;
ENDLOOP;
list ← CONS [[trans, publicWire], list];
[] ← RefTab.Store[table, actualWire, list];
};
IF NOT HasObject[decoration, cellInstance.type] THEN ERROR; -- this sub Cell has not been decorated
IF AtEdge[ir, [obj: GetObject[decoration, cellInstance.type], trans: trans]] THEN
[] ← CoreOps.VisitBindingSeq[cellInstance.actual, cellInstance.type.public, EachBind];
ENDLOOP;
[] ← CoreOps.VisitWireSeq[record.public, SetLazyPins];
};
Lazy Setting of Geometry
PutLazyGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire, lazyGeometryEnumerate: LazyEnumerateProc, data1, data2: REFNIL] = {
CoreProperties.PutWireProp[internal, decoration.geometryProp, NEW [LazyEnumerateDataRec ← [proc: lazyGeometryEnumerate, data1: data1, data2: data2]]];
};
Touch Procs
Touch: PUBLIC TouchProc = {
IF NOT CDBasics.Intersect[InlineBBox[instance1], InlineBBox[instance2]] THEN RETURN;
SELECT TRUE FROM
instance1.obj.class=CDRects.bareRectClass    => RETURN [TouchRect[touch, instance2, InlineBBox[instance1], instance1.obj.layer]];
IsCoreGeometryPin[instance1.obj]      => RETURN [TouchRect[touch, instance2, InlineBBox[instance1], GetCoreGeometryPinLayer[instance1]]];
ENDCASE             => {
TouchInstance2: EachInstanceProc = {quit ← touch[touch, instance, instance2]};
RETURN [FlattenInstance[instance1, TouchInstance2]];
};
};
TouchRect: PUBLIC PROC [touch: TouchProc, instance: Instance, rect: Rect, layer: CD.Layer] RETURNS [BOOLFALSE] = {
IF ~Intersect[rect, instance] THEN RETURN;
IF instance.obj.class=CDRects.bareRectClass THEN
RETURN [CDLayers.AbstractToPaint[instance.obj.layer]=CDLayers.AbstractToPaint[layer]];
RETURN [touch[
touch, instance,
[obj: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], trans: [CDBasics.BaseOfRect[rect]]]
]];
};
TouchList: PUBLIC PROC [touch: TouchProc, instances: Instances, instance: Instance] RETURNS [BOOLFALSE] = {
FOR list: Instances ← instances, list.rest WHILE list#NIL DO
IF touch[touch, list.first, instance] THEN RETURN [TRUE];
ENDLOOP;
};
TouchListList: PUBLIC PROC [touch: TouchProc, instances1, instances2: Instances] RETURNS [BOOLFALSE] = {
FOR list: Instances ← instances1, list.rest WHILE list#NIL DO
IF TouchList[touch, instances2, list.first] THEN RETURN [TRUE];
ENDLOOP;
};
OldEnumerateNeighbors: PROC [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType, eachPair: PROC [Wire, Wire] RETURNS [quit: BOOLFALSE]] RETURNS [quit: BOOL] = {
ir1: Rect = CD.InterestRect[GetObject[decoration, ct1]];
ir2: Rect = CD.InterestRect[GetObject[decoration, ct2]];
basicTransl: CD.Position = IF inX THEN [ir1.x2-ir1.x1, 0] ELSE [0, ir1.y2 - ir1.y1];
trans: Transformation = [CDBasics.AddPoints[basicTransl, CDBasics.SubPoints[CDBasics.BaseOfRect[ir1], CDBasics.BaseOfRect[ir2]]]];
EachPub2: CoreOps.EachWireProc = {
wire2: Wire = wire;
EachPin2: EachInstanceProc = {
instance2: Instance = instance;
EachPub1: CoreOps.EachWireProc = {
EachPin1: EachInstanceProc = {
IF touch[touch, instance, Transform[trans, instance2]]
THEN quit ← eachPair[wire, wire2];
};
quit ← EnumeratePins[decoration, wire, EachPin1];
};
IF TransfedNotAtEdge[trans, ir1, instance] THEN RETURN;
quit ← CoreOps.VisitWireSeq[ct1.public, EachPub1];
};
quit ← EnumeratePins[decoration, wire, EachPin2];
};
quit ← CoreOps.VisitWireSeq[ct2.public, EachPub2];
};
EnumerateNeighbors: PUBLIC PROC [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType, eachPair: PROC [Wire, Wire] RETURNS [quit: BOOLFALSE]] RETURNS [quit: BOOL] = {
obj1: CD.Object = GetObject[decoration, ct1];
obj2: CD.Object = GetObject[decoration, ct2];
ir1: Rect = CD.InterestRect[obj1];
ir2: Rect = CD.InterestRect[obj2];
basicTransl: CD.Position = IF inX THEN [ir1.x2-ir1.x1, 0] ELSE [0, ir1.y2 - ir1.y1];
trans: Transformation = [CDBasics.AddPoints[basicTransl, CDBasics.SubPoints[CDBasics.BaseOfRect[ir1], CDBasics.BaseOfRect[ir2]]]];
table2: InstanceTable.Table ← InstanceTable.Create[CDBasics.Extend[BBox[[obj2, trans]], 1]];
EachPub2: CoreOps.EachWireProc = {
EachPin2: EachInstanceProc = {
IF TransfedNotAtEdge[trans, ir1, instance] THEN RETURN;
InstanceTable.Insert[table2, Transform[trans, instance], wire];
};
[] ← EnumeratePins[decoration, wire, EachPin2];
};
EachPub1: CoreOps.EachWireProc ~ {
EachPin1: EachInstanceProc = {
EachOverlap: PROC [instance2: Instance, value: REF ANY] ~ {
IF touch[touch, instance, instance2] THEN quit ← eachPair[wire, NARROW[value]];
};
InstanceTable.Enumerate[table2, EachOverlap, InlineBBox[instance]];
};
quit ← EnumeratePins[decoration, wire, EachPin1];
};
[] ← CoreOps.VisitWireSeq[ct2.public, EachPub2];
quit ← CoreOps.VisitWireSeq[ct1.public, EachPub1];
InstanceTable.DeleteOutside[table2];
};
EnumerateNeighbors: PUBLIC PROC [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType, eachPair: PROC [Wire, Wire] RETURNS [quit: BOOLFALSE]] RETURNS [quit: BOOL] ~ {
SavePairs: PROC [wire1, wire2: Wire] RETURNS [quit: BOOLFALSE] ~ {
FOR list: LIST OF WirePair ← savedPairs, list.rest WHILE list#NIL DO
IF list.first=[wire1, wire2] THEN RETURN;
ENDLOOP;
savedPairs ← CONS [[wire1, wire2], savedPairs];
};
CheckIncluded: PROC [list1, list2: LIST OF WirePair] ~ {
FOR l1: LIST OF WirePair ← list1, l1.rest UNTIL l1=NIL DO
FOR l2: LIST OF WirePair ← list2, l2.rest UNTIL l2=NIL DO
IF l1.first=l2.first THEN EXIT;
REPEAT
FINISHED => ERROR; -- l1.first not found in list2
ENDLOOP;
ENDLOOP;
};
savedPairs, safePairs: LIST OF WirePair;
savedPairs ← NIL;
[] ← OldEnumerateNeighbors[decoration, touch, inX, ct1, ct2, SavePairs];
safePairs ← savedPairs; savedPairs ← NIL;
[] ← NewEnumerateNeighbors[decoration, touch, inX, ct1, ct2, SavePairs];
CheckIncluded[savedPairs, safePairs];
CheckIncluded[safePairs, savedPairs];
FOR l: LIST OF WirePair ← safePairs, l.rest UNTIL quit OR l=NIL DO
quit ← eachPair[l.first.wire1, l.first.wire2];
ENDLOOP;
};
CacheKeyRec: TYPE = RECORD [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType];
EqualCacheKey: RefTab.EqualProc = {
ck1: REF CacheKeyRec ← NARROW [key1];
ck2: REF CacheKeyRec ← NARROW [key2];
RETURN [ck1^=ck2^];
};
Munch: PROC [CARD32] RETURNS [CARD16] = TRUSTED MACHINE CODE { PrincOps.zXOR };
MunchRef: PROC [ref: REF] RETURNS [WORD] = INLINE {RETURN [Munch[LOOPHOLE [ref]]]};
HashCacheKey: RefTab.HashProc = {
ck: REF CacheKeyRec ← NARROW [key];
RETURN [
Basics.BITXOR[
Basics.BITXOR[
Basics.BITXOR[MunchRef[ck.decoration], LOOPHOLE[ck.touch]],
Basics.BITXOR[MunchRef[ck.ct1], MunchRef[ck.ct2]]
],
ORD[ck.inX]
]
];
};
CreateNeighborsCache: PUBLIC PROC [] RETURNS [cache: RefTab.Ref] = {
cache ← RefTab.Create[2, EqualCacheKey, HashCacheKey];
};
CachedEnumerateNeighbors: PUBLIC PROC [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType, cache: RefTab.Ref] RETURNS [pairs: LIST OF WirePair ← NIL] = {
EachPair: PROC [wire1, wire2: Wire] RETURNS [quit: BOOLFALSE] = {
FOR list: LIST OF WirePair ← pairs, list.rest WHILE list#NIL DO
IF list.first=[wire1, wire2] THEN RETURN;
ENDLOOP;
pairs ← CONS [[wire1, wire2], pairs];
};
ck: REF CacheKeyRec ← NEW [CacheKeyRec ← [decoration, touch, inX, ct1, ct2]];
pairs ← NARROW [RefTab.Fetch[cache, ck].val];
IF pairs#NIL THEN RETURN;
[] ← EnumerateNeighbors[decoration, touch, inX, ct1, ct2, EachPair];
[] ← RefTab.Store[cache, ck, pairs];
};
Geometry Utilities
Length: PUBLIC PROC [instances: Instances] RETURNS [count: INT ← 0] = {
WHILE instances#NIL DO count ← count + 1; instances ← instances.rest ENDLOOP;
};
BBox: PUBLIC PROC [instance: Instance] RETURNS [rect: Rect] = {rect ← InlineBBox[instance]};
AtEdge: PUBLIC PROC [ir: Rect, instance: Instance] RETURNS [BOOL] = {
RETURN [NOT CDBasics.Inside[InlineBBox[instance], CDBasics.Extend[ir, -1]]];
};
TransfedNotAtEdge: PUBLIC PROC [trans: Transformation, ir: Rect, instance: Instance] RETURNS [BOOL] = {
RETURN [CDBasics.Inside[
CDBasics.MapRect[instance.obj.bbox, CDBasics.ComposeTransform[instance.trans, trans]],
CDBasics.Extend[ir, -1]
]]
};
Intersect: PUBLIC PROC [clipRect: Rect, instance: Instance] RETURNS [BOOL] = {
RETURN [CDBasics.Intersect[InlineBBox[instance], clipRect]]
};
Transform: PUBLIC PROC [trans: Transformation, instance: Instance] RETURNS [Instance] = {
RETURN [[
obj: instance.obj,
trans: CDBasics.ComposeTransform[itemInCell: instance.trans, cellInWorld: trans]
]];
};
TransformList: PUBLIC PROC [trans: Transformation, instances: Instances] RETURNS [new: Instances ← NIL] = {
WHILE instances#NIL DO
new ← CONS [Transform[trans, instances.first], new];
instances ← instances.rest;
ENDLOOP;
};
DrawListToInstances: PUBLIC PROC [drawList: CDAtomicObjects.DrawList] RETURNS [instances: Instances ← NIL] = {
WHILE drawList#NIL DO
rect: CD.Rect ← drawList.first.r;
object: CD.Object ← CDRects.CreateRect[CDBasics.SizeOfRect[rect], drawList.first.layer];
instances ← CONS [[obj: object, trans: [CDBasics.BaseOfRect[rect]]], instances];
drawList ← drawList.rest;
ENDLOOP;
};
FlattenInstance: PUBLIC PROC [instance: Instance, eachInstance: EachInstanceProc] RETURNS [quit: BOOLFALSE] = {
EachSubInstance: CDCells.InstEnumerator = {
quit ← eachInstance[[inst.ob, CDBasics.ComposeTransform[itemInCell: inst.trans, cellInWorld: instance.trans]]];
};
flat: Object ← NARROW [CDProperties.GetObjectProp[instance.obj, $FlattenInstanceCache]];
SELECT TRUE FROM
flat#NIL => quit ← CDCells.EnumerateInstances[flat, EachSubInstance];
IsCoreGeometryPin[instance.obj]     => RETURN;
instance.obj.class=CDRects.bareRectClass   => ERROR;
instance.obj.class=CDCells.pCellClass    => quit ← CDCells.EnumerateInstances[instance.obj, EachSubInstance];
ENDCASE         => {
flat ← CDDirectory.Expand1ByDraw[instance.obj, CDDirectory.LeaveRectangles];
CDProperties.PutObjectProp[instance.obj, $FlattenInstanceCache, flat];
quit ← FlattenInstance[[flat, instance.trans], eachInstance];
};
};
CDPinToCoreGeometryPin: PUBLIC PROC [cdPin: Object, props: CD.PropList] RETURNS [coreGeometryPin: Object] = {
coreGeometryPin ← PW.CreateCell[LIST [CDInstances.NewInst[ob: cdPin, properties: props]]];
CDProperties.PutObjectProp[coreGeometryPin, $CoreGeometryPin, $CoreGeometryPin];
};
CoreGeometryPinToCDPin: PUBLIC PROC [coreGeometryPin: Instance] RETURNS [cdPin: CD.Instance] = {
instance: CD.Instance ← NIL;
AffectInstance: CDCells.InstEnumerator = {IF instance#NIL THEN ERROR; instance ← inst};
IF NOT IsCoreGeometryPin[coreGeometryPin.obj] THEN ERROR;
[] ← CDCells.EnumerateInstances[coreGeometryPin.obj, AffectInstance];
cdPin ← CDInstances.Composed[instance, coreGeometryPin.trans];
};
IsCoreGeometryPin: PUBLIC PROC [coreGeometryPin: Object] RETURNS [BOOL] = {
RETURN [CDCells.IsCell[coreGeometryPin] AND CDProperties.GetObjectProp[coreGeometryPin, $CoreGeometryPin]#NIL];
};
GetCoreGeometryPinLayer: PUBLIC PROC [coreGeometryPin: Instance] RETURNS [layer: CD.Layer] = {
RETURN [CDSymbolicObjects.GetLayer[CoreGeometryPinToCDPin[coreGeometryPin]]];
};
Initialization
CDProperties.PutLayerProp[CD.commentLayer, $RoutingLayer, $RoutingLayer];
END.