<> <> <> <> <> <> DIRECTORY DABasics, Convert, Rope, RTBasic, SC, SCNetUtil, SCPrivate, SCNewRoutePinsUtil; SCNewRoutePinsUtilImpl: CEDAR PROGRAM IMPORTS Convert, Rope, RTBasic, SC, SCNetUtil EXPORTS SCNewRoutePinsUtil SHARES SC = { <> InitGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle, rowChan: SCPrivate.RowChan] = { InitNet: SCNetUtil.EachNetProc = {net.netDat _ NIL}; chanDat: SCNewRoutePinsUtil.ChanDat _ NEW[SCNewRoutePinsUtil.ChanDatRec]; chanDat.head _ chanDat.tail _ NEW[SCNewRoutePinsUtil.PinInChanRec _ [min: FIRST[INT], max: FIRST[INT], depth: 0, layer: 0]]; rowChan.chanDat _ chanDat; rowChan.wireLength _ rowChan.chanDensity _ rowChan.chanWidth _ 0; [] _ SCNetUtil.EnumerateNets[handle, InitNet]}; <> TermGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle, rowChan: SCPrivate.RowChan] = { TermNet: SCNetUtil.EachNetProc = { netDat: SCNewRoutePinsUtil.NetDat _ NARROW[net.netDat]; IF netDat # NIL THEN { chanNetDat: SCNewRoutePinsUtil.ChanNetDat _ netDat[rowChan.chanNum]; IF chanNetDat # NIL THEN chanNetDat.firstPin _ chanNetDat.lastPin _ chanNetDat.leftmost _ chanNetDat.rightmost _ chanNetDat.exits[left] _ chanNetDat.exits[right] _ NIL; net.netDat _ NIL}}; EachPin: SCNewRoutePinsUtil.EachPinProc = { <> pin.prevPinInChan _ pin.nextPinInNet _ NIL}; EnumPinsInChan[rowChan, EachPin]; [] _ SCNetUtil.EnumerateNets[handle, TermNet]; rowChan.chanDat _ NIL}; <> EnterPin: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, min, max, depth: SC.Number, layer: SC.Layer, net: SCPrivate.Net, side: DABasics.TBSide, alwaysUse: BOOLEAN] RETURNS[pinInChan: SCNewRoutePinsUtil.PinInChan] = { chanDat: SCNewRoutePinsUtil.ChanDat _ NARROW[rowChan.chanDat]; tail: SCNewRoutePinsUtil.PinInChan _ chanDat.tail; chanDat.tail _ tail.nextPinInChan _ pinInChan _ NEW[SCNewRoutePinsUtil.PinInChanRec _ [ layer: layer, net: net, chanNet: NIL, min: min, max: max, depth: depth, pinClass: isPin, chanSide: side, nextPinInChan: NIL, prevPinInChan: tail, pinConn: unconnected, nextPinInNet: NIL, prevPinInNet: NIL, localDensity: 0 , alwaysUse: alwaysUse, chanNum: rowChan.chanNum]]; rowChan.chanDat _ chanDat}; <<>> <> EnterExit: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, pos: SC.Number, layer: SC.Layer, net: SCPrivate.Net, side: DABasics.LRSide] RETURNS[pinInChan: SCNewRoutePinsUtil.PinInChan] = { chanDat: SCNewRoutePinsUtil.ChanDat _ NARROW[rowChan.chanDat]; tail: SCNewRoutePinsUtil.PinInChan _ chanDat.tail; chanDat.tail _ tail.nextPinInChan _ pinInChan _ NEW[SCNewRoutePinsUtil.PinInChanRec _ [ layer: layer, net: net, chanNet: NIL, min: pos, max: pos, depth: 0, pinClass: isExit, chanSide: side, nextPinInChan: NIL, prevPinInChan: tail, pinConn: unconnected, nextPinInNet: NIL, prevPinInNet: NIL, localDensity: 0 , alwaysUse: TRUE, chanNum: rowChan.chanNum]]; rowChan.chanDat _ chanDat}; NoChange: PROCEDURE[mpin, pin: SCNewRoutePinsUtil.PinInChan] RETURNS[yes: BOOLEAN _ FALSE] = { IF mpin.nextPinInNet # NIL THEN yes _ (mpin.nextPinInNet.min = pin.min) AND (mpin.nextPinInNet.pinConn #unconnected); IF mpin.prevPinInNet # NIL THEN yes _ yes OR (mpin.prevPinInNet.min = pin.min) AND (mpin.prevPinInNet.pinConn # unconnected) }; MoveAPinInChan: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, pin: SCNewRoutePinsUtil.PinInChan, deltaX: SC.Number] RETURNS[scan: BOOLEAN _ FALSE] = { next: SCNewRoutePinsUtil.PinInChan _ pin; prev: SCNewRoutePinsUtil.PinInChan _ pin; origX, currX, dX: SC.Number; origX _ currX _ pin.min; pin.min _ pin.min + deltaX; pin.max _ pin.max + deltaX; IF pin.min = rowChan.chanDensity THEN scan _ TRUE; IF deltaX > 0 THEN { prev _ pin.prevPinInChan; IF (prev # NIL) AND (prev.min = currX) AND (pin.pinConn = left) THEN prev.localDensity _ prev.localDensity - 1; WHILE (pin.nextPinInChan # NIL) AND (pin.nextPinInChan.min <= pin.min) DO next _ pin.nextPinInChan; IF next.localDensity = rowChan.chanDensity THEN scan _ TRUE; dX _ next.min - currX; currX _ next.min; SwapTwoPins[pin, next]; SELECT pin.pinConn FROM left => { IF pin.net = next.net THEN { SELECT next.pinConn FROM interior => { pin.pinConn _ interior; next.pinConn _ left; pin.chanNet.leftmost _ next}; right => { pin.pinConn _ right; next.pinConn _ left; pin.chanNet.leftmost _ next; pin.chanNet.rightmost _ pin}; ENDCASE}; rowChan.wireLength _ rowChan.wireLength - dX}; interior => { IF pin.net = next.net THEN IF next.pinConn = right THEN { next.pinConn _ interior; pin.pinConn _ right; pin.chanNet.rightmost _ pin}}; right => { rowChan.wireLength _ rowChan.wireLength + dX}; ENDCASE; IF pin.net = next.net THEN SwapTwoPinsInNet[pin, next]; ENDLOOP; dX _ pin.min - currX; IF pin.pinConn = right THEN rowChan.wireLength _ rowChan.wireLength + dX; IF pin.pinConn = left THEN rowChan.wireLength _ rowChan.wireLength - dX; next _ pin.nextPinInChan} ELSE IF deltaX < 0 THEN { next _ pin.nextPinInChan; IF (next # NIL) AND (next.min = currX) AND (pin.pinConn = right) THEN next.localDensity _ next.localDensity - 1; WHILE (pin.prevPinInChan # NIL) AND (pin.prevPinInChan.min >= pin.min) DO prev _ pin.prevPinInChan; IF prev.localDensity = rowChan.chanDensity THEN scan _ TRUE; dX _ currX - prev.min; currX _ prev.min; SwapTwoPins[prev, pin]; SELECT pin.pinConn FROM right => { IF pin.net = prev.net THEN { SELECT prev.pinConn FROM interior => { pin.pinConn _ interior; prev.pinConn _ right; pin.chanNet.rightmost _ prev}; left => { pin.pinConn _ left; prev.pinConn _ right; pin.chanNet.leftmost _ pin; pin.chanNet.rightmost _ prev}; ENDCASE}; rowChan.wireLength _ rowChan.wireLength - dX}; interior => { IF pin.net = prev.net THEN IF prev.pinConn = left THEN { prev.pinConn _ interior; pin.pinConn _ left; pin.chanNet.leftmost _ pin}}; left => { rowChan.wireLength _ rowChan.wireLength + dX}; ENDCASE; IF pin.net = prev.net THEN SwapTwoPinsInNet[prev, pin]; ENDLOOP; dX _ currX - pin.min; IF pin.pinConn = left THEN rowChan.wireLength _ rowChan.wireLength + dX; IF pin.pinConn = right THEN rowChan.wireLength _ rowChan.wireLength - dX}}; SortPins: PROCEDURE[chanDat: SCNewRoutePinsUtil.ChanDat] = { stop: BOOLEAN _ FALSE; temp: SCNewRoutePinsUtil.PinInChan; head: SCNewRoutePinsUtil.PinInChan _ chanDat.head; WHILE ~stop DO rList: SCNewRoutePinsUtil.PinInChan _ head; stop _ TRUE; WHILE rList.nextPinInChan # NIL DO temp _ rList.nextPinInChan; IF rList.min > temp.min THEN { stop _ FALSE; SwapTwoPins[rList, temp]}; rList _ temp; ENDLOOP; ENDLOOP}; SwapTwoPins: PROCEDURE[pin1, pin2: SCNewRoutePinsUtil.PinInChan] = { IF pin2.nextPinInChan # NIL THEN pin2.nextPinInChan.prevPinInChan _ pin1; IF pin1.prevPinInChan # NIL THEN pin1.prevPinInChan.nextPinInChan _ pin2; pin1.nextPinInChan _ pin2.nextPinInChan; pin2.prevPinInChan _ pin1.prevPinInChan; pin1.prevPinInChan _ pin2; pin2.nextPinInChan _ pin1}; SwapTwoPinsInNet: PROCEDURE[pin1, pin2: SCNewRoutePinsUtil.PinInChan] = { chanNetDat: SCNewRoutePinsUtil.ChanNetDat _ pin1.chanNet; IF pin2.nextPinInNet # NIL THEN pin2.nextPinInNet.prevPinInNet _ pin1; IF pin1.prevPinInNet # NIL THEN pin1.prevPinInNet.nextPinInNet _ pin2; pin1.nextPinInNet _ pin2.nextPinInNet; pin2.prevPinInNet _ pin1.prevPinInNet; pin1.prevPinInNet _ pin2; pin2.nextPinInNet _ pin1; IF chanNetDat.firstPin = pin1 THEN chanNetDat.firstPin _ pin2; IF chanNetDat.lastPin = pin2 THEN chanNetDat.lastPin _ pin1}; <<>> <> EnumPinsInChan: PUBLIC PROCEDURE[rowChan: SCPrivate.RowChan, doEachPin: SCNewRoutePinsUtil.EachPinProc] = { chanDat: SCNewRoutePinsUtil.ChanDat _ NARROW[rowChan.chanDat]; IF chanDat # NIL THEN { head: SCNewRoutePinsUtil.PinInChan _ chanDat.head; FOR chanPin: SCNewRoutePinsUtil.PinInChan _ head.nextPinInChan, chanPin.nextPinInChan WHILE chanPin # NIL DO doEachPin[rowChan, chanPin]; ENDLOOP}}; <> EnumAllPinsInNetChan: PUBLIC PROCEDURE[chanNetDat: SCNewRoutePinsUtil.ChanNetDat, doEachNetPin: SCNewRoutePinsUtil.EachNetPinProc] = { IF chanNetDat # NIL THEN { FOR chanPin: SCNewRoutePinsUtil.PinInChan _ chanNetDat.firstPin, chanPin.nextPinInNet WHILE chanPin # NIL DO doEachNetPin[chanNetDat, chanPin]; ENDLOOP}}; <> EnumPinsInNetChan: PUBLIC PROCEDURE[chanNetDat: SCNewRoutePinsUtil.ChanNetDat, side: DABasics.Side, doEachNetPin: SCNewRoutePinsUtil.EachNetPinProc] = { IF chanNetDat # NIL THEN { FOR chanPin: SCNewRoutePinsUtil.PinInChan _ chanNetDat.firstPin, chanPin.nextPinInNet WHILE chanPin # NIL DO IF chanPin.chanSide = side OR chanPin.pinClass = isExit THEN doEachNetPin[chanNetDat, chanPin]; ENDLOOP}}; <> CreateNetDat: PUBLIC PROCEDURE[handle: SC.Handle, rowChan: SCPrivate.RowChan] = { DoEachPin: SCNewRoutePinsUtil.EachPinProc = { <> <<>> net: SCPrivate.Net _ pin.net; netDat: SCNewRoutePinsUtil.NetDat _ NARROW[net.netDat]; chanNum: NAT _ rowChan.chanNum; chanNetDat: SCNewRoutePinsUtil.ChanNetDat _ NIL; IF netDat = NIL THEN net.netDat _ netDat _ NARROW[NEW[SCNewRoutePinsUtil.NetDatRec _ ALL[NIL]]]; IF netDat[chanNum] = NIL THEN netDat[chanNum] _ NEW[SCNewRoutePinsUtil.ChanNetDatRec]; chanNetDat _ netDat[chanNum]; IF pin.pinClass = isExit THEN { IF chanNetDat.exits[pin.chanSide] # NIL THEN SC.Error[programmingError, "More than two exits for a net one side of a channel"] ELSE chanNetDat.exits[pin.chanSide] _ pin}; IF chanNetDat.firstPin = NIL THEN { chanNetDat.firstPin _ (chanNetDat.lastPin _ pin); chanNetDat.net _ net} ELSE { pin.prevPinInNet _ chanNetDat.lastPin; chanNetDat.lastPin.nextPinInNet _ pin; chanNetDat.lastPin _ pin}; chanNetDat.pinCount _ chanNetDat.pinCount + 1; pin.chanNet _ chanNetDat}; <
> SortPins[NARROW[rowChan.chanDat]]; EnumPinsInChan[rowChan, DoEachPin]}; <> GetANetSegInChan: PUBLIC PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan, net: SCPrivate.Net, segProc: SCNewRoutePinsUtil.SegProc, pinProc: SCNewRoutePinsUtil.PinProc, exitProc: SCNewRoutePinsUtil.ExitProc] ~ { <<>> <> DoExit: PROCEDURE[chanNetDat: SCNewRoutePinsUtil.ChanNetDat, side: DABasics.LRSide] = { exit: SCNewRoutePinsUtil.PinInChan _ chanNetDat.exits[side]; IF exit # NIL THEN { IF side = left THEN exit.pinConn _ interior ELSE IF side = right THEN exit.pinConn _ interior; IF exitProc # NIL THEN exitProc[side, exit.layer, exit.net]; numPinsUsed _ numPinsUsed + 1}}; <> DoPin: SCNewRoutePinsUtil.EachNetPinProc = { <> IF (chanNetDat.pinCount > 1 OR pin.alwaysUse) AND pin.pinClass = isPin THEN { pin.pinConn _ interior; IF pinProc # NIL THEN pinProc[pin.min, pin.max, pin.depth, pin.chanSide, pin.layer, pin.net]; numPinsUsed _ numPinsUsed + 1}}; <> DoAllPins: PROCEDURE[chanNetDat: SCNewRoutePinsUtil.ChanNetDat, side: DABasics.TBSide] = { EnumPinsInNetChan[chanNetDat, side, DoPin]}; <> DoFullMin: PROC [chanNetDat: SCNewRoutePinsUtil.ChanNetDat, fullSide, minSide: DABasics.TBSide] ~ { <> DoRange: SCNewRoutePinsUtil.EachNetPinProc = {fullRange _ RTBasic.Span[fullRange, [pin.min, pin.max]]}; <> <> DoMinPins: SCNewRoutePinsUtil.EachNetPinProc = { <> <<>> IF pin.pinClass = isPin THEN { trialRange: RTBasic.Range _ RTBasic.Span[fullRange, [pin.min, pin.max]]; trialLength: SC.Number _ trialRange.r - trialRange.l; IF trialLength < maxLength THEN {maxLength _ trialLength; minPin _ pin}}}; maxLength: SC.Number _ LAST[INT]; minPin: SCNewRoutePinsUtil.PinInChan _ NIL; <> fullRange: RTBasic.Range _ [LAST[INT], FIRST[INT]]; EnumPinsInNetChan[chanNetDat, fullSide, DoRange]; IF fullRange.l <= fullRange.r THEN { EnumPinsInNetChan[chanNetDat, minSide, DoMinPins]; IF minPin # NIL THEN DoPin[chanNetDat, minPin]}}; <> DoMinMin: PROC [chanNetDat: SCNewRoutePinsUtil.ChanNetDat] ~ { DoMinPins: SCNewRoutePinsUtil.EachNetPinProc = { <> IF pin.pinClass = isPin THEN { IF leftPin = NIL THEN leftPin _ pin; rightPin _ pin; lastPin[pin.chanSide] _ pin; IF lastPin[RTBasic.OtherSide[pin.chanSide]] # NIL THEN { trialLength: SC.Number; trialRange: RTBasic.Range _ RTBasic.Span[[lastPin[top].min, lastPin[top].max], [lastPin[bottom].min, lastPin[bottom].max]]; IF chanNetDat.exits[left] # NIL THEN { min: SC.Number _ lgRows.horzRowOrg; trialRange _ RTBasic.Span[trialRange, [min, min]]}; IF chanNetDat.exits[right] # NIL THEN { max: SC.Number _ lgRows.horzRowOrg + lgRows.maxRowWidth; trialRange _ RTBasic.Span[trialRange, [max, max]]}; trialLength _ trialRange.r - trialRange.l; IF trialLength < maxLength THEN { maxLength _ trialLength; minPin[top]_ lastPin[top]; minPin[bottom]_ lastPin[bottom]}}}}; maxLength: SC.Number _ LAST[INT]; lastPin: ARRAY DABasics.TBSide OF SCNewRoutePinsUtil.PinInChan _ [NIL, NIL]; minPin: ARRAY DABasics.TBSide OF SCNewRoutePinsUtil.PinInChan _ [NIL, NIL]; leftPin: SCNewRoutePinsUtil.PinInChan _ NIL; rightPin: SCNewRoutePinsUtil.PinInChan _ NIL; didLeftPin: BOOL _ FALSE; EnumAllPinsInNetChan[chanNetDat, DoMinPins]; IF minPin[top] # NIL THEN DoPin[chanNetDat, minPin[top]]; IF minPin[bottom] # NIL THEN DoPin[chanNetDat, minPin[bottom]]; IF chanNetDat.exits[left] # NIL AND leftPin # minPin[top] AND leftPin # minPin[bottom] THEN {DoPin[chanNetDat, leftPin]; didLeftPin _ TRUE}; IF chanNetDat.exits[right] # NIL AND rightPin # minPin[top] AND rightPin # minPin[bottom] AND ~didLeftPin THEN DoPin[chanNetDat, rightPin]}; <> ClearPin: SCNewRoutePinsUtil.EachNetPinProc = { <> pin.pinConn _ unconnected}; <> FixUpAndCheck: SCNewRoutePinsUtil.EachNetPinProc = { <> pinState _ pin.pinConn _ NextPinState[pinState, pin]; IF pinState = left THEN chanNetDat.leftmost _ pin; IF pinState = interior THEN lastConnectedPin _ pin}; <
> numPinsUsed: INT _ 0; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; netDat: SCNewRoutePinsUtil.NetDat _ NARROW[net.netDat]; chan: SCPrivate.ZMaxChanSr _ rowChan.chanNum; chanNetDat: SCNewRoutePinsUtil.ChanNetDat _ netDat[chan]; pinState: SCNewRoutePinsUtil.ConnectionType _ unconnected; lastConnectedPin: SCNewRoutePinsUtil.PinInChan _ NIL; EnumAllPinsInNetChan[chanNetDat, ClearPin]; IF chanNetDat # NIL THEN { SELECT TRUE FROM chan = 0 => -- this is a side {DoAllPins[chanNetDat, top]; DoAllPins[chanNetDat, bottom]}; net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = full => {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoAllPins[chanNetDat, top]; DoAllPins[chanNetDat, bottom]}; net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = min => {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoFullMin[chanNetDat, top, bottom]; DoAllPins[chanNetDat, top]}; net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = full => {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoFullMin[chanNetDat, bottom, top]; DoAllPins[chanNetDat, bottom]}; net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = min => {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoMinMin[chanNetDat]}; net.routeTopology[chan].upper = full => -- lower must be none {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoAllPins[chanNetDat, top]}; net.routeTopology[chan].lower = full => -- upper must be none {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]; DoAllPins[chanNetDat, bottom]}; chanNetDat.exits[left] # NIL AND chanNetDat.exits[right] # NIL => {DoExit[chanNetDat, left]; DoExit[chanNetDat, right]}; ENDCASE => <> IF chanNetDat.exits[left] # NIL OR chanNetDat.exits[right] # NIL THEN SC.Signal[callingError, "Unconnected public wire; make sure all publics hanve more than one pin"]; <> EnumAllPinsInNetChan[chanNetDat, FixUpAndCheck]; IF lastConnectedPin # NIL THEN {lastConnectedPin.pinConn _ right; chanNetDat.rightmost _ lastConnectedPin}; IF numPinsUsed = 1 AND chan # 1 AND chan # layoutData.rowChans.count THEN SC.Signal[callingError, Rope.Cat["Too few pins for wire: ", net.name, " on channel: ", Convert.RopeFromInt[chan]]]}}; GetAllNetSegInChan: PUBLIC PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan, segProc: SCNewRoutePinsUtil.SegProc, pinProc: SCNewRoutePinsUtil.PinProc, exitProc: SCNewRoutePinsUtil.ExitProc] ~ { <> EachNet: SCNetUtil.EachNetProc ~ { <> IF net.netDat # NIL THEN GetANetSegInChan[handle, rowChan, net, segProc, pinProc, exitProc]}; [] _ SCNetUtil.EnumerateNets[handle, EachNet]}; NextPinState: PROC [pinState: SCNewRoutePinsUtil.ConnectionType, pin: SCNewRoutePinsUtil.PinInChan] RETURNS [newPinState: SCNewRoutePinsUtil.ConnectionType] ~ { <> IF pin.pinConn = unconnected THEN { -- this pin is unconnected newPinState _ unconnected; IF pin.pinClass = isExit THEN SC.Signal[programmingError, Rope.Cat["Exit is unconnected for wire: ", pin.net.name, ". Call maintainer"]]} ELSE IF pin.pinConn = interior THEN { -- this pin is unconnected; determine which type IF pinState = unconnected THEN -- fitst pin we have come to newPinState _ left ELSE newPinState _ interior}}; PosOfPin: PROC [chanPin: SCNewRoutePinsUtil.PinInChan] RETURNS [INT] ~ INLINE{ RETURN[(chanPin.min+chanPin.max)/2]}; }.