SCSmashImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Frank Bowers February 13, 1986 11:04:31 am PST
Preas December 21, 1986 4:26:20 pm PST
DIRECTORY
IO, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCPrivate, SCRowUtil, SCPlaceUtil, Rope, RTSets, SCSmash, SCUtil, SCWidthUtil, TerminalIO;
SCSmashImpl: CEDAR PROGRAM
IMPORTS IO, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCWidthUtil, SCPlaceUtil, SCRowUtil, SCSmash, SCUtil, RTSets, TerminalIO
EXPORTS SCSmash
SHARES SC = {
debug: BOOLEANFALSE;
GetGoodFtPos: PROC [net: SCPrivate.Net, row: SCPrivate.MaxRowSr, nLgsOnRow: SCPrivate.ZMaxPosSr] RETURNS [midPos: SCPrivate.MaxPosSr] = {
minPos: SC.Number ← LAST[SC.Number];
maxPos: SC.Number ← FIRST[SC.Number];
EachPin: SCNetUtil.EachPinProc = {
instance: SCPrivate.Instance ← netPin.instance;
SELECT instance.whichClass FROM
ft, logic => {
SELECT instance.curRow FROM
row, row+1, row-1 => {
minPos ← MIN[minPos, instance.curPos];
maxPos ← MAX[maxPos, instance.curPos]};
ENDCASE;
};
ENDCASE
};
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPin];
IF minPos = LAST[SC.Number] AND maxPos = FIRST[SC.Number] THEN midPos ← (1+ nLgsOnRow)/2 -- no instances in channels near row
ELSE {
minPos ← SELECT minPos FROM
< 1 => 1, > nLgsOnRow => nLgsOnRow+1, ENDCASE => minPos;
maxPos ← SELECT maxPos FROM
< 1 => 1, > nLgsOnRow => nLgsOnRow+1, ENDCASE => maxPos;
midPos ← (minPos + maxPos)/2}};
AddFt: PROCEDURE[handle: SC.Handle, lgRow: SCPrivate.LgRow, net: SCPrivate.Net]
RETURNS [ftInst: SCPrivate.Instance] = {
add ft's on interior rows as required
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
bpRows: SCPrivate.BpRows ← layoutData.bpRows;
row: SCPrivate.MaxRowSr ← lgRow.rowNum;
savPos: SCPrivate.MaxPosSr ← 1;
ftInst ← NewFt[handle, net, lgRow];
IF net.ftsOnRow[(row)-1] THEN SC.Error[programmingError, NIL];
net.ftsOnRow ← RTSets.RTMdSetUnion[net.ftsOnRow,
RTSets.RTMdSetGenerateElement[(row)-1]];
savPos ← GetGoodFtPos[net, row, lgRow.nLgsOnRow]; -- find a good (not best) position for better performance
SCPlaceUtil.PutLgPos[handle, ftInst, row, savPos, SCInstUtil.defltLgOrien, TRUE]};
DetermineExits: PROCEDURE[handle: SC.Handle, side: SCPrivate.LRSide, net: SCPrivate.Net]
RETURNS [onChan: SCPrivate.ChanSet ← RTSets.RTMdSetEmpty] = {
add side exits as required to net lists
find preferred position for exit to side surface
ChanExitProc: SCChanUtil.EachRowChanProc = {
PROC [chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOL ← FALSE];
IF onChan[(chan) - 1] THEN AddExit[handle, rowChan, side, net]};
EachPinProc: SCNetUtil.EachPinProc = {
PROC [netPin: SCPrivate.NetPin] RETURNS [quit: BOOL ← FALSE];
instance: SCPrivate.Instance ← netPin.instance;
pin: SCPrivate.ObjectPin ← netPin.pin;
get position of instance on side
IF instance.whichClass = io THEN {
p: SCInstUtil.PinDescription ← SCInstUtil.PosOf[instance, pin];
IF instance.curSide = side
AND instance.curPos > 0 AND p.sideOn = chanSide THEN {
IF rowChans.count <= 2 THEN
exit must be on bottom channel
onChan ← RTSets.RTMdSetGenerateElement[(1)-1]
ELSE {
must compute the channel to put the exit on
ChanProc: SCChanUtil.EachRowChanProc = {
PROC [chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOLFALSE];
IF touchesChan[(chan)-1] THEN {
SetMinMaxDists: PROCEDURE [] =
{IF dist < minDist THEN {minDistChan ← chan; minDist ← dist};
IF chanPos > maxChanPos THEN {maxChan ← chan; maxChanPos ← chanPos};
IF chanPos < minChanPos THEN {minChan ← chan; minChanPos ← chanPos}};
chanPos: SC.Number ← rowChan.chanPos + rowChan.chanWidth/2;
dist: SC.Number ← ABS[chanPos - holdBpPos];
layoutParms: SCPrivate.LayoutParms ← layoutData.layoutParms;
SELECT TRUE FROM
~layoutParms.useInteriorChanExits => SetMinMaxDists;
layoutParms.useInteriorChanExits =>
IF (1 < chan AND chan < rowChans.count) THEN SetMinMaxDists;
ENDCASE}};
minDist, minChanPos: SC.Number ← LAST[INT];
maxChanPos: SC.Number ← -LAST[INT];
minDistChan, maxChan, minChan: SCPrivate.ZMaxChanSr ← 0;
holdBpPos: SC.Number ← SCInstUtil.BpPos[handle, instance] + p.yPos;
find distance of port to closest existing channel
[] ← SCChanUtil.EnumerateRowChans[handle, ChanProc];
determine channel to exit
SELECT TRUE FROM
holdBpPos > maxChanPos AND maxChan > 0 =>
onChan ← RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(maxChan)-1]];
holdBpPos < minChanPos AND minChan > 0 =>
onChan ← RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(minChan)-1]];
minDistChan > 0 =>
onChan ← RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(minDistChan)-1]];
ENDCASE}}}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
chanSide: RTBasic.Side ← RTBasic.OtherSide[side];
instList: SCPrivate.InstanceList ← SCNetUtil.InstsOnNets[LIST[net]];
touchesChan: SCPrivate.ChanSet ← SCInstUtil.ChansForInsts[handle, instList];
net.chanExits[side] ← RTSets.RTMdSetEmpty;
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPinProc];
found channels to exit from, indicated in onChan
[] ← SCChanUtil.EnumerateRowChans[handle, ChanExitProc]};
DoChans: PROC [handle: SC.Handle, net: SCPrivate.Net, lChan, uChan, maxChan: SCPrivate.MaxChanSr] ~ {
lastTopology: SCPrivate.UpperLowerConnection ← net.routeTopology[lChan-1];
FOR chan: SCPrivate.MaxChanSr IN [lChan .. uChan] DO
IF chan = maxChan THEN
net.routeTopology[chan] ← [full, full]
ELSE IF chan = maxChan -1 THEN {
net.routeTopology[chan] ←
IF lastTopology.upper = full THEN [min, full] ELSE [full, full]}
ELSE
net.routeTopology[chan] ←
IF lastTopology.upper = full THEN [min, min] ELSE [full, full];
lastTopology ← net.routeTopology[chan];
ENDLOOP};
ConnectRows: PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, onRow: SCPrivate.RowSet, leftOnChan, rightOnChan, inDoChans: SCPrivate.ChanSet, inDoRows: SCPrivate.RowSet]
RETURNS [doChanWidth: SCPrivate.ChanSet, doRowWidths: SCPrivate.RowSet] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
onChan: SCPrivate.ChanSet ← RTSets.RTMdSetUnion[leftOnChan, rightOnChan];
lRow: SCPrivate.MaxRowSr ← 1;
uRow: SCPrivate.ZMaxRowSr ← lgRows.count;
found: BOOLEANFALSE;
doRowWidths ← inDoRows;
doChanWidth ← inDoChans;
find lowest row that needs ft
WHILE lRow <= lgRows.count AND NOT found DO
IF onRow[(lRow)-1] THEN found ← TRUE
ELSE lRow ← lRow + 1;
ENDLOOP;
find upper row that needs ft
found ← FALSE;
WHILE uRow >= 1 AND ~found DO
IF onRow[(uRow)-1] THEN found ← TRUE
ELSE uRow ← uRow -1;
ENDLOOP;
determine global route for channels between lChan and uChan inclusive
IF lRow = 1 THEN {
net.routeTopology[1] ← [full, full];
net.routeTopology[2] ← IF lgRows.count <= 2 THEN [full, full] ELSE [full, min];
DoChans[handle, net, 3, uRow+1, rowChans.count]}
ELSE IF lRow = lgRows.count THEN {
net.routeTopology[rowChans.count-1] ← [full, full];
net.routeTopology[rowChans.count] ← [full, full]}
ELSE {
net.routeTopology[lRow] ← IF onChan[lRow-1] THEN [min, min] ELSE [none, none];
DoChans[handle, net, lRow+1, uRow+1, rowChans.count]};
add fts to required rows between lrow and urow
FOR row: SCPrivate.MaxRowSr IN [lRow .. uRow] DO
IF ~onRow[(row)-1] THEN {
[] ← AddFt[handle, lgRows.rows[row], net];
doRowWidths ← RTSets.RTMdSetUnion[doRowWidths, RTSets.RTMdSetGenerateElement[(row)-1]];
doChanWidth ← RTSets.RTMdSetUnion[doChanWidth,
RTSets.RTMdSetAddElement[(row)-1,
RTSets.RTMdSetGenerateElement[(row + 1)-1]]]};
ENDLOOP};
SmashNets: PUBLIC PROCEDURE[handle: SC.Handle, nets: SCPrivate.NetList, doWidths: BOOLEAN, inDoChans: SCPrivate.ChanSet, inDoSides: SCPrivate.LRSideSet, inDoRows: SCPrivate.RowSet]
RETURNS [doChanWidths: SCPrivate.ChanSet, doSideWidths: SCPrivate.LRSideSet, doRowWidths: SCPrivate.RowSet] = {
EachNet: SCNetUtil.EachNetProc = {
onSide: SCPrivate.SideSet;
onRow: SCPrivate.RowSet;
leftOnChan, rightOnChan: SCPrivate.ChanSet ← RTSets.RTMdSetEmpty;
instList: SCPrivate.InstanceList ← SCNetUtil.InstsOnNets[LIST[net]];
numInstances: SCPrivate.ZMaxInstanceSr ← SCInstUtil.NumInstsOnList[instList];
doChanWidths ← inDoChans;
doSideWidths ← inDoSides;
doRowWidths ← inDoRows;
CleanUpNet[handle, net];
[onSide, onRow] ← SCRowUtil.RowsForInsts[instList];
IF onSide[LOOPHOLE[SC.Side[left], INTEGER]] THEN
{leftOnChan ← DetermineExits[handle, left, net];
doSideWidths ← RTSets.RTSmSetUnion[doSideWidths, RTSets.RTSmSetGenerateElement[LOOPHOLE[SCPrivate.LRSide[left], INTEGER]]]};
doChanWidths ← RTSets.RTMdSetUnion[doChanWidths, leftOnChan];
IF onSide[LOOPHOLE[SC.Side[right], INTEGER]] THEN
{rightOnChan ← DetermineExits[handle, right, net];
doSideWidths ← RTSets.RTSmSetUnion[doSideWidths, RTSets.RTSmSetGenerateElement[LOOPHOLE[SCPrivate.LRSide[right], INTEGER]]]};
doChanWidths ← RTSets.RTMdSetUnion[doChanWidths, rightOnChan];
IF onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] AND ~ onRow[(1)-1] THEN {
[] ← AddFt[handle, lgRows.rows[1], net];
doRowWidths ← RTSets.RTMdSetUnion[doRowWidths, RTSets.RTMdSetGenerateElement[(1)-1]];
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(1)-1], onRow];
doChanWidths ← RTSets.RTMdSetUnion[ RTSets.RTMdSetUnion[doChanWidths, RTSets.RTMdSetGenerateElement[(1)-1]], RTSets.RTMdSetGenerateElement[(2)-1]]};
IF (onSide[LOOPHOLE[SC.Side[top], INTEGER]]) AND ~onRow[(lgRows.count)-1] THEN {
[] ← AddFt[handle, lgRows.rows[lgRows.count], net];
doRowWidths ← RTSets.RTMdSetUnion[doRowWidths, RTSets.RTMdSetGenerateElement[(lgRows.count)-1]];
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(lgRows.count)-1], onRow];
doChanWidths ← RTSets.RTMdSetUnion[ RTSets.RTMdSetUnion[doChanWidths , RTSets.RTMdSetGenerateElement[(lgRows.count)-1]], RTSets.RTMdSetGenerateElement[(lgRows.count + 1)-1]]};
[doChanWidths, doRowWidths] ← ConnectRows[handle, net, onRow, leftOnChan, rightOnChan, doChanWidths, doRowWidths];
now update the channel widths
IF doWidths THEN {
EachRow: SCRowUtil.EachRowProc = {IF doRowWidths[row - 1] THEN SCInstUtil.LgOffsets[handle, row, 0, SCPrivate.maxPos]};
EachChan: SCChanUtil.EachRowChanProc = {IF doChanWidths[chan - 1] THEN
[rowChan.chanWidth, rowChan.wireLength] ← SCWidthUtil.GetChanWidth[handle, rowChan, areaFom, TRUE]};
[] ← SCRowUtil.EnumerateRows[handle, EachRow];
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan]}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
FOR netLst: SCPrivate.NetList ← nets, netLst.rest WHILE netLst # NIL DO
[] ← EachNet[netLst.first.num, netLst.first];
ENDLOOP;
IF debug THEN {CheckExits[handle]; CheckFts[handle]};
};
SmashAllNets: PUBLIC PROCEDURE [handle: SC.Handle, doChanWidths: BOOLEAN] = {
add feedthrus to required rows
NetProc: SCNetUtil.EachNetProc = {
[] ← SmashNets[handle, LIST[net], doChanWidths, RTSets.RTMdSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTMdSetEmpty]};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
TerminalIO.PutRope["Begin topological route\n"];
SCChanUtil.InitChanWidths[handle];
SCInstUtil.AsgnChanPos[handle];
[] ← SCNetUtil.EnumerateNets[handle, NetProc];
SCInstUtil.AllOffsets[handle];
[lgRows.maxRowWidth, lgRows.numMaxRows] ← SCRowUtil.FindMaxRow[handle];
SCWidthUtil.AllChanWidths[handle, areaFom];
SCInstUtil.AsgnChanPos[handle];
[] ← SCUtil.WriteResults["End topological route\n estimated size:", handle, 0]};
RemoveSmash: PUBLIC PROCEDURE [handle: SC.Handle] = {
alter the smash of the nets
NetProc: SCNetUtil.EachNetProc = {
[] ← SCSmash.RemoveNetsWFts[handle, LIST[net], FALSE, RTSets.RTMdSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTMdSetEmpty]};
TerminalIO.PutRope["Remove topological route\n"];
[] ← SCNetUtil.EnumerateNets[handle, NetProc];
SCInstUtil.AllOffsets[handle];
TerminalIO.PutRope["End remove topological route\n"]};
ReSmash: PUBLIC PROCEDURE [handle: SC.Handle, doChanWidths: BOOLEAN] = {
RemoveSmash[handle];
SmashAllNets[handle, doChanWidths]};
NewFt: PUBLIC PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, lgRow: SCPrivate.LgRow] RETURNS [ftInst: SCPrivate.Instance] = {
add ft to row width
get a component entry for the ft, construct a new entry for instance
parms: SCPrivate.Parms ← NARROW[handle.parms];
name: Rope.ROPEIO.PutFR["%g-%g", IO.rope[net.name], IO.int[lgRow.rowNum]];
ftInst ← SCInstUtil.DefineInstance[handle, name, parms.ftObject, NIL, NIL];
ftInst.ftNet ← net;
construct and add an entry to net list for this instance
SCNetUtil.AddConnection[handle, net, ftInst, parms.ftObject.pins.p[0], 0, ftPin];
SCNetUtil.AddConnection[handle, net, ftInst, parms.ftObject.pins.p[1], 1, ftPin]};
AddExit: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, side: SC.Side, net: SCPrivate.Net] = {
add an exit to a channel
IF rowChan.chanNum = 0 THEN SC.Error[programmingError, NIL]
ELSE {
index: NAT ← rowChan.numExits[side] ← rowChan.numExits[side] + 1;
net.chanExits[side] ←
RTSets.RTMdSetUnion[net.chanExits[side], RTSets.RTMdSetGenerateElement[(rowChan.chanNum)-1]];
rowChan.exits[side][index].net ← net;
rowChan.exits[side][index].pos ← 0;
rowChan.exits[side][index].layer ← handle.rules.rowRules.trunkLayer}};
RemvAllExits: PUBLIC PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, lRSide: SCPrivate.LRSide] = {
remove all exits for net on a lRSide
ChanProc: SCChanUtil.EachRowChanProc = {
RemoveExit[handle, net, rowChan, lRSide]};
[] ← SCChanUtil.EnumerateRowChans[handle, ChanProc]};
RemoveExit: PUBLIC PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, rowChan: SCPrivate.RowChan, lrSide: SCPrivate.LRSide] = {
remove an exit for net on chan
ChanExitProc: SCChanUtil.EachExitProc = {
IF exit.net # net THEN {
index ← index + 1;
rowChan.exits[lrSide][index] ← rowChan.exits[lrSide][exitNum]}};
index: SCPrivate.ZMaxExitsSr ← 0;
net.chanExits[lrSide] ← RTSets.RTMdSetDifference[net.chanExits[lrSide], RTSets.RTMdSetGenerateElement[(rowChan.chanNum)-1]];
[] ← SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ChanExitProc];
rowChan.numExits[lrSide] ← index};
RemoveNetsWFts: PUBLIC PROCEDURE[handle: SC.Handle, netLst: SCPrivate.NetList, save: BOOLEAN, inDoChans: SCPrivate.ChanSet, inDoSides: SCPrivate.LRSideSet, inDoRows: SCPrivate.RowSet]
RETURNS [doChanWidths: SCPrivate.ChanSet, doSideWidths: SCPrivate.LRSideSet, doRowWidths: SCPrivate.RowSet] = {
remove specified nets with fts
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
globalRoute: SCSmash.GlobalRoute ← NEW[SCSmash.GlobalRouteRec];
layoutData.globalRoute ← globalRoute;
doChanWidths ← inDoChans;
doSideWidths ← inDoSides;
doRowWidths ← inDoRows;
save indicates whether current smash is to be saved
IF save THEN {globalRoute.numFts ← globalRoute.numNets ← 0};
FOR nets: SCPrivate.NetList ← netLst, nets.rest WHILE nets # NIL DO
EachInst: SCNetUtil.EachInstProc = {
IF instance.whichClass = ft THEN {
IF save THEN {
IF globalRoute.numFts >= SCSmash.maxFtsSaved THEN SC.Error[noResource, NIL];
globalRoute.numFts ← globalRoute.numFts + 1;
globalRoute.fts[globalRoute.numFts] ← NEW[SCSmash.FtDataRec ← [net, instance.curRow, instance.curPos]]};
now remove the ft
doRowWidths ← RTSets.RTMdSetUnion[doRowWidths, RTSets.RTMdSetGenerateElement[(instance.curRow)-1]];
doChanWidths ← RTSets.RTMdSetUnion[
RTSets.RTMdSetUnion[doChanWidths,
RTSets.RTMdSetGenerateElement[(instance.curRow)-1]],
RTSets.RTMdSetGenerateElement[(instance.curRow + 1)-1]];
SCPlaceUtil.RemvLgComp[handle, instance, FALSE]}};
EachChan: SCChanUtil.EachRowChanProc = {
FOR lrSide: SCPrivate.LRSide IN SCPrivate.LRSide DO
IF net.chanExits[lrSide][(chan)-1] THEN
{doChanWidths ← RTSets.RTMdSetUnion[doChanWidths, RTSets.RTMdSetGenerateElement[(chan)-1]];
doSideWidths ← RTSets.RTSmSetUnion[doSideWidths , RTSets.RTSmSetGenerateElement[LOOPHOLE[lrSide, INTEGER]]]};
ENDLOOP};
net: SCPrivate.Net ← nets.first;
run through the comps on this net
SCNetUtil.RemoveFtsOnNet[handle, net];
[] ← SCNetUtil.EnumerateInstsOnNets[LIST[net], EachInst];
now work on the exits
IF save THEN {
IF globalRoute.numNets >= SCSmash.maxNetsSaved THEN SC.Error[noResource, NIL];
globalRoute.numNets ← globalRoute.numNets + 1;
globalRoute.nets[globalRoute.numNets].net ← net;
globalRoute.nets[globalRoute.numNets].exit[left] ← net.chanExits[left];
globalRoute.nets[globalRoute.numNets].exit[right] ← net.chanExits[right]};
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan];
CleanUpNet[handle, net];
ENDLOOP;
IF debug THEN {CheckExits[handle]; CheckFts[handle]};
};
RestoreNetsWFts: PUBLIC PROCEDURE[handle: SC.Handle, netLst: SCPrivate.NetList, inDoChans: SCPrivate.ChanSet, inDoSides: SCPrivate.LRSideSet, inDoRows: SCPrivate.RowSet]
RETURNS [doChanWidths : SCPrivate.ChanSet, doSideWidths: SCPrivate.LRSideSet, doRowWidths: SCPrivate.RowSet]= {
save route data for specified nets
ChanRowProc: SCRowUtil.EachRowProc = {
IF doRowWidths[(row)-1] THEN SCInstUtil.LgOffsets[handle, row, 0, SCPrivate.maxPos]};
CheckConnection: PROCEDURE[net: SCPrivate.Net, leftExitChan, rightExitChan: SCPrivate.RowChan] = {
make sure feed throughs are in proper channels
instList: SCPrivate.InstanceList ← SCNetUtil.InstsOnNets[LIST[net]];
onSide: SCPrivate.SideSet;
onRow: SCPrivate.RowSet;
[onSide, onRow] ← SCRowUtil.RowsForInsts[instList];
IF leftExitChan.chanNum = 1 OR rightExitChan.chanNum = 1 THEN {
IF NOT (onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] OR onRow[(1)-1]) THEN
SC.Error[programmingError, NIL]}
ELSE IF leftExitChan.chanNum = rowChans.count OR rightExitChan.chanNum = rowChans.count THEN {
IF NOT (onSide[LOOPHOLE[SC.Side[top ], INTEGER]] OR onRow[(rowChans.count-1)-1]) THEN
SC.Error[programmingError, NIL]};
IF 1 < leftExitChan.chanNum AND leftExitChan.chanNum < rowChans.count THEN {
IF NOT (onRow[(leftExitChan.chanNum) - 1] OR onRow[(leftExitChan.chanNum-1) - 1]) THEN
SC.Error[programmingError, NIL]};
IF 1 < rightExitChan.chanNum AND rightExitChan.chanNum < rowChans.count THEN {
IF NOT (onRow[(rightExitChan.chanNum)-1] OR onRow[(rightExitChan.chanNum-1)-1]) THEN
SC.Error[programmingError, NIL]}};
RestoreNetsWFts
first restore the feedthroughs
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
globalRoute: SCSmash.GlobalRoute ← NARROW[layoutData.globalRoute];
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
doChanWidths ← inDoChans;
doSideWidths ← inDoSides;
doRowWidths ← inDoRows;
FOR ftIndex: SCSmash.ZMFtsSavedSr DECREASING IN [1 .. globalRoute.numFts] DO
net: SCPrivate.Net ← globalRoute.fts[ftIndex].net;
row: NAT ← globalRoute.fts[ftIndex].row;
ftInst: SCPrivate.Instance ← NewFt[handle, net, lgRows.rows[row]];
SCPlaceUtil.PutLgPos[handle, ftInst, row, globalRoute.fts[ftIndex].pos, SCInstUtil.defltLgOrien, FALSE];
doRowWidths ← RTSets.RTMdSetUnion[doRowWidths,
RTSets.RTMdSetGenerateElement[(row)-1]];
doChanWidths ← RTSets.RTMdSetUnion[doChanWidths,
RTSets.RTMdSetAddElement[(row)-1,
RTSets.RTMdSetGenerateElement[(row + 1)-1]]];
ENDLOOP;
find row widths
[] ← SCRowUtil.EnumerateRows[handle, ChanRowProc];
now the channel exits
FOR netIndex: SCSmash.MNetsSavedSr DECREASING IN [1 .. globalRoute.numNets] DO
ChanRowProc: SCChanUtil.EachRowChanProc = {
FOR lrSide: SC.Side IN SCPrivate.LRSide DO
RemoveExit[handle, net, rowChan, lrSide];
IF globalRoute.nets[netIndex].exit[lrSide][(chan)-1] THEN {
exitChan[lrSide] ← rowChan;
AddExit[handle, rowChan, lrSide, net];
doChanWidths ← RTSets.RTMdSetUnion[doChanWidths,
RTSets.RTMdSetGenerateElement[(chan)-1]];
doSideWidths ← RTSets.RTSmSetUnion[doSideWidths , RTSets.RTSmSetGenerateElement[LOOPHOLE[lrSide, INTEGER]]]};
ENDLOOP};
exitChan: ARRAY SCPrivate.LRSide OF SCPrivate.RowChan ← [NIL, NIL];
net: SCPrivate.Net ← globalRoute.nets[netIndex].net;
net.chanExits[left] ← RTSets.RTMdSetEmpty;
net.chanExits[right] ← RTSets.RTMdSetEmpty;
[] ← SCChanUtil.EnumerateRowChans[handle, ChanRowProc];
check to make sure the net is connected
CheckConnection[net, exitChan[left], exitChan[right]];
ENDLOOP;
IF debug THEN {CheckExits[handle]; CheckFts[handle]};
};
CheckExits: PUBLIC PROCEDURE [handle: SC.Handle] = {
audit the exits for consistancy
NetProc: SCNetUtil.EachNetProc = {
ChanExitProc: SCChanUtil.EachRowChanProc = {
SideProc: SCChanUtil.EachSideChanProc = {
ExitProc: SCChanUtil.EachExitProc = {
IF exit.net = net THEN quit ← TRUE};
exitPresent: BOOLEAN ← RTSets.RTMdSetIsSubset[ RTSets.RTMdSetGenerateElement[chan - 1], net.chanExits[lrSide]];
found: BOOLEAN ← SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ExitProc];
IF exitPresent AND ~found OR ~exitPresent AND found THEN
SC.Error[programmingError, NIL]};
[] ← SCChanUtil.EnumerateSideChans[handle, SideProc]};
[] ← SCChanUtil.EnumerateRowChans[handle, ChanExitProc]};
[] ← SCNetUtil.EnumerateNets[handle, NetProc]};
CheckFts: PUBLIC PROCEDURE [handle: SC.Handle] = {
audit the Fts on all nets for consistancy
EachNet: SCNetUtil.EachNetProc = {CheckFtsOnNet[handle, net]};
[] ← SCNetUtil.EnumerateNets[handle, EachNet]};
CheckFtsOnNet: PUBLIC PROCEDURE[handle: SC.Handle, net: SCPrivate.Net] = {
audit the Fts on net for consistancy
EachRow: SCRowUtil.EachRowProc = {
PosProc: SCRowUtil.EachInstProc = {
IF instance.whichClass = ft THEN {
netPin1: SCPrivate.Net ← instance.pinNets.n[0].net;
netPin2: SCPrivate.Net ← instance.pinNets.n[1].net;
IF netPin1 = NIL OR netPin2 = NIL OR netPin1 # netPin2 THEN
error in connection of net
SC.Error[programmingError, NIL];
IF netPin1 = net THEN {
IF ftsOnRow[row-1] THEN
more than one ft on row for this net on this row
SC.Error[programmingError, NIL];
ftsOnRow ← RTSets.RTMdSetUnion[ftsOnRow, RTSets.RTMdSetGenerateElement[(row)-1]]}}};
[] ← SCRowUtil.EnumerateAllInstsOnRow[handle, row, PosProc]};
ftsOnRow: SCPrivate.RowSet ← RTSets.RTMdSetEmpty;
[] ← SCRowUtil.EnumerateRows[handle, EachRow];
IF ~RTSets.RTMdSetIsSame[ftsOnRow, net.ftsOnRow] THEN
row data does not correspond to instance data
SC.Error[programmingError, NIL]};
CleanUpNet: PROCEDURE [handle: SC.Handle, net: SCPrivate.Net] = {
remove the global route on nets
EachChan: SCChanUtil.EachRowChanProc = {net.routeTopology[chan] ← [none, none]};
net.ftsOnRow ← RTSets.RTMdSetEmpty;
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan]};
}.