<> <> 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: BOOLEAN _ FALSE; AddFt: PROCEDURE[handle: SC.Handle, lgRow: SCPrivate.LgRow, net: SCPrivate.Net, leftOnChan, rightOnChan: SCPrivate.ChanSet] RETURNS [ftInst: SCPrivate.Instance] = { <> NetWireLength: PROCEDURE[handle: SC.Handle, net: SCPrivate.Net, lgRow: SCPrivate.LgRow, leftOnChan, rightOnChan: SCPrivate.ChanSet, pins: SCPrivate.NetPinsList] RETURNS [wireLength: SC.Number] = { <> 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}; <> lowMax, upMax: SC.Number _ -LAST[INT]; lowMin, upMin: SC.Number _ LAST[INT]; row: SCPrivate.MaxRowSr _ lgRow.rowNum; <> [] _ SCNetUtil.EnumeratePinsOnNet[net, EachPin]; <<>> <> 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]}; <> wireLength _ 0; IF lowMax > lowMin THEN wireLength _ wireLength + lowMax - lowMin; IF upMax > upMin THEN wireLength _ wireLength + upMax - upMin}; <> 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]; <> [] _ SCRowUtil.EnumerateInstsOnRow[handle, row, 2, lgRow.nLgsOnRow, PosProc]; <<>> <> 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] = { <> <> 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; <> 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; <> [] _ 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 IF rowChans.chans[chan].routeType = maxRoute THEN onChan _ RTSets.RTMdSetUnion[onChan, RTSets.RTMdSetGenerateElement[(chan)-1]]}}; ENDCASE; ENDLOOP; <<>> <> [] _ 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: BOOLEAN _ FALSE; doRowWidths _ inDoRows; <> 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; <<>> <> 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; <<>> <> 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]; <<>> <> 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] = { <> 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] = { <> 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.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] = { <> 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.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] = { <> 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.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; <<>> <> [] _ SCNetUtil.EnumerateInstsOnNets[LIST[net], EachInst]; SCNetUtil.RemoveFtsOnNet[handle, net]; <> 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]= { <> 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.rowExits[left] _ RTSets.RTMdSetEmpty; net.rowExits[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.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] = { <> 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]}; StrippedAddFt: PROCEDURE[handle: SC.Handle, lgRow: SCPrivate.LgRow, net: SCPrivate.Net] = { <> 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] = { <> 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: BOOLEAN _ FALSE; WHILE lRow <= lgRows.count AND ~ found DO IF onRow[(lRow)-1] OR onChan[(lRow)-1] THEN found _ TRUE ELSE lRow _ lRow + 1; ENDLOOP; <<>> <> 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; <<>> <> 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] = { <> NetProc: SCNetUtil.EachNetProc = { StrippedSmashNets[handle, LIST[net]]}; <> [] _ 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] = { << >> <> 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; <<>> <> [] _ SCRowUtil.EnumerateRows[handle, EachRow]; <> 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] = { <> <> 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; <> 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]}; }.