DIRECTORY Basics, BasicTime, CedarProcess, IO, List, MessageWindow, Pipal, PipalConnect, PipalInstanceTable, PipalInt, PipalMos, Process, RefTab, TerminalIO; PipalConnectImpl: CEDAR PROGRAM IMPORTS Basics, BasicTime, CedarProcess, IO, List, MessageWindow, Pipal, PipalInstanceTable, PipalInt, PipalMos, Process, RefTab, TerminalIO EXPORTS PipalConnect ~ BEGIN OPEN PipalConnect; ROPE: TYPE = Pipal.ROPE; Object: TYPE = Pipal.Object; Objects: TYPE = Pipal.Objects; Transformation: TYPE = PipalInt.Transformation; Rectangle: TYPE = PipalInt.Rectangle; GetType: PUBLIC GetTypeProc = { refProc: REF GetTypeProc _ NARROW [Pipal.ObjectMethod[object, mode.getTypeMethod]]; type _ (IF refProc=NIL THEN EnumerationType ELSE refProc^)[object, mode]; }; EnumerationType: PUBLIC GetTypeProc = { nbChildren: NAT _ PipalInt.CountChildren[object]; EachChild: PipalInt.EachChildProc = {type _ GetType[child, mode]}; IF nbChildren=0 THEN RETURN [null]; IF nbChildren#1 THEN RETURN [composite]; [] _ PipalInt.Enumerate[object, EachChild]; }; NullType: PUBLIC GetTypeProc = {type _ null}; LeafType: PUBLIC GetTypeProc = {type _ leaf}; CompositeType: PUBLIC GetTypeProc = {type _ composite}; EnumeratePorts: PUBLIC EnumeratePortsProc = { refProc: REF EnumeratePortsProc _ NARROW [Pipal.ObjectMethod[object, mode.enumeratePortsMethod]]; IF GetType[object, mode]=null THEN SIGNAL CallerBug[]; quit _ (IF refProc=NIL THEN EnumerationEnumeratePorts ELSE refProc^)[object, mode, privateArea, eachPort, transformation]; }; CountPorts: PUBLIC PROC [object: Pipal.Object, mode: Mode, privateArea: PipalInt.Rectangle] RETURNS [count: NAT _ 0] = { EachPort: EachPortProc = { IF port=Pipal.void THEN SIGNAL InternalBug[]; count _ count + 1; }; [] _ EnumeratePorts[object, mode, privateArea, EachPort]; }; EnumerationEnumeratePorts: PUBLIC EnumeratePortsProc = { singleChild: Object _ NIL; trans: Transformation; EachChild: PipalInt.EachChildProc = {singleChild _ child; trans _ transformation}; IF PipalInt.CountChildren[object]#1 THEN SIGNAL CallerBug[]; [] _ PipalInt.Enumerate[object, EachChild, transformation]; quit _ EnumeratePorts[singleChild, mode, privateArea, eachPort, trans]; }; ComposerEnumeratePorts: PUBLIC EnumeratePortsProc = { cc: Composer _ GetComposer[object, mode, privateArea]; FOR i: NAT IN [0 .. cc.ports.size) DO quit _ eachPort[transformation, i, cc.ports[i]]; IF quit THEN RETURN; ENDLOOP; }; AtomicEnumeratePorts: PUBLIC EnumeratePortsProc = { quit _ eachPort[transformation, 0, object]; }; BiAtomicEnumeratePorts: PUBLIC EnumeratePortsProc = { EachRectLayer: PipalMos.EachRectangleLayerProc = { box: Object _ PipalInt.TransformObject[[rect.base], PipalMos.CreateBox[rect.size, layer]]; IF PipalMos.IsWellLayer[layer] THEN well _ CONS [box, well] ELSE nonWell _ CONS [box, nonWell]; }; nonWell: Pipal.Objects _ NIL; well: Pipal.Objects _ NIL; [] _ PipalMos.EnumerateRectangleLayers[object: object, each: EachRectLayer]; IF well=NIL OR nonWell=NIL THEN SIGNAL InternalBug[]; quit _ eachPort[transformation, 0, Pipal.CreateOv[nonWell]] OR eachPort[transformation, 1, Pipal.CreateOv[well]]; }; TNode: TYPE = REF TNodeRec; -- T stands for temporary TNodeRec: TYPE = RECORD [ edgeObjects: Objects _ NIL, bindings: LIST OF Binding _ NIL ]; CreateTNode: PROC [fused: RefTab.Ref] RETURNS [tNode: TNode] = { tNode _ NEW [TNodeRec]; [] _ RefTab.Store[fused, tNode, NIL]; }; RootTNode: PROC [fused: RefTab.Ref, tNode: TNode] RETURNS [rootTNode: TNode] = { IF tNode=NIL THEN SIGNAL InternalBug[]; rootTNode _ NARROW [RefTab.Fetch[fused, tNode].val]; IF rootTNode=NIL THEN RETURN [tNode]; IF rootTNode=tNode THEN SIGNAL InternalBug[]; rootTNode _ RootTNode[fused, rootTNode]; [] _ RefTab.Replace[fused, tNode, rootTNode]; }; FuseTNodes: PROC [fused: RefTab.Ref, loser, winner: TNode] RETURNS [TNode] = { loser _ RootTNode[fused, loser]; winner _ RootTNode[fused, winner]; IF loser=winner THEN RETURN [winner]; [] _ RefTab.Store[fused, loser, winner]; FOR list: Objects _ loser.edgeObjects, list.rest WHILE list#NIL DO winner.edgeObjects _ CONS [list.first, winner.edgeObjects]; ENDLOOP; FOR list: LIST OF Binding _ loser.bindings, list.rest WHILE list#NIL DO winner.bindings _ CONS [list.first, winner.bindings]; ENDLOOP; RETURN [winner]; }; EnumerateTNodes: PROC [fused: RefTab.Ref, each: PROC [TNode]] = { EachPair: RefTab.EachPairAction = {IF val=NIL THEN each[NARROW [key]]}; [] _ RefTab.Pairs[fused, EachPair]; }; TTNode: TYPE = REF TTNodeRec; TTNodeRec: TYPE = RECORD [edgeObjects: Objects, bindings: LIST OF REF]; CompareBinding: List.CompareProc = { rb1: REF Binding = NARROW [ref1]; rb2: REF Binding = NARROW [ref2]; RETURN [IF rb1.childIndex=rb2.childIndex THEN Basics.CompareInt[rb1.nodeIndex, rb2.nodeIndex] ELSE Basics.CompareInt[rb1.childIndex, rb2.childIndex]]; }; CompareTTNodes: List.CompareProc = { comparison: Basics.Comparison _ equal; ttn1: TTNode = NARROW [ref1]; ttn2: TTNode = NARROW [ref2]; bindings1: LIST OF REF _ ttn1.bindings; bindings2: LIST OF REF _ ttn2.bindings; WHILE comparison=equal DO IF bindings1=NIL THEN RETURN [less]; IF bindings2=NIL THEN RETURN [greater]; comparison _ CompareBinding[bindings1.first, bindings2.first]; bindings1 _ bindings1.rest; bindings2 _ bindings2.rest; ENDLOOP; RETURN [comparison]; }; CreateNode: PROC [ttNode: TTNode] RETURNS [node: Node] = { bindings: LIST OF REF _ ttNode.bindings; size: NAT _ List.Length[bindings]; node _ NEW [NodeRec[size]]; FOR i: NAT IN [0 .. size) DO node[i] _ NARROW [bindings.first, REF Binding]^; bindings _ bindings.rest; ENDLOOP; IF bindings#NIL THEN SIGNAL InternalBug[]; }; MakeComposer: PROC [fused: RefTab.Ref, object: Object, privateArea: Rectangle] RETURNS [cc: Composer] = { portsSize, nodesSize, index: NAT _ 0; ttNodes: LIST OF REF _ NIL; CountNodes: PROC [tNode: TNode] = { lora: LIST OF REF _ NIL; ttNode: TTNode _ NEW [TTNodeRec]; nodesSize _ nodesSize + 1; IF tNode.edgeObjects#NIL THEN portsSize _ portsSize + 1; FOR bb: LIST OF Binding _ tNode.bindings, bb.rest WHILE bb#NIL DO lora _ CONS [NEW [Binding _ bb.first], lora]; ENDLOOP; ttNode.edgeObjects _ tNode.edgeObjects; ttNode.bindings _ List.Sort[lora, CompareBinding]; ttNodes _ CONS [ttNode, ttNodes]; }; EnumerateTNodes[fused, CountNodes]; cc _ NEW [ComposerRec[nodesSize]]; cc.object _ object; cc.ports _ NEW [PortsSequence[portsSize]]; ttNodes _ List.Sort[ttNodes, CompareTTNodes]; FOR list: LIST OF REF _ ttNodes, list.rest WHILE list#NIL DO ttNode: TTNode _ NARROW [list.first]; IF ttNode.edgeObjects=NIL THEN LOOP; -- we first only deal with publics cc[index] _ CreateNode[ttNode]; cc.ports[index] _ PipalMos.CreateClipEnum[privateArea, Pipal.CreateOv[ttNode.edgeObjects]]; index _ index+1; ENDLOOP; IF index#portsSize THEN SIGNAL InternalBug[]; FOR list: LIST OF REF _ ttNodes, list.rest WHILE list#NIL DO ttNode: TTNode _ NARROW [list.first]; IF ttNode.edgeObjects#NIL THEN LOOP; -- we now only deal with the internal only cc[index] _ CreateNode[ttNode]; index _ index+1; ENDLOOP; IF index#nodesSize THEN SIGNAL InternalBug[]; }; DefaultObjectLayer: PUBLIC PROC [Object] RETURNS [LayerRange] = {RETURN [[0, 0]]}; LayeredTable: TYPE = REF LayeredTableRec; LayeredTableRec: TYPE = RECORD [ objectLayer: PROC [Pipal.Object] RETURNS [LayerRange], rects: SEQUENCE nbOfLayers: NAT OF PipalInstanceTable.Table -- Association (per layer) [fusion geometry -> tNode]. TNode may or may not be a root. ]; LayeredTableCreate: PROC [object: Object, nbOfLayers: NAT, objectLayer: PROC [Pipal.Object] RETURNS [LayerRange]] RETURNS [table: LayeredTable] = { bbox: Rectangle _ PipalInt.BBox[object, []]; table _ NEW [LayeredTableRec[nbOfLayers]]; FOR i: NAT IN [0 .. nbOfLayers) DO table[i] _ PipalInstanceTable.Create[bbox] ENDLOOP; table.objectLayer _ IF objectLayer=NIL THEN DefaultObjectLayer ELSE objectLayer; }; LayeredTableInsert: PROC [table: LayeredTable, transformation: Transformation, geometry: Object, tNode: TNode] = { layers: LayerRange _ table.objectLayer[geometry]; FOR i: NAT IN [layers.min .. layers.max] DO PipalInstanceTable.Insert[table[i], transformation, geometry, tNode]; ENDLOOP; }; LayeredTableErase: PROC [table: LayeredTable] = { FOR i: NAT IN [0 .. table.nbOfLayers) DO PipalInstanceTable.DeleteOutside[table[i], PipalInt.emptyRectangle]; ENDLOOP; }; FusionData: TYPE = REF FusionDataRec; FusionDataRec: TYPE = RECORD [ mode: Mode, -- to avoid passing it around privateArea: Rectangle, -- Rectangles for which geometry that is strictly inside (edge excluded) is not promoted public fused: RefTab.Ref, -- Association [fused -> root] [TNode -> TNode]. If root=NIL, then this tNode is a root. Basically all the wires ever created belong to this table. rects: LayeredTable -- Association (per layer) [fusion geometry -> tNode]. TNode may or may not be a root. ]; rect: PROC [r: Rectangle] RETURNS [IO.Value] = { RETURN [IO.rope[PipalInt.RectangleToRope[r]]]; }; IsGeometryAtEdge: PROC [privateArea: Rectangle, transformation: Transformation, geometry: Object] RETURNS [BOOL] = { IsAtEdge: PipalInt.EachChildProc = {quit _ PipalInt.AtEdge[privateArea, transformation, child]}; RETURN [PipalMos.EnumerateAtomic[geometry, IsAtEdge, transformation]]; }; InsertGeometry: PROC [fusionData: FusionData, transformation: Transformation, geometry: Object, tNode: TNode, binding: Binding] = { IF ~RefTab.Fetch[fusionData.fused, tNode].found THEN SIGNAL InternalBug[]; IF RootTNode[fusionData.fused, tNode]#tNode THEN SIGNAL InternalBug[]; IF geometry=Pipal.void THEN SIGNAL InternalBug[]; LayeredTableInsert[fusionData.rects, transformation, geometry, tNode]; IF IsGeometryAtEdge[fusionData.privateArea, transformation, geometry] THEN tNode.edgeObjects _ CONS [PipalInt.TransformObject[transformation, geometry], tNode.edgeObjects]; tNode.bindings _ CONS [binding, tNode.bindings]; }; FusionGeometry: PROC [fusionData: FusionData, transformation: Transformation, geometry: Object, binding: Binding] RETURNS [tNode: TNode _ NIL] = { layers: LayerRange _ fusionData.rects.objectLayer[geometry]; rect: Rectangle _ PipalInt.BBox[geometry, transformation]; FindTouchingWires: PROC [trans: PipalInt.Transformation, geom: Pipal.Object, value: PipalInstanceTable.Value] = { thisTNode: TNode _ RootTNode[fusionData.fused, NARROW [value]]; IF ~RefTab.Fetch[fusionData.fused, thisTNode].found THEN SIGNAL InternalBug[]; IF thisTNode=tNode THEN RETURN; IF NOT fusionData.mode.touch[fusionData.mode.touch, trans, geom, transformation, geometry] THEN RETURN; IF tNode=NIL THEN tNode _ thisTNode ELSE tNode _ FuseTNodes[fusionData.fused, thisTNode, tNode]; }; FOR i: NAT IN [layers.min .. layers.max] DO PipalInstanceTable.Enumerate[fusionData.rects[i], FindTouchingWires, rect]; ENDLOOP; IF tNode=NIL THEN tNode _ CreateTNode[fusionData.fused]; InsertGeometry[fusionData, transformation, geometry, tNode, binding]; }; debugCache: BOOL _ FALSE; composerCache: Pipal.ObjectCache _ Pipal.CreateObjectCache[]; CacheData: TYPE = RECORD [ mode: Mode, privateArea: PipalInt.Rectangle, cc: Composer ]; SearchCache: PROC [object: Object, mode: Mode, privateArea: PipalInt.Rectangle] RETURNS [cc: Composer _ NIL] = { IF debugCache THEN RETURN; FOR list: LIST OF CacheData _ NARROW [RefTab.Fetch[composerCache, object].val], list.rest WHILE list#NIL DO IF list.first.mode=mode AND list.first.privateArea=privateArea THEN RETURN [list.first.cc]; ENDLOOP; }; AddInCache: PROC [object: Object, mode: Mode, privateArea: PipalInt.Rectangle, cc: Composer] = { cache: LIST OF CacheData _ NARROW [RefTab.Fetch[composerCache, object].val]; cache _ CONS [[mode: mode, privateArea: privateArea, cc: cc], cache]; [] _ RefTab.Store[composerCache, object, cache]; }; GetComposer: PUBLIC GetComposerProc = { priority: CedarProcess.Priority _ CedarProcess.GetPriority[]; refProc: REF GetComposerProc _ NARROW [Pipal.ObjectMethod[object, mode.getComposerMethod]]; cc _ SearchCache[object, mode, privateArea]; IF cc#NIL THEN RETURN; CedarProcess.CheckAbort[]; CedarProcess.SetPriority[background]; Process.Yield[]; IF GetType[object, mode]#composite THEN SIGNAL CallerBug[]; cc _ (IF refProc=NIL THEN EnumerationComposer ELSE refProc^)[object, mode, privateArea]; AddInCache[object, mode, privateArea, cc]; CedarProcess.SetPriority[priority]; }; GetNodeGeometry: PROC [object: Pipal.Object, mode: Mode, node: Node] RETURNS [geometry: Object] = { index: NAT _ 0; objects: Objects _ NIL; bindingIndex: NAT _ 0; EachChild: PipalInt.EachChildProc = { SELECT GetType[child, mode] FROM null => {}; leaf, composite => { EachPort: EachPortProc = { IF port=Pipal.void THEN SIGNAL InternalBug[]; IF bindingIndex=node.size OR node[bindingIndex].childIndex>index THEN RETURN [TRUE]; -- unnecessary to continue! IF node[bindingIndex].childIndex SIGNAL InternalBug[]; index _ index + 1; }; IF NOT PipalInt.Enumerate[object, EachChild] AND bindingIndex#node.size THEN SIGNAL InternalBug[]; geometry _ Pipal.CreateOv[objects]; }; EnumerationComposer: PUBLIC GetComposerProc = { index: NAT _ 0; EachChild: PipalInt.EachChildProc = { SELECT GetType[child, mode] FROM null => {}; leaf, composite => { EachPort: EachPortProc = { IF port=Pipal.void THEN SIGNAL InternalBug[]; [] _ FusionGeometry[fusionData, transformation, port, [index, portIndex]]; }; [] _ EnumeratePorts[child, mode, PipalInt.AbutBox[child], EachPort, transformation]; }; ENDCASE => SIGNAL InternalBug[]; index _ index + 1; }; fusionData: FusionData _ NEW [FusionDataRec _ [ mode: mode, privateArea: privateArea, fused: RefTab.Create[3], rects: LayeredTableCreate[object, mode.nbOfLayers, mode.objectLayer] ]]; time: BasicTime.GMT = BasicTime.Now[]; PutF[ "Connectizeing [%g] cell (bbox: %g)\n", IO.rope[mode.name], rect[PipalInt.BBox[object, []]]]; [] _ PipalInt.Enumerate[object, EachChild]; cc _ MakeComposer[fusionData.fused, object, privateArea]; LayeredTableErase[fusionData.rects]; PutF["Connectizeed [%g] cell (%g instances, %g sec.)\n", IO.rope[mode.name], IO.int[index], IO.int[BasicTime.Period[time, BasicTime.Now[]]]]; }; AbutComposer: PUBLIC GetComposerProc = { abut: PipalInt.Abut _ NARROW [object]; fusionData: FusionData _ NEW [FusionDataRec _ [ mode: mode, privateArea: privateArea, fused: RefTab.Create[3], rects: LayeredTableCreate[object, mode.nbOfLayers, mode.objectLayer] ]]; nextRects: LayeredTable _ LayeredTableCreate[object, mode.nbOfLayers, mode.objectLayer]; index: NAT _ 0; time: BasicTime.GMT = BasicTime.Now[]; EachChild: PipalInt.EachChildProc = { SELECT GetType[child, mode] FROM null => {}; leaf, composite => { EachPort: EachPortProc = { tNode: TNode _ FusionGeometry[fusionData, transformation, port, [index, portIndex]]; IF port=Pipal.void THEN SIGNAL InternalBug[]; LayeredTableInsert[nextRects, transformation, port, tNode]; }; [] _ EnumeratePorts[child, mode, PipalInt.AbutBox[child], EachPort, transformation]; FOR i: NAT IN [0 .. mode.nbOfLayers) DO table: PipalInstanceTable.Table _ fusionData.rects[i]; fusionData.rects[i] _ nextRects[i]; nextRects[i] _ table; PipalInstanceTable.DeleteOutside[table, PipalInt.emptyRectangle]; ENDLOOP; }; ENDCASE => SIGNAL InternalBug[]; index _ index + 1; }; PutF["Connectizeing [%g] abut (instances: %g)\n", IO.rope[mode.name], IO.int[abut.size]]; [] _ PipalInt.Enumerate[object, EachChild]; cc _ MakeComposer[fusionData.fused, object, privateArea]; LayeredTableErase[fusionData.rects]; LayeredTableErase[nextRects]; PutF["Connectizeed [%g] abut (%g instances, %g sec.)\n", IO.rope[mode.name], IO.int[index], IO.int[BasicTime.Period[time, BasicTime.Now[]]]]; }; RoutingComposer: PUBLIC GetComposerProc = { routing: PipalMos.Routing = NARROW [object]; bbox: Rectangle = PipalInt.BBox[routing, []]; PutF["Connectizeing [%g] routing (nodes: %g)\n", IO.rope[mode.name], IO.int[routing.size]]; FOR i: NAT IN [0 .. routing.size) DO IF PipalMos.ContainsWell[routing[i]] THEN RETURN GetComposer[object, mode, privateArea] ENDLOOP; cc _ NEW [ComposerRec[routing.size]]; cc.object _ object; cc.ports _ NEW [PortsSequence[routing.size]]; FOR i: NAT IN [0 .. routing.size) DO node: Node _ NEW [NodeRec[1]]; cc.ports[i] _ PipalMos.CreateClipEnum[bbox, routing[i]]; cc[i] _ node; node[0] _ [i, 0]; ENDLOOP; }; TileInstanceArray: TYPE = REF TileInstanceArrayRec; TileInstanceArrayRec: TYPE = RECORD [c: SEQUENCE sizeY: NAT OF TileInstanceLine]; TileInstanceLine: TYPE = REF TileInstanceLineRec; TileInstanceLineRec: TYPE = RECORD [c: SEQUENCE sizeX: NAT OF TileInstance]; TileInstance: TYPE = REF TileInstanceRec; TileInstanceRec: TYPE = RECORD [ trans: Transformation, obj: Object, tNodes: SEQUENCE size: NAT OF TNode -- each of these corresponds to the ports of obj! ]; FuseNeighbors: PROC [mode: Mode, fused: RefTab.Ref, inX: BOOL, ti1, ti2: TileInstance] = { EachPort2: EachPortProc = { index2: NAT _ portIndex; tt2: Transformation = transformation; port2: Object = port; EachPort1: EachPortProc = { IF port=Pipal.void THEN SIGNAL InternalBug[]; IF mode.touch[mode.touch, transformation, port, tt2, port2] THEN [] _ FuseTNodes[fused, ti1[portIndex], ti2[index2]]; }; IF port=Pipal.void THEN SIGNAL InternalBug[]; IF PipalInt.AtEdge[ab1, tt2, port2] THEN [] _ EnumeratePorts[ti1.obj, mode, ab1, EachPort1, trans1]; }; ab1: Rectangle _ PipalInt.AbutBox[ti1.obj]; ab2: Rectangle _ PipalInt.AbutBox[ti2.obj]; basicTransl: PipalInt.Vector = IF inX THEN [ab1.size.x, 0] ELSE [0, ab1.size.y]; trans: Transformation = [PipalInt.Add[basicTransl, PipalInt.Sub[ab1.base, ab2.base]]]; trans1: Transformation = ti1.trans; trans2: Transformation = PipalInt.Compose[trans, ti2.trans]; [] _ EnumeratePorts[ti2.obj, mode, ab2, EachPort2, trans2]; }; TilingComposer: PUBLIC GetComposerProc = { tiling: PipalMos.Tiling _ NARROW [object]; insideIR: Rectangle = PipalInt.Extend[privateArea, -1]; tileInstances: TileInstanceArray; fused: RefTab.Ref _ RefTab.Create[]; time: BasicTime.GMT = BasicTime.Now[]; index: NAT _ 0; ConnectizeEachTile: PipalMos.EachTileProc = { ab: Rectangle = PipalInt.AbutBox[tile]; trans: Transformation = [PipalInt.Sub[pos, ab.base]]; strictlyInside: BOOL _ PipalInt.IsInsideRectangle[insideIR, PipalInt.BBox[tile, trans]]; ti: TileInstance _ NEW [TileInstanceRec[CountPorts[tile, mode, ab]]]; EachPort: EachPortProc = { tNode: TNode _ CreateTNode[fused]; IF port=Pipal.void THEN SIGNAL InternalBug[]; ti[portIndex] _ tNode; IF NOT strictlyInside AND IsGeometryAtEdge[privateArea, transformation, port] THEN tNode.edgeObjects _ LIST [PipalInt.TransformObject[transformation, port]]; tNode.bindings _ LIST [[index, portIndex]]; }; IF GetType[tile, mode]=null THEN SIGNAL CallerBug[]; tileInstances[y][x] _ ti; ti.trans _ trans; ti.obj _ tile; [] _ EnumeratePorts[tile, mode, ab, EachPort, trans]; index _ index + 1; }; PutF["Connectizeing [%g] tiling (size: %g*%g)\n", IO.rope[mode.name], IO.int[tiling.sizeX], IO.int[tiling.sizeY]]; tileInstances _ NEW [TileInstanceArrayRec[tiling.sizeY]]; FOR y: NAT IN [0 .. tiling.sizeY) DO tileInstances[y] _ NEW [TileInstanceLineRec[tiling.sizeX]]; ENDLOOP; [] _ PipalMos.EnumerateTiles[tiling, ConnectizeEachTile]; FOR y: NAT IN [0 .. tiling.sizeY) DO FOR x: NAT IN [1 .. tiling.sizeX) DO FuseNeighbors[mode, fused, TRUE, tileInstances[y][x-1], tileInstances[y][x]]; ENDLOOP; ENDLOOP; FOR x: NAT IN [0 .. tiling.sizeX) DO FOR y: NAT IN [1 .. tiling.sizeY) DO FuseNeighbors[mode, fused, FALSE, tileInstances[y-1][x], tileInstances[y][x]]; ENDLOOP; ENDLOOP; IF index#tiling.sizeX*tiling.sizeY THEN SIGNAL InternalBug[]; cc _ MakeComposer[fused, object, privateArea]; PutF["Connectizeed [%g] tiling (%g sec.)\n", IO.rope[mode.name], IO.int[BasicTime.Period[time, BasicTime.Now[]]]]; }; InternalBug: PUBLIC SIGNAL [] = CODE; CallerBug: PUBLIC SIGNAL [] = CODE; OutputType: TYPE = {none, terminal, messageWindow}; outputFlag: OutputType _ terminal; PutF: PUBLIC PROC [format: ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]]] = { SELECT outputFlag FROM terminal => TerminalIO.PutF[format, v1, v2, v3, v4, v5]; messageWindow => MessageWindow.Append[IO.PutFR[format, v1, v2, v3, v4, v5], TRUE]; ENDCASE => {}; }; layoutMode: PUBLIC Mode _ NEW [ModeRec _ [ getTypeMethod: Pipal.RegisterMethod["LayoutGetType"], enumeratePortsMethod: Pipal.RegisterMethod["LayoutEnumeratePorts"], getComposerMethod: Pipal.RegisterMethod["LayoutGetComposer"], name: "Layout", touch: PipalMos.LayoutTouch, nbOfLayers: nbOfInterestingLayers, objectLayer: LayoutObjectLayer ]]; rawLayoutMode: PUBLIC Mode _ NEW [ModeRec _ [ getTypeMethod: Pipal.RegisterMethod["RawLayoutGetType"], -- maybe the same as layoutMode? enumeratePortsMethod: Pipal.RegisterMethod["RawLayoutEnumeratePorts"], -- maybe the same as layoutMode? getComposerMethod: Pipal.RegisterMethod["RawLayoutGetComposer"], name: "RawLayout", touch: PipalMos.LayoutTouch, nbOfLayers: nbOfInterestingLayers, objectLayer: LayoutObjectLayer ]]; nbOfInterestingLayers: NAT = 10; defaultLayerRange: LayerRange = [min: 0, max: nbOfInterestingLayers-1]; interestingLayers: RefTab.Ref _ RefTab.Create[]; Interestinglayers: PROC [layer: PipalMos.Layer] RETURNS [LayerRange] = { refLayerRange: REF LayerRange _ NARROW [RefTab.Fetch[interestingLayers, layer].val]; RETURN [IF refLayerRange=NIL THEN defaultLayerRange ELSE refLayerRange^]; }; SetInterestinglayers: PROC [layer: PipalMos.Layer, range: LayerRange] = { [] _ RefTab.Store[interestingLayers, layer, NEW [LayerRange _ range]]; }; LayoutObjectLayer: PROC [object: Pipal.Object] RETURNS [layerRange: LayerRange] = { EachChild: PipalInt.EachChildProc = { thisLayerRange: LayerRange _ WITH child SELECT FROM box: PipalMos.Box => Interestinglayers[box.layer], marker: PipalMos.Marker => Interestinglayers[marker.layer], text: PipalMos.Text => [nbOfInterestingLayers-1, 0], picture: PipalMos.Picture => [nbOfInterestingLayers-1, 0], ENDCASE => ERROR; layerRange _ [min: MIN [thisLayerRange.min, layerRange.min], max: MAX [thisLayerRange.max, layerRange.max]]; IF layerRange=defaultLayerRange THEN quit _ TRUE; }; layerRange _ [nbOfInterestingLayers-1, 0]; [] _ PipalMos.EnumerateAtomic[object, EachChild]; IF layerRange.min>layerRange.max THEN layerRange _ defaultLayerRange; }; SetLayout: PROC [class: Pipal.Class, type: GetTypeProc, ports: EnumeratePortsProc _ NIL, composer: GetComposerProc _ NIL] = { FOR modes: LIST OF Mode _ LIST [layoutMode, rawLayoutMode], modes.rest WHILE modes#NIL DO mode: Mode _ modes.first; Pipal.PutClassMethod[class, mode.getTypeMethod, NEW [GetTypeProc _ type]]; IF ports#NIL THEN Pipal.PutClassMethod[class, mode.enumeratePortsMethod, NEW [EnumeratePortsProc _ ports]]; IF composer#NIL THEN Pipal.PutClassMethod[class, mode.getComposerMethod, NEW [GetComposerProc _ composer]]; ENDLOOP; }; LayoutBoxType: PUBLIC GetTypeProc = { box: PipalMos.Box = NARROW [object]; type _ IF box.layer=PipalMos.errorLayer OR box.layer=PipalMos.commentLayer THEN null ELSE leaf; }; LayoutAnnotationType: GetTypeProc = { annotation: Pipal.Annotation = NARROW [object]; SELECT annotation.key FROM PipalMos.atomicProp => RETURN [leaf]; PipalMos.biAtomicProp => RETURN [leaf]; PipalMos.transistorProp => RETURN [leaf]; ENDCASE => RETURN [GetType[annotation.child, mode]]; }; LayoutAnnotationEnumeratePorts: EnumeratePortsProc = { annotation: Pipal.Annotation = NARROW [object]; proc: EnumeratePortsProc _ EnumeratePorts; child: Object _ annotation.child; SELECT annotation.key FROM PipalMos.atomicProp => proc _ AtomicEnumeratePorts; PipalMos.biAtomicProp => proc _ BiAtomicEnumeratePorts; PipalMos.transistorProp => {proc _ TransistorEnumeratePorts; child _ object}; PipalInt.abutBoxProp => privateArea _ NARROW [annotation.value, REF Rectangle]^; ENDCASE => {}; RETURN [proc[child, mode, privateArea, eachPort, transformation]]; }; TransistorEnumeratePorts: EnumeratePortsProc = { type: PipalMos.TransistorType; ch1, ch2, gate, bulk: Object; width, length: INT; [type, ch1, ch2, gate, bulk, width, length] _ PipalMos.ExtractTransistor[object]; quit _ eachPort[transformation, 0, gate] OR eachPort[transformation, 1, ch1] OR eachPort[transformation, 2, ch2] OR (bulk#Pipal.void AND eachPort[transformation, 3, bulk]); }; LayoutAnnotationComposer: PUBLIC GetComposerProc = { annotation: Pipal.Annotation = NARROW [object]; IF annotation.key=PipalInt.abutBoxProp THEN privateArea _ NARROW [annotation.value, REF Rectangle]^; RETURN [GetComposer[annotation.child, mode, privateArea]]; }; StarType: GetTypeProc = { star: PipalMos.Star = NARROW [object]; RETURN [GetType[star.master, mode]]; }; StarEnumeratePorts: EnumeratePortsProc = { star: PipalMos.Star = NARROW [object]; RETURN [EnumeratePorts[star.master, mode, PipalInt.AbutBox[star.master], eachPort, transformation]]; }; StarComposer: GetComposerProc = { star: PipalMos.Star = NARROW [object]; RETURN [GetComposer[star.master, mode, PipalInt.AbutBox[star.master]]]; }; schematicMode: PUBLIC Mode _ NEW [ModeRec _ [ getTypeMethod: Pipal.RegisterMethod["SchematicGetType"], enumeratePortsMethod: Pipal.RegisterMethod["SchematicEnumeratePorts"], getComposerMethod: Pipal.RegisterMethod["SchematicGetComposer"], name: "Schematic", touch: PipalMos.SchematicTouch ]]; SetSchematic: PROC [class: Pipal.Class, type: GetTypeProc, ports: EnumeratePortsProc _ NIL, composer: GetComposerProc _ NIL] = { Pipal.PutClassMethod[class, schematicMode.getTypeMethod, NEW [GetTypeProc _ type]]; IF ports#NIL THEN Pipal.PutClassMethod[class, schematicMode.enumeratePortsMethod, NEW [EnumeratePortsProc _ ports]]; IF composer#NIL THEN Pipal.PutClassMethod[class, schematicMode.getComposerMethod, NEW [GetComposerProc _ composer]]; }; SchematicBoxType: PUBLIC GetTypeProc = { box: PipalMos.Box = NARROW [object]; SELECT box.layer FROM PipalMos.blueCommentLayer => type _ null; PipalMos.commentLayer => type _ leaf; ENDCASE => SIGNAL CallerBug[]; }; SchematicAnnotationType: GetTypeProc = { annotation: Pipal.Annotation = NARROW [object]; SELECT annotation.key FROM PipalMos.atomicProp, PipalMos.biAtomicProp, PipalMos.transistorProp => SIGNAL CallerBug[]; ENDCASE => RETURN [GetType[annotation.child, mode]]; }; SchematicAnnotationEnumeratePorts: EnumeratePortsProc = { annotation: Pipal.Annotation = NARROW [object]; SELECT annotation.key FROM PipalMos.atomicProp, PipalMos.biAtomicProp, PipalMos.transistorProp => SIGNAL CallerBug[]; PipalInt.abutBoxProp => privateArea _ NARROW [annotation.value, REF Rectangle]^; ENDCASE => {}; RETURN [EnumeratePorts[annotation.child, mode, privateArea, eachPort, transformation]]; }; SchematicAnnotationComposer: PUBLIC GetComposerProc = { annotation: Pipal.Annotation = NARROW [object]; IF annotation.key=PipalInt.abutBoxProp THEN privateArea _ NARROW [annotation.value, REF Rectangle]^; RETURN [GetComposer[annotation.child, mode, privateArea]]; }; SetInterestinglayers[$Met2, [0, 0]]; SetInterestinglayers[$Met, [1, 1]]; SetInterestinglayers[$Pol, [2, 2]]; SetInterestinglayers[$Pdif, [3, 3]]; SetInterestinglayers[$Ndif, [4, 4]]; SetInterestinglayers[$Pwell, [5, 5]]; SetInterestinglayers[$Nwell, [6, 6]]; SetInterestinglayers[$Ovg, [0, 7]]; SetInterestinglayers[$PwellCont, [8, 8]]; SetInterestinglayers[$NwellCont, [9, 9]]; SetInterestinglayers[$Cut2, [0, 1]]; SetInterestinglayers[$Cut, [1, 4]]; SetLayout[PipalMos.textClass, NullType]; SetLayout[PipalMos.pictureClass, NullType]; SetLayout[PipalMos.boxClass, LayoutBoxType, AtomicEnumeratePorts]; SetLayout[PipalMos.markerClass, LeafType, AtomicEnumeratePorts]; SetLayout[Pipal.overlayClass, CompositeType, ComposerEnumeratePorts, EnumerationComposer]; SetLayout[PipalInt.abutClass, CompositeType, ComposerEnumeratePorts, AbutComposer]; SetLayout[PipalMos.routingClass, CompositeType, ComposerEnumeratePorts, RoutingComposer]; SetLayout[PipalMos.tilingClass, CompositeType, ComposerEnumeratePorts, TilingComposer]; SetLayout[Pipal.annotationClass, LayoutAnnotationType, LayoutAnnotationEnumeratePorts, LayoutAnnotationComposer]; SetLayout[PipalMos.starClass, StarType, StarEnumeratePorts, StarComposer]; SetSchematic[PipalMos.textClass, NullType]; SetSchematic[PipalMos.pictureClass, NullType]; SetSchematic[PipalMos.boxClass, SchematicBoxType, AtomicEnumeratePorts]; SetSchematic[PipalMos.markerClass, LeafType, AtomicEnumeratePorts]; SetSchematic[Pipal.overlayClass, CompositeType, ComposerEnumeratePorts, EnumerationComposer]; SetSchematic[PipalInt.abutClass, CompositeType, ComposerEnumeratePorts, AbutComposer]; SetSchematic[PipalMos.tilingClass, CompositeType, ComposerEnumeratePorts, TilingComposer]; SetSchematic[Pipal.annotationClass, SchematicAnnotationType, SchematicAnnotationEnumeratePorts, SchematicAnnotationComposer]; SetSchematic[PipalMos.starClass, StarType, StarEnumeratePorts, StarComposer]; END. ΦPipalConnectImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Created by Bertrand Serlet, March 18, 1988 5:38:12 pm PST Bertrand Serlet April 24, 1988 7:09:04 pm PDT Short Cuts Connector Type Ports Enumeration TNodes The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity bindings in a LORA for convenience, but denotes sorted list of bindings in order to enumerate ports in the same order, it is important to sort nodes. Multi-Layers InstanceTable Auxiliary Fusion functions binding indicates if this geometry is only going to be used for fusion and does not have to figure in the geometry and pins properties (real geometry versus geometry at the level below). If a pin is found we just note that this is a public tNode Connectize Maps object -> LIST OF CacheData Searches the cache. cc=NIL if not in cache We fill the cache unnecessary, but let's keep it for now. Bogus for AbutBoxAnnotation because the nodes number are the one of the child not the ones of the annotation. Overlay/Enumerate and Abut Connectizeion The main loop over "instances". Attention, we are assuming here that we are seing instances from left to right and bottom to top We check if none of the objects contains well, and expand if not We connectize sub objects We fuse neighbors Exceptions Progress Report Layout Methods Maps [layer -> REF LayerRange] For boxes which connector type is leaf, except when the layer is PipalMos.errorLayer or PipalMos.commentLayer, in which case it is null. Schematic Methods For boxes which connector type is leaf, except when the layer is PipalMos.errorLayer or PipalMos.commentLayer, in which case it is null. Layout Initialization Schematic Initialization Κ˜codešœ™Kšœ<™˜>Jšœ7˜7Jšœ˜—Jšœ˜Jšœ˜J˜—šž œœœ˜:Kšœ œœœ˜(Kšœœ˜"Jšœœ˜šœœœ ˜Kšœ œœ%˜JKšœ˜—Jšœ œœœ˜*J˜J˜—JšœM™Mšž œœ=œ˜iJšœœ˜%Jš œ œœœœ˜šž œœ˜#Kš œœœœœ˜Jšœœ ˜!Jšœ˜Jšœœœ˜8š œœœ#œœœ˜BKšœœœ˜-Kšœ˜—Jšœ'˜'Jšœ2˜2Jšœ œ˜!Jšœ˜—Jšœ#˜#Jšœœ/˜7Jšœ œ˜*Jšœ-˜-š œœœœœœ˜ -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN]šœ:˜:šžœœZ˜qJšœ/œ ˜?Jšœ2œœ˜NJšœœœ˜JšœœUœœ˜gJšœœœœ8˜`J˜—šœœœ˜+JšœK˜KJšœ˜—Jšœœœ'˜8JšœE˜EJ˜——™ Jšœ œœ˜šœ=˜=Jšœœœ ™ —šœ œœ˜Jšœ-˜-Jšœ ˜ Jšœ˜J˜—Jšœœ™+šž œœ?œœ˜pJšœ œœ˜š œœœ œ6œœ˜kšœœ$˜?Jšœœ˜—Jšœ˜—J˜J˜—J™šž œœP˜`Jšœœœ œ+˜LJšœœ9˜EJšœ0˜0J˜J˜—šž œœ˜'Jšœ=˜=Jšœ œœ6˜[Jšœ,˜,Jšœœœœ˜Jšœ˜Jšœ%˜%Jšœ˜Jšœ!œœ ˜;Jš œœ œœœ&˜XJšœ+˜+Jšœ#˜#J˜J˜—Kšœ˜™˜šžœœ0œ˜cJšœœ˜Jšœœ˜Jšœœ˜šž œ˜%šœ˜ Jšœ˜šœ˜šžœ˜Jšœœœ˜-Jš œœ%œœœŸ˜pJšœ%œœ˜AJšœ(œœ˜Dšœ(œ˜0Jšœ œ;˜IJšœ ˜ J˜—J˜—JšœVœ˜qJ˜—Jšœœ˜#—Jšœ˜J˜—Jš œœ'œœœ˜bKšœ#˜#K˜——™(šžœœ˜/Jšœœ˜šž œ˜%šœ˜ Jšœ˜šœ˜šžœ˜Kšœœœ˜.JšœJ˜JJ˜—JšœT˜TJ˜—Jšœœ˜#—Jšœ˜J˜—šœœ˜/Jšœ?˜?JšœD˜DJšœ˜—Jšœœ˜&šœ˜Jšœ(˜(Jšœ˜Jšœ!˜!—J˜+Jšœ9˜9Jšœ$˜$Jšœ9œœ œ/˜J˜J˜—šž œœ˜(Jšœœ ˜&šœœ˜/Jšœ?˜?JšœD˜DJšœ˜—JšœX˜XJšœœ˜Jšœœ˜&šž œ˜%šœ˜ Jšœ˜šœ˜šžœ˜JšœT˜TKšœœœ˜.Jšœ;˜;J˜—JšœT˜Tšœœœ˜'Jšœ6˜6Jšœ:˜:JšœA˜AJšœ˜—J˜—Jšœœ˜#—Jšœ˜J˜—Jšœ2œœ˜YJšœ™J˜+Jšœ9˜9Jšœ$˜$Jšœ˜Jšœ9œœ œ/˜Jšœ˜J˜—šžœœ˜+Kšœœ ˜,Jšœ-˜-Jšœ1œœ˜[Kšœ@™@šœœœ˜$Kšœ#œœ'˜WKšœ˜—Jšœœ˜%J˜Jšœ œ˜-šœœœ˜$Kšœ œ˜Kšœ8˜8Kšœ˜Kšœ˜—K˜K˜—Kšœœœ˜3Kš œœœœœœ˜QKšœœœ˜1Kš œœœœœœ˜LKšœœœ˜)šœœœ˜ Jšœ˜Jšœ ˜ JšœœœœŸ1˜U˜K˜——šž œœ&œ˜Zšž œ˜Kšœœ ˜Kšœ%˜%Kšœ˜šž œ˜Kšœœœ˜.šœ:˜œ˜tK˜K˜—šžœœ˜(KšœŠ™ŠJšœœ ˜$šœ ˜Jšœ+˜+Jšœ(˜(Jšœ œ ˜&—J˜K˜—šžœ˜(Jšœœ ˜/šœ˜JšœGœ ˜ZJšœœ#˜4—J˜J˜—šž!œ˜9Jšœœ ˜/šœ˜JšœGœ ˜ZJšœ&œœ ˜PJšœ ˜—JšœQ˜WJ˜J˜—šžœœ˜7Jšœœ ˜/Jšœ%œœœ ˜dJšœ4˜:J˜——šœ™Kšœ$˜$Kšœ#˜#Kšœ#˜#Kšœ$˜$Kšœ$˜$Kšœ%˜%Kšœ%˜%Kšœ#˜#Kšœ)˜)Kšœ)˜)Kšœ$˜$šœ#˜#K™—Kšœ(˜(šœ+˜+K˜—KšœB˜Bšœ@˜@K˜—KšœZ˜ZKšœS˜SKšœY˜YšœW˜WK˜—šœq˜qK˜—šœJ˜JK˜——šœ™Kšœ+˜+šœ.˜.K˜—KšœH˜HšœC˜CK˜—Kšœ]˜]KšœV˜VšœZ˜ZK˜—šœ}˜}K˜—šœM˜MK˜——Kšœ˜—…—q•z