DIRECTORY
Basics, CD, Convert, List, Rope, RoutePrivate, RTBasic, SC, SCNetUtil, SCPrivate, SCRoutePinsUtil;
SCRoutePinsUtilImpl:
CEDAR
PROGRAM
IMPORTS Convert, List, Rope, 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[min, max, depth:
SC.Number, netPin: SCPrivate.PinNet, side:
SC.Side, alwaysUse:
BOOLEAN] = {
net: SCPrivate.Net ← netPin.net;
netDat: SCRoutePinsUtil.NetDat ← NARROW[net.netDat];
chanPin: SCRoutePinsUtil.ChannelPin ← NEW[SCRoutePinsUtil.ChannelPinRec ← [min: min, max: max, depth: depth, netPin: netPin, 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] = {
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[SCPrivate.ExitRec ← [net: exit.net, pos: exit.pos, pinInChan: NIL, layer: exit.layer]]};
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: SCPrivate.Exit ← netDat.exits[side];
IF exit #
NIL
THEN {
pos: INT ← IF side = left THEN lgRows.horzRowOrg ELSE lgRows.horzRowOrg + lgRows.maxRowWidth;
netDat.bounds1 ← MIN[netDat.bounds1, pos];
netDat.bounds2 ← MAX[netDat.bounds2, pos];
IF exitProc # NIL THEN exitProc[exit, 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.min];
netDat.bounds2 ← MAX[netDat.bounds2, cP.max];
IF pinProc # NIL THEN pinProc[cP.min, cP.max, cP.depth, cP.netPin, cP.side];
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 ← RTBasic.Span[fullRange, [cP.min, cP.max]]};
DoMinPins: CPProc = {
PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin]
trialRange: RTBasic.Range ← RTBasic.Span[fullRange, [cP.min, cP.max]];
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: RTBasic.Range ← [last, -last];
IF netDat.chanPins[fullSide] #
NIL
THEN
EnumChanPins[netDat, netDat.chanPins[fullSide], DoRange];
IF netDat.exits[left] #
NIL
THEN {
min: SC.Number ← lgRows.horzRowOrg;
fullRange ← RTBasic.Span[fullRange, [min, min]]};
IF netDat.exits[right] #
NIL
THEN {
max: SC.Number ← lgRows.horzRowOrg + lgRows.maxRowWidth;
fullRange ← RTBasic.Span[fullRange, [max, max]]};
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 = {
-- PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin];
IF leftPin = NIL THEN leftPin ← cP;
rightPin ← cP;
lastPin[cP.side] ← cP;
IF lastPin[RTBasic.OtherSide[cP.side]] #
NIL
THEN {
trialLength: SC.Number;
trialRange: RTBasic.Range ← RTBasic.Span[[lastPin[top].min, lastPin[top].max], [lastPin[bottom].min, lastPin[bottom].max]];
IF netDat.exits[left] #
NIL
THEN {
min: SC.Number ← lgRows.horzRowOrg;
trialRange ← RTBasic.Span[trialRange, [min, min]]};
IF netDat.exits[right] #
NIL
THEN {
max: SC.Number ← lgRows.horzRowOrg + lgRows.maxRowWidth;
trialRange ← RTBasic.Span[trialRange, [max, max]]};
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, rightPin: SCRoutePinsUtil.ChannelPin ← NIL;
didLeftPin: BOOL ← FALSE;
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]; didLeftPin ← TRUE};
IF netDat.exits[right] #
NIL
AND rightPin # minPin[top]
AND rightPin # minPin[bottom]
AND ~didLeftPin
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]};
netDat.exits[left] #
NIL
AND netDat.exits[right] #
NIL =>
{DoExit[netDat, left]; DoExit[netDat, right]};
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].min;
p2: SC.Number ← NARROW[ref2, SCRoutePinsUtil.ChannelPin].min;
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.