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 September 4, 1987 4:33:41 pm PDT
DIRECTORY
Basics,
CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts,
Convert,
CoreClasses, CoreFlat, CoreOps, CoreProperties,
CoreGeometry, CoreGeometryBackdoor,
GList,
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, 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;
};
EnumerateNeighbors: PUBLIC 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];
};
CacheKeyRec: TYPE = RECORD [decoration: Decoration, touch: TouchProc, inX: BOOL, ct1, ct2: CellType, trans: Transformation];
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.