RouteChannelRetrieveImpl.mesa ///Route/RouteChannelRetrieveImpl.mesa
Bryan Preas February 13, 1986 7:26:57 pm PST
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
by Bryan Preas July 26, 1985 2:29:20 pm PDT
last edited by Bryan Preas July 26, 1985 2:29:22 pm PDT
DIRECTORY
CD,
CDBasics,
CDSymbolicObjects,
CDProperties,
CDRects,
Rope,
Route,
RouteChannel,
RoutePrivate,
RouteUtil;
RouteChannelRetrieveImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDSymbolicObjects, CDProperties, CDRects, Route, RouteChannel, RouteUtil
EXPORTS RouteChannel
SHARES Route = {
GetRouting: PUBLIC PROCEDURE[routingArea: Route.RoutingArea,
rect: Route.Rect,
properties: Route.PropList,
EnumSegments: RouteChannel.EnumSegmentsProc,
EnumPins: RouteChannel.EnumPinsProc,
EnumVias: RouteChannel.EnumViasProc,
EnumExits: RouteChannel.EnumExitsProc,
EnumIncompletes: RouteChannel.EnumIncompletesProc] RETURNS [externalConnections: Route.PinList ← NIL] = {
Enumerate routing results entities
EachTrack: RouteChannel.EachTrackActionProc = {
run through the segments on the track
FOR seg: RouteChannel.Segment ← RouteChannel.TrackSegAbs[routingArea, trackIndex], seg.nextSeg
WHILE seg # NIL DO
AddInterval: PosSizeProc ~ {
thisRange: RoutePrivate.Range ← [pos - size/2, pos+size/2];
found: BOOLEANFALSE;
list: RoutePrivate.RangeList ← NIL;
FOR l: RoutePrivate.RangeList ← intervalList, l.rest WHILE l # NIL DO
currentRange: RoutePrivate.Range ← l.first;
IF RouteChannel.Overlaps[thisRange, currentRange] THEN {
currentRange ← RouteChannel.Span[thisRange, currentRange];
found ← TRUE};
list ← CONS[currentRange, list];
ENDLOOP;
IF ~found THEN list ← CONS[thisRange, list];
intervalList ← list};
trackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, seg.trackNum];
leftPin: RouteChannel.ChanPin ← seg.exteriorPins[chanLeft];
rightPin: RouteChannel.ChanPin ← seg.exteriorPins[chanRight];
leftBranchWidth, rightBranchWidth: Route.Number ← 0;
segLayer: Route.Layer ← RouteUtil.RoutingLayerToLayer[routingArea, seg.routingLayer];
intervalList: RoutePrivate.RangeList ← NIL;
nextSeg: RouteChannel.Segment;
doRight: BOOLEAN;
audit the pins to which this segment point
RouteChannel.CheckPins[seg, leftPin, chanRight];
RouteChannel.CheckPins[seg, rightPin, chanLeft];
figure out the left branch
leftBranchWidth ← AnalyzeBranch[routingArea, seg.exteriorPins[chanLeft].pinPosition, seg, chanLeft, chanRight, AddInterval];
process the interior pins
FOR pinList: RouteChannel.ChanPinList ← seg.interiorPins, pinList.rest WHILE pinList # NIL DO
pin: RouteChannel.ChanPin ← pinList.first;
[] ← AnalyzeBranch[routingArea, pin.pinPosition, seg, chanLeft, chanRight, AddInterval];
ENDLOOP;
do the right branch if no following segment in this track
nextSeg ← NextSegment[seg];
IF nextSeg # NIL THEN doRight ← seg.trackNum # nextSeg.trackNum
ELSE doRight ← TRUE;
IF doRight THEN
rightBranchWidth ← AnalyzeBranch[routingArea, rightPin.pinPosition, seg, chanRight, chanLeft, AddInterval];
do the vias collected during the AnalyzeBranch Calls
DoVias[routingArea, seg, intervalList];
enumerate trunk segment
EnumSegments[routingArea, seg.net.name, seg.net.netPart,
RouteUtil.PQToXY[routingArea, [PinPos[leftPin] - leftBranchWidth/2, trackLoc]],
RouteUtil.PQToXY[routingArea, [PinPos[rightPin] + rightBranchWidth/2, trackLoc]],
seg.qWidth, segLayer];
ENDLOOP};
DoVias: PROC [routingArea: Route.RoutingArea, seg: RouteChannel.Segment, intervalList: RoutePrivate.RangeList] ~ {
trunkL: Route.Layer ← RouteUtil.RoutingLayerToLayer[routingArea, trunk];
branchL: Route.Layer ← RouteUtil.RoutingLayerToLayer[routingArea, branch];
trackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, seg.trackNum];
FOR list: RoutePrivate.RangeList ← intervalList, list.rest WHILE list # NIL DO
range: RoutePrivate.Range ← list.first;
EnumVias[routingArea, seg.net.name, seg.net.netPart, RouteUtil.PQToXY[routingArea, [(range.l+range.r)/2, trackLoc]], RouteUtil.PQToXY[routingArea, [range.r-range.l, seg.qWidth]], trunkL, branchL];
ENDLOOP};
PinPos: PROCEDURE[pin: RouteChannel.ChanPin] RETURNS [pos: Route.Number] = {
IF pin.kindOfPin # exitPin THEN pos ← pin.pinPosition.pLoc
ELSE {
pos ← IF pin.pinSide = chanLeft THEN pos1.p
ELSE IF pin.pinSide = chanRight THEN pos2.p
ELSE Route.Error[programmingError, "Invalid data. Call maintainer."]}};
ExitSegPos: PROCEDURE[pin: RouteChannel.ChanPin, width: Route.Number] RETURNS [pos: Route.Number] = {
pos ← IF pin.pinSide = chanLeft THEN pos1.p + width/2
ELSE IF pin.pinSide = chanRight THEN pos2.p - width/2
ELSE Route.Error[programmingError, "Invalid data. Call maintainer."]};
EachPin: RouteChannel.EachPinActionProc = {
IF pin # NIL THEN
IF pin.kindOfPin # noPin THEN {
pin is present, look at the segments on the right side
seg: RouteChannel.Segment ← pin.conctSeg[chanRight];
IF seg # NIL THEN {
leftPinPosition: Route.Number ← seg.exteriorPins[chanLeft].pinPosition.pLoc;
rightPinPosition: Route.Number ← seg.exteriorPins[chanRight].pinPosition.pLoc;
RouteChannel.CheckSegs[seg, pin];
IF (seg.trackNum = 0 AND leftPinPosition # rightPinPosition) OR seg.failed THEN {
a routing failure
qLoc: Route.Number ← IF seg.trackNum = 0 THEN 0
ELSE RouteChannel.TrackLoc[routingArea, seg.trackNum];
EnumIncompletes[routingArea, seg.net.name, seg.net.netPart,
RouteUtil.PQToXY[routingArea, [leftPinPosition, qLoc]],
RouteUtil.PQToXY[routingArea, [rightPinPosition, qLoc]]]}}}};
PosSizeProc: TYPE = PROC[pos, size: Route.Number];
AnalyzeBranch: PROCEDURE[routingArea: Route.RoutingArea,
branchPos: RouteChannel.PinPosition,
segmentLink: RouteChannel.Segment,
branchSide, segmentSide: RouteChannel.ChanLRSide, callBack: PosSizeProc] RETURNS [branchWidth: Route.Number] = {
analyze the branch for this segment
problems with dogleg outside pin range
AnalyzeEachPin: RouteChannel.EachPinActionProc = {
IF pin # NIL THEN {
SELECT pin.kindOfPin FROM
chanConnect, compPin => {
seg: RouteChannel.Segment ← pin.conctSeg[segmentSide];
IF seg # NIL THEN {
segLength: Route.Number ← RouteChannel.Length[seg];
IF seg = segmentLink THEN
{trackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, seg.trackNum];
otherSeg: RouteChannel.Segment;
qLoc: Route.Number;
pLoc: Route.Number ← pin.pinPosition.pLoc;
newPin: Route.Pin;
SELECT pin.pinSide FROM
chanTop => {
qLoc ← topLoc + pin.qLoc;
upperMaxQ ← MAX[upperMaxQ, qLoc];
upperMinQ ← MIN[upperMinQ, qLoc];
upperBranchWidth ← MAX[upperBranchWidth, pin.pWidth]};
chanBottom => {
qLoc ← bottomLoc + pin.qLoc;
lowerMaxQ ← MAX[lowerMaxQ, qLoc];
lowerMinQ ← MIN[lowerMinQ, qLoc];
lowerBranchWidth ← MAX[lowerBranchWidth, pin.pWidth]};
ENDCASE;
newPin ← BuildPin[routingArea, pin, seg, [pLoc, qLoc]];
EnumPins[routingArea, seg.net.name, seg.net.netPart, RouteUtil.PQToXY[routingArea, [pLoc, qLoc]], branchL, newPin];
IF seg.routingLayer = trunk AND segLength > 0 THEN
callBack[pin.pinPosition.pLoc, pin.pWidth];
otherSeg ← pin.conctSeg[branchSide];
IF otherSeg # NIL THEN
IF otherSeg.trackNum # 0 THEN {
otherTrackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, otherSeg.trackNum];
IF (otherTrackLoc # 0) AND (otherTrackLoc # trackLoc OR otherSeg.routingLayer # segmentLink.routingLayer) THEN {
otherSegLength: Route.Number ← RouteChannel.Length[otherSeg];
upperMaxQ ← MAX[upperMaxQ, otherTrackLoc + otherSeg.qWidth/2];
upperMinQ ← MIN[upperMinQ, otherTrackLoc - otherSeg.qWidth/2];
lowerMaxQ ← MAX[lowerMaxQ, otherTrackLoc + otherSeg.qWidth/2];
lowerMinQ ← MIN[lowerMinQ, otherTrackLoc - otherSeg.qWidth/2];
IF otherSeg.routingLayer = trunk AND otherSegLength > 0 THEN
callBack[pin.pinPosition.pLoc, pin.pWidth];
}}}};
};
dogLeg => {
segList: RouteChannel.SegmentList ← RouteChannel.GetSegsOnPin[pin];
FOR segs: RouteChannel.SegmentList ← segList, segs.rest WHILE segs # NIL DO
seg: RouteChannel.Segment ← segs.first;
IF seg.trackNum # 0 THEN {
trackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, seg.trackNum];
IF trackLoc # 0 THEN
{lowerBranchWidth ← MAX[lowerBranchWidth, pin.pWidth];
upperBranchWidth ← MAX[upperBranchWidth, pin.pWidth];
upperMaxQ ← MAX[upperMaxQ, trackLoc + seg.qWidth/2];
upperMinQ ← MIN[upperMinQ, trackLoc - seg.qWidth/2];
lowerMaxQ ← MAX[lowerMaxQ, trackLoc + seg.qWidth/2];
lowerMinQ ← MIN[lowerMinQ, trackLoc - seg.qWidth/2];
IF seg.routingLayer = trunk AND seg = segmentLink THEN
callBack[pin.pinPosition.pLoc, pin.pWidth];
}};
ENDLOOP};
exitPin => {
seg: RouteChannel.Segment ← pin.conctSeg[segmentSide];
IF seg # NIL THEN
IF seg = segmentLink AND seg.trackNum # 0 THEN {
layer: Route.Layer ← RouteUtil.RoutingLayerToLayer[routingArea, seg.routingLayer];
exitP: Route.Number ← PinPos[pin];
trackQ: Route.Number ← RouteChannel.TrackLoc[routingArea, seg.trackNum];
exitQ: Route.Number;
exitPos: Route.Position;
newPin: Route.Pin;
IF parms.routerUsed = channel THEN
exitQ ← trackQ
ELSE {
maxQ: Route.Number ← MAX[trackQ+seg.qWidth/2, pin.qLoc+seg.qWidth/2];
minQ: Route.Number ← MIN[trackQ-seg.qWidth/2, pin.qLoc-seg.qWidth/2];
pPos: Route.Number 𡤎xitSegPos[pin, routingArea.rules.trunkWidth];
EnumSegments[routingArea,
segmentLink.net.name, segmentLink.net.netPart,
RouteUtil.PQToXY[routingArea, [pPos, maxQ]],
RouteUtil.PQToXY[routingArea, [pPos, minQ]],
routingArea.rules.trunkWidth, layer];
exitQ ← pin.qLoc};
exitPos ← RouteUtil.PQToXY[routingArea, [exitP, exitQ]];
newPin ← BuildPin[routingArea, pin, seg, [exitP, exitQ]];
externalConnections ← CONS[newPin, externalConnections];
EnumExits[routingArea, seg.net.name, seg.net.netPart, exitPos, layer, newPin, seg.exitBreak]}};
ENDCASE}};
trackLoc: Route.Number ← RouteChannel.TrackLoc[routingArea, segmentLink.trackNum];
branchL: Route.Layer ← RouteUtil.RoutingLayerToLayer[routingArea, branch];
lowerMaxQ, upperMaxQ: Route.Number ← trackLoc + segmentLink.qWidth/2;
lowerMinQ, upperMinQ: Route.Number ← trackLoc - segmentLink.qWidth/2;
lowerBranchWidth, upperBranchWidth: Route.Number ← 0;
parms: RoutePrivate.RoutingAreaParms ← NARROW[routingArea.parms];
analyze component pin branches
[] ← RouteChannel.EnumPins[routingArea, branchPos, AnalyzeEachPin];
enumerate this branch segment
IF lowerMaxQ > lowerMinQ + segmentLink.qWidth AND lowerBranchWidth > 0 THEN
EnumSegments[routingArea, segmentLink.net.name, segmentLink.net.netPart,
RouteUtil.PQToXY[routingArea, [branchPos.pLoc, lowerMinQ]],
RouteUtil.PQToXY[routingArea, [branchPos.pLoc, lowerMaxQ]],
lowerBranchWidth, branchL];
IF upperMaxQ > upperMinQ + segmentLink.qWidth AND upperBranchWidth > 0 AND (lowerMaxQ # upperMaxQ OR lowerMinQ # upperMinQ) THEN
EnumSegments[routingArea, segmentLink.net.name, segmentLink.net.netPart,
RouteUtil.PQToXY[routingArea, [branchPos.pLoc, upperMinQ]],
RouteUtil.PQToXY[routingArea, [branchPos.pLoc, upperMaxQ]],
upperBranchWidth, branchL];
branchWidth ← MAX[lowerBranchWidth, upperBranchWidth];
}; -- AnalyzeBranch
chanData: RouteChannel.ChannelData ← NARROW[routingArea.privateData];
chanPins: RouteChannel.RoutingChannelPins ← chanData.chanPins;
nRect: Route.Rect ← CDBasics.NormalizeRect[rect];
pos1: RoutePrivate.PQPosition ← RouteUtil.XYToPQ[routingArea, [nRect.x1, nRect.y1]];
pos2: RoutePrivate.PQPosition ← RouteUtil.XYToPQ[routingArea, [nRect.x2, nRect.y2]];
bottomLoc: Route.Number ← pos1.q - chanData.chanSides[chanBottom].routeAreaCoord;
topLoc: Route.Number ← pos2.q;
[] ← RouteChannel.EnumTracks[routingArea, EachTrack];
enumerate the incompletes and audit the segments
FOR index: RouteChannel.MPinsOnCh IN [1 .. chanPins.count] DO
[] ← RouteChannel.EnumPins[routingArea, chanPins.sides[index], EachPin];
ENDLOOP};
BuildPin: PROCEDURE[routingArea: Route.RoutingArea, iPin: RouteChannel.ChanPin, seg: RouteChannel.Segment, pos: RoutePrivate.PQPosition] RETURNS [pin: Route.Pin] = {
build a pin record for the external exit
chanData: RouteChannel.ChannelData ← NARROW[routingArea.privateData];
chanPins: RouteChannel.RoutingChannelPins ← chanData.chanPins;
pinName: Rope.ROPE;
layer: Route.Layer;
loc: Route.Rect;
side: Route.Side;
cdPin: CD.Instance;
p1, p2: Route.Position;
p, q, pO, qO: Route.Number;
iSide: RouteChannel.ChanSide;
IF iPin.pin = NIL THEN { -- this is a constructed pin
iSide ← IF pos.p <= chanPins.cEnd1 THEN chanLeft ELSE chanRight;
side ← RouteChannel.IntSideToExtSide[routingArea, iSide];
q ← seg.net.trunkWidth/2;
p ← routingArea.rules.CDLambda/2;
layer ← RouteUtil.RoutingLayerToLayer[routingArea, trunk];
pinName ← seg.net.name}

ELSE { -- this exit came from the client
iSide ← iPin.pinSide;
IF iSide = chanBottom OR iSide = chanTop THEN
{p ← iPin.pWidth/2; q ← routingArea.rules.CDLambda/2}
ELSE {
p ← routingArea.rules.CDLambda/2; q ← seg.net.trunkWidth/2};
side ← RouteChannel.IntSideToExtSide[routingArea, iPin.pinSide];
layer ← RouteUtil.RoutingLayerToLayer[routingArea, iPin.pin.layer];
pinName ← iPin.pin.name};
SELECT iSide FROM
chanBottom => {pO ← 0; qO ← q};
chanRight => {pO ← -p; qO ← 0};
chanTop => {pO ← 0; qO ← -q};
chanLeft => {pO ← p; qO ← 0};
ENDCASE;
p1 ← RouteUtil.PQToXY[routingArea, [pos.p - p + pO, pos.q - q + qO]];
p2 ← RouteUtil.PQToXY[routingArea, [pos.p + p + pO, pos.q + q + qO]];
loc ← [p1.x, p1.y, p2.x, p2.y];
cdPin ← RouteUtil.CreateCDPin[pinName, loc, layer];
pin ← NEW[Route.PinRec ← [cdPin, side]];
};
RetrieveSegments: PUBLIC RouteChannel.EnumSegmentsProc = {
application: CD.Instance;
ob: CD.Object;
rectSize, position: CD.Position;
parms: RoutePrivate.RoutingAreaParms ← NARROW[routingArea.parms];
[position, rectSize] ←RouteUtil.LineToRect[pos1, pos2, width];
ob ← CDRects.CreateRect[rectSize, layer];
application ← RouteUtil.Include[parms.object, ob, position];
CDProperties.PutProp[application, $SignalName, name]};
RetrieveVias: PUBLIC RouteChannel.EnumViasProc ={
parms: RoutePrivate.RoutingAreaParms ← NARROW[routingArea.parms];
RouteUtil.AddVia[parms.object, name, pos, size, layer1, layer2, routingArea.rules.CDLambda]};
RetrievePins: PUBLIC RouteChannel.EnumPinsProc = {
pinLayer: Route.Layer ← CDSymbolicObjects.GetLayer[pin.pin];
parms: RoutePrivate.RoutingAreaParms ← NARROW[routingArea.parms];
RouteUtil.AddPin[parms.object, pin];
IF pinLayer # layer THEN
Route.Signal[errorType: callingError, explanation: "Pin on invalid layer"]};
RetrieveExits: PUBLIC RouteChannel.EnumExitsProc = {
pinLayer: Route.Layer ← CDSymbolicObjects.GetLayer[pin.pin];
parms: RoutePrivate.RoutingAreaParms ← NARROW[routingArea.parms];
RouteUtil.AddPin[parms.object, pin];
IF pinLayer # layer THEN
Route.Signal[errorType: callingError, explanation: "Channel or switchBox exit on invalid layer"]};
RetrieveIncompletes: PUBLIC RouteChannel.EnumIncompletesProc = {};
NextSegment: PROC [seg: RouteChannel.Segment] RETURNS [nextSeg: RouteChannel.Segment] ~ {
nextSeg ← seg.exteriorPins[chanRight].conctSeg[chanRight];
IF nextSeg = NIL THEN
nextSeg ← seg.exteriorPins[chanRight].altConctSeg[chanRight];
};
}.