ComputeArc: HashTable.EachPairAction = {
net: Net ← NARROW [value];
ringWidth: INT ← IF net.width=0 THEN CDSimpleRules.MinWidth[ringLayer] ELSE net.width;
pitch: INT = MAX [contactWidth, ringWidth]+CDSimpleRules.MinDist[ringLayer, ringLayer];
net.arc ← OnionCoreArc.EmptyArc[CDBasics.Extend[CDBasics.RectAt[innerPos, innerSize], pitch]];
FOR innerSegs:
LIST
OF Seg ← net.innerSegs, innerSegs.rest
WHILE innerSegs#
NIL
DO
min, max: INT;
[min, max] ← SegToMinMax[innerSegs.first];
net.arc ← OnionCoreArc.ConnectSegBitToArc[min, max, innerSegs.first.side1, net.arc];
ENDLOOP;
FOR outerSegs:
LIST
OF Seg ← net.outerSegs, outerSegs.rest
WHILE outerSegs#
NIL
DO
min, max: INT;
[min, max] ← SegToMinMax[outerSegs.first];
SELECT outerSegs.first.side1
FROM
bottom, right => max ← MAX[max, min+contactWidth];
top, left => min ← MIN[min, max-contactWidth];
ENDCASE => ERROR;
net.arc ← OnionCoreArc.ConnectSegBitToArc[min, max, outerSegs.first.side1, net.arc];
ENDLOOP;
};
DepositOuterContacts: HashTable.EachPairAction = {
DrawOuterPin:
PROC [outerSeg: Seg] = {
Add a contact and a pin
IncludeContact[outer, outerSeg, assignedArc.rect, netRingWidth, radialLayer, ringLayer];
net.newInnerSegs ← CONS [outerSeg, net.newInnerSegs];
};
net: Net ← NARROW [value];
wrong: BOOL ← FALSE; nbOuterSegs, nbNonRoutedOuterSegs: INT ← 0;
IF ~net.chosen THEN {IF net.eval#LAST [INT] THEN TerminalIO.WriteF["%g ", IO.rope[net.name]]; RETURN};
FOR outerSegs:
LIST
OF Seg ← net.outerSegs, outerSegs.rest
WHILE outerSegs#
NIL
DO
nbOuterSegs ← nbOuterSegs+1;
IF RoughlyFacesSomeNet[nets, net, outerSegs.first, radialLayer, ringLayer]
THEN {nbNonRoutedOuterSegs ← nbNonRoutedOuterSegs + 1; IF net.routeEveryOuterSeg THEN wrong ← TRUE}
ELSE DrawOuterPin[outerSegs.first];
ENDLOOP;
IF wrong THEN TerminalIO.WriteF["\n****** ROUTING IS WRONG for net %g: at least 2 different nets are facing each other. No cure possible until Dogleg is introduced in Onion!\n", IO.rope[net.name]];
IF nbNonRoutedOuterSegs#0 THEN TerminalIO.WriteF["\n*** Warning for net %g: %g segments non routed out of %g segments. Check your result!\n", IO.rope[net.name], IO.int[nbNonRoutedOuterSegs], IO.int[nbOuterSegs]];
};
WHILE innerPos.x>=0
AND innerPos.y>=0
AND innerSize.x+innerPos.x<=outerSize.x
AND innerSize.y+innerPos.y<=outerSize.y
AND
NOT AllNetsFacing[nets]
DO
ChooseMinEval: HashTable.EachPairAction = {
net: Net ← NARROW [value];
IF net.facing OR net.eval>minEval OR net.eval=LAST [INT] THEN RETURN;
minEval ← net.eval; minNet ← net;
netRingWidth ← IF net.width=0 THEN CDSimpleRules.MinWidth[ringLayer] ELSE net.width;
assignedArc ← net.arc;
};
Length:
PROC [list:
LIST
OF Seg]
RETURNS [length:
INT ← 0] = {
WHILE list#NIL DO length ← length+1; list ← list.rest ENDLOOP;
};
ChooseCompatibleOthers: HashTable.EachPairAction = {
net: Net ← NARROW [value];
ringWidth: INT ← IF net.width=0 THEN CDSimpleRules.MinWidth[ringLayer] ELSE net.width;
IF net.facing OR net.chosen OR net.eval>minEval OR net.eval=LAST [INT] THEN RETURN;
IF minNet#net AND (~CDBasics.Inside[net.arc.rect, assignedArc.rect] OR ~OnionCoreArc.NotOverlapping[assignedArc, net.arc, CDSimpleRules.MinDist[ringLayer, ringLayer]+contactWidth] OR ringWidth#netRingWidth) THEN RETURN;
net.chosen ← TRUE; TerminalIO.WriteF["Routing the net : %g innerPins: %g outerPins: %g Cost: %g\n", IO.rope[net.name], IO.int[Length[net.innerSegs]], IO.int[Length[net.outerSegs]], IO.int[net.eval]];
};
netRingWidth ← 0; assignedArc ← NIL; minEval ← LAST [INT]; minNet ← NIL;
-- We compute the Arc necessited by the net for being routed
[] ← HashTable.Pairs[nets, ComputeArc];
We compute evaluation function, i.e. LAST [INT]/2+Length[Arc] if there is an innerPin in front of some outerPin of the net, LAST [INT] if all pins of the net are matching some pins of the same net, Length[Arc] else.
[] ← HashTable.Pairs[nets, ComputeEval];
We choose the mininum of this evaluation function over each non-chosen net non intersecting (using the design rules) assignedArc and being inside assignedArc.rect (only if someNetAssigned), set assignedArc to the corresponding value, and set the chosen bit of the chosen net. We start again and again until no more net is found.
TerminalIO.WriteF["Allocating a new track\n"];
[] ← HashTable.Pairs[nets, ChooseMinEval];
IF minEval=
LAST [
INT]
THEN {
TerminalIO.WriteF["*** Routing Impossible (Too big) ***\n*** Current state returned! ****\n"];
RETURN [FALSE];
};
[] ← HashTable.Pairs[nets, ChooseCompatibleOthers];
-- We now generate geometry
-- We shrink the assignedArc.rect if some sides are unused
IF OnionCoreArc.NotOverlapping[assignedArc,
NEW[OnionCoreArc.ArcRec ← [rect: assignedArc.rect, segs:
LIST [
NEW[OnionCoreArc.SegRec ← [assignedArc.rect.y2, assignedArc.rect.y1, left, left]]]]],
CDSimpleRules.MinDist[ringLayer, ringLayer]+contactWidth] THEN assignedArc.rect.x1 ← innerPos.x;
IF OnionCoreArc.NotOverlapping[assignedArc, NEW[OnionCoreArc.ArcRec ← [rect: assignedArc.rect, segs: LIST [NEW[OnionCoreArc.SegRec ← [assignedArc.rect.y1, assignedArc.rect.y2, right, right]]]]], CDSimpleRules.MinDist[ringLayer, ringLayer]+contactWidth] THEN assignedArc.rect.x2 ← innerPos.x+innerSize.x;
IF OnionCoreArc.NotOverlapping[assignedArc, NEW[OnionCoreArc.ArcRec ← [rect: assignedArc.rect, segs: LIST [NEW[OnionCoreArc.SegRec ← [assignedArc.rect.x1, assignedArc.rect.x2, bottom, bottom]]]]], CDSimpleRules.MinDist[ringLayer, ringLayer]+contactWidth] THEN assignedArc.rect.y1 ← innerPos.y;
IF OnionCoreArc.NotOverlapping[assignedArc, NEW[OnionCoreArc.ArcRec ← [rect: assignedArc.rect, segs: LIST [NEW[OnionCoreArc.SegRec ← [assignedArc.rect.x2, assignedArc.rect.x1, top, top]]]]], CDSimpleRules.MinDist[ringLayer, ringLayer]+contactWidth] THEN assignedArc.rect.y2 ← innerPos.y+innerSize.y;
-- We place the sides of the routing (in metal2)
OnionCoreArc.EnumerateSegBits[assignedArc, DrawRingBit];
-- We deposit contacts facing the outer pins which touch the routing ring. By the way we print the names of non-chosen nets
TerminalIO.WriteF["Non routed nets: "];
[] ← HashTable.Pairs[nets, DepositOuterContacts];
TerminalIO.WriteF["\n"];
-- We deposit wires in metal for inner pins and if the pin belongs to the net, then add a contact, else add a pin.
[] ← HashTable.Pairs[nets, DepositInnerWiresEtAl];
-- We affect parameters consequently
innerPos ← CDBasics.BaseOfRect[assignedArc.rect];
innerSize ← [assignedArc.rect.x2-assignedArc.rect.x1, assignedArc.rect.y2-assignedArc.rect.y1];
[] ← HashTable.Pairs[nets, CopyNextInnerSegs];
ENDLOOP;