///StdCell/SCSmashImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
DIRECTORY
IO,
Rope,
RTBasic,
SC,
SCChanUtil,
SCInstUtil,
SCNetUtil,
SCPrivate,
SCRowUtil,
SCPlaceUtil,
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;
AddFt: PROCEDURE[handle: SC.Handle, lgRow: SCPrivate.LgRow, net: SCPrivate.Net, leftOnChan, rightOnChan: SCPrivate.ChanSet]
RETURNS [ftInst: SCPrivate.Instance] = {
add ft's on interior rows as required
NetWireLength: PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, lgRow: SCPrivate.LgRow, leftOnChan, rightOnChan: SCPrivate.ChanSet, pins: SCPrivate.NetPinsList] RETURNS [wireLength: SC.Number] = {
compute wirelength of net in channels adjacent to row
EachPin: SCNetUtil.EachPinProc = {
instance: SCPrivate.Instance ← netPin.instance;
p: SCInstUtil.PinDescription ← SCInstUtil.PosOf[instance, netPin.pin];
SELECT instance.whichClass FROM
ft, logic => {
IF instance.curRow = row AND p.sideOn = top THEN {
pinPos: SC.Number ← lgRow.rowOrg.p + instance.offset + p.xPos;
upMax ← MAX[upMax, pinPos];
upMin ← MIN[upMin, pinPos]}
ELSE IF instance.curRow = row AND p.sideOn = bottom THEN {
pinPos: SC.Number ← lgRow.rowOrg.p + instance.offset + p.xPos ;
lowMax ← MAX[lowMax, pinPos];
lowMin ← MIN[lowMin, pinPos]}
ELSE IF instance.curRow = row-1 AND p.sideOn = top THEN {
pinPos: SC.Number ← lgRows.rows[row-1].rowOrg.p + instance.offset + p.xPos;
lowMax ← MAX[lowMax, pinPos];
lowMin ← MIN[lowMin, pinPos]}
ELSE IF instance.curRow = row + 1 AND p.sideOn = bottom THEN {
pinPos: SC.Number ← lgRows.rows[row + 1].rowOrg.p + instance.offset + p.xPos;
upMax ← MAX[upMax, pinPos];
upMin ← MIN[upMin, pinPos]}}; -- logic, ft pin
io => {
IF row = 1 AND instance.curSide = bottom AND p.sideOn = top THEN {
pinPos: SC.Number ← bpRows[bottom].sideOrg.p + instance.offset + p.xPos;
lowMax ← MAX[lowMax, pinPos];
lowMin ← MIN[lowMin, pinPos]}
ELSE IF row = lgRows.count AND instance.curSide = top AND p.sideOn = bottom THEN {
pinPos: SC.Number ← bpRows[top].sideOrg.p - instance.offset + p.xPos;
upMax ← MAX[upMax, pinPos];
upMin ← MIN[upMin, pinPos]}}; -- bonding pad pin
ENDCASE};
initialize the limits
lowMax, upMax: SC.Number ← -LAST[INT];
lowMin, upMin: SC.Number ← LAST[INT];
row: SCPrivate.MaxRowSr ← lgRow.rowNum;
run through the pins to find limits
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPin];
now extend the ends for the side exits
IF leftOnChan[(row)-1] THEN {
lowMax ← MAX[lowMax, lgRows.horzRowOrg];
lowMin ← MIN[lowMin, lgRows.horzRowOrg]};
IF leftOnChan[(row + 1)-1] THEN {
upMax ← MAX[upMax, lgRows.horzRowOrg];
upMin ← MIN[upMin, lgRows.horzRowOrg]};
IF rightOnChan[(row)-1] THEN {
lowMax ← MAX[lowMax, lgRows.horzRowOrg + lgRows.maxRowWidth];
lowMin ← MIN[lowMin, lgRows.horzRowOrg + lgRows.maxRowWidth]};
IF rightOnChan[(row + 1)-1] THEN {
upMax ← MAX[upMax, lgRows.horzRowOrg + lgRows.maxRowWidth];
upMin ← MIN[upMin, lgRows.horzRowOrg + lgRows.maxRowWidth]};
got extents on each adajacent channel, now compute wirelength
wireLength ← 0;
IF lowMax > lowMin THEN wireLength ← wireLength + lowMax - lowMin;
IF upMax > upMin THEN wireLength ← wireLength + upMax - upMin};
AddFt
PosProc: SCRowUtil.EachInstProc = {
SCPlaceUtil.ExchPosRow[handle, pos-1, pos, row];
wireLength ← NetWireLength[handle, net, lgRow, leftOnChan, rightOnChan, net.pins];
IF wireLength < savWireLength THEN { -- strict improvement, thats good
savWireLength ← wireLength; savPos ← pos}};
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;
savWireLength, wireLength: SC.Number;
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]];
SCPlaceUtil.PutLgPos[handle, ftInst, lgRow.rowNum, savPos];
savWireLength ← NetWireLength[handle, net, lgRow, leftOnChan, rightOnChan,
net.pins];
try new ft at rest of positions on row
[] ← SCRowUtil.EnumerateInstsOnRow[handle, row, 2, lgRow.nLgsOnRow, PosProc];
found best position, put ft there
SCPlaceUtil.RemvLgComp[handle, ftInst];
SCPlaceUtil.PutLgPos[handle, ftInst, row, savPos]};
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 = {
IF onChan[(chan) - 1] THEN AddExit[handle, rowChan, chanSide, net]};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
acBuses: SCPrivate.AcBuses ← layoutData.acBuses;
chanSide: RTBasic.Side ← RTBasic.OtherSide[side];
instList: SCPrivate.InstanceList ← SCNetUtil.InstsOnNets[LIST[net]];
touchesChan: SCPrivate.ChanSet ← SCInstUtil.ChansForInsts[handle, instList];
net.rowExits[side] ← RTSets.RTMdSetEmpty;
FOR pList: SCPrivate.NetPinsList ← net.pins, pList.rest WHILE pList # NIL DO
instance: SCPrivate.Instance ← pList.first.instance;
pin: SCPrivate.ObjectPin ← pList.first.pin;
get position of instance on side
SELECT instance.whichClass FROM
io => {IF net.feedThrusAllowed THEN {
p: SCInstUtil.PinDescription ← SCInstUtil.PosOf[instance, pin];
IF instance.curSide = side
AND instance.curPos > 0 AND p.sideOn = chanSide THEN {
ChanProc: SCChanUtil.EachRowChanProc = {
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;
useMaxRouteExits: BOOLEAN ← layoutParms.useMaxRouteExits;
useInteriorChanExits: BOOLEAN ← layoutParms.useInteriorChanExits;
SELECT TRUE FROM
~useMaxRouteExits AND ~useInteriorChanExits => SetMinMaxDists;
useMaxRouteExits AND ~useInteriorChanExits =>
IF rowChan.routeType = maxRoute THEN SetMinMaxDists;
~useMaxRouteExits AND useInteriorChanExits =>
IF (1 < chan AND chan < rowChans.count) THEN SetMinMaxDists;
useMaxRouteExits AND useInteriorChanExits =>
IF (1 < chan AND chan < rowChans.count) AND rowChan.routeType = maxRoute 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}}};
logic => {IF ~net.feedThrusAllowed THEN {
chan: SCPrivate.ZMaxChanSr ← 0;
pinSide: RTBasic.Side ← SCInstUtil.PosOf[instance, pin].sideOn;
IF pinSide = bottom THEN chan ← instance.curRow
ELSE IF pinSide = top THEN chan ← instance.curRow + 1;
IF chan # 0 AND net.acBus.onSide = side THEN
IF rowChans.chans[chan].routeType = maxRoute THEN
onChan ← RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(chan)-1]]}};
ENDCASE;
ENDLOOP;
found channels to exit from, indicated in onChan
[] ← SCChanUtil.EnumerateRowChans[handle, ChanExitProc]};
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;
onChan: SCPrivate.ChanSet ← RTSets.RTMdSetUnion[leftOnChan, rightOnChan];
lRow: SCPrivate.ZMaxRowSr ← 1;
uRow: SCPrivate.ZMaxRowSr ← lgRows.count;
found: BOOLEANFALSE;
doRowWidths ← inDoRows;
find lowest row that needs ft
doChanWidth ← inDoChans;
WHILE lRow <= lgRows.count AND NOT found DO
IF onRow[(lRow)-1] OR onChan[(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] OR onChan[(uRow + 1)-1] THEN found ← TRUE
ELSE uRow ← uRow -1;
ENDLOOP;
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, leftOnChan, rightOnChan];
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;
net.ftsOnRow ← RTSets.RTMdSetEmpty;
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
IF numInstances >= 2 THEN {
[onSide, onRow] ← SCRowUtil.RowsForInsts[instList];
IF onSide[LOOPHOLE[SC.Side[left], INTEGER]] OR ~net.feedThrusAllowed 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]] OR ~net.feedThrusAllowed THEN
{rightOnChan ← DetermineExits[handle, right, net];
doSideWidths ← RTSets.RTSmSetUnion[doSideWidths, RTSets.RTSmSetGenerateElement[LOOPHOLE[SCPrivate.LRSide[right], INTEGER]]]};
doChanWidths ← RTSets.RTMdSetUnion[doChanWidths, rightOnChan];
IF net.feedThrusAllowed THEN {
IF onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] AND ~ onRow[(1)-1] THEN {
[] ← AddFt[handle, lgRows.rows[1], net, leftOnChan, rightOnChan];
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, leftOnChan, rightOnChan];
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, 0]};
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;
FOR netLst: SCPrivate.NetList ← nets, netLst.rest WHILE netLst # NIL DO
[] ← EachNet[netLst.first.netNum, 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;
[] ← 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.WriteRope["Remove topological route\n"];
[] ← SCNetUtil.EnumerateNets[handle, NetProc];
SCInstUtil.AllOffsets[handle];
TerminalIO.WriteRope["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];
SCNetUtil.AddConnection[handle, net, ftInst, parms.ftObject.pins.p[1], 1]};
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.rowExits[side] ←
RTSets.RTMdSetUnion[net.rowExits[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.rowExits[lrSide] ← RTSets.RTMdSetDifference[net.rowExits[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]];
IF ~net.feedThrusAllowed THEN SC.Error[programmingError, NIL]};
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]}};
EachChan: SCChanUtil.EachRowChanProc = {
FOR lrSide: SCPrivate.LRSide IN SCPrivate.LRSide DO
IF net.rowExits[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.EnumerateInstsOnNets[LIST[net], EachInst];
SCNetUtil.RemoveFtsOnNet[handle, net];
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.rowExits[left];
globalRoute.nets[globalRoute.numNets].exit[right] ← net.rowExits[right]};
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan];
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
net.ftsOnRow ← RTSets.RTMdSetEmpty;
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, 0]};
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]];
IF ~net.feedThrusAllowed THEN SC.Error[programmingError, NIL];
SCPlaceUtil.PutLgPos[handle, ftInst, row, globalRoute.fts[ftIndex].pos];
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.rowExits[left] ← RTSets.RTMdSetEmpty;
net.rowExits[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.rowExits[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]};
StrippedAddFt: PROCEDURE[handle: SC.Handle, lgRow: SCPrivate.LgRow, net: SCPrivate.Net] = {
add ft's on interior rows as required
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
parms: SCPrivate.Parms ← NARROW[handle.parms];
IF net.ftsOnRow[(lgRow.rowNum)-1] THEN SC.Error[programmingError, NIL];
net.ftsOnRow ← RTSets.RTMdSetUnion[net.ftsOnRow,
RTSets.RTMdSetGenerateElement[(lgRow.rowNum)-1]];
lgRow.size.p ← lgRow.size.p + parms.ftObject.size.p;
lgRow.nFtsOnRow ← lgRow.nFtsOnRow + 1};
StrippedConnectRows: PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, onRow: SCPrivate.RowSet, leftOnChan, rightOnChan: SCPrivate.ChanSet, sign: SC.Number, addFts: BOOLEAN] = {
find lowest row that needs ft
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
onChan: SCPrivate.ChanSet ← RTSets.RTMdSetUnion[leftOnChan, rightOnChan];
uRow: SCPrivate.ZMaxRowSr ← lgRows.count;
lRow: SCPrivate.ZMaxRowSr ← 1;
found: BOOLEANFALSE;
WHILE lRow <= lgRows.count AND ~ found DO
IF onRow[(lRow)-1] OR onChan[(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] OR onChan[(uRow + 1)-1] THEN found ← TRUE
ELSE uRow ← uRow - 1;
ENDLOOP;
add fts to required rows between lrow and urow
IF lRow <= uRow THEN {
numFts: INT ← sign*MAX[uRow - lRow, 0];
rowChans.totNetChans ← rowChans.totNetChans + numFts;
IF onChan[lRow -1] THEN {
rowChan: SCPrivate.RowChan ← layoutData.rowChans.chans[lRow];
rowChans.totNetChans ← rowChans.totNetChans + sign;
rowChan.netChans ← rowChan.netChans + sign};
IF onChan[uRow -1] THEN {
rowChan: SCPrivate.RowChan ← layoutData.rowChans.chans[uRow];
rowChans.totNetChans ← rowChans.totNetChans + sign;
rowChan.netChans ← rowChan.netChans + sign};
FOR row: SCPrivate.ZMaxRowSr IN [lRow .. uRow] DO
lgRow: SCPrivate.LgRow ← layoutData.lgRows.rows[row];
rowChan: SCPrivate.RowChan ← layoutData.rowChans.chans[row];
IF row # lRow THEN rowChan.netChans ← rowChan.netChans + sign;
IF ~ onRow[(row)-1] AND addFts THEN StrippedAddFt[handle, lgRow, net];
ENDLOOP}};
StrippedSmashNets: PUBLIC PROCEDURE[handle: SC.Handle, nets: SCPrivate.NetList] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
FOR netLst: SCPrivate.NetList ← nets, netLst.rest WHILE netLst # NIL DO
net: SCPrivate.Net ← nets.first;
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];
net.ftsOnRow ← RTSets.RTMdSetEmpty;
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
IF numInstances >= 2 THEN {
[onSide, onRow] ← SCRowUtil.RowsForInsts[instList];
IF onSide[LOOPHOLE[SC.Side[left], INTEGER]] OR ~net.feedThrusAllowed THEN
leftOnChan ← DetermineExits[handle, left, net];
IF onSide[LOOPHOLE[SC.Side[right], INTEGER]] OR ~net.feedThrusAllowed THEN
rightOnChan ← DetermineExits[handle, right, net];
IF net.feedThrusAllowed THEN {
IF onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] AND NOT onRow[(1)-1] THEN {
StrippedAddFt[handle, lgRows.rows[1], net];
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(1)-1], onRow]};
IF (onSide[LOOPHOLE[SC.Side[top], INTEGER]]) AND NOT (onRow[(lgRows.count)-1]) THEN {
StrippedAddFt[handle, lgRows.rows[lgRows.count], net];
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(lgRows.count)-1], onRow]};
StrippedConnectRows[handle, net, onRow, leftOnChan, rightOnChan, 1, TRUE]}};
ENDLOOP;
};
StrippedSmashAllNets: PUBLIC PROCEDURE [handle: SC.Handle] = {
add feedthrus to required rows
NetProc: SCNetUtil.EachNetProc = {
StrippedSmashNets[handle, LIST[net]]};
SCRowUtil.AuditRowLengths};
[] ← SCNetUtil.EnumerateNets[handle, NetProc]};
StrippedRemoveSmash: PUBLIC PROCEDURE [handle: SC.Handle] =
{ -- alter the smash of the nets
NetProc: SCNetUtil.EachNetProc = {
StrippedRemoveNetsWFts[handle, LIST[net], FALSE]};
ClearNetChans[handle];
[] ← SCNetUtil.EnumerateNets[handle, NetProc]};
StrippedRemoveNetsWFts: PUBLIC PROCEDURE[handle: SC.Handle, netLst: SCPrivate.NetList, save: BOOLEAN] = {
remove specified nets with fts
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
globalRoute: SCSmash.GlobalRoute ← NARROW[layoutData.globalRoute];
parms: SCPrivate.Parms ← NARROW[handle.parms];
IF save THEN -- save indicates whether current smash is to be saved
{globalRoute.numFts ← 0; globalRoute.numNets ← 0};
FOR nets: SCPrivate.NetList ← netLst, nets.rest WHILE nets # NIL DO
EachRow: SCRowUtil.EachRowProc = {
IF net.ftsOnRow[row - 1] 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, row, 0]];
IF globalRoute.numFts >= SCSmash.maxFtsSaved THEN SC.Error[noResource, NIL]};
lgRow.size.p ← lgRow.size.p - parms.ftObject.size.p;
lgRow.nFtsOnRow ← lgRow.nFtsOnRow - 1;
IF lgRow.nFtsOnRow < 0 OR lgRow.size.p < 0 THEN
SC.Error[programmingError, NIL]}};
net: SCPrivate.Net ← nets.first;
run through the rows fon this net
[] ← SCRowUtil.EnumerateRows[handle, EachRow];
now work on the exits
IF save THEN {
IF globalRoute.numNets >= SCSmash.maxNetsSaved THEN SC.Error[programmingError, NIL];
globalRoute.numNets ← globalRoute.numNets + 1;
globalRoute.nets[globalRoute.numNets].net ← net;
globalRoute.nets[globalRoute.numNets].exit[left] ← net.rowExits[left];
globalRoute.nets[globalRoute.numNets].exit[right] ← net.rowExits[right]};
RemvAllExits[handle, net, left];
RemvAllExits[handle, net, right];
net.ftsOnRow ← RTSets.RTMdSetEmpty;
ENDLOOP};
StrippedRestoreNetsWFts: PUBLIC PROCEDURE[handle: SC.Handle] = {
restore route data for specified nets
first restore the feedthroughs
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
globalRoute: SCSmash.GlobalRoute ← NARROW[layoutData.globalRoute];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
FOR ftIndex: SCSmash.ZMFtsSavedSr DECREASING IN [1 .. globalRoute.numFts] DO
net: SCPrivate.Net ← globalRoute.fts[ftIndex].net;
row: NAT ← globalRoute.fts[ftIndex].row;
lgRow: SCPrivate.LgRow ← lgRows.rows[row];
IF ~net.feedThrusAllowed THEN SC.Error[programmingError, NIL];
StrippedAddFt[handle, lgRow, net];
ENDLOOP;
now the channel exits
FOR netIndex: SCSmash.MNetsSavedSr DECREASING IN [1 .. globalRoute.numNets] DO
ChanProc: SCChanUtil.EachRowChanProc = {
FOR lrSide: SC.Side IN SCPrivate.LRSide DO
RemoveExit[handle, net, rowChan, lrSide];
IF globalRoute.nets[netIndex].exit[lrSide][(rowChan.chanNum)-1] THEN {AddExit[handle, rowChan, lrSide, net]};
ENDLOOP};
net: SCPrivate.Net ← globalRoute.nets[netIndex].net;
net.rowExits[left] ← RTSets.RTMdSetEmpty;
net.rowExits[right] ← RTSets.RTMdSetEmpty;
[] ← SCChanUtil.EnumerateRowChans[handle, ChanProc];
ENDLOOP;
}; -- StrippedRestoreNetsWFts
ModNetChans: PUBLIC PROCEDURE[handle: SC.Handle, nets: SCPrivate.NetList, sign: SC.Number] = {
EachNet: SCNetUtil.EachNetProc = {
onSide: SCPrivate.SideSet;
onRow: SCPrivate.RowSet;
leftOnChan: SCPrivate.ChanSet ← net.rowExits[left];
rightOnChan: SCPrivate.ChanSet ← net.rowExits[right];
instList: SCPrivate.InstanceList ← SCNetUtil.InstsOnNets[LIST[net]];
numInstances: SCPrivate.ZMaxInstanceSr ← SCInstUtil.NumInstsOnList[instList];
IF numInstances >= 2 THEN {
[onSide, onRow] ← SCRowUtil.RowsForInsts[instList];
IF net.feedThrusAllowed THEN {
IF onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] AND ~ onRow[(1)-1] THEN
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(1)-1], onRow];
IF onSide[LOOPHOLE[SC.Side[top], INTEGER]] AND ~ onRow[(lgRows.count)-1] THEN
onRow ← RTSets.RTMdSetUnion[ RTSets.RTMdSetGenerateElement[(lgRows.count)-1], onRow];
StrippedConnectRows[handle, net, onRow, leftOnChan, rightOnChan, sign, FALSE]}}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
[] ← SCNetUtil.EnumerateNets[handle, EachNet]};
ClearNetChans: PUBLIC PROCEDURE [handle: SC.Handle] = {
EachChan: SCChanUtil.EachRowChanProc = {rowChan.netChans ← 0};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
layoutData.rowChans.totNetChans ← 0;
[] ← SCChanUtil.EnumerateRowChans[handle, EachChan]};
}.