DIRECTORY IO, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCPrivate, SCRowUtil, SCPlaceUtil, Rope, RTSets, SCSmash, SCUtil, SCWidthUtil, TerminalIO; SCSmashImpl: CEDAR PROGRAM IMPORTS IO, Rope, 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: PROC[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.RTLgSetUnion[net.ftsOnRow, RTSets.RTLgSetGenerateElement[(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: PROC[handle: SC.Handle, side: SCPrivate.LRSide, net: SCPrivate.Net] RETURNS [onChan: SCPrivate.ChanSet _ RTSets.RTLgSetEmpty] = { 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 { ChanProc: SCChanUtil.EachRowChanProc = { chanPos: SC.Number _ rowChan.chanPos + rowChan.chanWidth/2; dist: SC.Number _ ABS[chanPos - holdBpPos]; useThisChan: BOOLEAN _ (1 < chan AND chan < rowChans.count) OR (chan = 1 AND rowChans.count = 2); IF useThisChan AND dist < minDist THEN {minDistChan _ chan; minDist _ dist}; IF useThisChan AND touchesChan[(chan)-1] THEN { IF chanPos > maxChanPos THEN {maxChan _ chan; maxChanPos _ chanPos}; IF chanPos < minChanPos THEN {minChan _ chan; minChanPos _ chanPos}}}; minDist, minChanPos: SC.Number _ LAST[INT]; maxChanPos: SC.Number _ FIRST[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.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(maxChan)-1]]; holdBpPos < minChanPos AND minChan > 0 => onChan _ RTSets.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(minChan)-1]]; minDistChan > 0 => onChan _ RTSets.RTLgSetUnion[onChan, RTSets.RTLgSetGenerateElement[(minDistChan)-1]]; ENDCASE => SC.Error[programmingError, "Not suppose to happen."]}}}; 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.RTLgSetEmpty; [] _ SCNetUtil.EnumeratePinsOnNet[net, EachPinProc]; [] _ 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 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: PROC[handle: SC.Handle, net: SCPrivate.Net, onRow: SCPrivate.RowSet, onSide: SCPrivate.SideSet, 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.RTLgSetUnion[leftOnChan, rightOnChan]; lRow: SCPrivate.MaxRowSr _ 1; uRow: SCPrivate.ZMaxRowSr _ lgRows.count; found: BOOLEAN _ FALSE; doRowWidths _ inDoRows; doChanWidth _ inDoChans; IF ~onSide[LOOPHOLE[SC.Side[bottom], INTEGER]] THEN { WHILE lRow <= lgRows.count AND NOT found DO IF onRow[(lRow)-1] OR leftOnChan[(lRow)-1] OR rightOnChan[(lRow)-1] THEN found _ TRUE ELSE lRow _ lRow + 1; ENDLOOP}; found _ FALSE; IF ~onSide[LOOPHOLE[SC.Side[top], INTEGER]] THEN { WHILE uRow >= 1 AND ~found DO IF onRow[(uRow)-1] OR leftOnChan[(uRow+1)-1] OR rightOnChan[(uRow+1)-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[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] OR leftOnChan[lRow-1] OR rightOnChan[lRow-1] THEN [min, min] ELSE [none, none]; DoChans[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.RTLgSetUnion[doRowWidths, RTSets.RTLgSetGenerateElement[(row)-1]]; doChanWidth _ RTSets.RTLgSetUnion[doChanWidth, RTSets.RTLgSetAddElement[(row)-1, RTSets.RTLgSetGenerateElement[(row + 1)-1]]]}; ENDLOOP}; SmashNets: PUBLIC PROC[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: PROC [net: SCPrivate.Net] = { onSide: SCPrivate.SideSet; onRow: SCPrivate.RowSet; leftOnChan, rightOnChan: SCPrivate.ChanSet _ RTSets.RTLgSetEmpty; 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.RTLgSetUnion[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.RTLgSetUnion[doChanWidths, rightOnChan]}; [doChanWidths, doRowWidths] _ ConnectRows[handle, net, onRow, onSide, 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]; ENDLOOP; IF debug THEN {CheckExits[handle]; CheckFts[handle]}; }; SmashAllNets: PUBLIC PROC [handle: SC.Handle, doChanWidths: BOOLEAN] = { NetProc: SCNetUtil.EachNetProc = { [] _ SmashNets[handle, LIST[net], doChanWidths, RTSets.RTLgSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTLgSetEmpty]}; 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 PROC [handle: SC.Handle] = { NetProc: SCNetUtil.EachNetProc = { [] _ SCSmash.RemoveNetsWFts[handle, LIST[net], FALSE, RTSets.RTLgSetEmpty, RTSets.RTSmSetEmpty, RTSets.RTLgSetEmpty]}; TerminalIO.PutRope["Remove topological route\n"]; [] _ SCNetUtil.EnumerateNets[handle, NetProc]; SCInstUtil.AllOffsets[handle]; TerminalIO.PutRope["End remove topological route\n"]}; ReSmash: PUBLIC PROC [handle: SC.Handle, doChanWidths: BOOLEAN] = { RemoveSmash[handle]; SmashAllNets[handle, doChanWidths]}; NewFt: PUBLIC PROC[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]]; ftObject: SCPrivate.Object _ SELECT TRUE FROM Rope.Equal["Vdd", net.name] => parms.vddObject, Rope.Equal["Gnd", net.name] => parms.gndObject, ENDCASE => parms.ftObject; ftInst _ SCInstUtil.DefineInstance[handle, name, ftObject, 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 PROC[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.RTLgSetUnion[net.chanExits[side], RTSets.RTLgSetGenerateElement[(rowChan.chanNum)-1]]; rowChan.exits[side][index] _ NEW[SCPrivate.ExitRec _ [net: net, pos: 0, pinInChan: NIL, layer: handle.rules.rowRules.trunkLayer]]}}; RemvAllExits: PUBLIC PROC[handle: SC.Handle, net: SCPrivate.Net, lRSide: SCPrivate.LRSide] = { ChanProc: SCChanUtil.EachRowChanProc = { RemoveExit[handle, net, rowChan, lRSide]}; [] _ SCChanUtil.EnumerateRowChans[handle, ChanProc]}; RemoveExit: PUBLIC PROC[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.RTLgSetDifference[net.chanExits[lrSide], RTSets.RTLgSetGenerateElement[(rowChan.chanNum)-1]]; [] _ SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ChanExitProc]; rowChan.numExits[lrSide] _ index}; RemoveNetsWFts: PUBLIC PROC[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.RTLgSetUnion[doRowWidths, RTSets.RTLgSetGenerateElement[(instance.curRow)-1]]; doChanWidths _ RTSets.RTLgSetUnion[ RTSets.RTLgSetUnion[doChanWidths, RTSets.RTLgSetGenerateElement[(instance.curRow)-1]], RTSets.RTLgSetGenerateElement[(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.RTLgSetUnion[doChanWidths, RTSets.RTLgSetGenerateElement[(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 PROC[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: PROC[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.RTLgSetUnion[doRowWidths, RTSets.RTLgSetGenerateElement[(row)-1]]; doChanWidths _ RTSets.RTLgSetUnion[doChanWidths, RTSets.RTLgSetAddElement[(row)-1, RTSets.RTLgSetGenerateElement[(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.RTLgSetUnion[doChanWidths, RTSets.RTLgSetGenerateElement[(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.RTLgSetEmpty; net.chanExits[right] _ RTSets.RTLgSetEmpty; [] _ SCChanUtil.EnumerateRowChans[handle, ChanRowProc]; CheckConnection[net, exitChan[left], exitChan[right]]; ENDLOOP; IF debug THEN {CheckExits[handle]; CheckFts[handle]}; }; CheckExits: PUBLIC PROC [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.RTLgSetIsSubset[ RTSets.RTLgSetGenerateElement[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 PROC [handle: SC.Handle] = { EachNet: SCNetUtil.EachNetProc = {CheckFtsOnNet[handle, net]}; [] _ SCNetUtil.EnumerateNets[handle, EachNet]}; CheckFtsOnNet: PUBLIC PROC[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.RTLgSetUnion[ftsOnRow, RTSets.RTLgSetGenerateElement[(row)-1]]}}}; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, PosProc]}; ftsOnRow: SCPrivate.RowSet _ RTSets.RTLgSetEmpty; [] _ SCRowUtil.EnumerateRows[handle, EachRow]; IF ~RTSets.RTLgSetIsSame[ftsOnRow, net.ftsOnRow] THEN SC.Error[programmingError, NIL]}; CleanUpNet: PROC [handle: SC.Handle, net: SCPrivate.Net] = { EachChan: SCChanUtil.EachRowChanProc = {net.routeTopology[chan] _ [none, none]}; net.ftsOnRow _ RTSets.RTLgSetEmpty; RemvAllExits[handle, net, left]; RemvAllExits[handle, net, right]; [] _ SCChanUtil.EnumerateRowChans[handle, EachChan]}; }. ZSCSmashImpl.mesa Copyright Σ 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reserved. Frank Bowers February 13, 1986 11:04:31 am PST Preas March 26, 1988 6:53:42 pm PST Jean-Marc Frailong October 11, 1987 3:41:03 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 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šœN™NKšœ+Οk™.Kšœ#™#K™2—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˜JKšœ!˜(Kšœ&™&K˜Kšœ#œ˜=Kšœ-˜-Kšœ-˜-K˜'Kšœ˜Kšœ#˜#Kšœ œœœ˜Gšœ1˜1Kšœ1˜1—K™Kšœ+Οc9˜dšœTœ˜\K˜——šžœœ œ4˜SKšœ6˜=Kšœ(™(K˜Kšœ0™0šž œ ˜,KšœZ™ZKšœœ&˜@K˜—šž œ˜&Kšœ=™=Kšœ/˜/Kšœ&˜&K˜Kšœ!™!šœœ˜"Kšœ9˜9Kšœ@˜@šœœœœ˜OKšœ+™+šžœ ˜(Kšœ9œœœ™ZK˜Kšœ œ0˜;Kšœœ œ˜+Kš œ œ œœ œ˜aKšœ œœ&˜Lšœ œœ˜/Kšœœ(˜DKšœœ*˜F—K˜—Kšœœ œœ˜+Kšœ œ œœ˜#Kšœ8˜8Kšœ œ4˜AK˜Kšœ1™1Kšœ4˜4K˜Kšœ™šœœ˜šœœ˜)KšœQ˜QK˜—šœœ˜)KšœQ˜Q—K˜šœ˜KšœU˜U—Kš?œ˜C———K˜—Kšœ#œ˜=Kšœ3˜3Kšœ1˜1Kšœ9œ˜DKšœL˜LK˜Kšœ*˜*K˜Kšœ4˜4K™Kšœ1™1Kšœ9˜9K˜—šžœœE˜RK˜KšœJ˜Jšœœœ˜5šœ˜Kšœ&˜&—šœœœ˜ šœ˜Kšœœ œ˜@——šœ˜šœ˜Kšœœ œ˜?——Kšœ'˜'Kšœ˜ —K˜—šž œœ œ€˜ΐKšœD˜KK˜Kšœ#œ˜=Kšœ-˜-Kšœ3˜3KšœI˜IKšœ˜Kšœ)˜)Kšœœœ˜Kšœ˜Kšœ˜K˜Kšœ™š œ œœœœ˜5šœœœ˜+šœœœ˜HKšœ˜ —Kšœ˜Kšœ˜ ——K™Kšœ™Kšœœ˜š œ œœ œœ˜2šœ œ˜šœœœ˜LKšœ˜ —Kšœ˜Kšœ˜ K˜——KšœG™Gšœ œ˜Kšœ$˜$Kšœœœœ ˜OKšœ(˜(—šœœœ˜"Kšœ3˜3Kšœ1˜1—šœ˜Kš œœœœœ œ˜{Kšœ.˜.—K˜Kšœ0™0šœœœ˜1šœœ˜šœ*˜*KšœW˜Wšœ/˜/Kšœ"˜"Kšœ.˜.——Kšœ˜ ——K˜—š ž œœœ œ,œ[˜―Kšœh˜oK˜šžœœ˜&Kšœ˜Kšœ˜KšœA˜AKšœ9œ˜DKšœM˜MK˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜K˜Kšœ3˜3K˜š œœœ œ˜0Kšœ0˜0KšœOœœ˜{Kšœ>˜>—K˜š œœœœ˜1Kšœ2˜2KšœOœœ˜|Kšœ?˜?—K˜Kšœz˜zK™Kšœ™šœ œ˜Kšžœœœ9˜xšžœ!œ˜GKšœ]œ˜d—K˜Kšœ.˜.Kšœ6˜6K˜——Kšœ#œ˜=Kšœ-˜-Kšœ3˜3šœ/œ œœ˜HKšœ˜Kšœ˜K˜—Kšœœ(˜5Kšœ˜K˜—š ž œœœ œœ˜HKšœ™K˜šžœ˜"KšœœU˜p—K˜Kšœ#œ˜=Kšœ-˜-Kšœ0˜0Kšœ"˜"Kšœ˜Kšœ.˜.Kšœ˜KšœG˜GKšœ+˜+Kšœ˜KšœP˜PK˜—šž œœœ œ ˜0Kšœ™šžœ˜"Kšœ$œœB˜v—K˜Kšœ1˜1Kšœ.˜.Kšœ˜Kšœ6˜6K˜—š žœœœ œœ˜CKšœ˜Kšœ$˜$K˜—š žœœœ œ5œ!˜zKšœ™KšœE™EKšœœ˜.Kš œ œœœœ˜Mšœœ˜-Kšœ/˜/Kšœ/˜/Kšœ˜—Kšœ;œ˜@K˜K™Kšœ9™9KšœQ˜QKšœR˜RK™—š žœœœ œ+œ˜jKšœ™K˜Kšœœœœ˜;šœ˜Kšœœ7˜Ašœ˜Kšœ]˜]—Kšœ„˜„—K˜—šž œœœ œ:˜^Kšœ%™%K˜šžœ ˜(Kšœ*˜*—K˜Kšœ5˜5K˜—šž œœœ œV˜xKšœ™šž œ˜)šœœ˜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˜šž œœœ œ ˜EKšœ$™$K˜šžœ˜"šžœ˜#šœœ˜"Kšœ3˜3Kšœ3˜3š œ œœ œœ˜;Kšœ™Kšœœ˜ —šœœ˜šœ˜Kšœ0™0Kšœœ˜ —KšœT˜T——K˜—Kšœ=˜=K˜—Kšœ1˜1Kšœ.˜.šœ/˜5Kšœ-™-Kšœœ˜!——K˜šž œœ œ ˜