<> <> <> <> 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; 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] = { <> 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 = { <> <> SELECT netPin.instance.whichClass FROM ft, logic => { IF netPin.instance.curRow # 0 THEN { <> 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}; <> [] _ SCNetUtil.EnumeratePinsOnNet[net, EachPin]; <> 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]]; <> 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}; <> 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; <> IF midPos = 0 THEN midPos _ lgRow.nLgsOnRow + 1}; 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[(lgRow.rowNum)-1] THEN SC.Error[programmingError, NIL]; net.ftsOnRow _ RTSets.RTMdSetUnion[net.ftsOnRow, RTSets.RTMdSetGenerateElement[(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: 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]}; EachPinProc: SCNetUtil.EachPinProc = { <> instance: SCPrivate.Instance _ netPin.instance; pin: SCPrivate.ObjectPin _ netPin.pin; <> 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 { IF rowChans.count <= 2 THEN <> onChan _ RTSets.RTMdSetGenerateElement[(1)-1] ELSE { <> 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; 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] + 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}}}}; 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]; <<>> <> [] _ 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; <> 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]; 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]}; <> 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]; <<>> <> 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] = { <> 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] = { <> 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] = { <> <> 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, 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] = { <> 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] _ NEW[SCPrivate.ExitRec _ [net: net, pos: 0, pinInChan: NIL, 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]]}; <> 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; <<>> <> 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, SCPrivate.maxPos]}; 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]]; 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; <> [] _ 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]}; }.