<> <> <<-- InitGetChanPins - initialize for determining the width of a channel>> <<-- TermGetChanPins - terminate determining the width of a channel>> <<-- NewWsEntry - get a new wire segment entry and insert pos, return location>> <<-- EnterPin - enter a pin on a channel>> <<-- EnterExit - enter exit data for a channel>> <<-- EnterNetDat - minmium route channels need special processing to>> <> <<>> DIRECTORY Basics, CD, List, RouteChannel, RoutePrivate, RTBasic, SC, SCNetUtil, SCPrivate, SCRoutePinsUtil; SCRoutePinsUtilImpl: CEDAR PROGRAM IMPORTS List, RouteChannel, RTBasic, SC, SCNetUtil EXPORTS SCRoutePinsUtil SHARES SC = BEGIN last: INT _ LAST[INT]; <> InitGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle] = { InitNet: SCNetUtil.EachNetProc = { net.netDat _ NIL}; [] _ SCNetUtil.EnumerateNets[handle, InitNet]}; <> TermGetChanPins: PUBLIC PROCEDURE [handle: SC.Handle] = { TermNet: SCNetUtil.EachNetProc = { netDat: SCRoutePinsUtil.NetDat _ NARROW[net.netDat]; IF netDat # NIL THEN { netDat.exits _ ALL[NIL]; netDat.chanPins _ ALL[NIL]; net.netDat _ NIL}}; [] _ SCNetUtil.EnumerateNets[handle, TermNet]}; <> EnterPin: PUBLIC PROCEDURE[rect: SC.Rect, position: CD.Position, netPin: SCPrivate.PinNet, side: SC.Side, cell: CD.Object] = { net: SCPrivate.Net _ netPin.net; netDat: SCRoutePinsUtil.NetDat _ NARROW[net.netDat]; chanPin: SCRoutePinsUtil.ChannelPin _ NEW[SCRoutePinsUtil.ChannelPinRec _ [rect: rect, position: position, netPin: netPin, cell: cell, side: side]]; IF netDat = NIL THEN { netDat _ NARROW[NEW[SCRoutePinsUtil.NetDatRec]]; net.netDat _ netDat}; netDat.pinCount _ netDat.pinCount + 1; netDat.chanPins[side] _ CONS[chanPin, netDat.chanPins[side]]}; <<>> <> EnterExit: PUBLIC PROCEDURE[exit: SCPrivate.Exit, side: SCPrivate.LRSide, cell: CD.Object] = { net: SCPrivate.Net _ exit.net; netDat: SCRoutePinsUtil.NetDat _ NARROW[net.netDat]; IF netDat = NIL THEN { netDat _ NARROW[NEW[SCRoutePinsUtil.NetDatRec]]; net.netDat _ netDat}; IF netDat.exits[side] # NIL THEN SC.Error[programmingError, "Call maintainer"]; netDat.pinCount _ netDat.pinCount + 1; netDat.exits[side] _ NEW[SCRoutePinsUtil.ExitPinRec _ [cell: cell, exit: exit]]}; EnterNetDat: PUBLIC PROCEDURE [handle: SC.Handle, chan: SCPrivate.ZMaxChanSr, pinProc: SCRoutePinsUtil.PinProc, exitProc: SCRoutePinsUtil.ExitProc, netProc: SCRoutePinsUtil.NetProc] = { DoExit: PROCEDURE[netDat: SCRoutePinsUtil.NetDat, side: SCPrivate.LRSide] = { exit: SCRoutePinsUtil.ExitPin _ netDat.exits[side]; IF exit # NIL THEN { pos: INT _ IF side = left THEN 0 ELSE lgRows.maxRowWidth; netDat.bounds1 _ MIN[netDat.bounds1, pos]; netDat.bounds2 _ MAX[netDat.bounds2, pos]; IF exitProc # NIL THEN exitProc[exit.exit, exit.cell, exit.exit.net.trunkWidth, side]}}; DoPin: CPProc = { netDat.bounds1 _ MIN[netDat.bounds1, cP.position.x]; netDat.bounds2 _ MAX[netDat.bounds2, cP.position.x]; IF pinProc # NIL THEN pinProc[cP.rect, cP.position, cP.netPin, cP.cell]}; DoAllPins: PROCEDURE[netDat: SCRoutePinsUtil.NetDat, side: SCPrivate.TBSide] = { EnumChanPins[netDat, netDat.chanPins[side], DoPin]}; DoFullMin: PROC [netDat: SCRoutePinsUtil.NetDat, fullSide, minSide: SCPrivate.TBSide] ~ { DoRange: CPProc = {fullRange _ RouteChannel.Span[fullRange, [cP.position.x, cP.position.x]]}; DoMinPins: CPProc = { trialRange: RoutePrivate.Range _ RouteChannel.Span[fullRange, [cP.position.x, cP.position.x]]; trialLength: SC.Number _trialRange.r - trialRange.l; IF trialLength < maxLength THEN { maxLength _ trialLength; minPin _ cP}}; fullRange: RoutePrivate.Range _ [last, -last]; maxLength: SC.Number _ last; minPin: SCRoutePinsUtil.ChannelPin _ NIL; IF netDat.chanPins[fullSide] # NIL AND netDat.chanPins[minSide] # NIL THEN { EnumChanPins[netDat, netDat.chanPins[fullSide], DoRange]; IF netDat.exits[left] # NIL THEN fullRange _ RouteChannel.Span[fullRange, [0, 0]]; IF netDat.exits[left] # NIL THEN fullRange _ RouteChannel.Span[fullRange, [lgRows.maxRowWidth, lgRows.maxRowWidth]]; EnumChanPins[netDat, netDat.chanPins[minSide], DoMinPins]}; IF minPin # NIL THEN DoPin[netDat, minPin]}; DoMinMin: PROC [netDat: SCRoutePinsUtil.NetDat] ~ { DoMinPins: CPProc = { rightPin _ cP; lastPin[cP.side] _ cP; IF lastPin[RTBasic.OtherSide[cP.side]] # NIL THEN { trialLength: SC.Number; trialRange: RoutePrivate.Range _ RouteChannel.Span[[lastPin[top].position.x, lastPin[top].position.x], [lastPin[bottom].position.x, lastPin[bottom].position.x]]; IF netDat.exits[left] # NIL THEN trialRange _ RouteChannel.Span[trialRange, [0, 0]]; IF netDat.exits[left] # NIL THEN trialRange _ RouteChannel.Span[trialRange, [lgRows.maxRowWidth, lgRows.maxRowWidth]]; trialLength _ trialRange.r - trialRange.l; IF trialLength < maxLength THEN { maxLength _ trialLength; minPin[top]_ lastPin[top]; minPin[bottom]_ lastPin[bottom]}}}; maxLength: SC.Number _ last; lastPin: ARRAY SCPrivate.TBSide OF SCRoutePinsUtil.ChannelPin _ [NIL, NIL]; minPin: ARRAY SCPrivate.TBSide OF SCRoutePinsUtil.ChannelPin _ [NIL, NIL]; sortedPinList: SCRoutePinsUtil.ChannelPinList _ SortPinLists[netDat.chanPins[top], netDat.chanPins[bottom]]; leftPin: SCRoutePinsUtil.ChannelPin _ sortedPinList.first; rightPin: SCRoutePinsUtil.ChannelPin; EnumChanPins[netDat, sortedPinList, DoMinPins]; IF minPin[top] # NIL THEN DoPin[netDat, minPin[top]]; IF minPin[bottom] # NIL THEN DoPin[netDat, minPin[bottom]]; IF netDat.exits[left] # NIL AND leftPin # minPin[top] AND leftPin # minPin[bottom] THEN DoPin[netDat, leftPin]; IF netDat.exits[right] # NIL AND rightPin # minPin[top] AND rightPin # minPin[bottom] THEN DoPin[netDat, rightPin]}; EachNet: SCNetUtil.EachNetProc = { netDat: SCRoutePinsUtil.NetDat _ NARROW[net.netDat]; IF netDat # NIL THEN { IF netDat.pinCount > 1 OR chan = 1 OR chan = layoutData.rowChans.count THEN { SELECT TRUE FROM chan = 0 => -- this is a side {DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, top]; DoAllPins[netDat, bottom]}; net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = full => {DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, top]; DoAllPins[netDat, bottom]}; net.routeTopology[chan].upper = full AND net.routeTopology[chan].lower = min => {DoExit[netDat, left]; DoExit[netDat, right]; DoFullMin[netDat, top, bottom]; DoAllPins[netDat, top]}; net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = full => {DoExit[netDat, left]; DoExit[netDat, right]; DoFullMin[netDat, bottom, top]; DoAllPins[netDat, bottom]}; net.routeTopology[chan].upper = min AND net.routeTopology[chan].lower = min => {DoExit[netDat, left]; DoExit[netDat, right]; DoMinMin[netDat]}; net.routeTopology[chan].upper = full => -- lower must be none {DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, top]}; net.routeTopology[chan].lower = full => -- upper must be none {DoExit[netDat, left]; DoExit[netDat, right]; DoAllPins[netDat, bottom]}; ENDCASE => <> IF netDat.exits[left] # NIL OR netDat.exits[right] # NIL THEN SC.Error[programmingError, "Unconnected exit; not suppose to happen"]; IF netProc # NIL THEN netProc[net]}}}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; [] _ SCNetUtil.EnumerateNets[handle, EachNet]}; CPProc: TYPE = PROC [netDat: SCRoutePinsUtil.NetDat, cP: SCRoutePinsUtil.ChannelPin]; EnumChanPins: PROC [netDat: SCRoutePinsUtil.NetDat, pList: SCRoutePinsUtil.ChannelPinList, cPProc: CPProc] ~ { FOR rList: SCRoutePinsUtil.ChannelPinList _ pList, rList.rest WHILE rList # NIL DO cP: SCRoutePinsUtil.ChannelPin _ rList.first; cPProc[netDat, cP]; ENDLOOP}; SortPinLists: PROC [topList, bottomList: SCRoutePinsUtil.ChannelPinList] RETURNS [sortedList: SCRoutePinsUtil.ChannelPinList] ~ { PinCompare: List.CompareProc = { p1: SC.Number _ NARROW[ref1, SCRoutePinsUtil.ChannelPin].position.x; p2: SC.Number _ NARROW[ref2, SCRoutePinsUtil.ChannelPin].position.x; RETURN[IF p1 < p2 THEN Basics.Comparison.less ELSE IF p1 = p2 THEN Basics.Comparison.equal ELSE Basics.Comparison.greater]}; topMungedPinList: List.LORA _ List.Sort[ConvertToLORA[topList], PinCompare]; bottomMungedPinList: List.LORA _ List.Sort[ConvertToLORA[bottomList], PinCompare]; sortedPinList: List.LORA _ List.Merge[bottomMungedPinList, topMungedPinList, PinCompare]; sortedList _ConvertFromLORA[sortedPinList]}; ConvertToLORA: PROC [list: SCRoutePinsUtil.ChannelPinList] RETURNS[val: List.LORA] = { val _ NIL; UNTIL list = NIL DO val _ CONS[list.first, val]; list _ list.rest; ENDLOOP; RETURN[val]; }; -- of ConvertToLORA ConvertFromLORA: PROC [list: List.LORA] RETURNS[val: SCRoutePinsUtil.ChannelPinList] = { val _ NIL; UNTIL list = NIL DO this: SCRoutePinsUtil.ChannelPin _ NARROW[list.first]; val _ CONS[this, val]; list _ list.rest; ENDLOOP; RETURN[val]; }; -- of ConvertFromLORA END.