SCSmashImpl.mesa
Copyright Ó 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Frank Bowers February 13, 1986 11:04:31 am PST
Preas July 10, 1987 8:04:25 pm PDT
Jean-Marc Frailong October 11, 1987 3:41:03 pm PDT
DIRECTORY
IO, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCPrivate, SCRowUtil, SCPlaceUtil, Rope, RTSets, SCSmash, SCUtil, SCWidthUtil, TerminalIO;
SCSmashImpl:
CEDAR
PROGRAM
IMPORTS IO, Rope, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCWidthUtil, SCPlaceUtil, SCRowUtil, SCSmash, SCUtil, RTSets, TerminalIO
EXPORTS SCSmash
SHARES SC = {
debug: BOOLEAN ← FALSE;
ValidRange:
PROC [range: RTBasic.Range]
RETURNS [
BOOLEAN]
~ INLINE {RETURN[range.l <= range.r]};
MidRange:
PROC [range: RTBasic.Range]
RETURNS [SC.Number]
~ INLINE {RETURN[(range.l + range.r)/2]};
GetGoodFtPos:
PROC [handle:
SC.Handle, net: SCPrivate.Net, lgRow: SCPrivate.LgRow]
RETURNS [midPos: SCPrivate.ZMaxPosSr ← 0] = {
find a position for the feedthru
lgRows: SCPrivate.LgRows ← NARROW[handle.layoutData, SCPrivate.LayoutData].lgRows;
upperRange: RTBasic.Range ← [LAST[SC.Number], FIRST[SC.Number]];
lowerRange: RTBasic.Range ← [LAST[SC.Number], FIRST[SC.Number]];
loc: SC.Number;
EachPin: SCNetUtil.EachPinProc = {
PROC [netPin: SCPrivate.NetPin] RETURNS [quit: BOOL ← FALSE];
update positions of pins above and below the feedthru
SELECT netPin.instance.whichClass
FROM
ft, logic => {
IF netPin.instance.curRow # 0
THEN {
netPin.instance.curRow = 0 iff it is THIS feddthru
sideOn: SC.Side ← SCInstUtil.PosOf[netPin.instance, netPin.pin].sideOn;
xPos: SC.Number ← SCInstUtil.InstPosOf[handle, netPin.instance, netPin.pin].p;
SELECT
TRUE
FROM
netPin.instance.curRow = lgRow.rowNum-1 AND lgRow.rowNum # 1 AND sideOn = top => lowerRange ← RTBasic.Span[lowerRange, [xPos, xPos]];
netPin.instance.curRow = lgRow.rowNum+1 AND lgRow.rowNum # lgRows.count AND sideOn = bottom => upperRange ← RTBasic.Span[upperRange, [xPos, xPos]];
ENDCASE}};
io => {
IF netPin.instance.curSide = bottom
OR netPin.instance.curSide = top
THEN {
xPos: SC.Number ← SCInstUtil.BpPos[handle, netPin.instance];
SELECT
TRUE
FROM
lgRow.rowNum = 1 => lowerRange ← RTBasic.Span[lowerRange, [xPos, xPos]];
lgRow.rowNum = lgRows.count => upperRange ← RTBasic.Span[upperRange, [xPos, xPos]];
ENDCASE}};
ENDCASE};
find pin positions above and below this row
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPin];
include left and right exits
IF net.chanExits[left][lgRow.rowNum-1]
THEN
lowerRange ← RTBasic.Span[lowerRange, [lgRows.horzRowOrg, lgRows.horzRowOrg]];
IF net.chanExits[left][lgRow.rowNum]
THEN
upperRange ← RTBasic.Span[upperRange, [lgRows.horzRowOrg, lgRows.horzRowOrg]];
IF net.chanExits[right][lgRow.rowNum-1]
THEN
lowerRange ← RTBasic.Span[lowerRange, [lgRows.horzRowOrg + lgRows.maxRowWidth, lgRows.horzRowOrg + lgRows.maxRowWidth]];
IF net.chanExits[right][lgRow.rowNum]
THEN
upperRange ← RTBasic.Span[upperRange, [lgRows.maxRowWidth, lgRows.horzRowOrg + lgRows.maxRowWidth]];
find location for the feedthru
SELECT
TRUE
FROM
ValidRange[lowerRange]
AND ValidRange[upperRange] => {
IF RTBasic.Overlaps[lowerRange, upperRange]
THEN
loc ← MidRange[RTBasic.Overlap[lowerRange, upperRange]]
ELSE
loc ← MidRange[RTBasic.Gap[lowerRange, upperRange]]};
ValidRange[lowerRange] => loc ← MidRange[lowerRange];
ValidRange[upperRange] => loc ← MidRange[upperRange];
ENDCASE => {
SC.Signal[programmingError, "Not suppose to happen. Call maintainer"];
loc ← (lgRows.horzRowOrg + lgRows.maxRowWidth)/2};
find position closest to location; this HACK should be improved
FOR instIndex: SCPrivate.MaxPosSr IN [1 .. lgRow.nLgsOnRow]
WHILE midPos = 0
DO
IF lgRows.horzRowOrg + lgRow.rowOrg.p + lgRow.lgsOnRow[instIndex].offset >= loc
THEN midPos ← instIndex;
ENDLOOP;
maybe pin is beyond the last instance orgin
IF midPos = 0 THEN midPos ← lgRow.nLgsOnRow + 1};
AddFt:
PROC[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[(lgRow.rowNum)-1] THEN SC.Error[programmingError, NIL];
net.ftsOnRow ← RTSets.RTLgSetUnion[net.ftsOnRow,
RTSets.RTLgSetGenerateElement[(lgRow.rowNum)-1]];
savPos ← GetGoodFtPos[handle, net, lgRow]; -- find a good (not best) position for better performance
SCPlaceUtil.PutLgPos[handle, ftInst, lgRow.rowNum, savPos, SCInstUtil.defltLgOrien,
TRUE]};
DetermineExits:
PROC[handle:
SC.Handle, side: SCPrivate.LRSide, net: SCPrivate.Net]
RETURNS [onChan: SCPrivate.ChanSet ← RTSets.RTLgSetEmpty] = {
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 {
sideOn: SC.Side ← SCInstUtil.PosOf[instance, pin].sideOn;
yPos: SC.Number ← SCInstUtil.InstPosOf[handle, instance, pin].q;
IF instance.curSide = side
AND instance.curPos > 0
AND sideOn = chanSide
THEN {
must compute the channel to put the exit on
ChanProc: SCChanUtil.EachRowChanProc = {
PROC [chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOL ← FALSE];
chanPos: SC.Number ← rowChan.chanPos + rowChan.chanWidth/2;
dist: SC.Number ← ABS[chanPos - holdBpPos];
useThisChan: BOOLEAN ← (1 < chan AND chan < rowChans.count) OR (chan = 1 AND rowChans.count = 2);
IF useThisChan AND dist < minDist THEN {minDistChan ← chan; minDist ← dist};
IF useThisChan
AND touchesChan[(chan)-1]
THEN {
IF chanPos > maxChanPos THEN {maxChan ← chan; maxChanPos ← chanPos};
IF chanPos < minChanPos THEN {minChan ← chan; minChanPos ← chanPos}}};
minDist, minChanPos: SC.Number ← LAST[INT];
maxChanPos: SC.Number ← FIRST[INT];
minDistChan, maxChan, minChan: SCPrivate.ZMaxChanSr ← 0;
holdBpPos: SC.Number ← SCInstUtil.BpPos[handle, instance] + 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.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(maxChan)-1]];
holdBpPos < minChanPos
AND minChan > 0 =>
onChan ← RTSets.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(minChan)-1]];
minDistChan > 0 =>
onChan ← RTSets.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(minDistChan)-1]];
ENDCASE => SC.Error[programmingError, "Not suppose to happen."]}}};
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.RTLgSetEmpty;
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPinProc];
found channels to exit from, indicated in onChan
[] ← SCChanUtil.EnumerateRowChans[handle, ChanExitProc]};
DoChans:
PROC [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:
PROC[handle:
SC.Handle, net: SCPrivate.Net, onRow: SCPrivate.RowSet, onSide: SCPrivate.SideSet, 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.RTLgSetUnion[leftOnChan, rightOnChan];
lRow: SCPrivate.MaxRowSr ← 1;
uRow: SCPrivate.ZMaxRowSr ← lgRows.count;
found: BOOLEAN ← FALSE;
doRowWidths ← inDoRows;
doChanWidth ← inDoChans;
find lowest row that needs ft
IF ~onSide[
LOOPHOLE[
SC.Side[bottom],
INTEGER]]
THEN {
WHILE lRow <= lgRows.count
AND
NOT found
DO
IF onRow[(lRow)-1]
OR leftOnChan[(lRow)-1]
OR rightOnChan[(lRow)-1]
THEN
found ← TRUE
ELSE lRow ← lRow + 1;
ENDLOOP};
find upper row that needs ft
found ← FALSE;
IF ~onSide[
LOOPHOLE[
SC.Side[top],
INTEGER]]
THEN {
WHILE uRow >= 1
AND ~found
DO
IF onRow[(uRow)-1]
OR leftOnChan[(uRow+1)-1]
OR rightOnChan[(uRow+1)-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[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] OR leftOnChan[lRow-1] OR rightOnChan[lRow-1] THEN [min, min] ELSE [none, none];
DoChans[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.RTLgSetUnion[doRowWidths, RTSets.RTLgSetGenerateElement[(row)-1]];
doChanWidth ← RTSets.RTLgSetUnion[doChanWidth,
RTSets.RTLgSetAddElement[(row)-1,
RTSets.RTLgSetGenerateElement[(row + 1)-1]]]};
ENDLOOP};
SmashNets:
PUBLIC
PROC[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:
PROC [net: SCPrivate.Net] = {
onSide: SCPrivate.SideSet;
onRow: SCPrivate.RowSet;
leftOnChan, rightOnChan: SCPrivate.ChanSet ← RTSets.RTLgSetEmpty;
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.RTLgSetUnion[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.RTLgSetUnion[doChanWidths, rightOnChan]};
[doChanWidths, doRowWidths] ← ConnectRows[handle, net, onRow, onSide, 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];
ENDLOOP;
IF debug THEN {CheckExits[handle]; CheckFts[handle]};
};
SmashAllNets:
PUBLIC
PROC [handle:
SC.Handle, doChanWidths:
BOOLEAN] = {
add feedthrus to required rows
NetProc: SCNetUtil.EachNetProc = {
[] ← SmashNets[handle, LIST[net], doChanWidths, RTSets.RTLgSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTLgSetEmpty]};
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
PROC [handle:
SC.Handle] = {
alter the smash of the nets
NetProc: SCNetUtil.EachNetProc = {
[] ← SCSmash.RemoveNetsWFts[handle, LIST[net], FALSE, RTSets.RTLgSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTLgSetEmpty]};
TerminalIO.PutRope["Remove topological route\n"];
[] ← SCNetUtil.EnumerateNets[handle, NetProc];
SCInstUtil.AllOffsets[handle];
TerminalIO.PutRope["End remove topological route\n"]};
ReSmash:
PUBLIC
PROC [handle:
SC.Handle, doChanWidths:
BOOLEAN] = {
RemoveSmash[handle];
SmashAllNets[handle, doChanWidths]};
NewFt:
PUBLIC
PROC[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]];
ftObject: SCPrivate.Object ←
SELECT TRUE
FROM
Rope.Equal["Vdd", net.name] => parms.vddObject,
Rope.Equal["Gnd", net.name] => parms.gndObject,
ENDCASE => parms.ftObject;
ftInst ← SCInstUtil.DefineInstance[handle, name, ftObject, 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
PROC[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.RTLgSetUnion[net.chanExits[side], RTSets.RTLgSetGenerateElement[(rowChan.chanNum)-1]];
rowChan.exits[side][index] ← NEW[SCPrivate.ExitRec ← [net: net, pos: 0, pinInChan: NIL, layer: handle.rules.rowRules.trunkLayer]]}};
RemvAllExits:
PUBLIC
PROC[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
PROC[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.RTLgSetDifference[net.chanExits[lrSide], RTSets.RTLgSetGenerateElement[(rowChan.chanNum)-1]];
[] ← SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ChanExitProc];
rowChan.numExits[lrSide] ← index};
RemoveNetsWFts:
PUBLIC
PROC[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.RTLgSetUnion[doRowWidths, RTSets.RTLgSetGenerateElement[(instance.curRow)-1]];
doChanWidths ← RTSets.RTLgSetUnion[
RTSets.RTLgSetUnion[doChanWidths,
RTSets.RTLgSetGenerateElement[(instance.curRow)-1]],
RTSets.RTLgSetGenerateElement[(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.RTLgSetUnion[doChanWidths, RTSets.RTLgSetGenerateElement[(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
PROC[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:
PROC[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.RTLgSetUnion[doRowWidths,
RTSets.RTLgSetGenerateElement[(row)-1]];
doChanWidths ← RTSets.RTLgSetUnion[doChanWidths,
RTSets.RTLgSetAddElement[(row)-1,
RTSets.RTLgSetGenerateElement[(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.RTLgSetUnion[doChanWidths,
RTSets.RTLgSetGenerateElement[(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.RTLgSetEmpty;
net.chanExits[right] ← RTSets.RTLgSetEmpty;
[] ← 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
PROC [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.RTLgSetIsSubset[ RTSets.RTLgSetGenerateElement[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
PROC [handle:
SC.Handle] = {
audit the Fts on all nets for consistancy
EachNet: SCNetUtil.EachNetProc = {CheckFtsOnNet[handle, net]};
[] ← SCNetUtil.EnumerateNets[handle, EachNet]};
CheckFtsOnNet:
PUBLIC
PROC[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.RTLgSetUnion[ftsOnRow, RTSets.RTLgSetGenerateElement[(row)-1]]}}};
[] ← SCRowUtil.EnumerateAllInstsOnRow[handle, row, PosProc]};
ftsOnRow: SCPrivate.RowSet ← RTSets.RTLgSetEmpty;
[] ← SCRowUtil.EnumerateRows[handle, EachRow];
IF ~RTSets.RTLgSetIsSame[ftsOnRow, net.ftsOnRow]
THEN
row data does not correspond to instance data
SC.Error[programmingError, NIL]};
CleanUpNet:
PROC [handle:
SC.Handle, net: SCPrivate.Net] = {
remove the global route on nets
EachChan: SCChanUtil.EachRowChanProc = {net.routeTopology[chan] ← [none, none]};
net.ftsOnRow ← RTSets.RTLgSetEmpty;
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan]};
}.