GCUtilImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bryan Preas, January 15, 1987 11:46:23 am PST
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"]] = {
Determine order in which to route channels.
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: BOOLEANFALSE] = {
Enumerate routing channels in route order.
WrapProc: RouteDiGraph.EnumNodeProc ~ {
quit ← eachChannel[context, NARROW[node.nodeInfo]]};
[] ← RouteDiGraph.EnumNodesInTopoOrder[NARROW[context.topologicalOrder], WrapProc];
};
AssignCoordinates: PUBLIC PROC [context: GC.Context] = {
Assign locations to all channels and components.
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] = {
get the 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] ~ {
find position of a channel in PQ space
endCh: GCPrivate.Channel ← NARROW[IPCTG.End[channel.ch, neg].ch.any];
p: INTIF 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] ~ {
find upper right position of a channel in PQ space
endCh: GCPrivate.Channel ← NARROW[IPCTG.End[channel.ch, pos].ch.any];
p: INTIF 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] ~ {
find limits of width of a channel
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] ~ {
create channels for the 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] ~ {
destroy channels for the 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: BOOLEANFALSE] ~ {
onList ← TRUE iff phyPin is on the global routing list for net
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] = {
include an object in a cell; position refers to base of interest rect
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};
}.