file SCRoutePinsUtilImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bryan Preas, December 31, 1986 11:43:34 am PST
RoutePins utility routines
-- InitGetChanPins - initialize for determining the width of a channel
-- TermGetChanPins - terminate determining the width of a channel
-- NewWsEntry - get a new wire segment entry and insert pos, return location
-- EnterPin - enter a pin on a channel
-- EnterExit - enter exit data for a channel
-- EnterNetDat - minmium route channels need special processing to
include the minimun number of wire segments of minimum length
DIRECTORY
Basics,
CD,
Convert,
List,
Rope,
RouteChannel,
RoutePrivate,
RTBasic,
SC,
SCNetUtil,
SCPrivate,
SCRoutePinsUtil;
SCRoutePinsUtilImpl: CEDAR PROGRAM
IMPORTS Convert, List, Rope, RouteChannel, RTBasic, SC, SCNetUtil
EXPORTS SCRoutePinsUtil
SHARES SC =
BEGIN
last: INTLAST[INT];
initialize for determining the width of a channel
InitGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle] = {
InitNet: SCNetUtil.EachNetProc = {
net.netDat ← NIL};
[] ← SCNetUtil.EnumerateNets[handle, InitNet]};
terminate determining the width of a channel
TermGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle] = {
TermNet: SCNetUtil.EachNetProc = {
netDat: SCRoutePinsUtil.NetDat ← NARROW[net.netDat];
IF netDat # NIL THEN {
netDat.exits ← ALL[NIL];
netDat.chanPins ← ALL[NIL];
net.netDat ← NIL}};
[] ← SCNetUtil.EnumerateNets[handle, TermNet]};
enter a net on a channel into data structure
EnterPin: PUBLIC PROCEDURE[rect: SC.Rect, position: CD.Position, netPin: SCPrivate.PinNet, side: SC.Side, cell: CD.Object, alwaysUse: BOOLEAN] = {
net: SCPrivate.Net ← netPin.net;
netDat: SCRoutePinsUtil.NetDat ← NARROW[net.netDat];
chanPin: SCRoutePinsUtil.ChannelPin ← NEW[SCRoutePinsUtil.ChannelPinRec ← [rect: rect, position: position, netPin: netPin, cell: cell, side: side, alwaysUse: alwaysUse]];
IF netDat = NIL THEN {
netDat ← NARROW[NEW[SCRoutePinsUtil.NetDatRec]];
net.netDat ← netDat};
netDat.pinCount ← netDat.pinCount + 1;
netDat.chanPins[side] ← CONS[chanPin, netDat.chanPins[side]]};
enter exit data for a channel into routing data base
EnterExit: PUBLIC PROCEDURE[exit: SCPrivate.Exit, side: SCPrivate.LRSide, cell: CD.Object] = {
net: SCPrivate.Net ← exit.net;
netDat: SCRoutePinsUtil.NetDat ← NARROW[net.netDat];
IF netDat = NIL THEN {
netDat ← NARROW[NEW[SCRoutePinsUtil.NetDatRec]];
net.netDat ← netDat};
IF netDat.exits[side] # NIL THEN SC.Error[programmingError, "Call maintainer"];
netDat.pinCount ← netDat.pinCount + 1;
netDat.exits[side] ← NEW[SCRoutePinsUtil.ExitPinRec ← [cell: cell, exit: exit]]};
EnterNetDat: PUBLIC PROCEDURE [handle: SC.Handle, chan: SCPrivate.ZMaxChanSr, pinProc: SCRoutePinsUtil.PinProc, exitProc: SCRoutePinsUtil.ExitProc, netProc: SCRoutePinsUtil.NetProc] = {
DoExit: PROCEDURE[netDat: SCRoutePinsUtil.NetDat, side: SCPrivate.LRSide] = {
exit: SCRoutePinsUtil.ExitPin ← netDat.exits[side];
IF exit # NIL THEN {
pos: INTIF side = left THEN 0 ELSE lgRows.maxRowWidth;
netDat.bounds1 ← MIN[netDat.bounds1, pos];
netDat.bounds2 ← MAX[netDat.bounds2, pos];
IF exitProc # NIL THEN exitProc[exit.exit, exit.cell, exit.exit.net.trunkWidth, side];
numPins ← numPins + 1}};
DoPin: CPProc = {
-- PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin]
IF netDat.pinCount > 1 OR cP.alwaysUse THEN {
netDat.bounds1 ← MIN[netDat.bounds1, cP.position.x];
netDat.bounds2 ← MAX[netDat.bounds2, cP.position.x];
IF pinProc # NIL THEN pinProc[cP.rect, cP.position, cP.netPin, cP.cell];
numPins ← numPins + 1}};
DoAllPins: PROCEDURE[netDat: SCRoutePinsUtil.NetDat, side: SCPrivate.TBSide] = {
EnumChanPins[netDat, netDat.chanPins[side], DoPin]};
DoFullMin: PROC [netDat: SCRoutePinsUtil.NetDat, fullSide, minSide: SCPrivate.TBSide] ~ {
DoRange: CPProc = {fullRange ← RouteChannel.Span[fullRange, [cP.position.x, cP.position.x]]};
DoMinPins: CPProc = {
-- PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin]
trialRange: RoutePrivate.Range ← RouteChannel.Span[fullRange, [cP.position.x, cP.position.x]];
trialLength: SC.Number ←trialRange.r - trialRange.l;
IF trialLength < maxLength THEN {
maxLength ← trialLength;
minPin ← cP}};
maxLength: SC.Number ← last;
minPin: SCRoutePinsUtil.ChannelPin ← NIL;
compute span of pins that must be connected
fullRange: RoutePrivate.Range ← [last, -last];
IF netDat.chanPins[fullSide] # NIL THEN
EnumChanPins[netDat, netDat.chanPins[fullSide], DoRange];
IF netDat.exits[left] # NIL THEN
fullRange ← RouteChannel.Span[fullRange, [0, 0]];
IF netDat.exits[right] # NIL THEN
fullRange ← RouteChannel.Span[fullRange, [lgRows.maxRowWidth, lgRows.maxRowWidth]];
IF (fullRange.l <= fullRange.r) AND netDat.chanPins[minSide] # NIL THEN {
EnumChanPins[netDat, netDat.chanPins[minSide], DoMinPins]};
IF minPin # NIL THEN DoPin[netDat, minPin]};
DoMinMin: PROC [netDat: SCRoutePinsUtil.NetDat] ~ {
DoMinPins: CPProc = {
rightPin ← cP;
lastPin[cP.side] ← cP;
IF lastPin[RTBasic.OtherSide[cP.side]] # NIL THEN {
trialLength: SC.Number;
trialRange: RoutePrivate.Range ← RouteChannel.Span[[lastPin[top].position.x, lastPin[top].position.x], [lastPin[bottom].position.x, lastPin[bottom].position.x]];
IF netDat.exits[left] # NIL THEN
trialRange ← RouteChannel.Span[trialRange, [0, 0]];
IF netDat.exits[left] # NIL THEN
trialRange ← RouteChannel.Span[trialRange, [lgRows.maxRowWidth, lgRows.maxRowWidth]];
trialLength ← trialRange.r - trialRange.l;
IF trialLength < maxLength THEN {
maxLength ← trialLength;
minPin[top]← lastPin[top];
minPin[bottom]← lastPin[bottom]}}};
maxLength: SC.Number ← last;
lastPin: ARRAY SCPrivate.TBSide OF SCRoutePinsUtil.ChannelPin ← [NIL, NIL];
minPin: ARRAY SCPrivate.TBSide OF SCRoutePinsUtil.ChannelPin ← [NIL, NIL];
sortedPinList: SCRoutePinsUtil.ChannelPinList ← SortPinLists[netDat.chanPins[top], netDat.chanPins[bottom]];
leftPin: SCRoutePinsUtil.ChannelPin ← sortedPinList.first;
rightPin: SCRoutePinsUtil.ChannelPin;
EnumChanPins[netDat, sortedPinList, DoMinPins];
IF minPin[top] # NIL THEN DoPin[netDat, minPin[top]];
IF minPin[bottom] # NIL THEN DoPin[netDat, minPin[bottom]];
IF netDat.exits[left] # NIL AND leftPin # minPin[top] AND leftPin # minPin[bottom] THEN
DoPin[netDat, leftPin];
IF netDat.exits[right] # NIL AND rightPin # minPin[top] AND rightPin # minPin[bottom] THEN
DoPin[netDat, rightPin]};
EachNet: SCNetUtil.EachNetProc = {
netDat: SCRoutePinsUtil.NetDat ← NARROW[net.netDat];
numPins ← 0;
IF netDat # NIL THEN {
SELECT TRUE FROM
chan = 0 => -- this is a side
{DoExit[netDat, left]; DoExit[netDat, right];
DoAllPins[netDat, top]; DoAllPins[netDat, bottom]};
net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = full =>
{DoExit[netDat, left]; DoExit[netDat, right];
DoAllPins[netDat, top]; DoAllPins[netDat, bottom]};
net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = min =>
{DoExit[netDat, left]; DoExit[netDat, right];
DoFullMin[netDat, top, bottom]; DoAllPins[netDat, top]};
net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = full =>
{DoExit[netDat, left]; DoExit[netDat, right];
DoFullMin[netDat, bottom, top]; DoAllPins[netDat, bottom]};
net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = min =>
{DoExit[netDat, left]; DoExit[netDat, right]; DoMinMin[netDat]};
net.routeTopology[chan].upper = full => -- lower must be none
{DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, top]};
net.routeTopology[chan].lower = full => -- upper must be none
{DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, bottom]};
ENDCASE =>
check for unconnected exits
IF netDat.exits[left] # NIL OR netDat.exits[right] # NIL THEN
SC.Signal[callingError, "Unconnected public wire; make sure all publics hanve more than one pin"];
IF netProc # NIL THEN netProc[net];
IF numPins = 1 AND chan # 1 AND chan # layoutData.rowChans.count THEN SC.Signal[callingError, Rope.Cat["Too few pins for wire: ", net.name, " on channel: ", Convert.RopeFromInt[chan]]]
}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
numPins: INT;
[] ← SCNetUtil.EnumerateNets[handle, EachNet]};
CPProc: TYPE = PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin];
EnumChanPins: PROC [netDat: SCRoutePinsUtil.NetDat, pList: SCRoutePinsUtil.ChannelPinList, cPProc: CPProc] ~ {
FOR rList: SCRoutePinsUtil.ChannelPinList ← pList, rList.rest WHILE rList # NIL DO
cP: SCRoutePinsUtil.ChannelPin ← rList.first;
cPProc[netDat, cP];
ENDLOOP};
SortPinLists: PROC [topList, bottomList: SCRoutePinsUtil.ChannelPinList] RETURNS [sortedList: SCRoutePinsUtil.ChannelPinList] ~ {
PinCompare: List.CompareProc = {
p1: SC.Number ← NARROW[ref1, SCRoutePinsUtil.ChannelPin].position.x;
p2: SC.Number ← NARROW[ref2, SCRoutePinsUtil.ChannelPin].position.x;
RETURN[IF p1 < p2 THEN Basics.Comparison.less
ELSE IF p1 = p2 THEN Basics.Comparison.equal
ELSE Basics.Comparison.greater]};
topMungedPinList: List.LORA ← List.Sort[ConvertToLORA[topList], PinCompare];
bottomMungedPinList: List.LORA ← List.Sort[ConvertToLORA[bottomList], PinCompare];
sortedPinList: List.LORA ← List.Merge[bottomMungedPinList, topMungedPinList, PinCompare];
sortedList 𡤌onvertFromLORA[sortedPinList]};
ConvertToLORA: PROC [list: SCRoutePinsUtil.ChannelPinList] RETURNS[val: List.LORA] = {
val ← NIL;
UNTIL list = NIL DO
val ← CONS[list.first, val];
list ← list.rest;
ENDLOOP;
RETURN[val];
}; -- of ConvertToLORA
ConvertFromLORA: PROC [list: List.LORA] RETURNS[val: SCRoutePinsUtil.ChannelPinList] = {
val ← NIL;
UNTIL list = NIL DO
this: SCRoutePinsUtil.ChannelPin ← NARROW[list.first];
val ← CONS[this, val];
list ← list.rest;
ENDLOOP;
RETURN[val];
}; -- of ConvertFromLORA
END.