MakeSide:
PROC [context:
GC.Context, rules: Route.DesignRules, channel: GCPrivate.Channel, chanSide: RTBasic.Side, internal:
BOOLEAN]
RETURNS [shell:
CD.Object ← CDCells.CreateEmptyCell[]] ~ {
construct a shell for the chanSide of a channel and insert global routing info for this channel
DoExternalPins:
IPCTG.EachComponentAction ~ {
PROC[co: Component] RETURNS[quit: BOOL ← FALSE];
add the external pins accross the channel for boundry channels
IF co #
NIL
THEN {
instance: CoreRouteFlat.Instance ← NARROW[co.any];
FOR nns:
LIST
OF CoreRouteFlat.NetONode ← instance.netONodes, nns.rest
WHILE nns#
NIL
DO
IF ~ExternalNet[context.structure, nns.first.net] THEN LOOP;
FOR pins:
LIST
OF CoreRouteFlat.Pin ← nns.first.oNode.pins, pins.rest
WHILE pins#
NIL
DO
IF pins.first.side = otherSide
AND internal
OR pins.first.side = chanSide
AND ~internal
THEN {
netDesc: GCPrivate.NetDesc ←
NARROW
[RefTab.Fetch[channel.connections, nns.first.net].val];
phyPin: GCPrivate.PhyPinDesc ←
NEW[GCPrivate.PhyPinDescRec ←
[instance, nns.first.oNode, pins.first]];
tabIndex: Rope.
ROPE ←
IF GCPrivate.PinOnList[netDesc, phyPin]
THEN nns.first.net.name
ELSE Rope.Cat[nns.first.net.name, "@", instance.name, "@",
Convert.RopeFromInt[pins.first.range.min]];
netDat: NetInChan ←
IF nns.first.net.any =
NIL
THEN NEW[NetInChanRec]
ELSE NARROW[nns.first.net.any];
range: CoreRouteFlat.Range ← CoreRouteFlat.TranslateRange[instance, pins.first];
AddPin[nns.first.net, netDat, tabIndex, range, rules.branchLayer, chanSide,0];
maxWidth ←
MAX[maxWidth, IncludePin[
phyPin:
NEW[GCPrivate.PhyPinDescRec ←
[instance, nns.first.oNode, pins.first]],
name: tabIndex,
side: chanSide,
lower: lower,
upper: upper,
shell: shell ] ] };
ENDLOOP;
ENDLOOP } };
EachNet: RefTab.EachPairAction ~ {
PROC [key: Key, val: Val] RETURNS [quit: BOOL ← FALSE];
add the pins from the nets
netDesc: GCPrivate.NetDesc ← NARROW[val];
FOR list:
LIST
OF GCPrivate.PhyPinDesc ← netDesc.pinList, list.rest
WHILE list #
NIL
DO
net: CoreRouteFlat.Net ← NARROW[key];
exteriorPublic: BOOLEAN ← IPCTG.IsBoundingChannel[topology.ctg, channel.ch] AND ExternalNet[context.structure, net]; -- External pins already included
phyPin: GCPrivate.PhyPinDesc ← list.first;
IF phyPin.pPin.side = otherSide
AND ~exteriorPublic
THEN {
netDat: NetInChan ←
IF net.any =
NIL
THEN NEW[NetInChanRec]
ELSE NARROW[net.any];
range: CoreRouteFlat.Range ← CoreRouteFlat.TranslateRange
[phyPin.instance, phyPin.pPin];
AddPin[net, netDat, net.name, range, rules.branchLayer, chanSide, 0];
maxWidth ←
MAX[maxWidth, IncludePin
[list.first, net.name, chanSide, lower, upper, shell]]};
ENDLOOP};
DoChannelIntersection:
IPCTG.EachIntersectionAction ~ {
PROC[i: Intersection] RETURNS[quit: BOOL ← FALSE];
add the pins from the channel intersections
EachExit: PublicEnumerator ~ {
[name: Rope.ROPE, min, max: INT, side: DABasics.Side, layer: CD.Layer] RETURNS [quit: BOOL ← FALSE]
net: CoreRouteFlat.Net ← NARROW[SymTab.Fetch[context.structure.nets, name].val];
IF (internal
AND side = otherSide)
OR
(~internal
AND ExternalNet[context.structure, net]
AND side = chanSide)
THEN {
range: CoreRouteFlat.Range ←
SELECT chanSide
FROM
bottom, top => [otherChannel.position.x + min, otherChannel.position.x + max],
left, right => [otherChannel.position.y + min, otherChannel.position.y + max],
ENDCASE => GC.Error[programmingError, "Call maintainer"];
netDat: NetInChan ← IF net.any = NIL THEN NEW[NetInChanRec] ELSE NARROW[net.any];
AddPin[net, netDat, name, range, rules.branchLayer, chanSide, 0]}};
otherChannel: GCPrivate.Channel ← NARROW[i.ch.any];
[] ← EnumerateEdgePins[context, otherChannel, EachExit]};
rect: CD.Rect;
maxWidth: INT ← rules.branchWidth;
otherSide: RTBasic.Side ← RTBasic.OtherSide[chanSide];
bottomOrLeft: BOOLEAN ← chanSide = bottom OR chanSide = left;
topOrRight: BOOLEAN ← ~bottomOrLeft;
lower: RTBasic.PQPos ← GCPrivate.LowerChannelPQ[channel];
upper: RTBasic.PQPos ← GCPrivate.UpperChannelPQ[channel];
topology: IPTop.Ref ← NARROW[context.topology];
polarity: IP.PolarityTypes ← IF (internal AND bottomOrLeft) OR (~internal AND topOrRight) THEN neg ELSE pos;
IF
IPCTG.IsBoundingChannel[topology.ctg, channel.ch]
THEN [] ← IPCTG.Components[channel.ch, polarity, DoExternalPins];
[] ← RefTab.Pairs[channel.connections, EachNet];
[] ← IPCTG.Intersections[channel.ch, polarity, DoChannelIntersection];
IF channel.lowerIntType = inverted
THEN [] ← DoChannelIntersection[IPCTG.End[channel.ch, neg]];
IF channel.upperIntType = inverted
THEN [] ← DoChannelIntersection[IPCTG.End[channel.ch, pos]];
rect ←
SELECT chanSide
FROM
bottom => [lower.p, lower.q - maxWidth, upper.p, lower.q],
right => [upper.q, lower.p, upper.q + maxWidth, upper.p],
top => [lower.p, upper.q, upper.p, upper.q + maxWidth],
left => [lower.q - maxWidth, lower.p, lower.q, upper.p],
ENDCASE => GC.Error[programmingError, "Call maintainer"];
CDCells.SetInterestRect[design: NIL, cell: shell, r: rect]; -- set interestRect of shell
RTBasic.RepositionCell[shell]};
MakeEnd:
PROC [context:
GC.Context, rules: Route.DesignRules, channel: GCPrivate.Channel, side: RTBasic.Side] ~ {
construct the end object of a channel
EachNet: RefTab.EachPairAction ~ {
PROC [key: Key, val: Val] RETURNS [quit: BOOLEAN ← FALSE];
netDesc: GCPrivate.NetDesc ← NARROW[val];
net: CoreRouteFlat.Net ← NARROW[key];
publicNet: BOOLEAN ← CoreRouteFlat.IsPublic[net];
needsExit: BOOLEAN ← (side = bottom OR side = left) AND netDesc.bottomOrLeftExit OR (side = top OR side = right) AND netDesc.topOrRightExit;
IF needsExit
AND (ordinaryIntersection
OR publicNet)
THEN {
netDat: NetInChan ← IF net.any = NIL THEN NEW[NetInChanRec] ELSE NARROW[net.any];
AddEnd[net, netDat, net.name, side, 0]}};
ordinaryIntersection: BOOLEAN ← (channel.lowerIntType = normal AND (side = left OR side = bottom)) OR (channel.upperIntType = normal AND (side = right OR side = top));
[] ← RefTab.Pairs[channel.connections, EachNet]};
IncludePin:
PROC [phyPin: GCPrivate.PhyPinDesc, name: Rope.
ROPE, side: RTBasic.Side, lower, upper: RTBasic.PQPos, shell:
CD.Object]
RETURNS[width:
INT]~ {
include a pin in a shell; also extend a wire if necessary
instance: CoreRouteFlat.Instance ← phyPin.instance;
pPin: CoreRouteFlat.Pin ← phyPin.pPin;
range: CoreRouteFlat.Range ← CoreRouteFlat.TranslateRange[instance, pPin];
rangeSize: INT ← range.max - range.min;
wireLoc: CD.Position;
wireSize: CD.Position;
SELECT side
FROM
top => {
width ← instance.position.y - upper.q; -- + pPin.depth
wireSize ← [rangeSize, width];
wireLoc ← [range.min, upper.q]};
left => {
sidePos: INT ← instance.position.x + CD.InterestSize[instance.layObject].x;
width ← lower.q - sidePos; -- + pPin.depth;
wireSize ← [width, rangeSize];
wireLoc ← [sidePos -- -pPin.depth--, range.min]};
bottom => {
sidePos: INT ← instance.position.y + CD.InterestSize[instance.layObject].y;
width ← lower.q - sidePos; -- + pPin.depth;
wireSize ← [rangeSize, width];
wireLoc ← [range.min, sidePos -- -pPin.depth--]};
right => {
width ← instance.position.x - upper.q; -- + pPin.depth;
wireSize ← [width, rangeSize];
wireLoc ← [upper.q, range.min]};
ENDCASE;
IF width # 0
THEN {
wire: CD.Object ← CDRects.CreateRect[wireSize, pPin.layer];
CDProperties.PutProp[wire, $SignalName, name];
[] ← GCPrivate.IncludeOb[cell: shell, ob: wire, position: wireLoc]}};