DIRECTORY Basics, CD, CDBasics, CDOrient, CDPinObjects, List, Rope, Route, RouteChannel, RoutePrivate, RouteUtil; RouteChannelInitImpl: CEDAR PROGRAM IMPORTS CDBasics, CDOrient, CDPinObjects, 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] = { 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 _ 2*(RouteChannel.InfluenceTracks[routingArea, parms.widestTrunk] + 1); ConvertSide[routingArea, chanBottom, sideOrgins, rRect]; ConvertSide[routingArea, chanTop, sideOrgins, rRect]; ConvertEnd[routingArea, chanLeft, sideOrgins, rRect]; ConvertEnd[routingArea, chanRight, sideOrgins, rRect]; -- fix up the routing area orgins FixOrgins[routingArea, rRect]; netTab _ NARROW[routingArea.nets, RoutePrivate.NetTab]; FOR netIndex: RoutePrivate.ZMaxNets IN [1 .. netTab.count] DO InitNet[routingArea, netTab.n[netIndex]]; ENDLOOP; IF parms.routerUsed = switchBox THEN MakeSBTracks[routingArea] 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.combined 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] = { 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]; TRUSTED{mungedPinList _ List.Reverse[LOOPHOLE[net.internPinList]]}; sortedPinList _ List.Sort[mungedPinList, PPinCompare]; IF CheckChanPins[routingArea, net, sortedPinList] 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 _ CDPinObjects.GetLayer[old.pin]; rLayer: RoutePrivate.RoutingLayer _ RouteUtil.LayerToRoutingLayer[routingArea, layer]; name: Rope.ROPE _ CDPinObjects.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 --] RETURNS [ok: BOOLEAN _ TRUE] = { chanData: RouteChannel.ChannelData _ NARROW[routingArea.privateData]; chanPins: RouteChannel.RoutingChannelPins _ chanData.chanPins; netTab: RoutePrivate.NetTab _ NARROW[routingArea.nets, RoutePrivate.NetTab]; numPins: NAT _ 0; leftExit, rightExit: BOOLEAN _ FALSE; branchLayer: CD.Layer _ routingArea.rules.branchLayer; trunkLayer: CD.Layer _ routingArea.rules.trunkLayer; FOR pList: List.LORA -- RouteChannel.InternPinList -- _ pinList, pList.rest WHILE pList # NIL DO this: RouteChannel.InternPin _ NARROW[pList.first]; pinLayer: CD.Layer _ CDPinObjects.GetLayer[this.pin.pin]; numPins _ numPins + 1; 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; ENDLOOP; IF numPins <= 1 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; trunkWidth: Route.Number _ MAX[routingArea.rules.trunkWidth, net.trunkWidth]; seg: RouteChannel.Segment _ NEW[RouteChannel.SegmentRec _ [net: net, qWidth: trunkWidth]]; interiorPins: RouteChannel.ChanPinList _ NIL; rightInternPin: RouteChannel.InternPin _ NARROW[List.NthElement[pinList, -1]]; leftPin, rightPin: RouteChannel.ChanPin _ NIL; FOR pList: List.LORA -- RouteChannel.InternPinList -- _ pinList, pList.rest WHILE pList # NIL DO this: RouteChannel.InternPin _ NARROW[pList.first]; pinIndex: RouteChannel.ZMPinsOnCh _ FindPinPos[routingArea, this.location.p]; pinPosition: RouteChannel.PinPosition _ chanPins.sides[pinIndex]; chanPin: RouteChannel.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}; ENDLOOP; seg.exteriorPins[chanLeft] _ leftPin; seg.exteriorPins[chanRight] _ rightPin; seg.interiorPins _ interiorPins}; 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 _ pin.pWidth/2; pinPos: Route.Number _ pin.pinPosition.pLoc; IF pinPos < pLoc THEN quit _ pinPos + width + spacing > pLoc - pWidth ELSE -- pinPos >= pLoc quit _ pLoc + pWidth + spacing > 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; spacing: Route.Number _ routingArea.rules.pinSpacing - routingArea.rules.branchSpacing; pLoc: Route.Number _ pin.pinPosition.pLoc; pWidth: Route.Number _ pin.pWidth/2; testWidth: Route.Number _ parms.widestPin + routingArea.rules.branchToBranch - 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] = { 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]}; 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; lastPin: RouteChannel.ChanPin _ NIL; trackDist: Route.Number _ routingArea.rules.trunkToTrunk; FOR pList: List.LORA -- RouteChannel.InternPinList -- _ sortedExitPinList, pList.rest WHILE pList # NIL DO this: RouteChannel.ChanPin _ NARROW[pList.first]; SELECT this.pin.chanSide FROM chanLeft, chanRight => { thisPos: Route.Number _ this.pin.location.q; IF thisPos = lastPos THEN NULL ELSE IF thisPos < lastPos + trackDist THEN { pin2Name: Rope.ROPE _ IF lastPin = NIL THEN NIL ELSE lastPin.pin.name; Route.Signal[callingError, Rope.Cat["Pins too close on ends of switchbox, pin 1: ", this.pin.name, ", pin 2: ", pin2Name]]} ELSE { FOR trackPos: Route.Number _ lastPos + trackDist, trackPos + trackDist WHILE trackPos <= thisPos - trackDist DO AddTrack[routingArea, trackPos, NIL]; lastPos _ trackPos; ENDLOOP; AddTrack[routingArea, thisPos, this]; lastPos _ thisPos}}; ENDCASE; lastPin _ this; ENDLOOP; FOR trackPos: Route.Number _ lastPos + trackDist, trackPos + trackDist WHILE trackPos < chanData.chanSides[chanTop].routeAreaCoord - trackDist DO AddTrack[routingArea, trackPos, NIL]; lastPos _ trackPos; ENDLOOP; chanTracks.maxCount _ chanTracks.count}; 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, NIL]; ENDLOOP; chanTracks.maxCount _ chanTracks.count}; AddTrack: PROC [routingArea: Route.RoutingArea, trackPos: Route.Number, pin: RouteChannel.ChanPin] = { 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; chanTracks.tracks[chanTracks.count] _ NEW[RouteChannel.TrackRec _ [trackNum: chanTracks.count, trackPos: trackPos]]; IF pin # NIL THEN { sList: RouteChannel.SegmentList _ RouteChannel.GetSegsOnPin[pin]; pin.trackConstraint _ chanTracks.count; 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 _ chanTracks.count ELSE seg.secTrackConstraint _ chanTracks.count}; 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]]]]}; END. ~RouteChannelInitImpl.mesa ///Route/RouteChannelInitImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. by Bryan Preas July 10, 1985 6:57:00 pm PDT last edited by Bryan Preas December 16, 1985 12:24:12 pm PST Initialize for channel routing build the channel routing area; privatePart.constraints initialized in RouteChannelConstraintsImpl convert sides to p-q space and build side data structures convert the nets from x-y space to p-q space Convert a channel side to p-q space and set up side data convert routing barriers for a side clean up the rectangle and return it. convert a channel end to p-q space and set up side data now that all side data is available, compute the routing area fix up the routing area Initialize for channel routing Use Reverse to get a new copy of the list because Sort is destructive Translate the pin coordinates from x-y space to p-q space. Check the pins for this net. -- number of pins > 1 -- pins within range -- pin overlap -- pin spacing -- max number of pins build the channel pins data structure for this net. NOTE: this assumes that CheckChanPins has been invoked and that the inputs are valid!!! now update the segment build the PinPosition data structure for this pin at thisPLoc. NOTE: this assumes that CheckChanPins has been invoked and that the inputs are valid!!! build the channel segment data structure for this net. check for pin to pin violations. count down from index to find the pin that can still effect index count up from index to find the pin that can still effect index get the exit pins for this net. NOTE: this assumes that CheckChanPins has been invoked and that the inputs are valid!!! find the track positions find the track positions insert a track at the position update the track constraints for the segments attached to the pin Block the tracks covered by the layer. Block the tracks covered by the layer. Κ±˜Jšœ>™>˜Jšœ Οmœ1™™>—J˜šΟk ˜ J˜Jšžœ˜Jšœ ˜ J˜ J˜ J˜J˜Jšœ˜J˜ J˜ Jšœ ˜ J˜—šœžœž˜#JšžœM˜TJšžœ ˜Jšžœ˜J˜Jšž˜Jš œžœžœžœžœ6˜sJš œžœžœžœžœ˜[Jš œ žœžœžœžœ"˜bJ˜šΟn œžœž œ˜žJšœ™J™Jšœ˜Jšœ'žœ˜AJšœ8˜8JšœV˜VJšœU˜UJšœ-˜-J˜Jšœb™bJšœ(žœ˜IJšœžœ˜Jšœ!žœ&˜JJšœ$žœ&˜MJšœ"žœ&˜KJšœ#žœ&˜LJšœžœ'˜CJšœžœ%˜?Jšœžœ˜7Jšœ&˜&J˜Jšœ˜Jšœm˜mJ˜Jšœ9™9Jšœ8˜8Jšœ5˜5Jšœ5˜5Jšœ6˜6J˜J˜!Jšœ˜J˜Jšœ,™,Jšœ žœ(˜7šžœ!žœž˜=Jšœ)˜)Jšžœ˜—J˜Jšžœžœ˜>Jšžœ1˜5J˜Jšœ&˜&Jšœ#˜#Jšœ$˜$Jšœ&˜&J˜—šŸ œž œ†˜œJ™8J™Jšœ%žœ˜EJšœL˜LJšœ>˜>JšœK˜KJšœ.žœ˜OJšœB˜BJšœ/˜/Jšœ˜JšœH˜HJ˜JšœE˜EJ˜šžœžœžœ˜JšœX˜XJšœV˜VJšœD˜DJšœR˜RJšœ1˜1—J˜—šŸœž œržœ<˜ΡJ™#J™Jšœ.žœ˜OJšœ)˜)JšœB˜BJšœB˜Bšžœžœžœ˜šžœGžœ žœž˜^Jšœ0˜0Jšœ.˜.šžœžœ žœCžœ˜išžœ9žœ žœž˜PJšœZ˜Zšžœžœžœ˜Jšœ9˜9Jšœ!žœ3˜X—Jšžœ˜——Jšžœ˜ ——J˜—šŸ œžœbžœ'˜ŸJ™%J™JšœB˜BJšœP˜PJšœP˜PJšœ‘˜‘Jšœ‘˜‘Jšžœžœ#˜-J˜—šŸ œž œ†˜›J™7J™Jšœ%žœ˜EJšœL˜LJšœK˜KJšœ.žœ˜OJšœB˜BJ˜Jšœ˜Jšœ/˜/JšœH˜Hšžœžœžœ˜JšœX˜XJšœV˜VJšœR˜RJšœD˜DJšœ1˜1—J˜—šŸ œž œF˜ZJ™=J™Jšœ%žœ˜EJšœ>˜>JšœJ˜JJšœL˜LJšœN˜NJšœH˜HJšœΟc˜'J˜Jšœ™Jšœ)˜)Jšœ*˜*Jšœ"žœ'˜LJšœ"žœ(˜MJšœ-˜-Jšœ+˜+J˜—šŸœž œ;˜MJšœ™J™šœ!˜!Jšœžœ*˜CJšœžœ*˜Cšžœžœ žœ˜-Jšžœžœ žœ˜,Jšžœ˜!——J˜Jšœ#žœ˜(Jšœ'žœ˜AJšœB˜BJšœE˜EJšœE™EJšžœžœ˜CJšœ6˜6šžœ0ž˜6Jšœ/˜/—J˜—š ŸœžœXžœ  œžœ˜΅J™:J˜Jšœ%žœ˜EJšœ>˜>Jšœ'žœ˜Ašžœ(žœžœž˜>Jšœ˜Jšœ˜J˜Jšœ˜JšœV˜VJšœW˜WJšœL˜LJ˜4JšœV˜VJšœ žœ!˜0Jšœ@˜@Jšœ6˜6Jšœ˜J˜šžœ ž˜šœ ˜ Jšœ˜JšœS˜S—šœ˜Jšœ˜JšœD˜D—šœ ˜ Jšœ˜JšœS˜S—šœ ˜ Jšœ˜JšœD˜D—Jšžœ˜—J˜šžœ ž˜šœ˜JšœR˜RJšœ+˜+Jšœ*˜*Jšœ˜—šœ ˜ Jšžœžœ'˜Išžœžœžœ˜+JšœR˜RJšœ+˜+Jšœ˜Jšœ˜——šœ˜Jšžœžœ'˜Išžœžœž˜)JšœS˜SJšœ+˜+Jšœ˜Jšœ˜——Jšžœ˜—JšœžœH˜QJšœ žœ˜!Jšžœ˜ —J˜—š Ÿ œžœHž !œžœžœžœ˜’™Jšœ™J™Jšœ™Jšœ™Jšœ™J™—Jšœ%žœ˜EJšœ>˜>Jšœžœ(˜LJšœ žœ˜Jšœžœžœ˜%Jšœ6˜6Jšœ4˜4J˜š žœ žœ  œžœ žœž˜`Jšœžœ˜3Jšœ9˜9J˜šžœž˜šœ˜Jšœ$˜$šžœžœžœ˜6Jšœv˜v—šžœžœ˜ Jšœt˜t—Jšœ˜—šœ ˜ šžœžœ˜Jšœs˜s—šžœ žœ˜Jšœn˜n—Jšœ žœ˜—šœ˜šžœžœ˜Jšœs˜s—šžœ žœ˜Jšœn˜n—Jšœ žœ˜—Jšžœ˜—Jšžœ˜—J˜šžœžœ˜JšœOžœ˜V—šžœ&žœ˜.Jšœ9žœ˜A—J˜—šŸ œžœGžœ  œ˜„J™3J™WJ˜Jšœ%žœ˜EJšœ>˜>Jšœžœ/˜MJšœžœ;˜ZJšœ)žœ˜-Jšœ)žœ˜NJšœ*žœ˜.J˜š žœ žœ  œžœ žœž˜`Jšœžœ˜3JšœM˜MJšœA˜AJšœh˜hJ˜šžœž˜šœžœ*ž˜GJšœ,˜,—šœ˜Jšœžœ!˜=J˜—Jšžœ˜—šžœ žœžœ˜Jšœ0žœ$˜W—šžœžœžœ˜$Jšœ2žœ#˜X—šžœ˜Jšœžœ^˜q—Jšžœ˜—J˜Jšœ™Jšœ%˜%Jšœ'˜'Jšœ!˜!J˜—šŸ œžœžœ:žœ)˜Jšœ>™>JšœW™WJ˜Jšœ%žœ˜EJšœ>˜>Jšœžœžœ˜J˜šžœ!žœžœž˜LJšœ1˜1šžœž˜Jšœ ˜Jšœžœ˜ Jšœ˜Jšœ˜Jšœžœ2˜N—šžœžœž˜Jšœ %˜'Jšœžœ˜ Jšœ˜—Jšžœ˜—J˜šžœžœ #˜4Jšœ#˜#Jšœ˜Jšœžœ3˜N—Jšœ˜J˜—šŸœžœQ˜_J˜Jšœ#˜#šžœ ž œžœž˜PJšœ;˜;Jšœ˜Jšœ˜Jšžœ˜ —J˜—šŸœžœžœ ˜΄J™6J˜Jšœ'žœ˜Ašœ&žœžœžœ˜kJšžœ ˜ —šœžœžœ ˜DJšžœžœ˜ —Jšœžœ ˜5Jšœžœž˜§J˜—š Ÿ œžœTžœ žœžœ˜ŽJ™ J˜šœ-˜-šžœžœž˜šžœž˜Jšœ$˜$J˜,šžœž˜Jšœ/˜/—šžœ ˜Jšœ1˜1—Jšžœžœ˜%——J˜—Jšœ%žœ˜EJšœ>˜>Jšœ'žœ˜AJšœ-˜-Jšœ=˜=JšœW˜WJšœ*˜*Jšœ$˜$Jšœo˜oJšœ'žœ˜+J™JšœA™AJšœ3˜3š žœ$ž œžœžœ4žœ ž˜JšœV˜Všžœ ž˜Jšœž˜ž—Jšžœ˜—J˜Jšœ?™?Jšœ%˜%š žœ$žœžœ4žœ ž˜‘JšœV˜Všžœ ž˜Jšœž˜ž—Jšžœ˜ —J˜—š Ÿ œžœ"žœžœžœ˜ZJ™J™WJ˜šŸœžœ'˜;šžœ žœžœ˜šžœAžœ žœž˜XJšœ)˜)J˜šžœž˜Jšœ"žœ˜7Jšžœ˜—Jšžœ˜ J˜———Jšœ%žœ˜EJšœ>˜>Jšœ"˜"Jšžœžœ1˜KJ˜—šŸ œžœ%˜7J™J˜šœ$˜$Jšœžœ,˜EJšœžœ,˜Ešžœžœ žœ˜-Jšžœžœ žœ˜,Jšžœ˜!J˜——Jšœ%žœ˜EJšœD˜DJšœžœ˜2Jšœžœ*˜FJšœF˜FJšœ$˜$Jšœ9˜9š žœ žœ  œ"žœ žœž˜kJšœžœ˜1J˜šžœž˜šœ˜Jšœ,˜,Jšžœž ˜šžœžœž˜,JšœF˜FJšœ{˜{—šžœ˜šžœDžœ!ž˜oJšœ žœ˜%Jšœ˜Jšžœ˜—Jšœ%˜%Jšœ˜——Jšžœ˜—J˜Jšžœ˜—šžœDžœCž˜‘Jšœ žœ˜%Jšœ˜Jšžœ˜—Jšœ(˜(J˜—šŸ œžœ5žœ˜OJ™J˜Jšœ%žœ˜EJšœD˜DJšœ&žœ%˜Nšžœ%žœž˜?Jšœf˜fJšœžœ˜ Jšžœ˜—Jšœ(˜(J˜—šŸœžœX˜fJ™J˜Jšœ%žœ˜EJšœD˜Dšœ1˜1JšœE˜E—Jšœ(˜(Jšœ&žœK˜tšžœžœžœ˜JšœA™AJšœA˜AIcodešœ'˜'šžœ3žœžœž˜IJšœ'˜'šžœžœžœ˜Kšžœžœ'˜FKšžœ-˜1—K˜—Jšœ˜—J˜—šŸ œžœF˜XJ™&J™Jšœ%žœ˜EJšœL˜LJšœ>˜>Jšœ9˜9šžœ#žœž˜=šžœMžœ žœž˜dšœ/˜/JšœH˜Hšžœžœž˜CJšœžœ˜—J˜—Jšœ/˜/Jšœžœ%˜=Jšœžœ%˜=Jšœ5˜5Jšžœ˜—Jšžœ˜ —J˜—šŸ œžœF˜XJ™&J™Jšœ%žœ˜EJšœL˜Lšžœ#žœž˜=šžœMžœ žœž˜dšœ/žœ˜7J˜—Jšœ/˜/Jšœžœ%˜=Jšœžœ%˜=Jšœ5˜5Jšžœ˜—Jšžœ˜ —J˜—šŸœžœžœ˜Lšžœž˜Jšžœ˜Jšœžœžœ˜/Jšœžœžœžœ˜2—J˜—Jšžœ˜——…—a|7