<> <> <> <> <<>> 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]; IF nbChildren=0 THEN RETURN [null]; IF nbChildren#1 THEN RETURN [composite]; type _ GetType[PipalInt.NthChild[object].nthChild, mode]; }; 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 = { IF PipalInt.CountChildren[object]#1 THEN SIGNAL CallerBug[]; [transformation, object] _ PipalInt.NthChild[object, transformation]; quit _ EnumeratePorts[object, mode, privateArea, eachPort, transformation]; }; 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[]; < LIST OF CacheData>> 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[]; < REF LayerRange]>> <<>> 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.