<> <> <> <> 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: 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] = { <> 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]}; DetermineExits: PROCEDURE[handle: SC.Handle, side: SCPrivate.LRSide, net: SCPrivate.Net] RETURNS [onChan: SCPrivate.ChanSet _ RTSets.RTMdSetEmpty] = { <> <> ChanExitProc: SCChanUtil.EachRowChanProc = { IF onChan[(chan) - 1] THEN AddExit[handle, rowChan, side, 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.chanExits[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; <> 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; useInteriorChanExits: BOOLEAN _ layoutParms.useInteriorChanExits; SELECT TRUE FROM ~useInteriorChanExits => SetMinMaxDists; 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; <> [] _ SCChanUtil.EnumerateRowChans[handle, ChanProc]; <> 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 onChan _ RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(chan)-1]]}}; ENDCASE; ENDLOOP; <<>> <> [] _ 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 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; <> WHILE lRow <= lgRows.count AND NOT found DO IF onRow[(lRow)-1] THEN found _ TRUE ELSE lRow _ lRow + 1; ENDLOOP; <<>> <> found _ FALSE; WHILE uRow >= 1 AND ~found DO IF onRow[(uRow)-1] THEN found _ TRUE ELSE uRow _ uRow -1; ENDLOOP; <> IF lRow = 1 THEN { net.routeTopology[1] _ [full, full]; DoChans[net, 2, uRow+1, rowChans.count]} ELSE IF lRow = lgRows.count THEN { net.routeTopology[rowChans.count-1] _ [min, min]; net.routeTopology[rowChans.count] _ [full, full]} ELSE { net.routeTopology[lRow] _ IF onChan[lRow-1] THEN [min, min] ELSE [none, none]; DoChans[net, lRow, uRow+1, rowChans.count]}; <> 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]; 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]; 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]}; <<>> <> 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; rowChans: SCPrivate.RowChans _ layoutData.rowChans; 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] = { <> 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.WriteRope["Begin topological route\n"]; [] _ 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] = { <> 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] = { <> <> 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; <<>> <> 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] = { <> 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] = { <> 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] = { <> 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] = { <> layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; globalRoute: SCSmash.GlobalRoute _ NEW[SCSmash.GlobalRouteRec]; layoutData.globalRoute _ globalRoute; doChanWidths _ inDoChans; doSideWidths _ inDoSides; doRowWidths _ inDoRows; <> 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]}; <> 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.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; <<>> <> SCNetUtil.RemoveFtsOnNet[handle, net]; [] _ SCNetUtil.EnumerateInstsOnNets[LIST[net], EachInst]; <> 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]= { <> ChanRowProc: SCRowUtil.EachRowProc = { IF doRowWidths[(row)-1] THEN SCInstUtil.LgOffsets[handle, row, 0, 0]}; CheckConnection: PROCEDURE[net: SCPrivate.Net, leftExitChan, rightExitChan: SCPrivate.RowChan] = { <> 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]}}; <> <> 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; <> [] _ SCRowUtil.EnumerateRows[handle, ChanRowProc]; <<>> <> 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]; <> CheckConnection[net, exitChan[left], exitChan[right]]; ENDLOOP; <<>> IF debug THEN {CheckExits[handle]; CheckFts[handle]}; }; CheckExits: PUBLIC PROCEDURE [handle: SC.Handle] = { <> 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] = { <> EachNet: SCNetUtil.EachNetProc = {CheckFtsOnNet[handle, net]}; [] _ SCNetUtil.EnumerateNets[handle, EachNet]}; CheckFtsOnNet: PUBLIC PROCEDURE[handle: SC.Handle, net: SCPrivate.Net] = { <> 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 <> SC.Error[programmingError, NIL]; IF netPin1 = net THEN { IF ftsOnRow[row-1] THEN <> 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 <> SC.Error[programmingError, NIL]}; CleanUpNet: PROCEDURE [handle: SC.Handle, net: SCPrivate.Net] = { <> EachChan: SCChanUtil.EachRowChanProc = {net.routeTopology[chan] _ [none, none]}; net.ftsOnRow _ RTSets.RTMdSetEmpty; RemvAllExits[handle, net, left]; RemvAllExits[handle, net, right]; [] _ SCChanUtil.EnumerateRowChans[handle, EachChan]}; }.