<> <> <> <<>> DIRECTORY CD, RTBasic, SC, SCChanUtil, SCNetUtil, SCPrivate, SCNewRoutePinsUtil, SCRowUtil, SCNewWidth, SCWidthUtil, SCInstUtil, TerminalIO, IO; SCNewWidthImpl: CEDAR PROGRAM IMPORTS RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCNewRoutePinsUtil, SCRowUtil EXPORTS SCNewWidth SHARES SC = BEGIN vertWireToAreaFact: SC.Number _ 3; horzWireToAreaFact: SC.Number _ 3; ChanNetList: TYPE = LIST OF SCNewRoutePinsUtil.ChanNetDat; GetChanWidth: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, form: SCPrivate.FomType, doWidth: BOOLEAN] RETURNS [chanWidth, wireLength: SC.Number _ 0] = { -- lambda: SC.Number _ handle.rules.rowParms.technology.lambda; [chanWidth, wireLength] _ SetAuxiDS[handle, rowChan, form, doWidth]; -- TerminalIO.PutF[" Channel: %g, Width: %g, WireLength: %g\n", IO.int[rowChan.chanNum], IO.int[chanWidth/lambda], IO.int[wireLength/lambda]]; TermGetChanWidth[handle, rowChan]}; <> GetSideWidth: PUBLIC PROCEDURE[handle: SC.Handle, lRSide: SCPrivate.LRSide, fom: SCPrivate.FomType] RETURNS [chanWidth, wireLength: SC.Number _ 0] = {}; <> AllChanWidths: PUBLIC PROCEDURE[handle: SC.Handle, fom: SCPrivate.FomType] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; SideChan: SCChanUtil.EachSideChanProc = { [sideChan.sideChanWidth, sideChan.wireLength] _ GetSideWidth[handle, lrSide, fom]}; RowChan: SCChanUtil.EachRowChanProc = { [rowChan.chanWidth, rowChan.wireLength] _ GetChanWidth[handle, rowChan, fom, TRUE]}; [] _ SCChanUtil.EnumerateRowChans[handle, RowChan]; [] _ SCChanUtil.EnumerateSideChans[handle, SideChan]}; TermGetChanWidth: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan] = { InstProc: SCRowUtil.EachInstProc = { <<>> PinProc: SCInstUtil.EachPinProc = {netPin.pinInChan _ NIL}; [ ] _ SCInstUtil.EnumeratePinsOnInst[instance, PinProc]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; chanNum: NAT _ rowChan.chanNum; IF chanNum = 1 THEN { [] _ SCRowUtil.EnumerateAllInstsOnSide[handle, bottom, InstProc]; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle,1, InstProc]} ELSE IF chanNum = layoutData.rowChans.count THEN { [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, layoutData.lgRows.count, InstProc]; [] _ SCRowUtil.EnumerateAllInstsOnSide[handle, top, InstProc]} ELSE { [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, chanNum - 1, InstProc]; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, chanNum, InstProc]}; SCNewRoutePinsUtil.TermGetChanPins[handle, rowChan]; }; SetAuxiDS: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, form: SCPrivate.FomType, doWidth: BOOLEAN] RETURNS[chanWidth, chanWL: SC.Number _ 0] = { pinsHead, pinsTail: SCNewRoutePinsUtil.PinInChan _ NIL; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; IF doWidth THEN { lgRows: SCPrivate.LgRows _ layoutData.lgRows; rowChans: SCPrivate.RowChans _ layoutData.rowChans; pitch: SC.Number _ handle.rules.rowRules.trunkToTrunk; SCNewRoutePinsUtil.InitGetChanPins[handle, rowChan]; <> IF rowChan.chanNum = 1 THEN { EnterSideData[rowChan, handle, bottom, top, bottom]; EnterRowData[rowChan, handle, 1, bottom]} ELSE IF rowChan.chanNum = rowChans.count THEN { EnterRowData[rowChan, handle, lgRows.count, top]; EnterSideData[rowChan, handle, top, bottom, top]} ELSE { EnterRowData[rowChan, handle, rowChan.chanNum-1, top]; EnterRowData[rowChan, handle, rowChan.chanNum, bottom]}; EnterExitData[handle, rowChan, left]; EnterExitData[handle, rowChan, right]; InitProcess[handle, rowChan]; chanWL _ rowChan.wireLength; IF form = wlFom THEN { chanWidth _ chanWL * pitch * horzWireToAreaFact / lgRows.maxRowWidth; rowChan.chanWidth _ chanWidth} ELSE { chanWidth _ 2*handle.rules.rowRules.trunkToEdge + pitch*(rowChan.chanDensity-1); rowChan.chanWidth _ chanWidth}}}; EnterRowData: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, handle: SC.Handle, row: SCPrivate.MaxRowSr, interestingSide: SC.Side] = { <> InstProc: SCRowUtil.EachInstProc = { <> PinProc: SCInstUtil.EachPinProc = { <> IF netPin.pin # NIL AND netPin.net # NIL THEN { pinList: SCNewRoutePinsUtil.PinList _ NARROW[netPin.net.pinList]; IF SCInstUtil.PosOf[instance, netPin.pin].sideOn = interestingSide THEN { alwaysUse: BOOLEAN _ netPin.net.externNet = externalNet AND (chan = 1 AND SCNetUtil.ExitOnSide[handle, netPin.net, bottom]) OR (chan = rowChans.count AND SCNetUtil.ExitOnSide[handle, netPin.net, top]); rowOffset: SC.Number _ lgRows.horzRowOrg + lgRow.rowOrg.p; rect: CD.Rect _ SCInstUtil.RotateRect[instance, netPin.pin.rect]; min: SC.Number _ rowOffset + instance.offset + rect.x1; tail: SCNewRoutePinsUtil.PinInChan _ SCNewRoutePinsUtil.EnterPin[rowChan: rowChan, min: min, max: min + rect.x2 - rect.x1, depth: 0, layer: netPin.pin.layer, net: netPin.net, side: RTBasic.OtherSide[interestingSide], alwaysUse: alwaysUse]; netPin.pinInChan _ tail; pinList _ CONS[tail, pinList]; netPin.net.pinList _ pinList}}}; [ ] _ SCInstUtil.EnumeratePinsOnInst[instance, PinProc]}; rowChans: SCPrivate.RowChans _ NARROW[handle.layoutData, SCPrivate.LayoutData].rowChans; lgRows: SCPrivate.LgRows _ NARROW[handle.layoutData, SCPrivate.LayoutData].lgRows; lgRow: SCPrivate.LgRow _ lgRows.rows[row]; chan: SCPrivate.MaxChanSr _ rowChan.chanNum; [ ] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, InstProc]}; <> EnterSideData: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, handle: SC.Handle, side, interestingSide, chanSide: SC.Side] = { <> <> <> <<>> InstProc: SCRowUtil.EachInstProc = { PinProc: SCInstUtil.EachPinProc = { IF netPin.pin # NIL THEN { pd: SCInstUtil.PinDescription _ SCInstUtil.PosOf[instance, netPin.pin]; IF pd.sideOn = interestingSide AND netPin.net # NIL THEN { net: SCPrivate.Net _ netPin.net; IF net # NIL THEN { pinList: SCNewRoutePinsUtil.PinList _ NARROW[netPin.net.pinList]; rect: CD.Rect _ SCInstUtil.RotateRect[instance, netPin.pin.rect]; pqMin: SC.Number _ SELECT side FROM bottom, top => bpRow.sideOrg.p + instance.offset + rect.x1, left, right => bpRow.sideOrg.q + instance.offset + rect.y1, ENDCASE => SC.Error[programmingError, "Not suppose to happen."]; pqMax: SC.Number _ SELECT side FROM bottom, top => pqMin + rect.x2 - rect.x1, left, right => pqMin + rect.y2 - rect.y1, ENDCASE => SC.Error[programmingError, "Not suppose to happen."]; tail: SCNewRoutePinsUtil.PinInChan _ SCNewRoutePinsUtil.EnterPin[rowChan: rowChan, min: pqMin, max: pqMax, depth: 0, layer: netPin.pin.layer, net: netPin.net, side: chanSide, alwaysUse: TRUE]; netPin.pinInChan _ tail; pinList _ CONS[tail, pinList]; netPin.net.pinList _ pinList}}}}; [ ] _ SCInstUtil.EnumeratePinsOnInst[instance, PinProc]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; [ ] _ SCRowUtil.EnumerateAllInstsOnSide[handle, side, InstProc]}; <> EnterExitData: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan, lrSide: SCPrivate.LRSide] = { ExitProc: SCChanUtil.EachExitProc = { <> pos: SC.Number _ IF lrSide = left THEN lgRows.horzRowOrg ELSE lgRows.horzRowOrg + lgRows.maxRowWidth; pinList: SCNewRoutePinsUtil.PinList _ NARROW[exit.net.pinList]; tail: SCNewRoutePinsUtil.PinInChan _ SCNewRoutePinsUtil.EnterExit[rowChan, pos, exit.layer, exit.net, lrSide]; exit.pinInChan _ tail; pinList _ CONS[tail, pinList]; exit.net.pinList _ pinList}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; sideChan: SCPrivate.SideChan _ layoutData.sideChans[lrSide]; [] _ SCChanUtil.EnumerateExits[handle, rowChan, lrSide, ExitProc]}; OnThroughLine: PROCEDURE[pin: SCNewRoutePinsUtil.PinInChan] RETURNS [yes : BOOLEAN _ FALSE] = { oppEnd: SCNewRoutePinsUtil.ConnectionType; IF pin # NIL THEN { IF pin.pinConn = left THEN oppEnd _ right ELSE IF pin.pinConn = right THEN oppEnd _ left ELSE SC.Error[programmingError, "Invalid pin type"]; IF (pin.nextPinInChan # NIL) THEN IF(pin.nextPinInChan.net = pin.net) AND (pin.nextPinInChan.pinConn = oppEnd) AND (pin.nextPinInChan.min = pin.min) THEN yes _ TRUE; IF (pin.prevPinInChan # NIL) THEN IF (pin.prevPinInChan.net = pin.net) AND (pin.prevPinInChan.pinConn = oppEnd) AND (pin.prevPinInChan.min = pin.min) THEN yes _ TRUE}}; NetSpan: PROCEDURE[rightPin: SCNewRoutePinsUtil.PinInChan] RETURNS [length: SC.Number _ 0] = { leftPin: SCNewRoutePinsUtil.PinInChan _ rightPin; IF rightPin.pinConn # right THEN SC.Error[programmingError, "Not the end of a net span"] ELSE { WHILE leftPin.pinConn # left DO leftPin _ leftPin.prevPinInNet; ENDLOOP; length _ rightPin.min - leftPin.min}}; ComputeDW: PUBLIC PROCEDURE[ rowChan: SCPrivate.RowChan] RETURNS[density, wireLength: SC.Number _ 0] = { chanDat : SCNewRoutePinsUtil.ChanDat _ NARROW[rowChan.chanDat]; current: SCNewRoutePinsUtil.PinInChan _ chanDat.head; localD: SC.Number _ rowChan.numExits[left]; current _ current.nextPinInChan; WHILE (current # NIL) AND (current.pinClass = isExit) DO current.localDensity _ localD; current _ current.nextPinInChan; ENDLOOP; density _ localD; WHILE (current # NIL) AND (current.pinClass = isPin) DO [localD, density, wireLength] _ DensityAtAPin[current, localD, density, wireLength]; current _ current.nextPinInChan; ENDLOOP; WHILE (current # NIL) AND (current.pinClass = isExit) DO current.localDensity _ localD; current _ current.nextPinInChan; ENDLOOP}; DensityAtAPin: PROCEDURE[current: SCNewRoutePinsUtil.PinInChan, localD, density, wireLength: SC.Number] RETURNS[newLocalD, newDensity, newWireLength: SC.Number _ 0] = { pinConn: SCNewRoutePinsUtil.ConnectionType _ current.pinConn; IF (pinConn = interior) OR (pinConn = unconnected) THEN { IF (current.nextPinInChan # NIL) AND (current.nextPinInChan.pinConn = left) AND (current.nextPinInChan.min = current.min) THEN current.localDensity _ localD + 1 ELSE IF (current.prevPinInChan # NIL) AND (current.prevPinInChan.pinConn = right) AND (current.min = current.prevPinInChan.min) THEN current.localDensity _ localD + 1 ELSE current.localDensity _ localD} ELSE IF pinConn = left THEN { IF OnThroughLine[current] -- a through line THEN current.localDensity _ localD ELSE { localD _ localD + 1; current.localDensity _ localD; IF (current.nextPinInChan # NIL) AND (current.nextPinInChan.pinConn = left) AND (current.nextPinInChan.min = current.min) THEN current.localDensity _ current.localDensity + 1; IF (current.prevPinInChan # NIL) AND (current.prevPinInChan.pinConn = right) AND (current.min = current.prevPinInChan.min) THEN current.localDensity _ current.localDensity + 1; density _ MAX[density, current.localDensity]}} ELSE -- pinConn = right IF OnThroughLine[current] THEN current.localDensity _ localD ELSE { current.localDensity _ localD; IF (current.prevPinInChan # NIL) AND (current.prevPinInChan.pinConn = right) AND (current.min = current.prevPinInChan.min) THEN current.localDensity _ current.localDensity + 1; IF (current.nextPinInChan # NIL) AND (current.nextPinInChan.pinConn = left) AND (current.nextPinInChan.min = current.min) THEN current.localDensity _ current.localDensity + 1; localD _ localD - 1; IF localD < 0 THEN SC.Error[programmingError, "Invalid net segment"]; wireLength _ wireLength + NetSpan[current]}; newLocalD _ localD; newWireLength _ wireLength; newDensity _ density}; ComputeAllChanDW: PUBLIC PROCEDURE [handle: SC.Handle, form: SCPrivate.FomType] ~ { RowChan: SCChanUtil.EachRowChanProc = { [rowChan.chanDensity, rowChan.wireLength] _ ComputeDW[rowChan]; IF form = wlFom THEN rowChan.chanWidth _ rowChan.wireLength * pitch * horzWireToAreaFact / lgRows.maxRowWidth ELSE rowChan.chanWidth _ 2*handle.rules.rowRules.trunkToEdge + pitch*(rowChan.chanDensity-1)}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ NARROW[handle.layoutData, SCPrivate.LayoutData].lgRows; pitch: SC.Number _ handle.rules.rowRules.trunkToTrunk; [] _ SCChanUtil.EnumerateRowChans[handle, RowChan]}; InitProcess: PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan] = { <
> SCNewRoutePinsUtil.CreateNetDat[handle, rowChan]; SCNewRoutePinsUtil.GetAllNetSegInChan[handle, rowChan, NIL, NIL, NIL]; [rowChan.chanDensity, rowChan.wireLength] _ ComputeDW[rowChan]}; SwapPinsInChanOnTwoInsts: PUBLIC PROCEDURE[handle: SC.Handle, instance1, instance2: SCPrivate.Instance, deltaX1, deltaX2: SC.Number, side: RTBasic.Side, chanNum: NAT, whichFom: SCPrivate.FomType] = { MovePinsInChanOnInst: PROCEDURE[instance: SCPrivate.Instance, deltaX: SC.Number, side: RTBasic.Side ] = { <<'side' is the side of the instance those pins on.>> <<>> AddChanNetList: PROCEDURE[chanNetList: ChanNetList, chanNetDat: SCNewRoutePinsUtil.ChanNetDat] RETURNS [newList: ChanNetList] = { rList: ChanNetList _ NIL; FOR rList _ chanNetList, rList.rest WHILE (rList # NIL) AND (rList.first # chanNetDat) DO ENDLOOP; IF rList = NIL THEN newList _ CONS[chanNetDat, chanNetList] ELSE newList _ chanNetList}; <
> FOR pinNum: NAT IN [0 .. instance.pinNets.size) DO IF instance.pinNets.n[pinNum].net # NIL THEN { pin: SCNewRoutePinsUtil.PinInChan _ NARROW[instance.pinNets.n[pinNum].pinInChan]; IF (pin # NIL) AND (pin.chanSide = RTBasic.OtherSide[side]) THEN { IF (pin.prevPinInChan # NIL) AND (pin.prevPinInChan.min < leftBound) THEN { leftBound _ pin.prevPinInChan.min; leftPin _ pin.prevPinInChan}; IF (pin.nextPinInChan # NIL) AND (pin.nextPinInChan.min > rightBound) THEN { rightBound _ pin.nextPinInChan.min; rightPin _ pin.nextPinInChan}; scan _ SCNewRoutePinsUtil.MoveAPinInChan[rowChan, pin, deltaX] OR scan; IF (pin.prevPinInChan # NIL) AND (pin.prevPinInChan.min < leftBound) THEN { leftBound _ pin.prevPinInChan.min; leftPin _ pin.prevPinInChan}; IF (pin.nextPinInChan # NIL) AND (pin.nextPinInChan.min > rightBound) THEN { rightBound _ pin.nextPinInChan.min; rightPin _ pin.nextPinInChan}; IF (pin.net.routeTopology[chanNum].upper # full) OR (pin.net.routeTopology[chanNum].lower # full) THEN chanNetList _ AddChanNetList[chanNetList, pin.chanNet]}}; ENDLOOP}; UpdateNetsInChan: PROCEDURE[rowChan: SCPrivate.RowChan, chanNetList: ChanNetList] = { UpdateANetInChan: PROCEDURE[chanNet: SCNewRoutePinsUtil.ChanNetDat] = { EquiNetSeg: PROCEDURE[old, new: SCNewRoutePinsUtil.ChanNetDatRec] RETURNS[yes: BOOLEAN _ FALSE] = { IF (old.leftmost = NIL) AND (new.leftmost = NIL) THEN yes _ TRUE ELSE IF (old.leftmost = new.leftmost) AND (old.rightmost = new.rightmost) THEN yes _ TRUE ELSE yes _ FALSE}; DeleteWire: PROCEDURE[left, right: SCNewRoutePinsUtil.PinInChan] = { current: SCNewRoutePinsUtil.PinInChan _ left; length: SC.Number; length _ right.min - left.min; DO IF current.localDensity = rowChan.chanDensity THEN scan _ TRUE; current.localDensity _ current.localDensity - 1; IF current = right THEN EXIT ELSE current _ current.nextPinInChan; ENDLOOP; IF (left.prevPinInChan # NIL) AND (left.prevPinInChan.min = left.min) THEN left.prevPinInChan.localDensity _ left.prevPinInChan.localDensity - 1; IF (right.nextPinInChan # NIL) AND (right.nextPinInChan.min = right.min) THEN right.nextPinInChan.localDensity _ right.nextPinInChan.localDensity - 1; rowChan.wireLength _ rowChan.wireLength - length}; AddWire: PROCEDURE[left, right: SCNewRoutePinsUtil.PinInChan] = { current: SCNewRoutePinsUtil.PinInChan _ left; length: SC.Number; length _ right.min - left.min; IF (left.prevPinInChan # NIL) AND (left.prevPinInChan.min = left.min) THEN left.prevPinInChan.localDensity _ left.prevPinInChan.localDensity + 1; DO current.localDensity _ current.localDensity + 1; rowChan.chanDensity _ MAX[rowChan.chanDensity, current.localDensity]; IF current = right THEN EXIT ELSE current _ current.nextPinInChan; ENDLOOP; IF (right.nextPinInChan # NIL) AND (right.nextPinInChan.min = right.min) THEN right.nextPinInChan.localDensity _ right.nextPinInChan.localDensity + 1; rowChan.wireLength _ rowChan.wireLength + length}; <
> oldChanNetRec, newChanNetRec: SCNewRoutePinsUtil.ChanNetDatRec _ chanNet^; SCNewRoutePinsUtil.GetANetSegInChan[handle, rowChan, chanNet.net, NIL, NIL, NIL]; newChanNetRec _ chanNet^; IF ~ EquiNetSeg[oldChanNetRec, newChanNetRec] THEN { DeleteWire[oldChanNetRec.leftmost, oldChanNetRec.rightmost]; AddWire[newChanNetRec.leftmost, newChanNetRec.rightmost]}}; <
> FOR rList: ChanNetList _ chanNetList , rList.rest WHILE rList # NIL DO chanNet: SCNewRoutePinsUtil.ChanNetDat _ rList.first; UpdateANetInChan[chanNet]; ENDLOOP}; ChanScan: PROCEDURE[chanRow: SCPrivate.RowChan] RETURNS[density: SC.Number _ 0] = { chanDat : SCNewRoutePinsUtil.ChanDat _ NARROW[rowChan.chanDat]; pin: SCNewRoutePinsUtil.PinInChan _ chanDat.head.nextPinInChan; WHILE pin # NIL DO density _ MAX[density, pin.localDensity]; pin _ pin.nextPinInChan; ENDLOOP}; <
> layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; pitch: SC.Number _ handle.rules.rowRules.trunkToTrunk; rowChans: SCPrivate.RowChans _ layoutData.rowChans; rowChan: SCPrivate.RowChan _ rowChans.chans[chanNum]; chanNetList: ChanNetList _ NIL; scan: BOOLEAN _ FALSE; current, leftPin, rightPin: SCNewRoutePinsUtil.PinInChan_ NIL; leftBound: SC.Number _ LAST[INT]; rightBound: SC.Number _ FIRST[INT]; localD, density, dummy: SC.Number _ 0; MovePinsInChanOnInst[instance1, deltaX1, side]; MovePinsInChanOnInst[instance2, deltaX2, side]; IF leftPin.pinConn = right THEN IF (leftPin.prevPinInChan # NIL) AND (leftPin.prevPinInChan.min = leftPin.min) AND (leftPin.prevPinInChan.pinConn = right) THEN localD _ leftPin.localDensity - 2 ELSE localD _ leftPin.localDensity - 1 ELSE IF (leftPin.prevPinInChan # NIL) AND (leftPin.prevPinInChan.min = leftPin.min) AND (leftPin.prevPinInChan.pinConn = right) THEN localD _ leftPin.localDensity - 1 ELSE localD _ leftPin.localDensity; current _ leftPin.nextPinInChan; WHILE current # rightPin DO [localD, density, dummy] _ DensityAtAPin[current, localD, density, dummy]; current _ current.nextPinInChan; ENDLOOP; UpdateNetsInChan[rowChan, chanNetList]; IF scan AND (density < rowChan.chanDensity) THEN rowChan.chanDensity _ ChanScan[rowChan] ELSE rowChan.chanDensity_ MAX[ rowChan.chanDensity, density]; IF whichFom = wlFom THEN rowChan.chanWidth _ rowChan.wireLength * pitch * horzWireToAreaFact / layoutData.lgRows.maxRowWidth ELSE rowChan.chanWidth _ 2*handle.rules.rowRules.trunkToEdge + pitch*(rowChan.chanDensity-1)}; END. <<>>