<> <> <> <> DIRECTORY CD, CDCells, CDOps, D2Orient, GC, GCPrivate, IPCTG, IPCoTab, IPTop, RefTab, RouteDiGraph, RTBasic, CoreRouteFlat; GCUtilImpl: CEDAR PROGRAM IMPORTS GC, CDCells, CDOps, GCPrivate, IPCoTab, IPCTG, IPTop, RefTab, RouteDiGraph, RTBasic EXPORTS GCPrivate = { nameProp: PUBLIC ATOM _ $GCName; FindTopologicalOrder: PUBLIC PROC [topology: IPTop.Ref] RETURNS [topologicalOrder: GCPrivate.TopologicalOrder _ RouteDiGraph.CreateGraph["TopologicalOrder"]] = { <> AddConstraint: PROC [from, to: GCPrivate.Channel] ~ { IF from.topoOrder = NIL THEN from.topoOrder _ RouteDiGraph.AddNewNode[topologicalOrder, from]; IF to.topoOrder = NIL THEN to.topoOrder _ RouteDiGraph.AddNewNode[topologicalOrder, to]; IF RouteDiGraph.PathExists[topologicalOrder, from.topoOrder, to.topoOrder] THEN -- RouteDiGraph.PathExists[topologicalOrder, to.topoOrder, from.topoOrder] -- BTP November 2, 1987 4:11:13 pm PST GC.Signal[callingError, "Improper channel topology; you must change schematic."] ELSE [] _ RouteDiGraph.AddNewArc[topologicalOrder, NIL, to.topoOrder, from.topoOrder]}; EachChannel: IPCTG.EachChannelAction ~ { llCh: IPCTG.Channel _ IPCTG.End[ch, neg].ch; urCh: IPCTG.Channel _ IPCTG.End[ch, pos].ch; IF ch # bottomCh AND ch # topCh THEN { AddConstraint[NARROW[ch.any], NARROW[llCh.any]]; AddConstraint[NARROW[ch.any], NARROW[urCh.any]]}}; bottomCh, topCh: IPCTG.Channel; bottomChannel, topChannel: GCPrivate.Channel; [bottomCh, , topCh, ] _ IPCTG.GetBoundingChannels[topology.ctg]; bottomChannel _ NARROW[bottomCh.any]; bottomChannel.lowerIntType _ bottomChannel.upperIntType _ inverted; topChannel _ NARROW[topCh.any]; topChannel.lowerIntType _ topChannel.upperIntType _ inverted; [] _ IPCTG.Channels[topology.ctg, EachChannel]}; EnumerateChannelsInTopologicalOrder: PUBLIC PROC [context: GC.Context, eachChannel: GCPrivate.EachChannelAction] RETURNS [quit: BOOLEAN _ FALSE] = { <> <<>> WrapProc: RouteDiGraph.EnumNodeProc ~ { quit _ eachChannel[context, NARROW[node.nodeInfo]]}; [] _ RouteDiGraph.EnumNodesInTopoOrder[NARROW[context.topologicalOrder], WrapProc]}; AssignCoordinates: PUBLIC PROC [context: GC.Context] = { <> SetInstancePosition: IPCoTab.EachComponentAction ~ { instance: CoreRouteFlat.Instance _ NARROW[co.any]; instance.position _ co.origin}; SetChannelPosition: IPCTG.EachChannelAction ~ { channel: GCPrivate.Channel _ NARROW[ch.any]; channel.position _ GCPrivate.LowerChannelPosition[channel]; -- modify bounding channels because of a bug in Phoenix -- remove this SELECT TRUE FROM when bug is fixed -- SELECT TRUE FROM -- channel.ch = bottomChannel => channel.position.y _ channel.position.y - channel.width/2; -- channel.ch = leftChannel => channel.position.x _ channel.position.x - channel.width/2; -- ENDCASE; }; bottomChannel, rightChannel, topChannel, leftChannel: IPCTG.Channel; topology: IPTop.Ref _ NARROW[context.topology]; topology.initialized _ FALSE; [bottomChannel, rightChannel, topChannel, leftChannel] _ IPCTG.GetBoundingChannels[topology.ctg]; IPTop.Geometrize[topology, 0, 0]; IPCoTab.AllComponents[topology.coTab, SetInstancePosition]; [] _ IPCTG.Channels[topology.ctg, SetChannelPosition]}; CDOrien: PUBLIC PROCEDURE[num: INT] RETURNS [orien: CD.Orientation] = { <> SELECT num FROM 0 => orien _ original; 1 => orien _ original; 2 => orien _ rotate270; 3 => orien _ rotate180; 4 => orien _ rotate90; 5 => orien _ mirrorX; 6 => orien _ rotate180X; 7 => orien _ rotate270X; 8 => orien _ rotate90X; ENDCASE}; LowerChannelPQ: PUBLIC PROCEDURE[channel: GCPrivate.Channel] RETURNS [pq: RTBasic.PQPos] ~ { <> endCh: GCPrivate.Channel _ NARROW[IPCTG.End[channel.ch, neg].ch.any]; p: INT _ IF channel.lowerIntType = normal THEN ChannelLimits[endCh].upper ELSE ChannelLimits[endCh].lower; q: INT _ ChannelLimits[channel].lower; RETURN[[p, q]]}; UpperChannelPQ: PUBLIC PROCEDURE[channel: GCPrivate.Channel] RETURNS [pq: RTBasic.PQPos] ~ { <> endCh: GCPrivate.Channel _ NARROW[IPCTG.End[channel.ch, pos].ch.any]; p: INT _ IF channel.upperIntType = normal THEN ChannelLimits[endCh].lower ELSE ChannelLimits[endCh].upper; q: INT _ ChannelLimits[channel].upper; RETURN[[p, q]]}; ChannelLimits: PUBLIC PROCEDURE[channel: GCPrivate.Channel] RETURNS [lower, upper: INT] ~ { <> DoPosWidths: IPCTG.EachComponentAction ~ { upper _ MIN[upper, IF channel.ch.type = hor THEN co.origin.y ELSE co.origin.x]}; DoNegWidths: IPCTG.EachComponentAction ~ { lower _ MAX[lower, IF channel.ch.type = hor THEN co.origin.y + IPCoTab.GetDim[co].y ELSE co.origin.x + IPCoTab.GetDim[co].x]}; IF IPCTG.NoComponent[channel.ch, neg] THEN lower _ channel.ch.coord - channel.ch.width/2 ELSE { lower _ FIRST[INT]; [] _ IPCTG.Components[channel.ch, neg, DoNegWidths]}; IF IPCTG.NoComponent[channel.ch, pos] THEN upper _ channel.ch.coord + channel.ch.width/2 ELSE { upper _ LAST[INT]; [] _ IPCTG.Components[channel.ch, pos, DoPosWidths]}}; CreateChannels: PUBLIC PROC [context: GC.Context] ~ { <> CreateChannel: IPCTG.EachChannelAction ~ { channel: GCPrivate.Channel _ NEW[GCPrivate.ChannelRec _ [name: IPCTG.GetName[ch], connections: RefTab.Create[], width: IPCTG.GetWidth[ch], position: [0, 0], direction: IF ch.type = hor THEN horizontal ELSE vertical, ch: ch]]; ch.any _ channel}; topology: IPTop.Ref _ NARROW[context.topology]; [] _ IPCTG.Channels[topology.ctg, CreateChannel]}; DestroyChannels: PUBLIC PROC [context: GC.Context] ~ { <> DestroyChannel: IPCTG.EachChannelAction ~ { IF ch.any # NIL THEN { oldChannel: GCPrivate.Channel _ NARROW[ch.any]; oldChannel.ch _ NIL}; -- remove circular REF }; topology: IPTop.Ref _ NARROW[context.topology]; [] _ IPCTG.Channels[topology.ctg, DestroyChannel]}; PinOnList: PUBLIC PROC [netDesc: GCPrivate.NetDesc, phyPin: GCPrivate.PhyPinDesc] RETURNS [onList: BOOLEAN _ FALSE] ~ { <> IF netDesc # NIL THEN FOR list: LIST OF GCPrivate.PhyPinDesc _ netDesc.pinList, list.rest WHILE list # NIL AND ~onList DO IF list.first.instance = phyPin.instance AND list.first.oPin = phyPin.oPin AND list.first.pPin = phyPin.pPin THEN onList _ TRUE ENDLOOP}; -- [] _ CDProperties.RegisterProperty[GCPrivate.nameProp, NIL]; gets double registration IntersectionOnList: PUBLIC PROC [netDesc: GCPrivate.NetDesc, int: GCPrivate.IntersectionPinDesc] RETURNS [onList: BOOLEAN _ FALSE] ~ { <> IF netDesc # NIL THEN FOR list: LIST OF GCPrivate.IntersectionPinDesc _ netDesc.intersectionList, list.rest WHILE list # NIL AND ~onList DO IF list.first.channel = int.channel THEN onList _ TRUE ENDLOOP}; IncludeOb: PUBLIC PROC [cell: CD.Object, ob: CD.Object, position: CD.Position_[0, 0], orientation: D2Orient.Orientation_original] RETURNS [application: CD.Instance _ NIL] = { <> trans: CD.Transformation _ CDOps.FitObjectI[ob: ob, location:position, orientation: orientation]; application _ CDCells.IncludeOb[design: NIL, cell: cell, ob: ob, trans: trans].newInst}; }.