<> <> <> <> DIRECTORY Basics, CD, CDBasics, CDOrient, CDSymbolicObjects, List, Rope, Route, RouteChannel, RoutePrivate, RouteUtil; RouteChannelInitImpl: CEDAR PROGRAM IMPORTS CDBasics, CDOrient, CDSymbolicObjects, List, Rope, Route, RouteChannel, RouteUtil EXPORTS RouteChannel SHARES Route = BEGIN ChanSideName: PUBLIC ARRAY RouteChannel.ChanSide OF Rope.ROPE _ ["chanBottom", "chanTop", "chanLeft", "chanRight"]; AboveOrBelowName: PUBLIC ARRAY RouteChannel.AboveOrBelow OF Rope.ROPE _ ["above", "below"]; GoingName: PUBLIC ARRAY RouteChannel.GoingDirection OF Rope.ROPE _ ["leftToRight", "rightToLeft"]; InitChannel: PUBLIC PROCEDURE[routingArea: Route.RoutingArea, sideOrgins: Route.PositionVec, routingRect: Route.Rect, routerUsed: RoutePrivate.RouterUsed, signalSinglePinNets, signalCoincidentPins, okToDiddleLLPins, okToDiddleURPins: BOOLEAN] = { <> <<>> netTab: RoutePrivate.NetTab; parms: RoutePrivate.RoutingAreaParms _ NARROW[routingArea.parms]; nRect: Route.Rect _ CDBasics.NormalizeRect[routingRect]; lowPos: RoutePrivate.PQPosition _ RouteUtil.XYToPQ[routingArea, [nRect.x1, nRect.y1]]; upPos: RoutePrivate.PQPosition _ RouteUtil.XYToPQ[routingArea, [nRect.x2, nRect.y2]]; rRect: RoutePrivate.PQRect _ [lowPos, upPos]; <> channelData: RouteChannel.ChannelData _ NEW[RouteChannel.ChannelDataRec]; channelData.constraints _ NIL; channelData.chanSides[chanTop] _ NEW[RouteChannel.RoutingChannelSidesRec]; channelData.chanSides[chanBottom] _ NEW[RouteChannel.RoutingChannelSidesRec]; channelData.chanSides[chanLeft] _ NEW[RouteChannel.RoutingChannelSidesRec]; channelData.chanSides[chanRight] _ NEW[RouteChannel.RoutingChannelSidesRec]; channelData.chanTracks _ NEW[RouteChannel.RoutingChannelTracksRec]; channelData.chanPins _ NEW[RouteChannel.RoutingChannelPinsRec]; channelData.chanParms _ NEW[RouteChannel.ChanParmsRec]; routingArea.privateData _ channelData; parms.routerUsed _ routerUsed; channelData.chanParms.emptyTrackLimit _ RouteChannel.InfluenceTracks[routingArea, parms.widestTrunk]; channelData.chanParms.maxToConvert _ 10*routingArea.rules.branchToBranch; <> ConvertSide[routingArea, chanBottom, sideOrgins, rRect]; ConvertSide[routingArea, chanTop, sideOrgins, rRect]; ConvertEnd[routingArea, chanLeft, sideOrgins, rRect]; ConvertEnd[routingArea, chanRight, sideOrgins, rRect]; <> FixOrgins[routingArea, rRect]; <> netTab _ NARROW[routingArea.nets, RoutePrivate.NetTab]; FOR netIndex: RoutePrivate.ZMaxNets IN [1 .. netTab.count] DO InitNet[routingArea, netTab.n[netIndex], signalSinglePinNets, signalCoincidentPins]; ENDLOOP; IF parms.routerUsed = switchBox THEN MakeSBTracks[routingArea, okToDiddleLLPins, okToDiddleURPins] ELSE MakeCRTracks[routingArea, parms.numTracksToUse]; DoTBBarriers[routingArea, chanBottom]; DoTBBarriers[routingArea, chanTop]; DoLRBarriers[routingArea, chanLeft]; DoLRBarriers[routingArea, chanRight]}; ConvertSide: PROCEDURE[routingArea: Route.RoutingArea, chanSide: RouteChannel.ChanSide, sideOrgins: Route.PositionVec, routingRect: RoutePrivate.PQRect] = { <> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; activeSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanSide]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; extSide: Route.Side _ RouteChannel.IntSideToExtSide[routingArea, chanSide]; extSidesData: RoutePrivate.RoutingAreaSides _ NARROW[routingArea.routingSides]; extSideData: RoutePrivate.RoutingAreaSide _ extSidesData[extSide]; activeSide.enclosingBarrier _ [[0, 0], [0, 0]]; activeSide.extSide _ extSide; activeSide.sideOrg _ RouteUtil.XYToPQ[routingArea, sideOrgins[extSide]]; chanPins.cEnd1 _ routingRect.c1.p; chanPins.cEnd2 _ routingRect.c2.p; IF extSideData # NIL THEN { encloseBranch: RoutePrivate.PQRect _ TranslateBarriers[routingArea, activeSide, branch]; encloseTrunk: RoutePrivate.PQRect _ TranslateBarriers[routingArea, activeSide, trunk]; activeSide.enclosingBarrier _ Surround[encloseBranch, encloseTrunk]; activeSide.sideFiducial _ RouteUtil.XYToPQ[routingArea, extSideData.sideFiducial]; activeSide.properties _ extSideData.properties}}; TranslateBarriers: PROCEDURE[routingArea: Route.RoutingArea, activeSide: RouteChannel.RoutingChannelSides, rLayer: RoutePrivate.RoutingLayer] RETURNS [enclosingRect: RoutePrivate.PQRect _ [[0, 0], [0, 0]]] = { <> <<>> extSidesData: RoutePrivate.RoutingAreaSides _ NARROW[routingArea.routingSides]; extSide: Route.Side _ activeSide.extSide; extSideData: RoutePrivate.RoutingAreaSide _ extSidesData[extSide]; chanDirection: Route.Direction _ routingArea.rules.trunkDirection; IF extSideData # NIL THEN { FOR bList: Route.RoutingBarrierList _ extSideData.barrierList, bList.rest WHILE bList # NIL DO barrierItem: Route.RoutingBarrier _ bList.first; generalLayer: Route.Layer _ barrierItem.layer; IF generalLayer = CD.undefLayer OR RouteUtil.LayerToRoutingLayer[routingArea, generalLayer] = rLayer THEN { FOR rList: Route.RectList _ barrierItem.barrier, rList.rest WHILE rList # NIL DO cleanRectangle: RoutePrivate.PQRectRef _ CheckRect[routingArea, rList.first, activeSide]; IF cleanRectangle # NIL THEN { enclosingRect _ Surround[enclosingRect, cleanRectangle^]; activeSide.barrierList[rLayer] _ CONS[cleanRectangle^, activeSide.barrierList[rLayer]]}; ENDLOOP} ENDLOOP}}; CheckRect: PROC [routingArea: Route.RoutingArea, rect: Route.Rect, activeSide: RouteChannel.RoutingChannelSides] RETURNS[cleanRect: RoutePrivate.PQRectRef] = { <> <<>> chanDirection: Route.Direction _ routingArea.rules.trunkDirection; c1: RoutePrivate.PQPosition _ RouteUtil.XYToPQ[routingArea, [rect.x1, rect.y1]]; c2: RoutePrivate.PQPosition _ RouteUtil.XYToPQ[routingArea, [rect.x2, rect.y2]]; t1: RoutePrivate.PQPosition _ [c1.p - activeSide.sideFiducial.p + activeSide.sideOrg.p, c1.q - activeSide.sideFiducial.q + activeSide.sideOrg.q]; t2: RoutePrivate.PQPosition _ [c2.p - activeSide.sideFiducial.p + activeSide.sideOrg.p, c2.q - activeSide.sideFiducial.q + activeSide.sideOrg.q]; RETURN[NEW[RoutePrivate.PQRect _ [t1, t2]]]}; ConvertEnd: PROCEDURE[routingArea: Route.RoutingArea, chanSide: RouteChannel.ChanSide, sideOrgins: Route.PositionVec, routingRect: RoutePrivate.PQRect] = { <> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; activeSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanSide]; extSide: Route.Side _ RouteChannel.IntSideToExtSide[routingArea, chanSide]; extSidesData: RoutePrivate.RoutingAreaSides _ NARROW[routingArea.routingSides]; extSideData: RoutePrivate.RoutingAreaSide _ extSidesData[extSide]; activeSide.extSide _ extSide; activeSide.enclosingBarrier _ [[0, 0], [0, 0]]; activeSide.sideOrg _ RouteUtil.XYToPQ[routingArea, sideOrgins[extSide]]; IF extSideData # NIL THEN { encloseBranch: RoutePrivate.PQRect _ TranslateBarriers[routingArea, activeSide, branch]; encloseTrunk: RoutePrivate.PQRect _ TranslateBarriers[routingArea, activeSide, trunk]; activeSide.sideFiducial _ RouteUtil.XYToPQ[routingArea, extSideData.sideFiducial]; activeSide.enclosingBarrier _ Surround[encloseBranch, encloseTrunk]; activeSide.properties _ extSideData.properties}}; FixOrgins: PROCEDURE[routingArea: Route.RoutingArea, routingRect: RoutePrivate.PQRect] = { <> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; leftSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanLeft]; rightSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanRight]; bottomSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanBottom]; topSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanTop]; zero: Route.Number _ 0; -- don't laugh <> leftSide.routeAreaCoord _ chanPins.cEnd1; rightSide.routeAreaCoord _ chanPins.cEnd2; chanPins.cEnd1 _ chanPins.cEnd1 + MAX[zero, leftSide.enclosingBarrier.c2.p]; chanPins.cEnd2 _ chanPins.cEnd2 + MAX[zero, rightSide.enclosingBarrier.c1.p]; bottomSide.routeAreaCoord _ routingRect.c1.q; topSide.routeAreaCoord _ routingRect.c2.q}; InitNet: PROCEDURE[routingArea: Route.RoutingArea, net: RoutePrivate.Net, signalSinglePinNets, signalCoincidentPins: BOOLEAN] = { <> <<>> PPinCompare: List.CompareProc = { p1: Route.Number _ NARROW[ref1, RouteChannel.InternPin].location.p; p2: Route.Number _ NARROW[ref2, RouteChannel.InternPin].location.p; RETURN[IF p1 < p2 THEN Basics.Comparison.less ELSE IF p1 = p2 THEN Basics.Comparison.equal ELSE Basics.Comparison.greater]}; mungedPinList, sortedPinList: List.LORA; parms: RoutePrivate.RoutingAreaParms _ NARROW[routingArea.parms]; chanDirection: Route.Direction _ routingArea.rules.trunkDirection; net.internPinList _ FixPins[routingArea, net.pinList, chanDirection]; mungedPinList _ ConvertToLORA[NARROW[net.internPinList]]; sortedPinList _ List.Sort[mungedPinList, PPinCompare]; IF CheckChanPins[routingArea, net, sortedPinList, signalSinglePinNets, signalCoincidentPins] THEN BuildChanPin[routingArea, net, sortedPinList]}; FixPins: PROC [routingArea: Route.RoutingArea, pList: Route.PinList, chanDirection: Route.Direction] RETURNS [fixedPins: -- List.LORA _ NIL -- RouteChannel.InternPinList _ NIL ] = { <> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; parms: RoutePrivate.RoutingAreaParms _ NARROW[routingArea.parms]; FOR list: Route.PinList _ pList, list.rest WHILE list # NIL DO old: Route.Pin _ list.first; loc: RoutePrivate.PQPosition; oldWidth, width: Route.Number; new: RouteChannel.InternPin; oldPinSize: CD.Position _ CDOrient.OrientedSize[old.pin.ob.size, old.pin.orientation]; chanSide: RouteChannel.ChanSide _ RouteChannel.ExtSideToIntSide[routingArea, old.side]; activeSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanSide]; layer: Route.Layer _ CDSymbolicObjects.GetLayer[old.pin]; rLayer: RoutePrivate.RoutingLayer _ RouteUtil.LayerToRoutingLayer[routingArea, layer]; name: Rope.ROPE _ CDSymbolicObjects.GetName[old.pin]; sideFiducial: RoutePrivate.PQPosition _ activeSide.sideFiducial; sideOrg: RoutePrivate.PQPosition _ activeSide.sideOrg; oldLoc: Route.Position; SELECT old.side FROM bottom => { oldWidth _ oldPinSize.x; oldLoc _ [old.pin.location.x + oldPinSize.x/2, old.pin.location.y + oldPinSize.y]}; top => { oldWidth _ oldPinSize.x; oldLoc _ [old.pin.location.x + oldPinSize.x/2, old.pin.location.y]}; left => { oldWidth _ oldPinSize.y; oldLoc _ [old.pin.location.x + oldPinSize.x, old.pin.location.y + oldPinSize.y/2]}; right => { oldWidth _ oldPinSize.y; oldLoc _ [old.pin.location.x, old.pin.location.y + oldPinSize.y/2]}; ENDCASE; SELECT chanSide FROM chanBottom, chanTop => { loc _ RouteChannel.SubPoints[RouteUtil.XYToPQ[routingArea, oldLoc], sideFiducial]; loc _ RouteChannel.AddPoints[loc, sideOrg]; loc.q _ loc.q - activeSide.routeAreaCoord; width _ oldWidth}; chanLeft => { IF parms.routerUsed = channel THEN {loc _ [chanPins.cEnd1, 0]; width _ 0} ELSE IF parms.routerUsed = switchBox THEN { loc _ RouteChannel.SubPoints[RouteUtil.XYToPQ[routingArea, oldLoc], sideFiducial]; loc _ RouteChannel.AddPoints[loc, sideOrg]; loc.p _ chanPins.cEnd1; width _ oldWidth}}; chanRight => { IF parms.routerUsed = channel THEN {loc _ [chanPins.cEnd2, 0]; width _ 0} ELSE IF parms.routerUsed = switchBox THEN {loc _ RouteChannel.SubPoints[RouteUtil.XYToPQ[routingArea, oldLoc], sideFiducial]; loc _ RouteChannel.AddPoints[loc, sideOrg]; loc.p _ chanPins.cEnd2; width _ oldWidth}}; ENDCASE; new _ NEW[RouteChannel.InternPinRec _ [name, chanSide, loc, width, rLayer, old]]; fixedPins _ CONS[new, fixedPins]; ENDLOOP}; CheckChanPins: PROC [routingArea: Route.RoutingArea, net: RoutePrivate.Net, pinList: List.LORA -- RouteChannel.InternPinList --, signalSinglePinNets, signalCoincidentPins: BOOLEAN] RETURNS [ok: BOOLEAN _ TRUE] = { <> <<-- number of pins > 1>> <<-- pins within range>> <<-- pin overlap>> <<-- pin spacing>> <<-- max number of pins>> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; netTab: RoutePrivate.NetTab _ NARROW[routingArea.nets, RoutePrivate.NetTab]; numPins, numOverlaps: NAT _ 0; leftExit, rightExit: BOOLEAN _ FALSE; branchLayer: CD.Layer _ routingArea.rules.branchLayer; trunkLayer: CD.Layer _ routingArea.rules.trunkLayer; previousPin: RouteChannel.InternPin _ NIL; FOR pList: List.LORA -- RouteChannel.InternPinList -- _ pinList, pList.rest WHILE pList # NIL DO this: RouteChannel.InternPin _ NARROW[pList.first]; pinLayer: CD.Layer _ CDSymbolicObjects.GetLayer[this.pin.pin]; numPins _ numPins + 1; IF previousPin # NIL THEN { -- check for overlapping pins. IF previousPin.chanSide = this.chanSide THEN { rLast: RoutePrivate.Range _ [previousPin.location.p - previousPin.pWidth/2, previousPin.location.p + previousPin.pWidth/2]; rThis: RoutePrivate.Range _ [this.location.p - this.pWidth/2, this.location.p + this.pWidth/2]; IF RouteChannel.Overlaps[rLast, rThis] THEN { numOverlaps _ numOverlaps + 1; IF signalCoincidentPins OR ~(previousPin.location = this.location AND previousPin.pWidth = this.pWidth) THEN Route.Signal[callingError, Rope.Cat[Rope.Cat["Pins overlap, net: ", net.name, ", pins: "], Rope.Cat[this.name, ", ", previousPin.name]]]; ok _ FALSE}} }; SELECT this.chanSide FROM chanBottom, chanTop => { pos: Route.Number _ this.location.p; IF chanPins.cEnd1 > pos OR chanPins.cEnd2 < pos THEN { Route.Signal[callingError, Rope.Cat["Pin location out of range, net: ", net.name, ", pin: ", this.name]]; ok _ FALSE}; IF pinLayer # branchLayer THEN { Route.Signal[callingError, Rope.Cat["Pin not on branch layer, net: ", net.name, ", pin: ", this.name]]; ok _ FALSE}}; chanLeft => { IF pinLayer # trunkLayer THEN { Route.Signal[callingError, Rope.Cat["Pin not on trunk layer, net: ", net.name, ", pin: ", this.name]]; ok _ FALSE}; IF leftExit THEN { Route.Signal[callingError, Rope.Cat["Multiple channel exits: ", net.name, ", pin: ", this.name]]; ok _ FALSE}; leftExit _ TRUE}; chanRight => { IF pinLayer # trunkLayer THEN { Route.Signal[callingError, Rope.Cat["Pin not on trunk layer, net: ", net.name, ", pin: ", this.name]]; ok _ FALSE}; IF rightExit THEN { Route.Signal[callingError, Rope.Cat["Multiple channel exits: ", net.name, ", pin: ", this.name]]; ok _ FALSE}; rightExit _ TRUE}; ENDCASE; previousPin _ this; ENDLOOP; IF numPins - numOverlaps <= 1 THEN { IF signalSinglePinNets THEN Route.Signal[callingError, Rope.Cat["Too few pins for net: ", net.name]]; ok _ FALSE}; IF netTab.count + numPins > netTab.size THEN { Route.Signal[noResource, "Net table is too small"]; ok _ FALSE}}; BuildChanPin: PROC [routingArea: Route.RoutingArea, net: RoutePrivate.Net, pinList: List.LORA -- RouteChannel.InternPinList -- ] = { <> <> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; interiorPins: RouteChannel.ChanPinList _ NIL; rightInternPin: RouteChannel.InternPin _ NARROW[List.NthElement[pinList, -1]]; previousPin: RouteChannel.InternPin _ NIL; leftPin, rightPin: RouteChannel.ChanPin _ NIL; allPinsOverlap: BOOLEAN _ TRUE; seg: RouteChannel.Segment _ NEW[RouteChannel.SegmentRec _ [net: net]]; FOR pList: List.LORA -- RouteChannel.InternPinList -- _ pinList, pList.rest WHILE pList # NIL DO pinIndex: RouteChannel.ZMPinsOnCh; pinPosition: RouteChannel.PinPosition; chanPin: RouteChannel.ChanPin; this: RouteChannel.InternPin _ NARROW[pList.first]; useThisOne: BOOLEAN _ TRUE; IF previousPin # NIL THEN { -- This is a crock! If Bertrand checked for overlapping pins wouldn't be necessary!! rLast: RoutePrivate.Range _ [previousPin.location.p - previousPin.pWidth/2, previousPin.location.p + previousPin.pWidth/2]; rThis: RoutePrivate.Range _ [this.location.p - this.pWidth/2, this.location.p + this.pWidth/2]; IF previousPin.chanSide = this.chanSide AND RouteChannel.Overlaps[rLast, rThis] THEN useThisOne _ FALSE; IF this.chanSide # chanLeft AND this.chanSide # chanRight THEN allPinsOverlap _ allPinsOverlap AND RouteChannel.Equal[rLast, rThis] }; IF useThisOne THEN { pinIndex _ FindPinPos[routingArea, this.location.p]; pinPosition _ chanPins.sides[pinIndex]; chanPin _ BuildPin[routingArea, this, pinPosition, routingArea.rules.branchWidth]; SELECT this.chanSide FROM chanBottom, chanTop => IF ~PinViolation[routingArea, chanPin, net] THEN pinPosition.pins[chanPin.pinSide] _ chanPin; chanLeft, chanRight => pinPosition.innerPins _ CONS[chanPin, pinPosition.innerPins]; ENDCASE; IF leftPin = NIL THEN { leftPin _ chanPin; chanPin.conctSeg[chanLeft] _ NIL; chanPin.conctSeg[chanRight] _ seg} ELSE IF this = rightInternPin THEN { rightPin _ chanPin; chanPin.conctSeg[chanRight] _ NIL; chanPin.conctSeg[chanLeft] _ seg} ELSE { interiorPins _ CONS[chanPin, interiorPins]; chanPin.conctSeg[chanRight] _ seg; chanPin.conctSeg[chanLeft] _ seg}}; previousPin _ this; ENDLOOP; <> seg.exteriorPins[chanLeft] _ leftPin; seg.exteriorPins[chanRight] _ rightPin; seg.interiorPins _ interiorPins; seg.qWidth _ IF allPinsOverlap THEN routingArea.rules.trunkWidth ELSE net.trunkWidth}; FindPinPos: PUBLIC PROC [routingArea: Route.RoutingArea, thisPLoc: Route.Number] RETURNS [index: RouteChannel.ZMPinsOnCh _ 0] = { <> <> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; found: BOOLEAN _ FALSE; FOR pIndex: RouteChannel.ZMPinsOnCh IN [1 .. chanPins.count] WHILE ~found DO pLoc: Route.Number _ chanPins.sides[pIndex].pLoc; IF pLoc > thisPLoc THEN { -- add a new pinPosition found _ TRUE; MovePins[chanPins, pIndex]; index _ pIndex; chanPins.sides[pIndex] _ NEW[RouteChannel.PinPositionRec _ [index, thisPLoc]]} ELSE IF pLoc = thisPLoc THEN { -- pin position already taken, use it found _ TRUE; index _ pIndex}; ENDLOOP; IF ~found THEN { -- this pin goes after the last pin chanPins.count _ chanPins.count +1; index _ chanPins.count; chanPins.sides[index] _ NEW[RouteChannel.PinPositionRec _ [index, thisPLoc]]}; }; MovePins: PROC [chanPins: RouteChannel.RoutingChannelPins, pIndex: RouteChannel.ZMPinsOnCh] = { chanPins.count _ chanPins.count +1; FOR index: RouteChannel.ZMPinsOnCh DECREASING IN [pIndex+1 .. chanPins.count] DO pinPos: RouteChannel.PinPosition _ chanPins.sides[index-1]; pinPos.pinIndex _ index; chanPins.sides[index] _ pinPos; ENDLOOP}; BuildPin: PROC [routingArea: Route.RoutingArea, iPin: RouteChannel.InternPin, pinPosition: RouteChannel.PinPosition, pinWidth: Route.Number] RETURNS [pin: RouteChannel.ChanPin] = { <> parms: RoutePrivate.RoutingAreaParms _ NARROW[routingArea.parms]; kindOfPin: RouteChannel.ChanPinType _ IF iPin.chanSide = chanLeft OR iPin.chanSide = chanRight THEN exitPin ELSE compPin; thisPinWidth: Route.Number _ IF kindOfPin = exitPin THEN iPin.pWidth ELSE MAX[pinWidth, iPin.pWidth]; parms.widestPin _ MAX[thisPinWidth, parms.widestPin]; pin _ NEW[RouteChannel.ChanPinRec _ [pinSide: iPin.chanSide, qLoc: iPin.location.q, pWidth: thisPinWidth, kindOfPin: kindOfPin, pinPosition: pinPosition, pin: iPin]]}; PinViolation: PROC [routingArea: Route.RoutingArea, pin: RouteChannel.ChanPin, net: RoutePrivate.Net] RETURNS [violation: BOOLEAN _ FALSE] = { <> LimitProc: RouteChannel.EachPinActionProc = { IF pin # NIL THEN IF pin.pinSide = pinSide THEN {width: Route.Number _ RouteUtil.GetWidthWithContact[routingArea, pin.pWidth]/2; pinPos: Route.Number _ pin.pinPosition.pLoc; IF pinPos < pLoc THEN quit _ pinPos + width + routingArea.rules.branchSpacing > pLoc - pWidth ELSE -- pinPos >= pLoc quit _ pLoc + pWidth + routingArea.rules.branchSpacing > pinPos - width}; IF quit THEN violationPin _ pin.pin}; chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; parms: RoutePrivate.RoutingAreaParms _ NARROW[routingArea.parms]; pinSide: RouteChannel.ChanSide _ pin.pinSide; pinIndex: RouteChannel.ZMPinsOnCh _ pin.pinPosition.pinIndex; pLoc: Route.Number _ pin.pinPosition.pLoc; pWidth: Route.Number _ RouteUtil.GetWidthWithContact[routingArea, pin.pWidth]/2; testWidth: Route.Number _ RouteUtil.GetWidthWithContact[routingArea, parms.widestPin] + routingArea.rules.branchSpacing; violationPin: RouteChannel.InternPin _ NIL; <<>> <> iPos: Route.Number _ chanPins.sides[pinIndex].pLoc; FOR limitIndex: RouteChannel.MPinsOnCh DECREASING IN [1 .. pinIndex] WHILE chanPins.sides[limitIndex].pLoc + testWidth > iPos AND ~violation DO violation _ RouteChannel.EnumPins[routingArea, chanPins.sides[limitIndex], LimitProc]; IF violation THEN Route.Signal[callingError, Rope.Cat[Rope.Cat["Pins are too close. net 1: ", net.name, ", pin 1: ", pin.pin.name], Rope.Cat[ ", pin 2: ", violationPin.name]]]; ENDLOOP; <> iPos _ chanPins.sides[pinIndex].pLoc; FOR limitIndex: RouteChannel.MPinsOnCh IN [pinIndex .. chanPins.count] WHILE chanPins.sides[limitIndex].pLoc - testWidth < iPos AND ~violation DO violation _ RouteChannel.EnumPins[routingArea, chanPins.sides[limitIndex], LimitProc]; IF violation THEN Route.Signal[callingError, Rope.Cat[Rope.Cat["Pins are too close. net 1: ", net.name, ", pin 1: ", pin.pin.name], Rope.Cat[ ", pin 2: ", violationPin.name]]]; ENDLOOP}; GetExitPins: PROC [routingArea: Route.RoutingArea] RETURNS [exitPins: List.LORA _ NIL] = { <> <> ReallyGetExits: PROC [pinPos: RouteChannel.PinPosition] = { IF pinPos # NIL THEN { FOR pList: RouteChannel.ChanPinList _ pinPos.innerPins, pList.rest WHILE pList # NIL DO this: RouteChannel.ChanPin _ pList.first; SELECT this.pin.chanSide FROM chanLeft, chanRight => exitPins _ CONS[this, exitPins]; ENDCASE; ENDLOOP}}; chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; ReallyGetExits[chanPins.sides[1]]; IF chanPins.count > 0 THEN ReallyGetExits[chanPins.sides[chanPins.count]]}; MakeSBTracks: PROC [routingArea: Route.RoutingArea, okToDiddleLLPins, okToDiddleURPins: BOOLEAN] = { <> ExitPinCompare: List.CompareProc = { q1: Route.Number _ NARROW[ref1, RouteChannel.ChanPin].pin.location.q; q2: Route.Number _ NARROW[ref2, RouteChannel.ChanPin].pin.location.q; RETURN[IF q1 < q2 THEN Basics.Comparison.less ELSE IF q1 = q2 THEN Basics.Comparison.equal ELSE Basics.Comparison.greater]}; DoUp: PROC [thisPos: Route.Number]~ { FOR trackPos: Route.Number _ lastPos + trackDist, trackPos + trackDist WHILE trackPos <= thisPos - trackDist DO [] _ AddTrack[routingArea, trackPos]; lastPos _ trackPos; ENDLOOP}; ClosestTrack: PROC [thisPos: Route.Number] RETURNS [track: RouteChannel.Track _ NIL] ~ { dist: INT _ LAST[INT]; FOR trackNum: INT IN [1 .. chanTracks.count] DO trialTrack: RouteChannel.Track _ chanTracks.tracks[trackNum]; trialDist: INT _ ABS[trialTrack.trackPos - thisPos]; IF trialDist < dist THEN { track _ trialTrack; dist _ trialDist} ENDLOOP; }; chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanTracks: RouteChannel.RoutingChannelTracks _ chanData.chanTracks; exitPinList: List.LORA _ GetExitPins[routingArea]; sortedExitPinList: List.LORA _ List.Sort[exitPinList, ExitPinCompare]; lastPos: Route.Number _ chanData.chanSides[chanBottom].routeAreaCoord; previousPin: RouteChannel.ChanPin _ NIL; trackDist: Route.Number _ routingArea.rules.trunkToTrunk; lastTrack: RouteChannel.Track _ NIL; <> <<>> FOR pList: List.LORA -- RouteChannel.InternPinList -- _ sortedExitPinList, pList.rest WHILE pList # NIL DO this: RouteChannel.ChanPin _ NARROW[pList.first]; thisPos: Route.Number _ this.pin.location.q; pin2Name: Rope.ROPE _ IF previousPin = NIL THEN "none" ELSE previousPin.pin.name; track: RouteChannel.Track _ NIL; SELECT TRUE FROM ~okToDiddleLLPins AND ~okToDiddleURPins => { -- can't move any pins IF thisPos = lastPos THEN -- already have a track here track _ lastTrack ELSE IF thisPos >= lastPos + trackDist THEN { -- lots of room here DoUp[thisPos]; track _ AddTrack[routingArea, thisPos]} ELSE { Route.Signal[callingError, Rope.Cat["Pins too close on ends of switchbox, pin 1: ", this.pin.name, ", pin 2: ", pin2Name]]; track _ AddTrack[routingArea, thisPos]}; BindPinToTrack[this, track]; previousPin _ this; lastTrack _ track; lastPos _ thisPos}; okToDiddleLLPins AND okToDiddleURPins => { -- can move pins on both sides IF thisPos = lastPos THEN -- already have a track here track _ lastTrack ELSE IF thisPos >= lastPos + trackDist THEN { -- lots of room here DoUp[thisPos]; track _ AddTrack[routingArea, thisPos]} ELSE { thisPos _ lastPos + trackDist; track _ AddTrack[routingArea, thisPos]}; BindPinToTrack[this, track]; previousPin _ this; lastTrack _ track; lastPos _ thisPos}; okToDiddleLLPins => { -- can move only pins on the left IF this.pin.chanSide = chanRight THEN { -- this pin is on the right IF thisPos >= lastPos + trackDist THEN -- lots of room here DoUp[thisPos] ELSE -- not enough room, error Route.Signal[callingError, Rope.Cat["Pins too close on ends of switchbox, pin 1: ", this.pin.name, ", pin 2: ", pin2Name]]; track _ AddTrack[routingArea, thisPos]; BindPinToTrack[this, track]; previousPin _ this; lastTrack _ track; lastPos _ thisPos}}; okToDiddleURPins => { -- can move only pins on the right IF this.pin.chanSide = chanLeft THEN { -- this pin is on the left IF thisPos >= lastPos + trackDist THEN -- lots of room here DoUp[thisPos] ELSE -- not enough room, error Route.Signal[callingError, Rope.Cat["Pins too close on ends of switchbox, pin 1: ", this.pin.name, ", pin 2: ", pin2Name]]; track _ AddTrack[routingArea, thisPos]; BindPinToTrack[this, track]; previousPin _ this; lastTrack _ track; lastPos _ thisPos}}; ENDCASE; ENDLOOP; <> IF previousPin # NIL AND lastPos > chanData.chanSides[chanTop].routeAreaCoord - trackDist THEN { Route.Signal[callingError, Rope.Cat["Pins too close on ends of switchbox, pin : ", previousPin.pin.name]]}; FOR trackPos: Route.Number _ lastPos + trackDist, trackPos + trackDist WHILE trackPos < chanData.chanSides[chanTop].routeAreaCoord - trackDist DO [] _ AddTrack[routingArea, trackPos]; lastPos _ trackPos; ENDLOOP; chanTracks.maxCount _ chanTracks.count; IF okToDiddleLLPins # okToDiddleURPins THEN { <> FOR pList: List.LORA -- RouteChannel.InternPinList -- _ sortedExitPinList, pList.rest WHILE pList # NIL DO this: RouteChannel.ChanPin _ NARROW[pList.first]; thisPos: Route.Number _ this.pin.location.q; pin2Name: Rope.ROPE _ IF previousPin = NIL THEN "none" ELSE previousPin.pin.name; track: RouteChannel.Track; SELECT TRUE FROM okToDiddleLLPins => { -- can move only pins on the left IF this.pin.chanSide = chanLeft THEN { -- this pin is on the left track _ ClosestTrack[thisPos]; BindPinToTrack[this, track]}; }; okToDiddleURPins => { -- can move only pins on the right IF this.pin.chanSide = chanRight THEN { -- this pin is on the right track _ ClosestTrack[thisPos]; BindPinToTrack[this, track]}; }; ENDCASE; ENDLOOP}; }; MakeCRTracks: PROC [routingArea: Route.RoutingArea, maxTracksRequired: NAT] = { <> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanTracks: RouteChannel.RoutingChannelTracks _ chanData.chanTracks; trackLimit: RouteChannel.ZMaxTracks _ MIN[chanTracks.size, maxTracksRequired]; FOR trackIndex: RouteChannel.ZMaxTracks IN [1 .. trackLimit] DO loc: Route.Number _ routingArea.rules.trunkToEdge + (trackIndex - 1) * routingArea.rules.trunkToTrunk; [] _ AddTrack[routingArea, loc]; ENDLOOP; chanTracks.maxCount _ chanTracks.count}; AddTrack: PROC [routingArea: Route.RoutingArea, trackPos: Route.Number] RETURNS [track: RouteChannel.Track] = { <> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanTracks: RouteChannel.RoutingChannelTracks _ chanData.chanTracks; IF chanTracks.count >= RouteChannel.maxTrack THEN Route.Signal[noResource, "Too many tracks needed, call implementor"]; chanTracks.count _ chanTracks.count + 1; track _ chanTracks.tracks[chanTracks.count] _ NEW[RouteChannel.TrackRec _ [trackNum: chanTracks.count, trackPos: trackPos]]}; BindPinToTrack: PROC [pin: RouteChannel.ChanPin, track: RouteChannel.Track] ~ { IF pin # NIL THEN { <> sList: RouteChannel.SegmentList _ RouteChannel.GetSegsOnPin[pin]; pin.trackConstraint _ track.trackNum; FOR segs: RouteChannel.SegmentList _ sList, segs.rest WHILE segs # NIL DO seg: RouteChannel.Segment _ segs.first; IF seg # NIL THEN { IF seg.trackConstraint = 0 THEN seg.trackConstraint _ track.trackNum ELSE seg.secTrackConstraint _ track.trackNum}; ENDLOOP; }}; DoTBBarriers: PROC [routingArea: Route.RoutingArea, chanSide: RouteChannel.ChanSide] = { <> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; activeSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanSide]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; trackDist: Route.Number _ routingArea.rules.trunkToTrunk; FOR rlayer: RoutePrivate.RoutingLayer IN [trunk .. branch] DO FOR bList: RoutePrivate.PQRectList _ activeSide.barrierList[rlayer], bList.rest WHILE bList # NIL DO BlockProc: RouteChannel.EachTrackActionProc = { trackPos: Route.Number _ RouteChannel.TrackLoc[routingArea, trackIndex]; IF minQ < trackPos - trackDist AND trackPos + trackDist < maxQ THEN track.blocked _ TRUE}; barrierItem: RoutePrivate.PQRect _ bList.first; minQ: Route.Number _ MIN[barrierItem.c1.q, barrierItem.c2.q]; maxQ: Route.Number _ MAX[barrierItem.c1.q, barrierItem.c2.q]; [] _ RouteChannel.EnumTracks[routingArea, BlockProc]; ENDLOOP; ENDLOOP}; DoLRBarriers: PROC [routingArea: Route.RoutingArea, chanSide: RouteChannel.ChanSide] = { <> <<>> chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; activeSide: RouteChannel.RoutingChannelSides _ chanData.chanSides[chanSide]; FOR rlayer: RoutePrivate.RoutingLayer IN [trunk .. branch] DO FOR bList: RoutePrivate.PQRectList _ activeSide.barrierList[rlayer], bList.rest WHILE bList # NIL DO BlockProc: RouteChannel.EachTrackActionProc = { NULL }; barrierItem: RoutePrivate.PQRect _ bList.first; minQ: Route.Number _ MIN[barrierItem.c1.q, barrierItem.c2.q]; maxQ: Route.Number _ MAX[barrierItem.c1.q, barrierItem.c2.q]; [] _ RouteChannel.EnumTracks[routingArea, BlockProc]; ENDLOOP; ENDLOOP}; Surround: PROC [r1, r2: RoutePrivate.PQRect] RETURNS [RoutePrivate.PQRect] = INLINE { RETURN [RoutePrivate.PQRect[ [MIN[r1.c1.p, r2.c1.p], MIN[r1.c1.q, r2.c1.q]], [MAX[r1.c2.p, r2.c2.p], MAX[r1.c2.q, r2.c2.q]]]]}; ConvertToLORA: PROC [list: RouteChannel.InternPinList] RETURNS[val: List.LORA] = { val _ NIL; UNTIL list = NIL DO val _ CONS[list.first, val]; list _ list.rest; ENDLOOP; RETURN[val]; }; -- of ConvertToLORA END.