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]}; }. >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 find a position for the feedthru PROC [netPin: SCPrivate.NetPin] RETURNS [quit: BOOL _ FALSE]; update positions of pins above and below the feedthru netPin.instance.curRow = 0 iff it is THIS feddthru find pin positions above and below this row include left and right exits find location for the feedthru find position closest to location; this HACK should be improved maybe pin is beyond the last instance orgin add ft's on interior rows as required add side exits as required to net lists find preferred position for exit to side surface PROC [chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOL _ FALSE]; PROC [netPin: SCPrivate.NetPin] RETURNS [quit: BOOL _ FALSE]; get position of instance on side exit must be on bottom channel must compute the channel to put the exit on PROC [chan: SCPrivate.MaxChanSr, rowChan: SCPrivate.RowChan] RETURNS [quit: BOOL _ FALSE]; find distance of port to closest existing channel determine channel to exit found channels to exit from, indicated in onChan find lowest row that needs ft find upper row that needs ft determine global route for channels between lChan and uChan inclusive add fts to required rows between lrow and urow now update the channel widths add feedthrus to required rows alter the smash of the nets add ft to row width get a component entry for the ft, construct a new entry for instance construct and add an entry to net list for this instance add an exit to a channel remove all exits for net on a lRSide remove an exit for net on chan remove specified nets with fts save indicates whether current smash is to be saved now remove the ft run through the comps on this net now work on the exits save route data for specified nets make sure feed throughs are in proper channels RestoreNetsWFts first restore the feedthroughs find row widths now the channel exits check to make sure the net is connected audit the exits for consistancy audit the Fts on all nets for consistancy audit the Fts on net for consistancy error in connection of net more than one ft on row for this net on this row row data does not correspond to instance data remove the global route on nets Κ)˜codešœ™KšœH™HKšœ+Οk™.Kšœ"™"—K˜š ˜ Kšœ œ˜K˜—šΟn œœ˜Kšœœ œm˜„Kšœ˜Kšœœ˜K˜Kšœœœ˜K˜—šž œœœœ˜9Kšœœœ˜&K˜—šžœœœ ˜9Kšœœœ˜)K˜—šž œœ œ5œ&˜€Kšœ ™ K˜Kšœœ1˜RKš œœœ œœ ˜@Kš œœœ œœ ˜@Kšœœ˜K˜šžœ˜"Kšœœœœ™=Kšœ5™5šœ˜'šœ˜šœœ˜$Kšœ2™2Kšœœ=˜GKšœœF˜Nšœœ˜Kšœ(œœE˜…Kšœ(œœH˜“Kšœ˜ ———šœ˜šœ"œœ˜KKšœœ4˜<šœœ˜KšœH˜HKšœS˜SKšœ˜ ———Kšœ˜ —K˜—Kšœ+™+šœ1˜1K˜—Kšœ™šœ%˜+KšœN˜N—šœ#˜)KšœN˜N—šœ&˜,Kšœx˜x—šœ$˜*Kšœd˜d—K˜Kšœ™šœœ˜šœœ˜6šœ*˜0Kšœ7˜7—š˜Kšœ5˜5——Kšœ5˜5Kšœ5˜5šœ˜ KšœD˜FKšœ2˜2—K˜—Kšœ(œ™?šœ9œ ˜OšœNœ˜hKšœ˜—K˜—Kšœ+™+Kšœ œ˜1K˜—šžœ œ œ4˜OKšœ!˜(Kšœ&™&K˜Kšœ#œ˜=Kšœ-˜-Kšœ-˜-K˜'Kšœ˜Kšœ#˜#Kšœ œœœ˜Gšœ1˜1Kšœ1˜1—K™Kšœ+Οc9˜dšœTœ˜\K˜——šžœ œ œ4˜XKšœ6˜=Kšœ(™(K˜Kšœ0™0šž œ ˜,KšœZ™ZKšœœ&˜@K˜—šž œ˜&Kšœ=™=Kšœ/˜/Kšœ&˜&K˜Kšœ!™!šœœ˜"Kšœ9˜9Kšœ@˜@šœ˜Kšœœœ˜4šœœ˜Kšœ™Kšœ-˜-—šœ˜Kšœ+™+šžœ ˜(Kšœ9œœœ™Zšœœ˜K˜šžœ œ˜Kšœœœ&˜=Kšœœ(˜Dšœœ)˜EK˜——Kšœ œ0˜;Kšœœ œ˜+Kšœ<˜˜>K˜š œœœœœœ˜GKšœ(˜(KšœU˜UKšœJ˜JKšœ”˜”—K˜š œ œœ œœœ˜PKšœ3˜3Kšœ`˜`KšœU˜UKšœ―˜―—K˜Kšœr˜rK™Kšœ™šœ œ˜Kšžœœœ9˜xšžœ!œ˜GKšœ]œ˜d—K˜Kšœ.˜.Kšœ6˜6K˜——Kšœ#œ˜=Kšœ-˜-Kšœ3˜3šœ/œ œœ˜HKšœ-˜-Kšœ˜K˜—Kšœœ(˜5Kšœ˜K˜—š ž œœ œ œœ˜MKšœ™K˜šžœ˜"KšœœU˜p—K˜Kšœ#œ˜=Kšœ-˜-Kšœ0˜0Kšœ"˜"Kšœ˜Kšœ.˜.Kšœ˜KšœG˜GKšœ+˜+Kšœ˜KšœP˜PK˜—šž œœ œ œ ˜5Kšœ™šžœ˜"Kšœ$œœB˜v—K˜Kšœ1˜1Kšœ.˜.Kšœ˜Kšœ6˜6K˜—š žœœ œ œœ˜HKšœ˜Kšœ$˜$K˜—š žœœ œ œ5œ!˜Kšœ™KšœE™EKšœœ˜.Kš œ œœœœ˜MKšœAœœ˜KK˜K™Kšœ9™9KšœQ˜QKšœR˜RK™—š žœœ œ œ+œ˜oKšœ™K˜Kšœœœœ˜;šœ˜Kšœœ7˜Ašœ˜Kšœ]˜]—Kšœ„˜„—K˜—šž œœ œ œ:˜cKšœ%™%K˜šžœ ˜(Kšœ*˜*—K˜Kšœ5˜5K˜—šž œœ œ œV˜}Kšœ™šž œ˜)šœœ˜Kšœ˜Kšœ@˜@——K˜Kšœ!˜!Kšœ|˜|KšœF˜FKšœ"˜"K˜—š žœœ œ œ*œ[˜·˜Kšœh˜o—Kšœ™K˜Kšœ#œ˜=Kšœ#œ˜?Kšœ%˜%Kšœ˜Kšœ˜Kšœ˜K˜Kšœ4™4Kšœœ0˜Kšœ/˜/—K˜šž œœ œ œ ˜JKšœ$™$K˜šžœ˜"šžœ˜#šœœ˜"Kšœ3˜3Kšœ3˜3š œ œœ œœ˜;Kšœ™Kšœœ˜ —šœœ˜šœ˜Kšœ0™0Kšœœ˜ —KšœT˜T——K˜—Kšœ=˜=K˜—Kšœ1˜1Kšœ.˜.šœ/˜5Kšœ-™-Kšœœ˜!——K˜šž œ œ œ ˜AKšœ™K˜KšžœI˜QK˜Kšœ#˜#Kšœ ˜ Kšœ!˜!Kšœ5˜5—Kšœ˜—…—W v