DIRECTORY Basics, Cabbage, CabbagePrivate, CD, CDBasics, CDCells, CDOps, CDSimpleRules, CDSymbolicObjects, Connections, Convert, Core, CoreGeometry, CoreOps, HashTable, List, PW, PWPins, PWRoute, Rope, Route, RouteUtil, RTBasic, Sinix, SinixOps, TerminalIO; CabbageProcsImpl: CEDAR PROGRAM IMPORTS Basics, Cabbage, CD, CDBasics, CDCells, CDOps, CDSimpleRules, CDSymbolicObjects, Connections, Convert, CoreGeometry, CoreOps, HashTable, List, PW, PWPins, PWRoute, Rope, Route, RouteUtil, RTBasic, Sinix, SinixOps, TerminalIO EXPORTS CabbagePrivate SHARES Route = BEGIN CreateHandle: PUBLIC PROC [inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left: Cabbage.Object, connections: Connections.Table, parms: Cabbage.PadRingParams, name: Rope.ROPE, routeType: CabbagePrivate.RouteType] RETURNS [handle: CabbagePrivate.Handle]~ { handle _ NEW[CabbagePrivate.HandleRec _ [name: name, connections: connections, parms: parms]]; handle.routeType _ routeType; handle.rules _ CreateRouterParms[parms]; handle.globalRouting _ NEW[CabbagePrivate.GlobalRoutingRec]; IF routeType = normal THEN handle.detailedRouting _ NEW[CabbagePrivate.DetailedRoutingRec] ELSE handle.detailedRoutingPL _ NEW[CabbagePrivate.DetailedRoutingPLRec]; GetSizes[handle, inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left]; AssignPositions[handle]}; CreateRouterParms: PROC [parms: Cabbage.PadRingParams] RETURNS [designRules: CabbagePrivate.DesignRules] = { hLayer: CD.Layer _ CDSimpleRules.GetLayer[parms.technologyKey, parms.horizLayer]; vLayer: CD.Layer _ CDSimpleRules.GetLayer[parms.technologyKey, parms.vertLayer]; viaTable: HashTable.Table _ IF parms.viaTable # NIL THEN parms.viaTable ELSE HashTable.Create[equal: EqualProc, hash: HashProc]; designRules _ NEW[CabbagePrivate.DesignRulesRec]; designRules.horizParms.parms _ NEW[PWRoute.RouterParamsRec _ [trunkLayer: parms.horizLayer, branchLayer: parms.vertLayer, technologyKey: parms.technologyKey, wireWidthProc: NIL, signalIncomplete: parms.signalIncomplete, signalBreakAtExit: FALSE, signalSinglePinNets: parms.signalSinglePinNets, viaTable: viaTable]]; designRules.vertParms.parms _ NEW[PWRoute.RouterParamsRec _ [trunkLayer: parms.vertLayer, branchLayer: parms.horizLayer, technologyKey: parms.technologyKey, wireWidthProc: NIL, signalIncomplete: parms.signalIncomplete, signalBreakAtExit: FALSE, signalSinglePinNets: parms.signalSinglePinNets, viaTable: viaTable]]; designRules.horizParms.rules _ Route.CreateDesignRules[parms.technologyKey, hLayer, vLayer, horizontal]; designRules.vertParms.rules _ Route.CreateDesignRules[parms.technologyKey, hLayer, vLayer, vertical]}; GetSizes: PROC [handle: CabbagePrivate.Handle, inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left: Cabbage.Object] ~ { lambda: INT _ handle.rules.horizParms.rules.CDLambda; handle.inner _ GetObjectDescription[inner, lambda, lambda]; handle.bottom _ GetObjectDescription[bottom, lambda, lambda]; handle.right _ GetObjectDescription[right, lambda, lambda]; handle.top _ GetObjectDescription[top, lambda, lambda]; handle.left _ GetObjectDescription[left, lambda, lambda]; handle.bottomLeft _ GetObjectDescription[bottomLeft, handle.left.size.x, handle.bottom.size.y]; handle.bottomRight _ GetObjectDescription[bottomRight, handle.right.size.x, handle.bottom.size.y]; handle.topRight _ GetObjectDescription[topRight, handle.right.size.x, handle.top.size.y]; handle.topLeft _ GetObjectDescription[topLeft, handle.left.size.x, handle.top.size.y]}; GetObjectDescription: PROC [object: Cabbage.Object, minX, minY: INT] RETURNS [desc: CabbagePrivate.ObjectDescription] ~ { desc.object _ object; IF object = NIL THEN desc.size _ [minX, minY] ELSE { desc.size _ RTBasic.IRSize[object]; desc.size.x _ MAX[minX, desc.size.x]; desc.size.y _ MAX[minY, desc.size.y]}}; AssignPositions: PROC [handle: CabbagePrivate.Handle] ~ { hBottom, hTop, vLeft, vRight: INT; [hBottom, hTop, vLeft, vRight] _ GetSize[handle]; handle.bottom.orgin _ [handle.bottomLeft.size.x + (handle.size.x - hBottom)/2, 0]; handle.right.orgin _ [handle.size.x - handle.right.size.x, handle.bottomRight.size.y + (handle.size.y - vRight)/2]; handle.top.orgin _ [handle.topLeft.size.x + (handle.size.x - hTop)/2, handle.size.y - handle.top.size.y]; handle.left.orgin _ [0, handle.bottomLeft.size.y + (handle.size.y - vLeft)/2]; DoCorners[handle]}; InitWires: PROC [handle: CabbagePrivate.Handle] ~ { LookForGndAndVdd: Connections.EachNetAction ~ { IF Rope.Equal[net.name, "Vdd"] THEN handle.vddNet _ net ELSE IF Rope.Equal[net.name, "Gnd"] THEN handle.gndNet _ net}; EachNet: Connections.EachNetAction ~ { EachSegment: Connections.EachSegmentAction ~ { IF segment.object # handle.inner.object OR UseSegment[handle, segment, net] THEN newNet.width _ MAX[newNet.width, segment.range.max - segment.range.min] ELSE TerminalIO.PutRope[Rope.Cat[Rope.Cat["Segment ignored on net: ", net.name, ", side: ", RTBasic.sideName[RTBasic.OtherSide[segment.side]], ", range: ["], Rope.Cat[Convert.RopeFromInt[segment.range.min], ", ", Convert.RopeFromInt[segment.range.max], "]\n"]]]}; newNet: Connections.Net _ NEW[Connections.NetRec _ [name: net.name, width: net.width]]; IF net.width <= 0 THEN [] _ Connections.EnumerateSegments[net, EachSegment]; [] _ Connections.Store[handle.widthTable, net.name, newNet]}; handle.widthTable _ Connections.CreateForRopes[]; [] _ Connections.EnumerateNets[handle.connections, LookForGndAndVdd]; [] _ Connections.EnumerateNets[handle.connections, EachNet]}; CheckInnerPos: PUBLIC PROC [handle: CabbagePrivate.Handle, innerPos: CD.Position] ~ { actualInnerPos: CD.Position _ innerPos; lowerY: INT _ handle.bottom.orgin.y + handle.bottom.size.y; upperY: INT _ handle.top.orgin.y - handle.inner.size.y; lowerX: INT _ handle.left.orgin.x + handle.left.size.x; upperX: INT _ handle.right.orgin.x - handle.inner.size.x; IF ~((lowerX <= innerPos.x AND innerPos.x <= upperX) AND (lowerY <= innerPos.y AND innerPos.y <= upperY)) THEN { Cabbage.Signal[callingError, "The position specified for the inner object (innerPos) is invalid."]; actualInnerPos _ [(lowerX + upperX)/2, (lowerY + lowerY)/2]}; handle.inner.orgin _ actualInnerPos}; GlobalRoute: PUBLIC PROC [handle: CabbagePrivate.Handle] ~ { EachNet: Connections.EachNetAction ~ { sortedSegments: CabbagePrivate.SegmentSeq _ SortSegments[handle, net]; IF sortedSegments # NIL THEN { segmentPair: CabbagePrivate.SegmentPair _ FindStartEndSegments[handle, net, sortedSegments]; AddNetToGlobalRoute[handle, net, segmentPair]}}; IF handle.connections # NIL THEN InitWires[handle]; AdjustPositions[handle]; [] _ Connections.EnumerateNets[handle.connections, EachNet]}; SortSegments: PROC [handle: CabbagePrivate.Handle, net: Connections.Net] RETURNS [sortedSegments: CabbagePrivate.SegmentSeq _ NIL] ~ { CountSegments: Connections.EachSegmentAction ~ { IF UseSegment[handle, segment, net] THEN numSegments _ numSegments + 1}; PinCompare: List.CompareProc ~ { pos1, pos2: INT; TRUSTED{ pos1 _ PosOf[handle, net, LOOPHOLE[ref1]]; pos2 _ PosOf[handle, net, LOOPHOLE[ref2]]}; RETURN [Basics.CompareINT[pos1, pos2]]}; numSegments, index: INT _ 0; mungedSegmentList, sortedSegmentList: List.LORA; [] _ Connections.EnumerateSegments[net, CountSegments]; IF numSegments > 1 THEN { TRUSTED{mungedSegmentList _ List.Reverse[LOOPHOLE[net.segments]]}; sortedSegmentList _ List.Sort[mungedSegmentList, PinCompare]; sortedSegments _ NEW[CabbagePrivate.SegmentSeqRec[numSegments]]; FOR each: List.LORA _ sortedSegmentList, each.rest UNTIL each = NIL DO segment: Connections.Segment; TRUSTED{segment _ LOOPHOLE[each.first]}; IF UseSegment[handle, segment, net] THEN { sortedSegments[index] _ segment; index _ index + 1}; ENDLOOP}}; FindStartEndSegments: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, sortedSegments: CabbagePrivate.SegmentSeq] RETURNS [segmentPair: CabbagePrivate.SegmentPair _ [NIL, NIL]] ~ { minLength: INT _ LAST[INT]; perimeter: INT _ 2*(handle.size.x + handle.size.y); length: INT; startSeg, endSeg: Connections.Segment; FOR index: NAT IN [0 .. sortedSegments.numSegments) DO IF index < sortedSegments.numSegments - 1 THEN { startSeg _ sortedSegments[index+1]; endSeg _ sortedSegments[index]; length _ perimeter - PosOf[handle, net, startSeg] + PosOf[handle, net, endSeg]} ELSE { endSeg _ sortedSegments[index]; startSeg _ sortedSegments[0]; length _ PosOf[handle, net, endSeg] - PosOf[handle, net, startSeg]}; IF length < minLength THEN { minLength _ length; segmentPair.seg1 _ startSeg; segmentPair.seg2 _ endSeg} ENDLOOP; IF segmentPair.seg1 = NIL OR segmentPair.seg2 = NIL THEN Cabbage.Error[programmingError, "Not suppose to happen"]}; AddNetToGlobalRoute: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, segmentPair: CabbagePrivate.SegmentPair] ~ { pos1: INT _ PosOf[handle, net, segmentPair.seg1]; pos2: INT _ PosOf[handle, net, segmentPair.seg2]; IF pos1 < pos2 THEN { FOR d: CabbagePrivate.Division IN CabbagePrivate.Division DO IF pos1 < PosOfDivision[handle, d] AND PosOfDivision[handle, d] < pos2 THEN handle.globalRouting.exitLists[d] _ CONS[net, handle.globalRouting.exitLists[d]] ENDLOOP} ELSE { FOR d: CabbagePrivate.Division IN CabbagePrivate.Division DO IF PosOfDivision[handle, d] > pos1 OR PosOfDivision[handle, d] < pos2 THEN handle.globalRouting.exitLists[d] _ CONS[net, handle.globalRouting.exitLists[d]] ENDLOOP}; }; DetailedRoute: PUBLIC PROC [handle: CabbagePrivate.Handle] ~ { RouteChannels[handle]; AdjustPositions[handle]; IF handle.routeType = normal THEN RouteSwitchBoxes[handle] ELSE RouteSwitchBoxesPL[handle]; AdjustPositions[handle]}; RouteChannels: PROC [handle: CabbagePrivate.Handle] ~ { horizParms: CabbagePrivate.ParmSet _ handle.rules.horizParms; vertParms: CabbagePrivate.ParmSet _ handle.rules.vertParms; horizRange: Connections.Range _ [handle.inner.orgin.x, handle.inner.orgin.x + handle.inner.size.x]; vertRange: Connections.Range _ [handle.inner.orgin.y, handle.inner.orgin.y + handle.inner.size.y]; IF handle.routeType = normal THEN { handle.detailedRouting.channels[bottom] _ RouteChannel[handle, handle.bottom, handle.inner, bottom, bottomLeft, bottomRight, horizRange, horizParms]; handle.detailedRouting.channels[right] _ RouteChannel[handle, handle.inner, handle.right, right, rightBottom, rightTop, vertRange, vertParms]; handle.detailedRouting.channels[top] _ RouteChannel[handle, handle.inner, handle.top, top, topLeft, topRight, horizRange, horizParms]; handle.detailedRouting.channels[left] _ RouteChannel[handle, handle.left, handle.inner, left, leftBottom, leftTop, vertRange, vertParms]} ELSE { -- routeType = padLimited handle.detailedRoutingPL.channels[right] _ RouteChannel[handle, handle.inner, handle.right, right, rightBottom, rightTop, vertRange, vertParms]; handle.detailedRoutingPL.channels[left] _ RouteChannel[handle, handle.left, handle.inner, left, leftBottom, leftTop, vertRange, vertParms]}}; RouteChannel: PROC [handle: CabbagePrivate.Handle, llObject, urObject: CabbagePrivate.ObjectDescription, side: Route.Side, llDiv, urDiv: CabbagePrivate.Division, range: Connections.Range, parms: CabbagePrivate.ParmSet] RETURNS [channel: CabbagePrivate.Channel] ~ { result: Route.RoutingResult; retrieveRect: Route.RefRect; rect: CD.Rect; llSide, blSide: Route.Side; isX: BOOLEAN; dist, size, offset: INT; obj1, obj2, bottomOrLeftObj, topOrRightObj: Cabbage.Object; SELECT side FROM bottom => {isX _ FALSE; llSide _ top; blSide _ left}; right => {isX _ TRUE; llSide _ right; blSide _ bottom}; top => {isX _ FALSE; llSide _ top; blSide _ left}; left => {isX _ TRUE; llSide _ right; blSide _ bottom}; ENDCASE; obj1 _ BuildObject[handle, llObject, llSide, range, parms.rules, NIL]; obj2 _ BuildObject[handle, urObject, RTBasic.OtherSide[llSide], range, parms.rules, NIL]; bottomOrLeftObj _ BuildEnd[handle, llDiv, blSide, parms.rules]; topOrRightObj _ BuildEnd[handle, urDiv, RTBasic.OtherSide[blSide], parms.rules]; parms.parms.wireWidthProc _ GetWireWidth; parms.parms.context _ handle.widthTable; result _ PWRoute.DoRoute[obj1, obj2, bottomOrLeftObj, topOrRightObj, parms.parms, isX, channel]; rect _ result.routingRect; offset _ result.routingArea.rules.trunkToTrunk; SELECT side FROM bottom => { size _ urObject.orgin.y - (llObject.orgin.y + llObject.size.y); dist _ MIN[rect.y1, rect.y2 - size + offset]; retrieveRect _ NEW[CD.Rect _ [rect.x1, dist, rect.x2, rect.y2 + offset]]}; right => { size _ urObject.orgin.x - (llObject.orgin.x + llObject.size.x); dist _ MAX[rect.x2, size - offset]; retrieveRect _ NEW[CD.Rect _ [rect.x1 - offset, rect.y1, dist, rect.y2]]}; top => { size _ urObject.orgin.y - (llObject.orgin.y + llObject.size.y); dist _ MAX[rect.y2, size - offset]; retrieveRect _ NEW[CD.Rect _ [rect.x1, rect.y1 - offset, rect.x2, dist]]}; left => { size _ urObject.orgin.x - (llObject.orgin.x + llObject.size.x); dist _ MIN[rect.x1, rect.x2 - size + offset]; retrieveRect _ NEW[CD.Rect _ [dist, rect.y1, rect.x2 + offset, rect.y2]]}; ENDCASE; channel.object _ PWRoute.GetRouting[result, retrieveRect, parms.parms]; channel.size _ RTBasic.IRSize[channel.object]; channel.shell _ BuildChannelShell[handle, channel, parms]}; BuildObject: PROC [handle: CabbagePrivate.Handle, objectDes: CabbagePrivate.ObjectDescription, side: Route.Side, range: Connections.Range, rules: Route.DesignRules, opposingCell: Cabbage.Object] RETURNS [shell: Cabbage.Object _ CDCells.CreateEmptyCell[]] ~ { EachNet: Connections.EachNetAction ~ { EachSegment: Connections.EachSegmentAction ~ { IF (segment.object = objectDes.object AND segment.side = side) THEN { orgin: INT _ SELECT side FROM bottom, top => objectDes.orgin.x, right, left => objectDes.orgin.y, ENDCASE => Cabbage.Error[programmingError, "Not suppose to happen."]; adjustedRange: Connections.Range _ [orgin + segment.range.min, orgin + segment.range.max]; useThisOuter: BOOLEAN _ segment.object # handle.inner.object AND UseSegment[handle, segment, net] AND ~OverlapsOnOpposing[handle, opposingCell, adjustedRange, RTBasic.OtherSide[side], net.name]; IF useThisOuter AND CrossesBoundry[adjustedRange, range] THEN Cabbage.Signal[callingError, Rope.Cat["Segment on net: ", net.name, " crosses a seam between routing areas"]]; IF (useThisOuter OR objectDes.object = handle.inner.object) AND ProperSubset[adjustedRange, range] THEN { SELECT side FROM bottom => IncludePin[object: shell, name: net.name, denotes: [adjustedRange.min, oldIR.y1, adjustedRange.max, oldIR.y1+rules.trunkWidth], layer: segment.layer]; right => IncludePin[object: shell, name: net.name, denotes: [oldIR.x2-rules.trunkWidth, adjustedRange.min, oldIR.x2, adjustedRange.max], layer: segment.layer]; top => IncludePin[object: shell, name: net.name, denotes: [adjustedRange.min, oldIR.y2-rules.trunkWidth, adjustedRange.max, oldIR.y2], layer: segment.layer]; left => IncludePin[object: shell, name: net.name, denotes: [oldIR.x1, adjustedRange.min, oldIR.x1+rules.trunkWidth, adjustedRange.max], layer: segment.layer]; ENDCASE}}}; [] _ Connections.EnumerateSegments[net, EachSegment]}; oldIR: CD.Rect _ CD.InterestRect[objectDes.object]; interestRect: CD.Rect; [] _ Connections.EnumerateNets[handle.connections, EachNet]; SELECT side FROM bottom, top => interestRect _ [range.min, oldIR.y1, range.max, oldIR.y2]; left, right => interestRect _ [oldIR.x1, range.min, oldIR.x2, range.max]; ENDCASE; CDCells.SetInterestRect[design: NIL, cell: shell, r: interestRect]; RTBasic.RepositionCell[shell]}; BuildEnd: PROC [handle: CabbagePrivate.Handle, division: CabbagePrivate.Division, side: Route.Side, rules: Route.DesignRules] RETURNS [shell: Cabbage.Object _ CDCells.CreateEmptyCell[]] ~ { EachExit: EachExitAction ~ { width: INT _ MAX[rules.trunkWidth, net.width]; dist _ dist + rules.trunkWidth; SELECT side FROM bottom => IncludePin[object: shell, name: net.name, denotes: [dist, rules.trunkWidth, dist + width, 2*rules.trunkWidth], layer: rules.trunkLayer]; right => IncludePin[object: shell, name: net.name, denotes: [0, dist, rules.trunkWidth, dist + width], layer: rules.trunkLayer]; top => IncludePin[object: shell, name: net.name, denotes: [dist, 0, dist + width, rules.trunkWidth], layer: rules.trunkLayer]; left => IncludePin[object: shell, name: net.name, denotes: [rules.trunkWidth, dist, 2*rules.trunkWidth, dist + width], layer: rules.trunkLayer]; ENDCASE; dist _ dist + width}; dist: INT _ 0; interestRect: CD.Rect; [] _ EnumerateExits[handle.globalRouting.exitLists[division], division, EachExit]; interestRect _ SELECT side FROM bottom, top => [0, 0, dist + rules.trunkWidth, 2*rules.trunkWidth], left, right => [0, 0, 2*rules.trunkWidth, dist + rules.trunkWidth], ENDCASE => Cabbage.Error[programmingError, "Not suppose to happen"]; CDCells.SetInterestRect[design: NIL, cell: shell, r: interestRect]; RTBasic.RepositionCell[shell]}; BuildChannelShell: PROC [handle: CabbagePrivate.Handle, channel: CabbagePrivate.Channel, parms: CabbagePrivate.ParmSet] RETURNS [shell: Cabbage.Object _ CDCells.CreateEmptyCell[]] ~ { ChanPublics: CoreGeometry.EachWirePinProc ~ { name: Rope.ROPE _ CoreOps.GetShortWireName[wire]; SELECT side FROM bottom => IncludePin[object: shell, name: name, denotes: [rect.x1+min, rect.y1, rect.x1+max, rect.y1+depth], layer: layer]; right => IncludePin[object: shell, name: name, denotes: [rect.x2-depth, rect.y1+min, rect.x2, rect.y1+max], layer: layer]; top => IncludePin[object: shell, name: name, denotes: [rect.x1+min, rect.y2-depth, rect.x1+max, rect.y2], layer: layer]; left => IncludePin[object: shell, name: name, denotes: [rect.x1, rect.y1+min, rect.x1+depth, rect.y1+max], layer: layer]; ENDCASE}; mode: Sinix.Mode = SinixOps.GetExtractMode[parms.rules.technology]; cellType: Core.CellType _ NARROW [Sinix.Extract[channel.object, mode].result]; depth: Route.Number _ parms.rules.trunkWidth; rect: CD.Rect _ CD.InterestRect[channel.object]; [] _ CoreGeometry.EnumerateNonOverlappingSides[mode.decoration, cellType, ChanPublics]; CDCells.SetInterestRect[design: NIL, cell: shell, r: rect]; RTBasic.RepositionCell[shell]}; AdjustPositions: PROC [handle: CabbagePrivate.Handle] ~ { routeType: CabbagePrivate.RouteType _ handle.routeType; sizeBottomArea: INT _ handle.inner.orgin.y - (handle.bottom.orgin.y + handle.bottom.size.y); sizeBottomRouting: INT _ IF handle.routeType = normal THEN handle.detailedRouting.channels[bottom].size.y ELSE handle.detailedRoutingPL.switchBoxes[bottom].size.y; adjBottom: INT _ sizeBottomRouting - sizeBottomArea; sizeLeftArea: INT _ handle.inner.orgin.x - (handle.left.orgin.x + handle.left.size.x); sizeLeftRouting: INT _ IF handle.routeType = normal THEN handle.detailedRouting.channels[left].size.x ELSE handle.detailedRoutingPL.channels[left].size.x; adjLeft: INT _ sizeLeftRouting - sizeLeftArea; adjTop, adjRight, sizeTopArea, sizeTopRouting, sizeRightArea, sizeRightRouting: INT; handle.inner.orgin _ CDBasics.AddPoints[handle.inner.orgin, [MAX[0, adjLeft], MAX[0, adjBottom]]]; handle.bottom.orgin _ CDBasics.AddPoints[handle.bottom.orgin, [MAX[0, adjLeft], 0]]; handle.right.orgin _ CDBasics.AddPoints[handle.right.orgin, [MAX[0, adjLeft], MAX[0, adjBottom]]]; handle.top.orgin _ CDBasics.AddPoints[handle.top.orgin, [MAX[0, adjLeft], MAX[0, adjBottom]]]; handle.left.orgin _ CDBasics.AddPoints[handle.left.orgin, [0, MAX[0, adjBottom]]]; sizeTopArea _ handle.top.orgin.y - (handle.inner.orgin.y + handle.inner.size.y); sizeTopRouting _ IF handle.routeType = normal THEN handle.detailedRouting.channels[top].size.y ELSE handle.detailedRoutingPL.switchBoxes[top].size.y; adjTop _ sizeTopRouting - sizeTopArea; sizeRightArea _ handle.right.orgin.x - (handle.inner.orgin.x + handle.inner.size.x); sizeRightRouting _ IF handle.routeType = normal THEN handle.detailedRouting.channels[right].size.x ELSE handle.detailedRoutingPL.channels[right].size.x; adjRight _ sizeRightRouting - sizeRightArea; handle.top.orgin _ CDBasics.AddPoints[handle.top.orgin, [0, MAX[0, adjTop]]]; handle.right.orgin _ CDBasics.AddPoints[handle.right.orgin, [MAX[0, adjRight], 0]]; [] _ GetSize[handle]; DoCorners[handle]; IF handle.routeType = normal THEN { handle.detailedRouting.channels[bottom].orgin _ [handle.inner.orgin.x, handle.inner.orgin.y - handle.detailedRouting.channels[bottom].size.y]; handle.detailedRouting.channels[right].orgin _ [handle.inner.orgin.x + handle.inner.size.x, handle.inner.orgin.y]; handle.detailedRouting.channels[top].orgin _ [handle.inner.orgin.x, handle.inner.orgin.y + handle.inner.size.y]; handle.detailedRouting.channels[left].orgin _ [handle.inner.orgin.x - handle.detailedRouting.channels[left].size.x, handle.inner.orgin.y]; handle.detailedRouting.switchBoxes[bottomLeft].orgin _ [handle.left.orgin.x + handle.left.size.x, handle.bottom.orgin.y + handle.bottom.size.y]; handle.detailedRouting.switchBoxes[bottomRight].orgin _ [handle.inner.orgin.x + handle.inner.size.x, handle.bottom.orgin.y + handle.bottom.size.y]; handle.detailedRouting.switchBoxes[topRight].orgin _ [handle.inner.orgin.x + handle.inner.size.x, handle.inner.orgin.y + handle.inner.size.y]; handle.detailedRouting.switchBoxes[topLeft].orgin _ [handle.left.orgin.x + handle.left.size.x, handle.inner.orgin.y + handle.inner.size.y]} ELSE { -- routeType = padLimited handle.detailedRoutingPL.channels[right].orgin _ [handle.inner.orgin.x + handle.inner.size.x, handle.inner.orgin.y]; handle.detailedRoutingPL.channels[left].orgin _ [handle.inner.orgin.x - handle.detailedRoutingPL.channels[left].size.x, handle.inner.orgin.y]; handle.detailedRoutingPL.switchBoxes[bottom].orgin _ [handle.left.orgin.x + handle.left.size.x, handle.bottom.orgin.y + handle.bottom.size.y]; handle.detailedRoutingPL.switchBoxes[top].orgin _ [handle.left.orgin.x + handle.left.size.x, handle.inner.orgin.y + handle.inner.size.y]}; }; RouteSwitchBoxes: PROC [handle: CabbagePrivate.Handle] ~ { horizParms: CabbagePrivate.ParmSet _ handle.rules.horizParms; leftHorizRange: Connections.Range _ [handle.left.orgin.x + handle.left.size.x, handle.inner.orgin.x]; rightHorizRange: Connections.Range _ [handle.inner.orgin.x + handle.inner.size.x, handle.right.orgin.x]; bottomVertRange: Connections.Range _ [handle.bottom.orgin.y + handle.bottom.size.y, handle.inner.orgin.y]; topVertRange: Connections.Range _ [handle.inner.orgin.y + handle.inner.size.y, handle.top.orgin.y]; horizParms.parms.okToDiddleLLPins _ TRUE; horizParms.parms.okToDiddleURPins _ FALSE; handle.detailedRouting.switchBoxes[bottomLeft] _ RouteSwitchBox[handle, bottomLeft, leftHorizRange, bottomVertRange, horizParms]; horizParms.parms.okToDiddleLLPins _ FALSE; horizParms.parms.okToDiddleURPins _ TRUE; handle.detailedRouting.switchBoxes[bottomRight] _ RouteSwitchBox[handle, bottomRight, rightHorizRange, bottomVertRange, horizParms]; horizParms.parms.okToDiddleLLPins _ FALSE; horizParms.parms.okToDiddleURPins _ TRUE; handle.detailedRouting.switchBoxes[topRight] _ RouteSwitchBox[handle, topRight, rightHorizRange, topVertRange, horizParms]; horizParms.parms.okToDiddleLLPins _ TRUE; horizParms.parms.okToDiddleURPins _ FALSE; handle.detailedRouting.switchBoxes[topLeft] _ RouteSwitchBox[handle, topLeft, leftHorizRange, topVertRange, horizParms]; horizParms.parms.okToDiddleLLPins _ FALSE; horizParms.parms.okToDiddleURPins _ FALSE}; RouteSwitchBoxesPL: PROC [handle: CabbagePrivate.Handle] ~ { horizParms: CabbagePrivate.ParmSet _ handle.rules.horizParms; horizRange: Connections.Range _ [handle.left.orgin.x + handle.left.size.x, handle.right.orgin.x]; bottomVertRange: Connections.Range _ [handle.bottom.orgin.y + handle.bottom.size.y, handle.inner.orgin.y]; topVertRange: Connections.Range _ [handle.inner.orgin.y + handle.inner.size.y, handle.top.orgin.y]; horizParms.parms.okToDiddleLLPins _ TRUE; horizParms.parms.okToDiddleURPins _ TRUE; handle.detailedRoutingPL.switchBoxes[bottom] _ RouteSwitchBoxPL[handle, bottom, horizRange, bottomVertRange, horizParms]; handle.detailedRoutingPL.switchBoxes[top] _ RouteSwitchBoxPL[handle, top, horizRange, topVertRange, horizParms]; horizParms.parms.okToDiddleLLPins _ FALSE; horizParms.parms.okToDiddleURPins _ FALSE}; GetWireWidth: PWRoute.WireWidthProc ~ { table: Connections.Table _ NARROW[context]; net: Connections.Net _ Connections.Fetch[table, netName].net; wireWidth _ net.width}; RouteSwitchBoxPL: PROC [handle: CabbagePrivate.Handle, side: RTBasic.TBSide, horizRange, vertRange: Connections.Range, parms: CabbagePrivate.ParmSet] RETURNS [switchBox: CabbagePrivate.SwitchBox] ~ { bottomObject, topObject: Cabbage.Object; leftObject: Cabbage.Object _ BuildObject[handle, handle.left, right, vertRange, parms.rules, NIL]; rightObject: Cabbage.Object _ BuildObject[handle, handle.right, left, vertRange, parms.rules, NIL]; innerRange: Connections.Range _ [handle.inner.orgin.x, handle.inner.orgin.x + handle.inner.size.x]; SELECT side FROM bottom => { innerObject: Cabbage.Object _ BuildObject[handle, handle.inner, bottom, innerRange, parms.rules, NIL]; topObject _ PW.AbutListX[LIST[handle.detailedRoutingPL.channels[left].shell, innerObject, handle.detailedRoutingPL.channels[right].shell]]; bottomObject _ BuildObject[handle, handle.bottom, top, horizRange, parms.rules, topObject]}; top => { innerObject: Cabbage.Object _ BuildObject[handle, handle.inner, top, innerRange, parms.rules, NIL]; bottomObject _ PW.AbutListX[LIST[handle.detailedRoutingPL.channels[left].shell, innerObject, handle.detailedRoutingPL.channels[right].shell]]; topObject _ BuildObject[handle, handle.top, bottom, horizRange, parms.rules, bottomObject]}; ENDCASE; parms.parms.wireWidthProc _ GetWireWidth; parms.parms.context _ handle.widthTable; switchBox.object _ PWRoute.MakeChannel[bottomObject, topObject, leftObject, rightObject, NIL, parms.parms, FALSE, switchBox]; switchBox.size _ RTBasic.IRSize[switchBox.object]}; RouteSwitchBox: PROC [handle: CabbagePrivate.Handle, corner: CabbagePrivate.Corners, horizRange, vertRange: Connections.Range, parms: CabbagePrivate.ParmSet] RETURNS [switchBox: CabbagePrivate.SwitchBox] ~ { bottomObject, topObject, leftObject, rightObject: Cabbage.Object; SELECT corner FROM bottomLeft => { topObject _ handle.detailedRouting.channels[left].shell; bottomObject _ BuildObject[handle, handle.bottom, top, horizRange, parms.rules, topObject]; leftObject _ BuildObject[handle, handle.left, right, vertRange, parms.rules, NIL]; rightObject _ handle.detailedRouting.channels[bottom].shell}; bottomRight => { topObject _ handle.detailedRouting.channels[right].shell; bottomObject _ BuildObject[handle, handle.bottom, top, horizRange, parms.rules, topObject]; rightObject _ BuildObject[handle, handle.right, left, vertRange, parms.rules, NIL]; leftObject _ handle.detailedRouting.channels[bottom].shell}; topRight => { bottomObject _ handle.detailedRouting.channels[right].shell; topObject _ BuildObject[handle, handle.top, bottom, horizRange, parms.rules, bottomObject]; rightObject _ BuildObject[handle, handle.right, left, vertRange, parms.rules, NIL]; leftObject _ handle.detailedRouting.channels[top].shell}; topLeft => { bottomObject _ handle.detailedRouting.channels[left].shell; topObject _ BuildObject[handle, handle.top, bottom, horizRange, parms.rules, bottomObject]; leftObject _ BuildObject[handle, handle.left, right, vertRange, parms.rules, NIL]; rightObject _ handle.detailedRouting.channels[top].shell}; ENDCASE; parms.parms.wireWidthProc _ GetWireWidth; parms.parms.context _ handle.widthTable; switchBox.object _ PWRoute.MakeChannel[bottomObject, topObject, leftObject, rightObject, NIL, parms.parms, FALSE, switchBox]; switchBox.size _ RTBasic.IRSize[switchBox.object]}; MakeChip: PUBLIC PROC [handle: CabbagePrivate.Handle] RETURNS [chip: Cabbage.Object] ~ { chip _ CDCells.CreateEmptyCell[]; IncludeObject[handle.inner.object, handle.inner.orgin, chip]; IncludeObject[handle.bottomLeft.object, handle.bottomLeft.orgin, chip]; IncludeObject[handle.bottom.object, handle.bottom.orgin, chip]; IncludeObject[handle.bottomRight.object, handle.bottomRight.orgin, chip]; IncludeObject[handle.right.object, handle.right.orgin, chip]; IncludeObject[handle.topRight.object, handle.topRight.orgin, chip]; IncludeObject[handle.top.object, handle.top.orgin, chip]; IncludeObject[handle.topLeft.object, handle.topLeft.orgin, chip]; IncludeObject[handle.left.object, handle.left.orgin, chip]; IF handle.routeType = normal THEN { IncludeObject[handle.detailedRouting.channels[bottom].object, handle.detailedRouting.channels[bottom].orgin, chip]; IncludeObject[handle.detailedRouting.channels[right].object, handle.detailedRouting.channels[right].orgin, chip]; IncludeObject[handle.detailedRouting.channels[top].object, handle.detailedRouting.channels[top].orgin, chip]; IncludeObject[handle.detailedRouting.channels[left].object, handle.detailedRouting.channels[left].orgin, chip]; IncludeObject[handle.detailedRouting.switchBoxes[bottomLeft].object, handle.detailedRouting.switchBoxes[bottomLeft].orgin, chip]; IncludeObject[handle.detailedRouting.switchBoxes[bottomRight].object, handle.detailedRouting.switchBoxes[bottomRight].orgin, chip]; IncludeObject[handle.detailedRouting.switchBoxes[topRight].object, handle.detailedRouting.switchBoxes[topRight].orgin, chip]; IncludeObject[handle.detailedRouting.switchBoxes[topLeft].object, handle.detailedRouting.switchBoxes[topLeft].orgin, chip]} ELSE { IncludeObject[handle.detailedRoutingPL.channels[right].object, handle.detailedRoutingPL.channels[right].orgin, chip]; IncludeObject[handle.detailedRoutingPL.channels[left].object, handle.detailedRoutingPL.channels[left].orgin, chip]; IncludeObject[handle.detailedRoutingPL.switchBoxes[bottom].object, handle.detailedRoutingPL.switchBoxes[bottom].orgin, chip]; IncludeObject[handle.detailedRoutingPL.switchBoxes[top].object, handle.detailedRoutingPL.switchBoxes[top].orgin, chip]}; [] _ RTBasic.RepositionCell[chip]; }; IncludeObject: PROC [object: Cabbage.Object, orgin: CD.Position, chip: Cabbage.Object] ~ { IF object # NIL THEN [] _ RouteUtil.Include[cell: chip, ob: object, position: CDOps.FitObjectI[ob: object, location: orgin, orientation: original].off, orientation: original]}; PosOf: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, segment: Connections.Segment] RETURNS [INT] ~ { RETURN[MiddleOfRange[RangeOf[handle, net, segment]]]}; RangeOf: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, segment: Connections.Segment] RETURNS [range: Connections.Range] ~ { SELECT TRUE FROM segment.object = handle.inner.object => range _ InnerRange[handle, net, segment]; segment.object = handle.bottom.object => range _ OuterRange[handle, net, segment, bottom]; segment.object = handle.right.object => range _ OuterRange[handle, net, segment, right]; segment.object = handle.top.object => range _ OuterRange[handle, net, segment, top]; segment.object = handle.left.object => range _ OuterRange[handle, net, segment, left]; ENDCASE => Cabbage.Signal[callingError, Rope.Cat["Invalid object in net: ", net.name]]}; MiddleOfRange: PROC [range: Connections.Range] RETURNS [INT] ~ { RETURN[(range.min+range.max)/2]}; InnerRange: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, segment: Connections.Segment] RETURNS [range: Connections.Range] ~ { orgin: INT; SELECT segment.side FROM bottom => {orgin _ handle.inner.orgin.x; range _ [orgin + segment.range.min, orgin + segment.range.max]}; right => {orgin _ handle.size.x + handle.inner.orgin.y; range _ [orgin + segment.range.min, orgin + segment.range.max]}; top => {orgin _ handle.size.x +handle.size.y + (handle.size.x - handle.inner.orgin.x); range _ [orgin - segment.range.max, orgin - segment.range.min]}; left => {orgin _ 2*handle.size.x +handle.size.y + (handle.size.y - handle.inner.orgin.y); range _ [orgin - segment.range.max, orgin - segment.range.min]}; ENDCASE}; OuterRange: PROC [handle: CabbagePrivate.Handle, net: Connections.Net, segment: Connections.Segment, side: Route.Side] RETURNS [range: Connections.Range] ~ { orgin: INT; IF segment.side # RTBasic.OtherSide[side] THEN Cabbage.Signal[callingError, Rope.Cat["Invalid side in net: ", net.name]]; SELECT side FROM bottom => {orgin _ handle.bottom.orgin.x; range _ [orgin + segment.range.min, orgin + segment.range.max]}; right => {orgin _ handle.size.x + handle.right.orgin.y; range _ [orgin + segment.range.min, orgin + segment.range.max]}; top => {orgin _ handle.size.x +handle.size.y + (handle.size.x - handle.top.orgin.x); range _ [orgin - segment.range.max, orgin - segment.range.min]}; left => {orgin _ 2*handle.size.x +handle.size.y + (handle.size.y - handle.left.orgin.y); range _ [orgin - segment.range.max, orgin - segment.range.min]}; ENDCASE}; PosOfDivision: PROC [handle: CabbagePrivate.Handle, division: CabbagePrivate.Division] RETURNS [pos: INT] ~ { SELECT division FROM bottomLeft => pos _ handle.inner.orgin.x; bottomRight => pos _ handle.inner.orgin.x + handle.inner.size.x; rightBottom => pos _ handle.size.x + handle.inner.orgin.y; rightTop => pos _ handle.size.x + handle.inner.orgin.y + handle.inner.size.y; topRight => pos _ handle.size.x +handle.size.y + (handle.size.x - handle.inner.orgin.x - handle.inner.size.x); topLeft => pos _ handle.size.x +handle.size.y + (handle.size.x - handle.inner.orgin.x); leftTop => pos _ 2*handle.size.x +handle.size.y + (handle.size.y - handle.inner.orgin.y - handle.inner.size.y); leftBottom => pos _ 2*handle.size.x +handle.size.y + (handle.size.y - handle.inner.orgin.y); ENDCASE}; EachExitAction: TYPE = PROC [division: CabbagePrivate.Division, net: Connections.Net] RETURNS [quit: BOOLEAN _ FALSE]; EnumerateExits: PROC [exitList: CabbagePrivate.ExitList, division: CabbagePrivate.Division, eachExitAction: EachExitAction] RETURNS [quit: BOOLEAN _ FALSE] ~ { FOR list: CabbagePrivate.ExitList _ exitList, list.rest WHILE ~quit AND list # NIL DO exit: Connections.Net _ list.first; quit _ eachExitAction[division, exit]; ENDLOOP}; CrossesBoundry: PROC [r1, r2: Connections.Range] RETURNS [crosses: BOOLEAN] ~ { crosses _(r1.min <= r2.min AND r2.min <= r1.max) OR (r1.min <= r2.max AND r2.max <= r1.max); }; ProperSubset: PROC [r1, r2: Connections.Range] RETURNS [subset: BOOLEAN] ~ { subset _((r2.min <= r1.min AND r1.min <= r2.max) AND (r2.min <= r1.max AND r1.max <= r2.max)); }; GetSize: PROC [handle: CabbagePrivate.Handle] RETURNS [hBottom, hTop, vLeft, vRight: INT] ~ { vMiddle, hMiddle: INT; IF handle.routeType = normal THEN { vMiddle _ handle.bottom.size.y + handle.detailedRouting.channels[bottom].size.y + handle.inner.size.y + handle.detailedRouting.channels[top].size.y + handle.top.size.y; hMiddle _ handle.left.size.x + handle.detailedRouting.channels[left].size.x + handle.inner.size.x + handle.detailedRouting.channels[right].size.x + handle.right.size.x} ELSE { hCenter: INT _ handle.detailedRoutingPL.channels[left].size.x + handle.inner.size.x + handle.detailedRoutingPL.channels[right].size.x; hInner: INT _ MAX[hCenter, handle.detailedRoutingPL.switchBoxes[top].size.x, handle.detailedRoutingPL.switchBoxes[bottom].size.x]; vMiddle _ handle.bottom.size.y + handle.detailedRoutingPL.switchBoxes[bottom].size.y + handle.inner.size.y + handle.detailedRoutingPL.switchBoxes[top].size.y + handle.top.size.y; hMiddle _ handle.left.size.x + hInner + handle.right.size.x}; vLeft _ handle.bottomLeft.size.y + handle.left.size.y + handle.topLeft.size.y; vRight _ handle.bottomRight.size.y + handle.right.size.y + handle.topRight.size.y; hBottom _ handle.bottomLeft.size.x + handle.bottom.size.x + handle.bottomRight.size.x; hTop _ handle.topLeft.size.x + handle.top.size.x + handle.topRight.size.x; handle.size.y _ MAX[vLeft, vMiddle, vRight]; handle.size.x _ MAX[hBottom, hMiddle, hTop]}; DoCorners: PROC [handle: CabbagePrivate.Handle] ~ { handle.bottomLeft.orgin _ [0, 0]; handle.bottomRight.orgin _ [handle.size.x - handle.bottomRight.size.x, 0]; handle.topRight.orgin _ [handle.size.x - handle.topRight.size.x, handle.size.y - handle.topRight.size.y]; handle.topLeft.orgin _ [0, handle.size.y - handle.topLeft.size.y]}; IncludePin: PROC [object: CD.Object, name: Rope.ROPE, denotes: CD.Rect, layer: CD.Layer] ~ { pin: CD.Object _ CDSymbolicObjects.CreatePin[CDBasics.SizeOfRect[denotes]]; pinInstance: CD.Instance _ RouteUtil.Include[cell: object, ob: pin, position: CDBasics.BaseOfRect[denotes], orientation: original]; CDSymbolicObjects.SetName[pinInstance, name]; CDSymbolicObjects.SetLayer[pinInstance, layer]}; UseSegment: PROC [handle: CabbagePrivate.Handle, segment: Connections.Segment, net: Connections.Net] RETURNS [useIt: BOOLEAN _ TRUE] ~ { IF net = handle.vddNet AND segment.object # handle.inner.object AND SegsOverlap[handle, segment, net, handle.gndNet] THEN useIt _ FALSE ELSE IF net = handle.gndNet AND segment.object # handle.inner.object AND SegsOverlap[handle, segment, net, handle.vddNet] THEN useIt _ FALSE}; SegsOverlap: PROC [handle: CabbagePrivate.Handle, testSegment: Connections.Segment, testNet, net: Connections.Net] RETURNS [overlaps: BOOLEAN] ~ { EachSegment: Connections.EachSegmentAction ~ { IF Overlaps[expandedRange, RangeOf[handle, net, segment]] THEN quit _ TRUE}; testRange: Connections.Range _ RangeOf[handle, testNet, testSegment]; spacing: INT _ IF testSegment.side = top OR testSegment.side = bottom THEN handle.rules.vertParms.rules.branchToBranch ELSE handle.rules.horizParms.rules.branchToBranch; expandedRange: Connections.Range _ [testRange.min - spacing, testRange.max + spacing]; overlaps _ Connections.EnumerateSegments[net, EachSegment]}; Overlaps: PUBLIC PROC [r1, r2: Connections.Range] RETURNS [BOOL] = { RETURN [(r1.min<=r2.max) AND (r2.min<=r1.max)]}; OverlapsOnOpposing: PROC [handle: CabbagePrivate.Handle, opposingCell: Cabbage.Object, range: Connections.Range, side: Connections.Side, netName: Rope.ROPE] RETURNS [overlap: BOOLEAN _ FALSE] ~ { EachPin: PWPins.InstanceEnumerator ~ { IF pwSide = PWPins.GetSide[opposingCell, inst] AND ((Rope.Equal[netName, handle.vddNet.name] AND Rope.Equal[CDSymbolicObjects.GetName[inst], handle.gndNet.name]) OR (Rope.Equal[netName, handle.gndNet.name] AND Rope.Equal[CDSymbolicObjects.GetName[inst], handle.vddNet.name])) THEN { rect: CD.Rect _ CDBasics.MapRect[inst.ob.bbox, inst.trans]; pinRange: Connections.Range _ SELECT side FROM bottom, top => [rect.x1, rect.x2], right, left => [rect.y1, rect.y2], ENDCASE => Cabbage.Error[programmingError, "Not suppose to happen."]; quit _ Overlaps[pinRange, expandedRange]}}; pwSide: PWPins.Side _ SELECT side FROM bottom => bottom, right => right, top => top, left => left, ENDCASE => Cabbage.Error[programmingError, "Not suppose to happen."]; spacing: INT _ IF side = top OR side = bottom THEN handle.rules.vertParms.rules.branchToBranch ELSE handle.rules.horizParms.rules.branchToBranch; expandedRange: Connections.Range _ [range.min - spacing, range.max + spacing]; IF opposingCell # NIL THEN overlap _ PWPins.EnumerateEdgePins[opposingCell, EachPin]}; EqualProc: PROC [k1, k2: HashTable.Key] RETURNS [eq: BOOL] = { p1: Route.Position _ NARROW[k1, REF Route.Position]^; p2: Route.Position _ NARROW[k2, REF Route.Position]^; eq _ p1.x = p2.x AND p1.y = p2.y}; HashProc: PROC [k: HashTable.Key] RETURNS [hash: CARDINAL] = { size: Route.Position _ NARROW[k, REF Route.Position]^; hash _ size.x + size.y}; END. ’ CabbageProcsImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reversed. Created by Bryan Preas, June 4, 1986 4:02:08 pm PDT Bryan Preas February 6, 1987 5:28:36 pm PST Power routing to pads needs a better concept. Dropping interfering pins is a kludge! Cabbage needs to be fixed when PWRoute removes PWPins. Initialization Define the routing design rules. technologyKey values are predefinded for now. horizLayer, vertLayer should be "poly", "metal" or "metal2". Global Routing Sort the segments on this net in order arround the periphery Use Reverse to get a new copy of the list because Sort is destructive Find the start and end segments of a net arround the periphery Add this net to the global route Detailed Routing route all of the channels or just the left and right channels depending on routeType route one of the channels build a shell for side of channel or switchbox; input to router opposingCell is a HACK to check for constraint loops caused by the routing channel ends build a shell for end of channel; input to router build a PWPins shell for the channel PROC [wire: Wire, min, max: INT, side: Side, layer: CD.Layer] RETURNS [quit: BOOL _ FALSE]; add decoration for public; wire is an unbound wire adjust he positions of everything to account for the actual channel widths adjust for the vertical dimension route all of the switchBoxes (the corners) route the bottom and top switchBoxes PROC [netName: ROPE, context: REF ANY] RETURNS [wireWidth: INT] Object Generation Utility Procedures Find the position of a segment projected to the periphery. The lower left corner is the orgin. Find the range of a segment projected to the periphery. The lower left corner is the orgin. Given a segment, compute the middle of the connection point returns TRUE if either end but not both ends of r1 is within r2 returns TRUE if r1 is within r2 Check for overlaps by net; partially redundant with OverlapsOnOpposing This is a HACK. Needs to be changed when PWPins/shells are removed! Test for constraint loop creation. SegOverlap does not test for constraint loops caused by ends of channels. Returns TRUE if there are overlaps accross the channe;l or switchbox ΚI˜Icode– "Cedar" style™– "Cedar" stylešœ™Kšœ Οmœ1™K˜—šŸœ˜&šŸ œ#˜.šžœ&žœ"ž˜PKšœžœ5˜G—Kšžœ„˜ˆ—K˜Kšœžœ:˜Wšžœžœ˜Kšœ5˜5—Kšœ=˜=K˜—K˜1KšœE˜EKšœ=˜=K˜—šŸ œžœžœ+žœ˜UK˜Kšœžœ˜'Kšœžœ0˜;Kšœžœ,˜7Kšœžœ,˜7Kšœžœ.˜9š žœžœžœžœžœ˜pKšœc˜cKšœ=˜=—Kšœ%˜%K˜—Lš ™šŸ œžœžœ$˜™>š Ÿœžœbžœ-žœžœ˜ΎK˜Kšœ žœžœžœ˜Kšœ žœ%˜3Kšœžœ˜ Kšœ&˜&šžœžœžœ#ž˜6šžœ(žœ˜0Kšœ#˜#Kšœ˜KšœO˜O—šžœ˜Kšœ˜Kšœ˜KšœD˜D—šžœžœ˜Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜—š žœžœžœžœžœ˜9K˜:——K˜Kšœ ™ šŸœžœc˜|K˜Kšœžœ(˜1Kšœžœ(˜1šžœ žœ˜šžœžœž˜<šžœ"žœ!ž˜LKšœ$žœ(˜P—Kšžœ˜——šžœ˜šžœžœž˜<šžœ!žœ!ž˜JKšœ$žœ(˜P—Kšžœ˜ ——K˜K˜—Lš ™šŸ œžœžœ$˜>K˜Kšœ˜K˜Kšžœžœ˜:Kšžœ˜ K˜K˜—KšœT™TšŸ œžœ$˜7K˜Kšœ=˜=Kšœ;˜;Kšœc˜cKšœb˜bK˜šžœžœ˜#Kšœ•˜•KšœŽ˜ŽKšœ†˜†Kšœ‰˜‰—šžœΟc˜ Kšœ˜Kšœ˜—K˜—Kšœ™šŸ œžœ ˜2Kšœ5˜5Kšœ˜Kšœ@˜@Kšœ˜Kšžœ&˜-K˜Kšœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœžœ˜ Kšœžœ˜Kšœ;˜;K˜šžœž˜Kšœžœ˜5Kšœžœ#˜7Kšœžœ˜2Kšœžœ#˜6Kšžœ˜—K˜KšœAžœ˜FKšœTžœ˜YKšœ?˜?KšœP˜PK˜K˜)K˜(Kšœ`˜`K˜K˜Kšœ/˜/šžœž˜šœ ˜ Kšœ?˜?Kšœžœ#˜-Kšœžœžœ5˜J—šœ ˜ Kšœ?˜?Kšœžœ˜#Kšœžœžœ5˜J—šœ˜Kšœ?˜?Kšœžœ˜#Kšœžœžœ5˜J—šœ ˜ Kšœ?˜?Kšœžœ#˜-Kšœžœžœ5˜J—Kšžœ˜K˜—KšœG˜GKšœ.˜.Kšœ;˜;K˜—šŸ œžœ²žœ8˜‚Kšœ?™?šœžœA™WK˜—šŸœ˜&šŸ œ#˜.šžœ$žœžœ˜Ešœžœžœž˜Kšœ!˜!Kšœ!˜!Kšžœ>˜E—KšœZ˜ZKšœžœ(žœ"žœ]˜Βšžœžœ&žœ˜>K˜n—šžœžœ)žœ$žœ˜jšžœž˜Kšœ ˜ KšœŸ˜ŸKšœ˜Kšœž˜žKšžœ˜ ————K˜Kšœ6˜6K˜—Kšœžœžœ ˜3Kšœžœ˜Kšœ<˜<šžœž˜KšœI˜IKšœI˜IKšžœ˜—Kšœ žœ ˜CKšœ˜K˜—šŸœžœpžœ8˜½šœ1™1K˜—šŸœ˜˜Kšœžœžœ˜.Kšœ˜šžœž˜Kšœ’˜’Kšœ€˜€Kšœ~˜~Kšœ˜Kšžœ˜—Kšœ˜K˜——Kšœžœ˜Kšœžœ˜KšœR˜Ršœžœž˜KšœC˜CKšœC˜CKšžœ=˜D—Kšœ žœ ˜CKšœ˜K˜—šŸœžœažœ8˜·Kšœ$™$K˜šŸ œ"˜-Kš žœžœžœžœžœžœ™[Kšœ2™2Kšœ žœ"˜1šžœž˜Kšœ{˜{Kšœz˜zKšœx˜xKšœy˜yKšžœ˜ —K˜—JšœC˜CJšœžœ.˜NKšœ-˜-Kšœžœžœ˜0KšœW˜WKšœ žœ˜;Kšœ˜K˜—KšœJ™JšŸœžœ$˜9Kšœ!™!K˜Kšœ7˜7KšœžœI˜\šœžœžœžœ/˜iKšžœ5˜9—Kšœ žœ&˜4KšœžœE˜Všœžœžœžœ-˜eKšžœ0˜4—Kšœ žœ"˜.KšœPžœ˜TK˜Kšœ=žœžœ˜bKšœ?žœ˜TKšœ=žœžœ˜bKšœ9žœžœ˜^Kšœ>žœ˜RK˜KšœP˜Pšœžœžœ,˜^Kšžœ2˜6—Kšœ&˜&KšœT˜Tšœžœžœ.˜bKšžœ1˜5—Kšœ,˜,Kšœ<žœ˜MKšœ=žœ˜SK˜K˜K˜šžœžœ˜#KšœŽ˜ŽKšœr˜rKšœp˜pKšœŠ˜ŠK˜Kšœ˜Kšœ“˜“KšœŽ˜ŽKšœ‹˜‹—šžœ‘˜ Kšœt˜tKšœŽ˜ŽKšœŽ˜ŽKšœŠ˜Š—Kšœ˜K˜—Kšœ*™*šŸœžœ$˜:K˜Kšœ=˜=K˜Kšœe˜eKšœh˜hKšœj˜jKšœc˜cK˜Kšœ$žœ&žœ˜TKšœ˜K˜Kšœ$žœ&žœ˜TKšœ„˜„K˜Kšœ$žœ&žœ˜TKšœ{˜{K˜Kšœ$žœ&žœ˜TKšœx˜xKšœ$žœ&žœ˜VK˜—Kšœ$™$šŸœžœ$˜˜E—Kšœ+˜+—K˜—šœžœž˜&Kšœ;˜;Kšžœ>˜E—šœ žœžœ žœž˜2Kšœ+˜+Kšžœ.˜2—KšœN˜Nšžœžœž˜Kšœ;˜;—K˜—šŸ œžœžœžœ˜>Kšœžœžœ˜5Kšœžœžœ˜5Kšœžœ˜"K˜—šŸœžœžœžœ˜>Kšœžœžœ˜6Kšœ˜—Kšžœ˜—K˜—…—™<Ό