DIRECTORY CD, CDCells, CDOps, D2Orient, GC, GCPrivate, HashTable, IPCTG, IPCoTab, IPTop, RouteDiGraph, RTBasic, RTStructure; GCUtilImpl: CEDAR PROGRAM IMPORTS GC, CDCells, CDOps, GCPrivate, HashTable, IPCoTab, IPCTG, IPTop, 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, to.topoOrder, from.topoOrder] THEN 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: RTStructure.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: HashTable.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 IncludeOb: PUBLIC PROC [cell: CD.Object, ob: CD.Object, position: CD.Position_[0, 0], orientation: D2Orient.Orientation_original] RETURNS [application: CD.Instance] = { trans: CD.Transformation _ CDOps.FitObjectI[ob: ob, location:position, orientation: orientation]; application _ CDCells.IncludeOb[design: NIL, cell: cell, ob: ob, trans: trans, mode: dontResize].newInst}; }. lGCUtilImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bryan Preas, January 15, 1987 11:46:23 am PST Determine order in which to route channels. Enumerate routing channels in route order. Assign locations to all channels and components. get the CD orientation find position of a channel in PQ space find upper right position of a channel in PQ space find limits of width of a channel create channels for the context destroy channels for the context onList _ TRUE iff phyPin is on the global routing list for net include an object in a cell; position refers to base of interest rect Κ8– "cedar" style˜šœ™Jšœ Οmœ1™žœžœ˜pKšœE™EK˜KšœžœX˜aKšœ(žœ?˜j—J˜Jšœ˜—J˜J˜J˜J˜—…—Ϊ"~