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; 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]] ] ]]; }; 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 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 = { EachTransSubInstance: EachInstanceProc = { 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 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; }; font: CDTexts.CDFont _ CDTexts.MakeFont["Xerox/TiogaFonts/Helvetica8", 4]; 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"]]; }; 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; }; 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 { 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]; 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]; }; PutLazyGeometry: PUBLIC PROC [decoration: Decoration, internal: Wire, lazyGeometryEnumerate: LazyEnumerateProc, data1, data2: REF _ NIL] = { CoreProperties.PutWireProp[internal, decoration.geometryProp, NEW [LazyEnumerateDataRec _ [proc: lazyGeometryEnumerate, data1: data1, data2: data2]]]; }; 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]; }; 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]; }; 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]]]; }; CDProperties.PutLayerProp[CD.commentLayer, $RoutingLayer, $RoutingLayer]; END. FCoreGeometryImpl.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 Creating Decoration Pins Object Geometry We came from that one from a RecordCell [vertical move] Enumerates next level instances. Applies eachInstance to the appropriate transformed subInstances. Transformation Enumeration of Sides for Routers pinIR is the rectangle expressing the InterestRect of the pin in the InterestRect coordinate system of the outer. Fabrication of Shells for Routers or for IO Font used for the text labels Checking of Decorations Lazy Setting of Pins Replaces lazy pins by the physical instances iff it is appropriate. We avoid duplicates Lazy Setting of Geometry Touch Procs 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; }; Geometry Utilities Initialization Ê ©˜codešœ™KšœB™BKšœ6Ïk™9Kšœ2™2Kšœ$™'K™2—K™š ˜ Kšœ˜Kšœ}˜K˜ J˜/Kšœ#˜#K˜K˜Kšœ œ˜—K˜šÐbn Ñblnœœ˜Kšœ œÉœ˜ëKšœ#˜*Kšœœœ$˜H—headšœ™š Ïnœœœœœ˜Ošœ œ˜#Kšœ ˜ šœ*˜*Kšœ.˜.KšœN˜NKšœ˜—šœ,˜,Kšœ0˜0KšœN˜NKšœ˜—šœ.˜.Kšœ2˜2KšœN˜NKšœ˜—šœ+˜+Kšœ/˜/KšœN˜NKšœ˜—K˜—K˜——™š œœœœ œ"œœœ˜wKšœœœœ˜šœœ˜šœœœœ˜>Jš œœœœœœ˜<—šœœ œœ˜/Kšœœœœ˜4Kšœ˜Kšœ˜—Jšœd˜dš œœœ œœ˜)JšœUœœœ˜jJšœ˜Jšœ˜—šœ˜Jšœ˜šœœœ˜(š  œ˜"Kšœ(œœ˜6Kšœ0˜0K˜—Jšœ-˜-šœ]˜_Jšœœœ˜—Jšœ˜—J˜—Jšœv˜vKšœœÏcd˜v—K˜K™—š   œœœHœœ˜zKšœt˜tK˜K™—š   œœœ(œ œ ˜ZKš œ)˜:Kšœœ;˜EKšœœœœ˜šœœ˜Jšœ1˜1Jšœ3˜3JšœM˜T—K˜K™—š  œœœ(œœ˜NKš œœ˜1Kšœ5˜;K˜K˜—š  œœœ(œœ˜_Kš  œœ˜?Kšœ4˜4K˜K™—š œœœ<˜PKšœœ˜šœœœ˜(Kšœœ˜4šœœœ ˜Kšœ,˜,Kšœ˜—KšœC˜CKšœœ?˜E—K˜K˜—š œœœ<˜Pš  œ˜!šœœœ˜.Kšœœœœ˜(—Kšœœ˜—Kšœœœœ˜Kšœ4˜4Kšœ#˜#——™š   œœœ.œœ˜VJšœ"œ˜-Kšœ˜K˜—š  œœœ.œ˜`Kšœ œC˜RKšœ˜K˜—š  œœœA˜WKšœH˜HK˜——™šžœœœœ#œœœœ˜ýKšœ7™7š œ ˜.Jšœ7˜7Jšœ œœ˜-Jšœd˜dJšœGœ,˜vK˜—š  œÏbœ˜)Jšœ œœ˜-Kšœ1œ ˜Wšœœ˜"Kšœœœœ[˜”Kšœ˜K˜—šœ(œ˜0š œ˜(Jšœœ$˜CJšœœœœ˜1Jš œœœœœ.˜sJ˜—Jšœ"œ ˜5Jšœœœœ;˜tKšœœœ˜Kšœx˜xK˜—Kšœt˜xK˜—KšœZœ˜uK˜K˜—š œœœœ œ"œœœ˜{Kšœœœœ˜šœœ˜šœœ œœ˜/Kšœœœœ˜4Kšœ˜Kšœ˜—šœœœœ˜>Jš œœœœœœ˜<—Jšœv˜vKšœœ¡l˜~—K˜K™—š  œœœVœœœ˜—šœ ˜šœ ˜ Kšœ)œ ˜˜VKšœœ˜šœœœ˜(Kšœœœ ˜9š œœœœ˜!Kšœ8˜8Kšœ˜—KšœE˜EKšœœE˜K—K˜K˜—š  œœœ>˜VKš  œ!œ˜HKšœ œœœ˜Kšœ7˜7Kšœ(˜(K˜——™š  œœœ6œœ˜]KšœIœ˜TKšœ˜K™—š œœœ6œ˜nKšœ œœJ˜oKšœ˜Kšœ˜K˜—š œœœP˜eKšœGœ˜eK˜——™ š œœœœ˜SJšœ:œ[˜—J˜J˜—Jšœq™qš  œœœ˜FJšœ œ$˜/JšœO˜OJšœ@˜@Jšœ>˜>JšœQ˜QJ˜J˜—š  œœœPœœ˜ƒš   œœœœœœ˜PJšœ\¡>˜šJšœ%˜%Jšœ(˜(Jšœ1œœœ˜Cšœ œœ˜Jšœ œ˜Jšœœœ˜Jšœ œ œ"˜AJšœ œ œ"˜AJšœ)œœ˜7Jšœ˜—J˜—š œ˜%šœœ˜JšœQœB˜•JšœHœQ˜›Jšœ6˜=—J˜—Jšœ œ/˜˜>Jšœ+œ˜/JšœœR˜\K˜——™š  œœœ.œœ˜_Kš   œœœœœœ˜RKšœ%˜%Kšœ5˜5K˜K™—š   œœœ,œœ˜\Kšœ#œ˜8Kš œœ$œœœ˜>šœœœ˜Kšœ%œ œœ˜B—K˜——™KšœC™Cš  œœ+˜;Kšœœ!˜+šœœ˜JšœEœ˜Jšœ"œ˜?Jšœœ˜0Jš  œA˜KJšœ4˜4Kšœ œœ˜Kšœ>˜>K˜—Kšœ˜—K˜K˜—š   œœœ\œœ˜‚Kšœ8œQ˜ŒKšœ˜K˜K™—š œœœ;˜[KšœB˜BKšœ˜K˜K™—š  œœœ3œœ ˜eKšœC˜CKšœ˜K˜K™—š œœœ;˜[Kšœœ;˜Ešœœ˜Kšœ:œ˜DKšœœ7˜@Kšœ˜šœœœ˜!Kšœ7œ˜NKš œœœ œœ!œ*œ˜„šœ˜ Kšœœ˜Jš  œœ˜?Jšœ5˜5Jšœ7˜7Kšœ"˜"J˜———K˜K˜—š  œœœ4œœ˜xJšœœ¡#˜3Kšœ˜Kšœœœ œ˜šœ œ˜Jšœ(˜(Jšœ(˜(Jš œœ)˜Yšœ<˜>Jšœœ˜6—Jšœ˜Jšœ˜—Kšœœ˜*Kšœ˜Jš œœœœ,œ˜RKšœE˜EKšœ˜K˜K™—š œœœ\˜Kšœ,œ˜JK˜K™—š œœœ9˜WJšœ&œ˜;Jšœ6˜6š  œ˜%Jšœœœ œ!˜AKšœ4˜4J˜—šœœœ˜$Jšœ4˜4Jšœ;˜;š œ˜&Jšœœœ œ'˜GJšœ™š œœœœœ˜œU˜–K˜——™ š œœ˜JšœœBœœ˜Tšœœ˜Jšœ0œK˜Jšœ)œZ˜‰šœ˜Jš œ@˜NJšœ.˜4Jšœ˜——J˜J˜—š  œœœ;œœœœ˜uJšœœœ˜*šœ*œ˜1JšœP˜V—šœ˜Jšœ˜Jšœ_˜_Jšœ˜—J˜J˜—š   œœœ>œœœ˜nšœ(œœ˜˜>J˜J˜—š  œœœœœ˜KJšœ"œ?œ˜oJ˜J˜—š  œœœœ œ ˜^JšœG˜MJ˜——™Jšœœ-˜I—K˜Kšœ˜—…—|t¥c