SCSmashImpl:
CEDAR
PROGRAM
IMPORTS IO, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCWidthUtil, SCPlaceUtil, SCRowUtil, SCSmash, SCUtil, RTSets, TerminalIO
EXPORTS SCSmash
SHARES SC = {
debug: BOOLEAN ← FALSE;
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: BOOL ← FALSE];
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: BOOLEAN ← FALSE;
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.ROPE ← IO.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]};
}.