<> <> <> <> <<-- 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, Convert, List, Rope, RoutePrivate, RTBasic, SC, SCNetUtil, SCPrivate, SCRoutePinsUtil; SCRoutePinsUtilImpl: CEDAR PROGRAM IMPORTS Convert, List, Rope, 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[min, max, depth: SC.Number, netPin: SCPrivate.PinNet, side: SC.Side, alwaysUse: BOOLEAN] = { net: SCPrivate.Net _ netPin.net; netDat: SCRoutePinsUtil.NetDat _ NARROW[net.netDat]; chanPin: SCRoutePinsUtil.ChannelPin _ NEW[SCRoutePinsUtil.ChannelPinRec _ [min: min, max: max, depth: depth, netPin: netPin, side: side, alwaysUse: alwaysUse]]; 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] = { 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[SCPrivate.ExitRec _ [net: exit.net, pos: exit.pos, pinInChan: NIL, layer: exit.layer]]}; 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: SCPrivate.Exit _ netDat.exits[side]; IF exit # NIL THEN { pos: INT _ IF side = left THEN lgRows.horzRowOrg ELSE lgRows.horzRowOrg + lgRows.maxRowWidth; netDat.bounds1 _ MIN[netDat.bounds1, pos]; netDat.bounds2 _ MAX[netDat.bounds2, pos]; IF exitProc # NIL THEN exitProc[exit, side]; numPins _ numPins + 1}}; DoPin: CPProc = { <> IF netDat.pinCount > 1 OR cP.alwaysUse THEN { netDat.bounds1 _ MIN[netDat.bounds1, cP.min]; netDat.bounds2 _ MAX[netDat.bounds2, cP.max]; IF pinProc # NIL THEN pinProc[cP.min, cP.max, cP.depth, cP.netPin, cP.side]; numPins _ numPins + 1}}; 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 _ RTBasic.Span[fullRange, [cP.min, cP.max]]}; DoMinPins: CPProc = { <> trialRange: RTBasic.Range _ RTBasic.Span[fullRange, [cP.min, cP.max]]; trialLength: SC.Number _trialRange.r - trialRange.l; IF trialLength < maxLength THEN {maxLength _ trialLength; minPin _ cP}}; maxLength: SC.Number _ last; minPin: SCRoutePinsUtil.ChannelPin _ NIL; <> fullRange: RTBasic.Range _ [last, -last]; IF netDat.chanPins[fullSide] # NIL THEN EnumChanPins[netDat, netDat.chanPins[fullSide], DoRange]; IF netDat.exits[left] # NIL THEN { min: SC.Number _ lgRows.horzRowOrg; fullRange _ RTBasic.Span[fullRange, [min, min]]}; IF netDat.exits[right] # NIL THEN { max: SC.Number _ lgRows.horzRowOrg + lgRows.maxRowWidth; fullRange _ RTBasic.Span[fullRange, [max, max]]}; IF (fullRange.l <= fullRange.r) AND netDat.chanPins[minSide] # NIL THEN { 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: RTBasic.Range _ RTBasic.Span[[lastPin[top].min, lastPin[top].max], [lastPin[bottom].min, lastPin[bottom].max]]; IF netDat.exits[left] # NIL THEN { min: SC.Number _ lgRows.horzRowOrg; trialRange _ RTBasic.Span[trialRange, [min, min]]}; IF netDat.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; 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]; numPins _ 0; IF netDat # NIL 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.Signal[callingError, "Unconnected public wire; make sure all publics hanve more than one pin"]; IF netProc # NIL THEN netProc[net]; IF numPins = 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]]]}}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; numPins: INT; [] _ 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].min; p2: SC.Number _ NARROW[ref2, SCRoutePinsUtil.ChannelPin].min; 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.