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 March 13, 1987 11:55:48 pm PST
Barth, February 18, 1987 8:19:50 pm PST
DIRECTORY
Basics,
CD, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts,
Convert,
CoreClasses, CoreFlat, CoreOps, CoreProperties,
CoreGeometry, CoreGeometryBackdoor,
GList, HashTable,
PWObjects, Rope;
CoreGeometryImpl: CEDAR PROGRAM
IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDInstances, CDLayers, CDProperties, CDRects, CDSymbolicObjects, CDTexts, Convert, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, GList, HashTable, PWObjects, 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 = {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, leafProc: LeafProc, eachFlatWire: EachFlatWireProc ← NIL, eachFlatCell: EachFlatCellProc ← NIL] = {
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 leafProc[cell] THEN {
IF eachFlatCell#NIL THEN eachFlatCell[bindings: bindings, cell: cell, flatCell: flatCell, trans: refTrans^];
RETURN;
};
IF cell.class=CoreClasses.recordCellClass THEN {
RecordGeometry: CoreOps.EachWireProc = {
refBoundWire: FlatWire ← NARROW [HashTable.Fetch[bindings, wire].value];
IF NOT HasGeometry[decoration, wire] THEN RETURN;
eachFlatWire[wire, IF refBoundWire#NIL THEN refBoundWire^ ELSE [flatCell: flatCell, wire: wire], refTrans^];
};
rct: CoreClasses.RecordCellType = NARROW [cell.data];
IF eachFlatWire#NIL THEN [] ← CoreOps.VisitWireSeq[rct.internal, RecordGeometry];
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, 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.
};
EnumerateGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire, eachInstance: EachInstanceProc] RETURNS [quit: BOOL] = {
quit ← RawEnumerateGeometry[decoration.geometryProp, CoreProperties.GetWireProp[internal, decoration.geometryProp], eachInstance];
};
HasGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire] RETURNS [BOOL] = {
HasGeom: EachInstanceProc = {quit ← TRUE};
RETURN [EnumerateGeometry[decoration, internal, HasGeom]];
};
GetGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire] RETURNS [geometry: Instances ← NIL] = {
ConsEachGeom: EachInstanceProc = {geometry ← CONS [instance, geometry]};
[] ← EnumerateGeometry[decoration, internal, ConsEachGeom];
};
PutGeometry: PUBLIC PROC [decoration: Decoration, internal: 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[internal, decoration.geometryProp, instances];
} ELSE CoreProperties.PutWireProp[internal, decoration.geometryProp, geometry];
};
AddGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire, geometry: Instances] = {
ConsEachGeom: EachInstanceProc = {geometry ← CONS [instance, geometry]};
IF geometry=NIL THEN RETURN;
[] ← EnumerateGeometry[decoration, internal, ConsEachGeom];
PutGeometry[decoration, internal, geometry];
};
Transformation
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] = {
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   => EnumerateSeg[CDBasics.MapRect[CD.InterestRect[instance.obj], instance.trans], instance.obj.layer];
IsCoreGeometryPin[instance.obj]     =>
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]};
quit ← EnumerateSides[decoration, cellType, wire, EachPin];
};
quit ← CoreOps.VisitWireSeq[cellType.public, EachWireSide];
};
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];
[] ← 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];
[] ← CoreOps.VisitWireSeq[cellType.public, ConstructEachWire];
shell ← PWObjects.CreateCell[instances, ir];
};
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: CoreGeometry.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: HashTable.Table ← HashTable.Create[record.public.size];
SetLazyPins: CoreOps.EachWireProc = {
list: LIST OF TransWire ← NARROW [HashTable.Fetch[table, wire].value];
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 [HashTable.Fetch[table, actualWire].value];
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];
[] ← HashTable.Store[table, actualWire, list];
};
IF NOT CoreGeometry.HasObject[decoration, cellInstance.type] THEN ERROR; -- this sub Cell has not been decorated
[] ← 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]]];
};
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;
};
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.ExpandByDraw[instance.obj, TRUE, TRUE];
CDProperties.PutObjectProp[instance.obj, $FlattenInstanceCache, flat];
quit ← FlattenInstance[[flat, instance.trans], eachInstance];
};
};
Touch: PUBLIC TouchProc = {
IF NOT CDBasics.Intersect[InlineBBox[instance1], InlineBBox[instance2]] THEN RETURN;
SELECT TRUE FROM
instance1.obj.class=CDRects.bareRectClass    => RETURN [TouchRect[instance2, InlineBBox[instance1], instance1.obj.layer]];
IsCoreGeometryPin[instance1.obj]      => RETURN [TouchRect[instance2, InlineBBox[instance1], GetCoreGeometryPinLayer[instance1]]];
ENDCASE             => {
TouchInstance2: EachInstanceProc = {quit ← Touch[instance, instance2]};
RETURN [FlattenInstance[instance1, TouchInstance2]];
};
};
TouchRect: PUBLIC PROC [instance: Instance, rect: Rect, layer: CD.Layer] RETURNS [BOOLFALSE] = {
IF ~Intersect[rect, instance] THEN RETURN;
IF CDProperties.GetLayerProp[layer, $Well]#NIL THEN RETURN;
IF instance.obj.class=CDRects.bareRectClass THEN
RETURN [CDLayers.AbstractToPaint[instance.obj.layer]=CDLayers.AbstractToPaint[layer]];
RETURN [Touch[
instance,
[obj: CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], trans: [CDBasics.BaseOfRect[rect]]]
]];
};
TouchList: PUBLIC PROC [instances: Instances, instance: Instance] RETURNS [BOOLFALSE] = {
FOR list: Instances ← instances, list.rest WHILE list#NIL DO
IF Touch[list.first, instance] THEN RETURN [TRUE];
ENDLOOP;
};
TouchListList: PUBLIC PROC [instances1, instances2: Instances] RETURNS [BOOLFALSE] = {
FOR list: Instances ← instances1, list.rest WHILE list#NIL DO
IF TouchList[instances2, list.first] THEN RETURN [TRUE];
ENDLOOP;
};
CDPinToCoreGeometryPin: PUBLIC PROC [cdPin: Object, props: CD.PropList] RETURNS [coreGeometryPin: Object] = {
coreGeometryPin ← PWObjects.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.