<> <> <> <> <> <> <<>> 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> 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]; }; <> EnumerateFlatGeometry: PUBLIC PROC [decoration: Decoration, root: CellType, target: FlatCellTypeRec _ CoreFlat.allFlatCells, leafProc: LeafProc, eachFlatWire: EachFlatWireProc _ NIL, eachFlatCell: EachFlatCellProc _ NIL] RETURNS [quit: BOOL _ FALSE] = { <> 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 = { <> 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> 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]]; }; <> 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]]]]; }; <> 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; }; <> 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]; }; <> <> <> <> <> <> <<};>> <> <> <> <> <> < ERROR; -- l1.first not found in list2>> <> <> <<};>> <> <> <<[] _ OldEnumerateNeighbors[decoration, touch, inX, ct1, ct2, SavePairs];>> <> <<[] _ NewEnumerateNeighbors[decoration, touch, inX, ct1, ct2, SavePairs];>> <> <> <> <> <> <<};>> <<>> 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.