DIRECTORY Basics, Convert, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, Imager, ImagerFont, ImagerTransformation, List, Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PrincOps, RefTab, Rope; PipalCoreImpl: CEDAR PROGRAM IMPORTS Basics, Convert, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, ImagerFont, ImagerTransformation, List, Pipal, PipalInstanceTable, PipalInt, PipalIO, PipalMos, RefTab, Rope EXPORTS PipalCore ~ BEGIN OPEN PipalCore; CellType : TYPE = Core.CellType; Properties : TYPE = Core.Properties; ROPE: TYPE = Core.ROPE; Wire: TYPE = Core.Wire; CellInstance: TYPE = CoreClasses.CellInstance; FlatWire: TYPE = CoreFlat.FlatWire; FlatWireRec: TYPE = CoreFlat.FlatWireRec; FlatCellType: TYPE = CoreFlat.FlatCellType; FlatCellTypeRec: TYPE = CoreFlat.FlatCellTypeRec; Bindings: TYPE = CoreFlat.Bindings; InstancePath: TYPE = CoreFlat.InstancePath; Object: TYPE = Pipal.Object; Objects: TYPE = Pipal.Objects; Transformation: TYPE = PipalInt.Transformation; Rectangle: TYPE = PipalInt.Rectangle; layoutDecoration: PUBLIC Decoration _ CreateDecoration["Layout", TRUE]; schematicsDecoration: PUBLIC Decoration _ CreateDecoration["Schematic", TRUE]; rawLayoutDecoration: PUBLIC Decoration _ CreateDecoration["RawLayout", TRUE]; CreateDecoration: PUBLIC PROC [name: ROPE, coreSave: BOOL _ FALSE] RETURNS [decoration: Decoration] ~ { decoration _ NEW [DecorationRec _ [ name: name, portProp: CoreProperties.RegisterProperty[ Convert.AtomFromRope[Rope.Cat[name, "Port"]], 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]] ] ]]; IF NOT coreSave THEN RETURN; [] _ CoreIO.RegisterProperty[decoration.objectProp, ObjectPropWrite, ObjectPropRead]; [] _ CoreIO.RegisterProperty[decoration.portProp, ObjectPropWrite, ObjectPropRead]; [] _ CoreIO.RegisterProperty[decoration.geometryProp, ObjectPropWrite, ObjectPropRead]; [] _ CoreIO.RegisterProperty[decoration.transProp, TransPropWrite, TransPropRead]; }; ObjectPropWrite: CoreIO.PropWriteProc = {PipalIO.WriteObject[stream, NARROW [value]]}; ObjectPropRead: CoreIO.PropReadProc = {value _ PipalIO.ReadObject[stream]}; TransPropWrite: CoreIO.PropWriteProc = {PipalIO.WriteIntTransformation[stream, NARROW [value, REF PipalInt.Transformation]^]}; TransPropRead: CoreIO.PropReadProc = {value _ NEW [PipalInt.Transformation _ PipalIO.ReadIntTransformation[stream]]}; HasPort: PUBLIC PROC [decoration: Decoration, public: Wire] RETURNS [BOOL] = { RETURN [GetPort[decoration, public]#Pipal.void]; }; GetPort: PUBLIC PROC [decoration: Decoration, public: Wire] RETURNS [port: Object] = { port _ CoreProperties.GetWireProp[public, decoration.portProp]; IF port=Pipal.void THEN ERROR; IF port=NIL THEN port _ Pipal.void; }; PutPort: PUBLIC PROC [decoration: Decoration, public: Wire, port: Object] = { IF port=NIL THEN ERROR; IF port=Pipal.void THEN port _ NIL; CoreProperties.PutWireProp[public, decoration.portProp, port]; }; AddPort: PUBLIC PROC [decoration: Decoration, public: Wire, port: Object] = { IF port=NIL THEN ERROR; PutPort[decoration, public, Pipal.CreateOv[LIST [port, GetPort[decoration, public]]]]; }; PutClippedPort: PUBLIC PROC [decoration: Decoration, public: Wire, abutBox: Rectangle, subPort: Object] = { IF subPort=NIL THEN ERROR; PutPort[decoration, public, PipalMos.CreateClipEnum[abutBox, subPort]]; }; TransWire: TYPE = RECORD [trans: Transformation, wire: Wire]; PutRecordPorts: PUBLIC PROC [decoration: Decoration, record: CellType, abutBox: Rectangle] = { recData: CoreClasses.RecordCellType = NARROW [record.data]; table: RefTab.Ref _ RefTab.Create[record.public.size]; SetLazyPort: CoreOps.EachWireProc = { subs: Objects _ NIL; FOR list: LIST OF TransWire _ NARROW [RefTab.Fetch[table, wire].val], list.rest WHILE list#NIL DO subs _ CONS [PipalMos.CreateClipEnum[abutBox, PipalInt.TransformObject[list.first.trans, GetPort[decoration, list.first.wire]]], subs]; ENDLOOP; PutPort[decoration, wire, Pipal.CreateOv[subs]]; }; 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 PipalInt.AtEdge[abutBox, trans, GetObject[decoration, cellInstance.type]] THEN [] _ CoreOps.VisitBindingSeq[cellInstance.actual, cellInstance.type.public, EachBind]; ENDLOOP; [] _ CoreOps.VisitWireSeq[record.public, SetLazyPort]; }; 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]; }; HasGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire] RETURNS [BOOL] = { RETURN [GetGeometry[decoration, wire]#Pipal.void]; }; GetGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire] RETURNS [geometry: Object] = { geometry _ CoreProperties.GetWireProp[wire, decoration.geometryProp]; IF geometry=Pipal.void THEN ERROR; IF geometry=NIL THEN geometry _ Pipal.void; }; PutGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire, geometry: Object] = { IF geometry=NIL THEN ERROR; IF geometry=Pipal.void THEN geometry _ NIL; CoreProperties.PutWireProp[wire, decoration.geometryProp, geometry]; }; AddGeometry: PUBLIC PROC [decoration: Decoration, wire: Wire, geometry: Object] = { IF geometry=NIL THEN ERROR; PutGeometry[decoration, wire, Pipal.CreateOv[LIST [geometry, GetGeometry[decoration, wire]]]]; }; 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 = PipalInt.Compose[refTrans^, trans]; 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 _ []]]; }; EnumerateAllGeometry: PUBLIC PROC [decoration: Decoration, cell: CellType, wire: Wire, each: PipalInt.EachChildProc, trans: Transformation] RETURNS [quit: BOOL _ FALSE] = { SELECT cell.class FROM CoreClasses.recordCellClass => { recordCell: CoreClasses.RecordCellType = NARROW [cell.data]; quit _ each[trans, GetGeometry[decoration, wire]]; FOR i: NAT IN [0 .. recordCell.size) UNTIL quit DO EnumerateSubInstances: CoreOps.EachWirePairProc = { IF actualWire = wire THEN quit _ EnumerateAllGeometry[decoration: decoration, cell: cellInstance.type, wire: publicWire, each: each, trans: thisTrans] }; cellInstance: CoreClasses.CellInstance = recordCell[i]; thisTrans: Transformation = PipalInt.Compose[trans, GetTrans[decoration: decoration, cellInstance: cellInstance]]; quit _ CoreOps.VisitBinding[actual: cellInstance.actual, public: cellInstance.type.public, eachWirePair: EnumerateSubInstances].quit ENDLOOP }; CoreClasses.transistorCellClass => quit _ each[trans, GetGeometry[decoration, wire]]; 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], each: each, trans: trans] }; }; GetAllGeometry: PUBLIC PROC [decoration: Decoration, cell: CellType, wire: Wire] RETURNS [geometry: Object] = { geoms: Objects _ NIL; ConsEach: PipalInt.EachChildProc = { geoms _ CONS [PipalInt.TransformObject[transformation, child], geoms]; }; [] _ EnumerateAllGeometry[decoration, cell, wire, ConsEach, []]; geometry _ Pipal.CreateOv[geoms]; }; 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]]; }; routingLayers: RefTab.Ref _ RefTab.Create[]; RegisterRoutingLayer: PUBLIC PROC [layer: PipalMos.Layer] = { [] _ RefTab.Store[routingLayers, layer, $TRUE]; }; GetSides: PUBLIC PROC [abutBox: Rectangle, trans: Transformation, port: Pipal.Object] RETURNS [sides: Sides _ noSide] = { sides _ PinIRSides[abutBox, PipalInt.TransformRectangle[trans, PipalInt.AbutBox[port]]]; }; PinIRSides: PROC [abutBox, bbox: Rectangle] RETURNS [sides: Sides _ noSide] = { objSize: PipalInt.Size = abutBox.size; pinIR: Rectangle = PipalInt.Translate[bbox, PipalInt.Neg[abutBox.base]]; sides[top] _ PipalInt.DoRectanglesIntersect[pinIR, [[0, objSize.y-1], [objSize.x, 1]]]; sides[bottom] _ PipalInt.DoRectanglesIntersect[pinIR, [[0, 0], [objSize.x, 1]]]; sides[left] _ PipalInt.DoRectanglesIntersect[pinIR, [[0, 0], [1, objSize.y]]]; sides[right] _ PipalInt.DoRectanglesIntersect[pinIR, [[objSize.x-1, 0], [1, objSize.y]]]; }; EnumerateSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, wire: Wire, eachPin: EachPinProc] RETURNS [quit: BOOL] = { EnumerateSeg: PipalMos.EachRectangleLayerProc = { sides: Sides = PinIRSides[abutBox, rect]; IF NOT RefTab.Fetch[routingLayers, layer].found THEN RETURN; FOR side: Side IN Side DO pinIR: Rectangle = PipalInt.Translate[rect, PipalInt.Neg[abutBox.base]]; -- rect of the pin in the obj coordinate system of the outer min, max: INT _ 0; IF ~sides[side] THEN LOOP; IF side=top OR side=bottom THEN {min _ pinIR.base.x; max _ pinIR.base.x+pinIR.size.x}; IF side=left OR side=right THEN {min _ pinIR.base.y; max _ pinIR.base.y+pinIR.size.y}; IF (quit _ eachPin[min, max, side, layer]) THEN RETURN; ENDLOOP; }; abutBox: Rectangle = PipalInt.AbutBox[GetObject[decoration, cellType]]; quit _ PipalMos.EnumerateRectangleLayers[GetPort[decoration, wire], EnumerateSeg]; }; 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, $TRUE] THEN RETURN; -- only once quit _ EnumerateSides[decoration, cellType, wire, EachPin]; }; visitOnceTab: RefTab.Ref _ RefTab.Create[]; quit _ CoreOps.VisitWireSeq[cellType.public, EachWireSide]; }; WMMSL: TYPE = RECORD [wire: Wire, min, max: INT, side: Side, layer: PipalMos.Layer]; EnumerateNonOverlappingSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, eachWirePin: EachWirePinProc] RETURNS [quit: BOOL] = { list: LIST OF REF _ NIL; sorted: LIST OF REF; CompareWMMSL: List.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]; sorted _ List.Sort[list, CompareWMMSL]; -- modifies the list for good FOR wmmsls: LIST OF REF _ sorted, wmmsls.rest WHILE wmmsls#NIL DO wmmsl1: REF WMMSL = NARROW [wmmsls.first]; merge: BOOL _ TRUE; WHILE merge DO FOR aux: LIST OF REF _ wmmsls, aux.rest WHILE aux#NIL AND aux.rest#NIL DO wmmsl2: REF WMMSL = NARROW [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 sorted#NIL DO wmmsl: REF WMMSL = NARROW [sorted.first]; quit _ eachWirePin[wmmsl.wire, wmmsl.min, wmmsl.max, wmmsl.side, wmmsl.layer]; IF quit THEN EXIT; sorted _ sorted.rest; ENDLOOP; }; WMML: TYPE = RECORD [wire: Wire, min, max: INT, layer: PipalMos.Layer]; EnumerateSortedSides: PUBLIC PROC [decoration: Decoration, cellType: CellType, side: Side, eachSortedPin: EachSortedPinProc] RETURNS [quit: BOOL] = { list: LIST OF REF _ NIL; sorted: LIST OF REF; sideFilter: Side = side; CompareWMML: List.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]; sorted _ List.Sort[list, CompareWMML]; -- modifies the list for good WHILE sorted#NIL DO wmml: REF WMML = NARROW [list.first]; quit _ eachSortedPin[wmml.wire, wmml.min, wmml.max, wmml.layer]; IF quit THEN EXIT; sorted _ sorted.rest; ENDLOOP; }; font: Imager.Font _ ImagerFont.Modify[ ImagerFont.Find["Xerox/TiogaFonts/Helvetica8"], ImagerTransformation.Scale[4] ]; CreateShell: PUBLIC PROC [decoration: Decoration, cellType: CellType, withCuteFonts: BOOL _ FALSE] RETURNS [shell: Object] = { objects: Objects _ NIL; visitOnceTab: RefTab.Ref _ RefTab.Create[]; ConstructEachWire: CoreOps.EachWireProc = { name: ROPE _ CoreOps.GetFullWireName[cellType.public, wire]; IF ~RefTab.Store[visitOnceTab, wire, $TRUE] THEN RETURN; -- only once objects _ CONS [ Pipal.CreateAnnotation[GetPort[decoration, wire], Pipal.nameProp, name], objects]; IF withCuteFonts THEN { ConstructFonts: EachPinProc = { trans: Transformation = [ SELECT side FROM left => [-300, min], right => [iSize.x+10, min], top => [min, iSize.y+10], bottom => [min, -300], ENDCASE => ERROR, SELECT side FROM left, right => identity, top, bottom => rotate90, ENDCASE => ERROR ]; objects _ CONS [PipalInt.TransformObject[trans, text], objects]; }; text: Object _ PipalMos.CreateText[name, font]; [] _ EnumerateSides[decoration, cellType, wire, ConstructFonts]; }; }; abutBox: Rectangle = PipalInt.AbutBox[GetObject[decoration, cellType]]; iSize: PipalInt.Size _ abutBox.size; [] _ CoreOps.VisitWireSeq[cellType.public, ConstructEachWire]; shell _ PipalInt.CreateAbutBoxAnnotation[Pipal.CreateOv[objects], abutBox]; }; CheckInterface: PUBLIC PROC [decoration: Decoration, cellType: CellType] RETURNS [ok: BOOL] = { CheckPort: PROC [wire: Wire] = {IF NOT HasPort[decoration, wire] THEN ok _ FALSE}; ok _ HasObject[decoration, cellType]; CoreOps.VisitRootAtomics[cellType.public, CheckPort]; }; 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; }; EnumerateNeighbors: PUBLIC PROC [decoration: Decoration, touch: PipalMos.TouchProc, inX: BOOL, ct1, ct2: CellType, eachPair: PROC [Wire, Wire] RETURNS [quit: BOOL _ FALSE]] RETURNS [quit: BOOL] = { obj1: Object = GetObject[decoration, ct1]; obj2: Object = GetObject[decoration, ct2]; abutBox1: Rectangle = PipalInt.AbutBox[obj1]; abutBox2: Rectangle = PipalInt.AbutBox[obj2]; basicTransl: PipalInt.Vector = IF inX THEN [abutBox1.size.x, 0] ELSE [0, abutBox1.size.y]; trans: Transformation = [PipalInt.Add[basicTransl, PipalInt.Sub[abutBox1.base, abutBox2.base]]]; table2: PipalInstanceTable.Table _ PipalInstanceTable.Create[PipalInt.Extend[PipalInt.BBox[obj2, trans], 1]]; EachPub2: CoreOps.EachWireProc = { pin2: Object _ GetPort[decoration, wire]; IF PipalInt.AtEdge[abutBox1, trans, pin2] THEN PipalInstanceTable.Insert[table2, trans, pin2, wire]; }; EachPub1: CoreOps.EachWireProc ~ { pin1: Object _ GetPort[decoration, wire]; rect1: Rectangle = PipalInt.BBox[pin1, []]; EachOverlap: PROC [trans2: Transformation, pin2: Object, value: REF ANY] ~ { IF touch[touch, [], pin1, trans2, pin2] THEN quit _ eachPair[wire, NARROW [value]]; }; PipalInstanceTable.Enumerate[table2, EachOverlap, rect1]; }; [] _ CoreOps.VisitWireSeq[ct2.public, EachPub2]; quit _ CoreOps.VisitWireSeq[ct1.public, EachPub1]; }; CacheKeyRec: TYPE = RECORD [decoration: Decoration, touch: PipalMos.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: PipalMos.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]; }; RegisterRoutingLayer[PipalMos.commentLayer]; END. PipalCoreImpl.mesa Copyright Σ 1986, 1987, 1988 by Xerox Corporation. All rights reserved. Created by Bertrand Serlet, August 6, 1986 0:38:23 am PDT Bertrand Serlet May 8, 1988 11:16:36 pm PDT Barth, February 18, 1987 8:19:50 pm PST Jean-Marc Frailong January 17, 1988 5:41:55 pm PST Short Cuts Theory Previous experience has shown that, if ports are stored in the trivial way [Instances], most of the memory goes into those ports, and that seriously limits the size of designs the DA system can handle. Therefore, it is important to be able to store ports in a lazy way: every time the time penalty is not too important, recompute ports instead of storing them. Enumerations are prefered to explicit lists for both storage efficiency [enumerations create less objects] and time efficiency [enumerations may return early]. Common cases when ports can be recomputed: Indirection: ports of a given wire are the same as the ones of some other wire. This is heavily used in PWCore that generates lots of indirections. The time penalty in that case is a constant time. Indirection and transformation: ports of a given wire are the same as the ones of some other wire, once applied a geometrical transformation. This case is very frequent for abuts (think of the vertical wires of lines). The time penalty is a constant time. Routing Cell: both ports and geometry can be deduced from the routing object itself. RecordCell: ports of a public of a RecordCell can always be obtained by enumerating the instances to which the public is bound, assuming that some geometric transformations and some clipping are done. This is of course a very common case, but the time penalty might be quite high (looping both on instances and bindings). Common cases when ports can be recorded directly: Small number of instances. The implementation of this interface tries to make the best space/time trade-offs using those heuristics. Invariant: Port (/geometry) decoration=NIL <=> no pins (/no geometry). Non-NIL port (/geometry) decoration have at least one atomic child. Therefore when we create a clipped enumeration, we must make sure it's non-empty. Creating Decoration Ports We avoid duplicates Object Geometry We came from that one from a RecordCell [vertical move] Enumerates next level instances. Transformation Enumeration of Sides for Routers bbox is the rectangle expressing the AbutBox of the pin in the outer coordinate system. Fabrication of Shells for Routers or for IO Font used for the text labels Checking of Decorations Neighbors Initialization Κ˜codešœ™KšœH™HKšœ6Οk™9Kšœ+™+Kšœ$™'Kšœ/™2—K™š ˜ Kšœ˜K˜ J˜=Kšœ)˜)K˜KšœB˜BKšœ˜K˜—šΟn œœ˜KšœΆ˜½Kšœ ˜Kšœœœ ˜—head™ Kšœ œ˜ Kšœ œ˜$Kšœœœ˜Kšœœ ˜Kšœœ˜.Kšœ œ˜#Kšœ œ˜)Kšœœ˜+Kšœœ˜1Kšœ œ˜#Kšœœ˜+Kšœœ˜Kšœ œ˜Kšœœ˜/Kšœ œ˜%—™bodyšœ΄œΦ™ŒMšœ*™*Iitem™ΗN™N™TN™ΒMšœ1™1N™N™™kM™—Mšž œœ"œŽ™έ——šœ™Kšœœ)œ˜GKšœœ,œ˜Nšœœ,œ˜MK˜—šžœœœœ œœœ˜gšœ œ˜#Kšœ ˜ šœ*˜*Kšœ.˜.KšœN˜NKšœ˜—šœ,˜,Kšœ0˜0KšœN˜NKšœ˜—šœ.˜.Kšœ2˜2KšœN˜NKšœ˜—šœ+˜+Kšœ/˜/KšœN˜NKšœ˜—K˜—Kšœœ œœ˜KšœU˜UKšœS˜SKšœW˜WKšœR˜RK˜K˜—Kšžœ6œ ˜Všžœ=˜KK˜—KšžœAœ œ˜~Kšž œ!œD˜u—™š žœœœ(œœ˜NKšœ*˜0K˜K˜—šžœœœ(œ˜VKšœ?˜?Kšœœœ˜Kšœœœ˜#K˜K™—šžœœœ9˜MKšœœœœ˜Kšœœœ˜#Kšœ>˜>K˜K˜—šžœœœ9˜MKšœœœœ˜Kšœ+œ'˜VK˜K˜—šžœœœP˜kKšœ œœœ˜KšœG˜GK˜K˜—šœ œœ%˜=K˜—šžœœœC˜^Jšœ&œ˜;Jšœ6˜6šž œ˜%Jšœœ˜š œœœ œ,œœ˜aKšœœ|˜‡Jšœ˜—Jšœ0˜0J˜—šœœœ˜$Jšœ4˜4Jšœ;˜;šžœ˜&Jšœœœ œ'˜GJšœ™š œœœœœ˜˜‡Jšœ œ˜Jšœœœ˜Jšœ œ œ7˜VJšœ œ œ7˜VJšœ)œœ˜7Jšœ˜—J˜—JšœG˜GKšœR˜RJ˜J™—š žœœœLœœ˜ƒšž œ˜&KšžœB˜IKšœ*œœŸ ˜EJšœ;˜;Jšœ˜—Kšœ+˜+Kšœ;˜;Jšœ˜K˜—šœœœœ%˜TJ˜—š žœœœLœœ˜Jš œœœœœ˜Jšœœœœ˜šž œ˜"Kšœœœœ˜"Kšœœœœ˜"Kšœ-˜3K˜—šž œ˜ Kšœœœœ)˜@J˜—Kšœ;˜;Kšœœ Ÿ˜Eš œ œœœœœ˜AKšœœœœ˜*Kšœœœ˜šœ˜šœœœœœœœ œ˜IKšœœœœ˜,šœœœœ˜qJšœœ5œ˜Q—Jšœœ œ˜!Jšœ˜—Jšœ˜—Kšœ˜—šœœ˜Kšœœœœ˜)KšœN˜NKšœœœ˜Kšœ˜Kšœ˜—K˜K˜—šœœœœ˜GJ˜—š žœœœ\œœ˜•Jš œœœœœ˜Jšœœœœ˜Jšœ˜šž œ˜!Kšœœœœ˜ Kšœœœœ˜ Kšœ+˜1K˜—šž œ˜ Jš œœœœœ#˜QJ˜—Kšœ;˜;KšœœŸ˜Dšœœ˜Kšœœœœ˜%Kšœ@˜@Kšœœœ˜Kšœ˜Kšœ˜—K˜——šœ)™+šœ&˜&JšœM˜MJšœ˜J™J™—š ž œœœ=œœœ˜~Kšœœ˜Kšœ+˜+šžœ˜+Jšœœ2˜˜>JšœK˜KK˜——™š žœœœ.œœ˜_Kš ž œœœœœœ˜RKšœ%˜%Kšœ5˜5K˜K™—š ž œœœ,œœ˜\Kšœ#œ˜8Kš œœ$œœœ˜>šœœœ˜Kšœ%œ œœ˜B—K˜——™ šžœœœ:œ œœœœœœ˜ΕKšœ*˜*Kšœ*˜*Kšœ-˜-Kšœ-˜-Kšœœœœ˜ZKšœ`˜`Kšœm˜mšžœ˜"Kšœ)˜)Kšœ(œ6˜dJ˜—šžœ˜"Kšœ)˜)Kšœ+˜+šž œœ/œœ˜LKšœ&œœ ˜SK˜—Kšœ9˜9K˜—Kšœ0˜0Kšœ2˜2K˜K˜—Kšœ œœ:œ˜nšž œ˜#Kšœœœ˜%Kšœœœ˜%Kšœ ˜K˜—Kšžœœœœœœœœ˜OKšžœœœœœœœœ ˜Sšž œ˜!Kšœœœ˜#šœ˜šœœ˜šœœ˜Kšœœœ ˜