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] = { ports: Objects _ NIL; IF port=NIL THEN ERROR; IF port#Pipal.void THEN ports _ LIST [port]; port _ GetPort[decoration, public]; IF port#Pipal.void THEN ports _ CONS [port, ports]; PutPort[decoration, public, Pipal.CreateOv[ports]]; }; 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] = { geometries: Objects _ NIL; IF geometry=NIL THEN ERROR; IF geometry#Pipal.void THEN geometries _ LIST [geometry]; geometry _ GetGeometry[decoration, wire]; IF geometry#Pipal.void THEN geometries _ CONS [geometry, geometries]; PutGeometry[decoration, wire, Pipal.CreateOv[geometries]]; }; 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 0:30:38 am 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 Êg��˜�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šœœœœ˜Kšœœ œ˜,Kšœ#˜#Kšœœ œ˜3Kšœ3˜3K˜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šœœ˜(Jšœ+˜+Jšœ˜—Jš œœ*œœÏc'˜cšœKœ˜RJšœV˜V—Jšœ˜—Jšœ6˜6K˜——™š ž œœœ.œœ˜VJšœ"œ˜-Kšœ˜K˜�—šž œœœ.œ˜`Kšœ œC˜RKšœ˜K˜�—šž œœœA˜WKšœH˜HK˜——™š žœœœ&œœ˜PKšœ,˜2K˜K™�—šžœœœ&œ˜\KšœE˜EKšœœœ˜"Kšœ œœ˜+K˜K™�—šžœœœ;˜SKšœ œœœ˜Kšœœœ˜+KšœD˜DK˜K˜�—šžœœœ;˜SKšœœ˜Kšœ œœœ˜Kšœœœ˜9Kšœ)˜)Kšœœœ˜EKšœ:˜:K˜K˜�—šÐbnœœœœ#œœœœ˜ýKšœ7™7šžœ ˜.Jšœ7˜7Jšœ œœ˜-JšœB˜BJšœ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šœ)œ ˜<Kšœ2˜2š œœœœ˜2šžœ˜3K™ šœœ˜Kšœ|˜|—K˜—Kšœ7˜7Kšœr˜rKšœ„˜„Kš˜—Kšœ˜—šœ"˜"Kšœ2˜2—šœ˜Kšœ0˜0Kšœ_˜_KšœLœE˜—K˜——K˜K˜�—šžœœœ6œ˜oKšœœ˜šžœ˜$Kšœœ:˜FK˜—Kšœ@˜@Kšœ!˜!K˜——™š žœœœ6œœ˜]KšœIœ˜TKšœ˜K™�—šžœœœ6œ˜nKšœ œœJ˜oKšœ˜Kšœ˜K˜�—šžœœœP˜eKšœGœ˜eK˜——™ šœ,˜,J˜�—šžœœœ˜=Jšœ/˜/J˜J˜�—šžœœœAœ˜yJšœY˜YJ˜J˜�—JšœW™Wšž œœœ˜OJšœ&˜&JšœH˜HJšœW˜WJšœP˜PJšœN˜NJšœY˜YJ˜J˜�—š žœœœPœœ˜ƒšžœ%˜1Jšœ)˜)Jšœœ*œœ˜<šœœœ˜JšœIŸ>˜‡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˜<Kšœ*œœŸ˜Ešœ œ˜JšœH˜HJšœ ˜ —šœœ˜šžœ˜šœ˜šœœ˜Kšœ1˜1Kšœ1˜1Kšœœ˜—šœœ˜Kšœ2œ˜B—Kšœ˜—Kšœ œ2˜@J˜—Jšœ/˜/Jšœ@˜@J˜—J˜—KšœG˜GKšœ$˜$Jšœ>˜>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šœœœ ˜<Kšœœ$˜1Kšœ˜—Kšœ˜K˜—Kšœ˜—K˜—šžœœœœ˜DKšœ6˜6K˜—šžœœœ:œ)œ œœœ˜·š žœœœœœ˜Dšœœœœœ˜?Kšœœœ˜)Kšœ˜—Kšœœ˜%K˜—Kšœœœ4˜MKšœœ˜-Kšœœœœ˜JšœD˜DKšœ$˜$K˜——™šœ,˜,K˜�——Kšœ˜—�…—����Of��m×��