SCRoutePinsUtilImpl:
CEDAR
PROGRAM
IMPORTS Convert, List, Rope, RouteChannel, RTBasic, SC, SCNetUtil
EXPORTS SCRoutePinsUtil
SHARES SC =
BEGIN
last: INT ← LAST[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: INT ← IF 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.