MakeSide:
PROC [context:
GC.Context, rules: Route.DesignRules, channel: GCPrivate.Channel, chanSide: DABasics.Side, internal:
BOOLEAN, layoutStyle: GC.LayoutStyle]
RETURNS [shell:
CD.Object ←
NIL] ~ {
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];
sideOfCell: DABasics.Side ← IF internal THEN otherSide ELSE chanSide;
FOR nns:
LIST
OF CoreRouteFlat.NetONode ← instance.netONodes, nns.rest
WHILE nns#
NIL
DO
isPowerNet: BOOLEAN ← Rope.Equal[nns.first.net.name, "Vdd"] OR Rope.Equal[nns.first.net.name, "Gnd"];
IF ExternalNet[context.structure, nns.first.net]
AND (layoutStyle = ic
OR ~isPowerNet)
THEN {
Gnd and Vdd are on separate planes for hybrids
sidesForExternalNet: DABasics.Sides ← SidesForExternalNet[context.structure, nns.first.net];
FOR pins:
LIST
OF CoreRouteFlat.Pin ← nns.first.oNode.pins, pins.rest
WHILE pins#
NIL
DO
phyPin: GCPrivate.PhyPinDesc ← NEW[GCPrivate.PhyPinDescRec ← [instance, nns.first.oNode, pins.first]];
netDesc: GCPrivate.NetDesc ← NARROW [RefTab.Fetch[channel.connections, nns.first.net].val];
IF pins.first.layer = rules.branchLayer
AND ~GCPrivate.PinOnList[netDesc, phyPin]
AND sidesForExternalNet[sideOfCell]
AND ((pins.first.side = otherSide
AND internal)
OR (pins.first.side = chanSide
AND ~internal))
THEN {
include pin if it is a public pin, on the right layer, not on a global route and on a public side
tabIndex: Rope.ROPE ← 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, nns.first.net.name, tabIndex, range, rules.branchLayer, chanSide, defaultTrunkWidth];
maxWidth ←
MAX[maxWidth, IncludePin[
phyPin: NEW[GCPrivate.PhyPinDescRec ← [instance, nns.first.oNode, pins.first]],
name: tabIndex,
side: chanSide,
lower: lower,
upper: upper,
nodes: nodes ] ] };
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];
phyPin: GCPrivate.PhyPinDesc ← list.first;
netDat: NetInChan ←
IF net.any =
NIL
THEN NEW[NetInChanRec]
ELSE NARROW[net.any];
range: CoreRouteFlat.Range ← CoreRouteFlat.TranslateRange[phyPin.instance, phyPin.pPin];
externalNet: BOOLEAN ← IPCTG.IsBoundingChannel[topology.ctg, channel.ch] AND ExternalNet[context.structure, net];
IF phyPin.pPin.layer # rules.branchLayer THEN GC.Signal[programmingError, "Call Maintainer"];
maxWidth ← MAX[maxWidth, IncludePin [list.first, net.name, chanSide, lower, upper, nodes]];
IF phyPin.pPin.side = otherSide
THEN
AddPin[net, netDat, net.name, net.name, range, rules.branchLayer, chanSide, defaultTrunkWidth];
IF externalNet
THEN {
sidesForExternalNet: DABasics.Sides ← SidesForExternalNet[context.structure, net];
sideOfCell: DABasics.Side ← IF internal THEN otherSide ELSE chanSide;
IF ~internal
AND sidesForExternalNet[sideOfCell]
AND phyPin.pPin.side = chanSide
THEN
AddPin[net, netDat, net.name, net.name, range, rules.branchLayer, chanSide, defaultTrunkWidth]};
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];
sidesForExternalNet: DABasics.Sides ← SidesForExternalNet[context.structure, net];
sideOfCell: DABasics.Side ← IF internal THEN otherSide ELSE chanSide;
IF (internal
AND side = otherSide)
OR
(~internal
AND sidesForExternalNet[sideOfCell]
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, name, range, rules.branchLayer, chanSide, defaultTrunkWidth]}};
otherChannel: GCPrivate.Channel ← NARROW[i.ch.any];
[] ← EnumerateEdgePins[context, otherChannel, EachExit]};
AddVdd: IPCTG.EachComponentAction ~ {
PROC[co: Component] RETURNS[quit: BOOL ← FALSE];
add the vdd connections for hybrids
IF co # NIL THEN {
instance: CoreRouteFlat.Instance ← NARROW[co.any];
instSize: CD.Position ← CD.InterestSize[instance.layObject];
width: INT ← SELECT side FROM
top => instance.position.y - upper.q,
left => lower.q - instance.position.x - instSize.x,
bottom => lower.q - instance.position.y - instSize.y,
right => instance.position.x - upper.q,
ENDCASE => GC.Error[programmingError, "Not suppose to happen"];
IF width > 0 THEN {
vddLayer: CD.Layer ← CDSimpleRules.GetLayer[context.rules.technology.key, "poly"]; -- a HACK for Vdd layer
wire: CD.Object ← SELECT side FROM
bottom, top => CDRects.CreateRect[[instSize.x, width], vddLayer],
left, right => CDRects.CreateRect[[[width, instSize.y], width], vddLayer],
ENDCASE => GC.Error[programmingError, "Not suppose to happen"];
po: CDRoutingObjects.PlacedObject ← SELECT side FROM
SELECT side FROM
top => [wire, [instance.position.x, upper.q]],
left => [wire, [instance.position.x + instSize.x, instance.position.y]],
bottom => [wire, [instance.position.x, instance.position.y + instSize.y]],
right => [wire, [upper.q, instance.position.y]],
ENDCASE => GC.Error[programmingError, "Not suppose to happen"];
pos: REF LIST OF CDRoutingObjects.PlacedObject ← NEW[LIST OF CDRoutingObjects.PlacedObject ← NIL];
[]←SymTab.Store[nodes, "Vdd", pos];
pos^ ← CONS[po, pos^] } } };
defaultTrunkWidth: INT ← rules.trunkWidth;
rect: CD.Rect;
maxWidth: INT ← 0;
otherSide: DABasics.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;
nodes: SymTab.Ref ← SymTab.Create[];
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"];
IF layoutStyle = hybrid AND maxWidth > 0 THEN
[] ← IPCTG.Components[channel.ch, polarity, AddVdd];
IF SymTab.GetSize[nodes] > 0
THEN
shell ← CDRoutingObjects.CreateRoutingObject[
nodes: CDRoutingObjects.CreateNodes[nodes],
ir: rect]
};
MakeEnd:
PROC [context:
GC.Context, rules: Route.DesignRules, channel: GCPrivate.Channel, side: DABasics.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, net.name, side, defaultTrunkWidth]}};
defaultTrunkWidth: INT ← rules.trunkWidth;
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: DABasics.Side, lower, upper: RTBasic.PQPos, nodes: SymTab.Ref]
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];
po: CDRoutingObjects.PlacedObject ← [wire, wireLoc];
pos: REF LIST OF CDRoutingObjects.PlacedObject ← NEW[LIST OF CDRoutingObjects.PlacedObject ← NIL];
[]←SymTab.Store[nodes, Rope.Cat[name, "-", Convert.RopeFromInt[range.min]], pos];
pos^ ← CONS[po, pos^]}};