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;
CoreGeometry
Impl:
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;
Pins
RawEnumeratePins:
PUBLIC
PROC [prop:
ATOM, value:
REF, eachInstance: EachInstanceProc]
RETURNS [quit:
BOOL ←
FALSE] = {
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]};
Geometry
EnumerateFlatGeometry:
PUBLIC
PROC [decoration: Decoration, root: CellType, target: FlatCellTypeRec ← CoreFlat.allFlatCells, leafProc: LeafProc, eachFlatWire: EachFlatWireProc ←
NIL, eachFlatCell: EachFlatCellProc ←
NIL]
RETURNS [quit:
BOOL ←
FALSE] = {
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:
BOOL ←
FALSE] = {
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:
BOOL ←
FALSE] = {
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];
};
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:
BOOL ←
FALSE]= {
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 WMMSL ← NIL;
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: BOOL ← TRUE;
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 WMML ← NIL;
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:
BOOL ←
FALSE]
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"]];
};
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:
REF ←
NIL] = {
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];
};
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 [
BOOL ←
FALSE] = {
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 [
BOOL ←
FALSE] = {
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 [
BOOL ←
FALSE] = {
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:
BOOL ←
FALSE]]
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:
BOOL ←
FALSE]]
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: BOOL ← FALSE]] RETURNS [quit: BOOL] ~ {
SavePairs: PROC [wire1, wire2: Wire] RETURNS [quit: BOOL ← FALSE] ~ {
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:
BOOL ←
FALSE] = {
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:
BOOL ←
FALSE] = {
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]]];
};