DIRECTORY CD, CDBasics, CDCells, CDOrient, CDSymbolicObjects, CDProperties, CDRects, CDSimpleRules, CMosB, IO, Onion, OnionArc, PW, PWPins, SymTab, TerminalIO; OnionImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDOrient, CDSymbolicObjects, CDProperties, CDRects, CDSimpleRules, CMosB, OnionArc, IO, PW, PWPins, SymTab, TerminalIO EXPORTS Onion = BEGIN OPEN Onion; defaultLayersParameters: PUBLIC LayersParameters = NEW [LayersParametersRec _ [ radialLayer: CMosB.met, ringLayer: CMosB.met2, ringWidth: RingWidthIs4l, wireExtendProc: WireExtendMetToMet ]]; channelDefaultParameters: PUBLIC LayersParameters = NEW [LayersParametersRec _ [ radialLayer: CMosB.met, ringLayer: CMosB.met2, ringWidth: RingWidthIs4l, wireExtendProc: WireExtendMetToMet ]]; WireExtendMetToMet: PUBLIC WireExtendProc = { wire _ CDRects.CreateRect[[length, width], CMosB.met]; }; WireExtendPolToMetForPads: PUBLIC WireExtendProc = { nb: INT _ MAX[8, width]; -- for computing how many! wire _ CDCells.CreateEmptyCell[]; [] _ PW.IncludeInCell[wire, CDRects.CreateRect[[length-14, width], CMosB.met], [0, 0]]; FOR i: INT IN [0 .. nb/8) DO [] _ PW.IncludeInCell[wire, CDSimpleRules.Contact[CMosB.pol, CMosB.met], [length-14, 8*i]] ENDLOOP; [] _ PW.IncludeInCell[wire, CDRects.CreateRect[[6, width], CMosB.pol], [length-6, 0]]; CDCells.SetInterestRect[wire, [0, 0, length, width]]; [] _ CDCells.RepositionCell[wire, NIL]; }; RingWidthIs4l: PUBLIC RingWidthProc = {ringWidth _ 4 * CMosB.lambda}; Arc: TYPE = OnionArc.Arc; RotateSide: PROC [side: PWPins.Side] RETURNS [PWPins.Side] = { RETURN [SELECT side FROM bottom => right, right => top, top => left, left => bottom, ENDCASE => ERROR]; }; Net: TYPE = REF NetRec; NetRec: TYPE = RECORD [ chosen: BOOL _ FALSE, -- chosen for being routed eval: INT _ 0, -- evaluation function arc: Arc _ NIL, -- arc used by this net innerPins, outerPins: LIST OF CD.Instance _ NIL -- pins of the net ]; FetchNet: PROC [nets: SymTab.Ref, name: ROPE] RETURNS [net: Net] = { found: BOOL; val: SymTab.Val; [found, val] _ SymTab.Fetch[nets,name]; net _ IF found THEN NARROW[val] ELSE NEW[NetRec]; }; StoreNet: PROC [nets: SymTab.Ref, name: ROPE, net: Net] = { [] _ SymTab.Store[nets, name, net]; }; IncludePin: PUBLIC PROC [cell: CD.Object, name: ROPE, layer: CD.Layer, size, position: CD.Position, orientation: CD.Orientation _ 0] RETURNS [newInst: CD.Instance] = { newInst _ PW.IncludeInCell[cell: cell, obj: CDSymbolicObjects.CreatePin[size], position: position, orientation: orientation].newInst; CDSymbolicObjects.SetName[newInst, name]; CDSymbolicObjects.SetLayer[newInst, layer]; }; IncludeContact: PUBLIC PROC [cell: CD.Object, side: PWPins.Side, layer1, layer2: CD.Layer, size: INT, position: CD.Position, orientation: CD.Orientation _ 0] = { contact: CD.Object _ CDSimpleRules.Contact[layer1, layer2]; contactSize: INT _ contact.size.x; -- **** WRONG nb: INT _ MAX[contactSize, size]; -- **** WRONG FOR i: INT IN [0..nb/contactSize) DO [] _ PW.IncludeInCell[ cell, contact, SELECT side FROM left => [position.x, position.y+i*contactSize], right => [position.x-contactSize, position.y+i*contactSize], bottom => [position.x+i*contactSize, position.y], top => [position.x+i*contactSize, position.y-contactSize], ENDCASE => ERROR]; ENDLOOP; }; Center: PUBLIC PROC [inner, outer: CD.Object] RETURNS [innerPos: CD.Position] = { innerPos _ CDBasics.SubPoints[ CDBasics.SizeOfRect[CD.InterestRect[outer]], CDBasics.SizeOfRect[CD.InterestRect[inner]]]; innerPos.x _ innerPos.x/2; innerPos.y _ innerPos.y/2; }; MakeInner: PUBLIC PROC [obj: CD.Object] RETURNS [inner: CD.Object] = { dist: INT _ 18; ---???? ExtendPinOnEdge: PWPins.InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] -- = { newInst: CD.Instance; location: CD.Position _ CDBasics.SubPoints[ inst.location, CDBasics.BaseOfRect[CD.InterestRect[obj]]]; realSize: CD.Position _ CDOrient.OrientedSize[inst.ob.size, inst.orientation]; side: PWPins.Side _ PWPins.GetSide[obj, inst].side; newInst _ IncludePin[ inner, CDSymbolicObjects.GetName[inst], CMosB.met, realSize, SELECT side FROM right => [location.x+dist, location.y], left => [location.x-dist, location.y], top => [location.x, location.y+dist], bottom => [location.x, location.y-dist], ENDCASE => ERROR]; [] _ PW.IncludeInCell[ inner, CDRects.CreateRect[ SELECT side FROM left, right => [dist, realSize.y], top, bottom => [realSize.x, dist], ENDCASE => ERROR, CDSymbolicObjects.GetLayer[inst]], SELECT side FROM left => [location.x-dist, location.y], right => [location.x+realSize.x, location.y], bottom => [location.x, location.y-dist], top => [location.x, location.y+realSize.y], ENDCASE => ERROR]; SELECT CDSymbolicObjects.GetLayer[inst] FROM CMosB.met => {}; CMosB.met2 => { IncludeContact[inner, side, CMosB.met, CMosB.met2, (SELECT side FROM left, right => realSize.y, bottom, top => realSize.x, ENDCASE => ERROR), SELECT side FROM left => [location.x-dist, location.y], right => [location.x+realSize.x+dist, location.y], bottom => [location.x, location.y-dist], top => [location.x, location.y+realSize.y+dist], ENDCASE => ERROR]; }; CMosB.pol => { IncludeContact[inner, side, CMosB.met, CMosB.pol, (SELECT side FROM left, right => realSize.y, bottom, top => realSize.x, ENDCASE => ERROR), SELECT side FROM left => [location.x-dist, location.y], right => [location.x+realSize.x+dist, location.y], bottom => [location.x, location.y-dist], top => [location.x, location.y+realSize.y+dist], ENDCASE => ERROR]; }; ENDCASE => TerminalIO.WriteF["**** MakeInner: Layer unknown for extending pin %g. Extension WRONG!!!\n", IO.rope[CDSymbolicObjects.GetName[inst]]]; }; inst: CD.Instance; inner _ CDCells.CreateEmptyCell[]; inst _ PW.IncludeInCell[inner, obj]; CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; [] _ PWPins.EnumerateEdgePins[obj, ExtendPinOnEdge]; CDCells.SetInterestRect[inner, CDBasics.Extend[ CDBasics.RectAt[[0, 0], CDBasics.SizeOfRect[CD.InterestRect[obj]]], dist]]; [] _ CDCells.RepositionCell[inner, NIL]; }; LRSRouteOnce: PUBLIC PROC [inner, outer: CD.Object, innerPos: CD.Position, params: LayersParameters _ defaultLayersParameters] RETURNS [cell: CD.Object, newInnerPos: CD.Position, status: Status] = { contactWidth: INT; innerRect: CD.Rect = CDBasics.MoveRect[CDBasics.RectAt[[0, 0], CDBasics.SizeOfRect[CD.InterestRect[inner]]], innerPos]; -- in the outer coord system InnerPinLocation: PROC [pin: CD.Instance] RETURNS [location: CD.Position] = { location _ CDBasics.AddPoints[CDBasics.SubPoints[pin.location, CDBasics.BaseOfRect[CD.InterestRect[inner]]], innerPos]; }; OuterPinLocation: PROC [pin: CD.Instance] RETURNS [location: CD.Position] = { location _ CDBasics.SubPoints[pin.location, CDBasics.BaseOfRect[CD.InterestRect[outer]]]; }; InnerPinBiProjection: PROC [pin: CD.Instance] RETURNS [min, max: INT] = { rect: CD.Rect _ CDOrient.RectAt[InnerPinLocation[pin], pin.ob.size, pin.orientation]; SELECT PWPins.GetSide[inner, pin].side FROM bottom, top => {min _ rect.x1; max _ rect.x2}; left, right => {min _ rect.y1; max _ rect.y2}; ENDCASE => ERROR; }; OuterPinBiProjection: PROC [pin: CD.Instance] RETURNS [min, max: INT] = { rect: CD.Rect _ CDOrient.RectAt[OuterPinLocation[pin], pin.ob.size, pin.orientation]; SELECT PWPins.GetSide[outer, pin].side FROM bottom, top => {min _ rect.x1; max _ rect.x2}; left, right => {min _ rect.y1; max _ rect.y2}; ENDCASE => ERROR; }; OuterCoordsToCellCoords: PROC [outerPos: CD.Position] RETURNS [cellPos: CD.Position] = { cellPos _ CDBasics.SubPoints[outerPos, CDBasics.BaseOfRect[assignedArc.rect]]; }; AddInnerPinToNets: PWPins.InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] -- = { name: ROPE _ CDSymbolicObjects.GetName[inst]; net: Net _ FetchNet[nets, name]; IF CDSymbolicObjects.GetLayer[inst]#params.radialLayer THEN TerminalIO.WriteF["*** Pin %g discarded: not of radialLayer material.\n", IO.rope[name]] ELSE net.innerPins _ CONS[inst, net.innerPins]; StoreNet[nets, name, net]; }; AddOuterPinToNets: PWPins.InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] -- = { name: ROPE _ CDSymbolicObjects.GetName[inst]; net: Net _ FetchNet[nets, name]; net.outerPins _ CONS[inst, net.outerPins]; StoreNet[nets, name, net]; }; ComputeArc: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; pitch: INT = MAX[contactWidth, params.ringWidth[key]]+CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]; net.arc _ OnionArc.EmptyArc[CDBasics.Extend[innerRect, pitch]]; FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO side: PWPins.Side _ PWPins.GetSide[inner, innerPins.first].side; min, max: INT; [min, max] _ InnerPinBiProjection[innerPins.first]; SELECT side FROM bottom, right => max _ MAX[max, min+contactWidth]; top, left => min _ MIN[min, max-contactWidth]; ENDCASE => ERROR; net.arc _ OnionArc.ConnectSegBitToArc[min, max, side, net.arc]; ENDLOOP; FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO side: PWPins.Side _ PWPins.GetSide[outer, outerPins.first].side; min, max: INT; [min, max] _ OuterPinBiProjection[outerPins.first]; SELECT side FROM bottom, right => max _ MAX[max, min+contactWidth]; top, left => min _ MIN[min, max-contactWidth]; ENDCASE => ERROR; net.arc _ OnionArc.ConnectSegBitToArc[min, max, side, net.arc]; ENDLOOP; quit _ FALSE; }; ComputeEval: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; allOuterPinsMatchSomeInnerPin: BOOL _ TRUE; quit _ FALSE; FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO matches: BOOL _ FALSE; FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO IF Faces[innerPins.first, outerPins.first] THEN {matches _ TRUE; EXIT}; ENDLOOP; IF ~matches THEN {allOuterPinsMatchSomeInnerPin _ FALSE; EXIT}; ENDLOOP; IF allOuterPinsMatchSomeInnerPin THEN {net.eval _ LAST[INT]; RETURN}; net.eval _ OnionArc.Length[net.arc] + net.arc.rect.x2 - net.arc.rect.x1 + net.arc.rect.y2 - net.arc.rect.y1; FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO FindDifferentNetFacing: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { thisNet: Net _ NARROW[val]; quit _ FALSE; IF thisNet=net THEN RETURN; FOR innerPins: LIST OF CD.Instance _ thisNet.innerPins, innerPins.rest WHILE innerPins#NIL DO IF RoughlyFaces[innerPins.first, outerPins.first] THEN {quit _ TRUE; RETURN}; ENDLOOP; }; IF SymTab.Pairs[nets, FindDifferentNetFacing] THEN {net.eval _ net.eval + LAST [INT] /2; RETURN}; ENDLOOP; }; Faces: PROC [innerPin, outerPin: CD.Instance] RETURNS [faces: BOOL] = { side: PWPins.Side _ PWPins.GetSide[inner, innerPin].side; faces _ side=PWPins.GetSide[outer, outerPin].side AND OuterPinBiProjection[outerPin]=InnerPinBiProjection[innerPin]; }; RoughlyFaces: PROC [innerPin, outerPin: CD.Instance] RETURNS [faces: BOOL] = { side: PWPins.Side _ PWPins.GetSide[inner, innerPin].side; innerMin, innerMax, outerMin, outerMax: INT; [innerMin, innerMax] _ InnerPinBiProjection[innerPin]; [outerMin, outerMax] _ OuterPinBiProjection[outerPin]; innerMax _ MAX [innerMax, innerMin + contactWidth] + CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]; outerMax _ MAX [outerMax, outerMin + contactWidth] + CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]; faces _ side=PWPins.GetSide[outer, outerPin].side AND (innerMin IN [outerMin .. outerMax] OR outerMin IN [innerMin .. innerMax]); }; ChooseMinEval: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; quit _ FALSE; IF net.chosen OR net.eval>minEval OR net.eval=LAST[INT] THEN RETURN; IF assignedArc#NIL AND (net.eval>=LAST[INT]/2 OR ~CDBasics.Inside[net.arc.rect, assignedArc.rect] OR ~OnionArc.NotOverlinsting[assignedArc, net.arc, CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]+contactWidth] OR params.ringWidth[key]#netRingWidth) THEN RETURN; minEval _ net.eval; minNetName _ key; }; IncludeInCellSide: PROC [ob: CD.Object, side: PWPins.Side, position: CD.Position, orientation: CD.Orientation _ 0] = { position _ OuterCoordsToCellCoords[position]; SELECT side FROM left => position.y _ position.y-ob.size.y; right => position.x _ position.x-ob.size.x; bottom => {}; top => {position.x _ position.x-ob.size.x; position.y _ position.y-ob.size.y}; ENDCASE => ERROR; [] _ PW.IncludeInCell[cell: cell, obj: ob, position: position, orientation: orientation]; }; IncludePinSide: PROC [name: ROPE, side: PWPins.Side, size, position: CD.Position] = { pinDeep: INT _ 2; position _ OuterCoordsToCellCoords[position]; SELECT side FROM left => position.y _ position.y-size.y; right => position.x _ position.x-size.x; bottom => {}; top => {position.x _ position.x-size.x; position.y _ position.y-size.y}; ENDCASE => ERROR; [] _ IncludePin[cell, name, params.radialLayer, size, position]; }; IncludeContactSide: PROC [side: PWPins.Side, size: INT, position: CD.Position] = { nb: INT _ MAX[contactWidth, size]; FOR i: INT IN [0..nb/contactWidth) DO IncludeInCellSide[CDSimpleRules.Contact[params.radialLayer, params.ringLayer], side, SELECT side FROM left => [position.x, position.y-contactWidth*i], right => [position.x, position.y+contactWidth*i], bottom => [position.x+contactWidth*i, position.y], top => [position.x-contactWidth*i, position.y], ENDCASE => ERROR]; ENDLOOP }; DrawRingBit: OnionArc.EachSegBitProc -- [min: D2Basic.Number, max: D2Basic.Number, side: Onion.PWPins.Side] -- = { SELECT side FROM bottom => [] _ PW.IncludeInCell[cell, CDRects.CreateRect[[max-min, netRingWidth], params.ringLayer], [min-assignedArc.rect.x1, 0]]; right => [] _ PW.IncludeInCell[cell, CDRects.CreateRect[[netRingWidth, max-min], params.ringLayer], [assignedArc.rect.x2-assignedArc.rect.x1-netRingWidth, min-assignedArc.rect.y1]]; top => [] _ PW.IncludeInCell[cell, CDRects.CreateRect[[max-min, netRingWidth], params.ringLayer], [min-assignedArc.rect.x1, assignedArc.rect.y2-assignedArc.rect.y1-netRingWidth]]; left => [] _ PW.IncludeInCell[cell, CDRects.CreateRect[[netRingWidth, max-min], params.ringLayer], [0, min-assignedArc.rect.y1]]; ENDCASE => ERROR; }; DepositOuterContacts: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { DrawOuterPin: PROC [inst: CD.Instance, name: ROPE] = { side: PWPins.Side _ PWPins.GetSide[outer, inst].side; size: CD.Position _ CDOrient.OrientedSize[inst.ob.size, inst.orientation]; position: CD.Position _ OuterPinLocation[inst]; pos: CD.Position _ SELECT side FROM left => [assignedArc.rect.x1, position.y + size.y], right => [assignedArc.rect.x2, position.y], bottom => [position.x, assignedArc.rect.y1], top => [position.x + size.x, assignedArc.rect.y2], ENDCASE => ERROR; IncludeContactSide[side, (SELECT side FROM left, right => size.y, bottom, top => size.x, ENDCASE => ERROR), pos]; IncludePinSide[name, side, size, pos]; }; net: Net _ NARROW [val]; quit _ FALSE; IF ~net.chosen THEN {IF net.eval#LAST[INT] THEN TerminalIO.WriteF["%g ", IO.rope[key]]; RETURN}; FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO DrawOuterPin[outerPins.first, key]; ENDLOOP; }; DepositInnerWiresEtAl: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { DrawInnerPin: PROC [inst: CD.Instance, chosen: BOOL, name: ROPE] = { side: PWPins.Side _ PWPins.GetSide[inner, inst].side; size: CD.Position _ CDOrient.OrientedSize[inst.ob.size, inst.orientation]; rectSize: CD.Position _ size; pos: CD.Position; -- base of wire in the outer coord system position: CD.Position _ InnerPinLocation[inst]; SELECT side FROM left => { pos _ [assignedArc.rect.x1, position.y + size.y]; -- origin of wire and Al in the outer coord system rectSize.x _ innerRect.x1-assignedArc.rect.x1; }; right => { pos _ [assignedArc.rect.x2, position.y]; -- origin of wire and Al in the outer coord system rectSize.x _ assignedArc.rect.x2-innerRect.x2; }; bottom => { pos _ [position.x, assignedArc.rect.y1]; -- origin of wire and Al in the outer coord system rectSize.y _ innerRect.y1-assignedArc.rect.y1; }; top => { pos _ [position.x + size.x, assignedArc.rect.y2]; -- origin of wire and Al in the outer coord system rectSize.y _ assignedArc.rect.y2-innerRect.y2; }; ENDCASE => ERROR; IF rectSize.x#0 AND rectSize.y#0 THEN IncludeInCellSide[CDRects.CreateRect[rectSize, params.radialLayer], side, pos]; IF chosen THEN -- add contact(s) IncludeContactSide[side, (SELECT side FROM left, right => size.y, bottom, top => size.x, ENDCASE => ERROR), pos] ELSE -- add a pin -- IncludePinSide[name, side, size, pos]; }; net: Net _ NARROW [val]; quit _ FALSE; FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO DrawInnerPin[innerPins.first, net.chosen, key]; ENDLOOP; }; ExtendAllWires: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; quit _ FALSE; IF net.outerPins#NIL AND net.outerPins.rest=NIL AND net.innerPins=NIL THEN RETURN; -- only 1 outerPin and 0 innerPin FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO IF Faces[innerPins.first, outerPins.first] THEN { innerPos: CD.Position _ InnerPinLocation[innerPins.first]; outerPos: CD.Position _ OuterPinLocation[outerPins.first]; innerSize: CD.Position _ CDOrient.OrientedSize[innerPins.first.ob.size, innerPins.first.orientation]; outerSize: CD.Position _ CDOrient.OrientedSize[outerPins.first.ob.size, outerPins.first.orientation]; side: PWPins.Side _ PWPins.GetSide[inner, innerPins.first].side; length: INT _ SELECT side FROM left => innerPos.x - outerPos.x - outerSize.x, right => outerPos.x - innerPos.x - innerSize.x, bottom => innerPos.y - outerPos.y - outerSize.y, top => outerPos.y - innerPos.y - innerSize.y, ENDCASE => ERROR; width: INT _ SELECT side FROM left, right => MIN[innerSize.y, outerSize.y], bottom, top => MIN[innerSize.x, outerSize.x], ENDCASE => ERROR; wire: CD.Object _ params.wireExtendProc[width, length]; [] _ PW.IncludeInCell[ cell: cell, obj: wire, position: SELECT side FROM left => [outerPos.x + outerSize.x, outerPos.y], right => [outerPos.x - length, outerPos.y], bottom => [outerPos.x, outerPos.y + outerSize.y], top => [outerPos.x, outerPos.y - length], ENDCASE => ERROR, orientation: SELECT side FROM left => CDOrient.rotate180, right => CDOrient.original, bottom => CDOrient.rotate270, top => CDOrient.rotate90, ENDCASE => ERROR ]; EXIT; }; ENDLOOP; ENDLOOP; }; assignedArc: Arc _ NIL; nets: SymTab.Ref _ SymTab.Create[]; minEval: INT; minNetName: ROPE; -- for choosing the nets netRingWidth: INT _ 0; -- all nets on the same track have the same width IF CDSimpleRules.Contact[params.radialLayer, params.ringLayer]=NIL THEN { TerminalIO.WriteF["ImpossibleTechnology: I do not know how to contact radialLayer and ringLayer!\n"]; ERROR; }; contactWidth _ CDBasics.SizeOfRect[CD.InterestRect[CDSimpleRules.Contact[params.radialLayer, params.ringLayer]]].x; -- ****** ??W?!?!?!?? WRONG! IF ~CDBasics.Inside[innerRect, CDBasics.RectAt[[0, 0], CDBasics.SizeOfRect[CD.InterestRect[outer]]]] THEN {TerminalIO.WriteF["**** Routing Impossible (Too big) ****\n**** Current state returned! ****\n"]; RETURN[inner, innerPos, impossible];}; [] _ PWPins.EnumerateEdgePins[inner, AddInnerPinToNets]; [] _ PWPins.EnumerateEdgePins[outer, AddOuterPinToNets]; BEGIN deletedNets: LIST OF ROPE _ NIL; ToBeDeleted: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; quit _ FALSE; IF (net.innerPins#NIL AND net.innerPins.rest=NIL AND net.outerPins=NIL) OR (net.outerPins#NIL AND net.outerPins.rest=NIL AND net.innerPins=NIL) THEN deletedNets _ CONS[key, deletedNets]; }; [] _ SymTab.Pairs[nets, ToBeDeleted]; WHILE deletedNets#NIL DO TerminalIO.WriteF["*** Net: %g has only 1 pin. Not routed\n", IO.rope[deletedNets.first]]; [] _ SymTab.Delete[nets, deletedNets.first]; deletedNets _ deletedNets.rest; ENDLOOP; END; [] _ SymTab.Pairs[nets, ComputeArc]; [] _ SymTab.Pairs[nets, ComputeEval]; TerminalIO.WriteF["Allocating a new track\n"]; DO Count: PROC [pins: LIST OF CD.Instance] RETURNS [rope: ROPE] = { count: INT _ 0; WHILE pins#NIL DO count _ count+1; pins _ pins.rest ENDLOOP; rope _ IO.PutR[IO.int[count]]; }; minNet: Net; minEval _ LAST[INT]; minNetName _ NIL; [] _ SymTab.Pairs[nets, ChooseMinEval]; IF minEval=LAST[INT] THEN EXIT; IF minEval>=LAST[INT]/2 THEN TerminalIO.WriteF["****** ROUTING IS WRONG: at least 2 different nets are facing each other. No cure possible until Dogleg is introduced in Onion!\n"]; minNet _ FetchNet[nets, minNetName]; IF assignedArc=NIL THEN netRingWidth _ params.ringWidth[minNetName]; assignedArc _ IF assignedArc=NIL THEN minNet.arc ELSE OnionArc.Union[assignedArc, minNet.arc]; minNet.chosen _ TRUE; TerminalIO.WriteF["Routing the net : %g innerPins: %g outerPins: %g Cost: %g\n", IO.rope[minNetName], IO.rope[Count[minNet.innerPins]], IO.rope[Count[minNet.outerPins]], IO.int[minNet.eval]]; ENDLOOP; cell _ CDCells.CreateEmptyCell[]; IF assignedArc=NIL THEN { IF params.wireExtendProc#NIL THEN [] _ SymTab.Pairs[nets, ExtendAllWires]; [] _ PW.IncludeInCell[cell, inner, innerPos]; IF params.wireExtendProc#NIL THEN [] _ PW.IncludeInCell[cell, outer, [0, 0]]; [] _ CDCells.RepositionCell[cell, NIL]; RETURN[cell, [0, 0], finishedAll]; } ELSE { IF OnionArc.NotOverlinsting[assignedArc, NEW[OnionArc.ArcRec _ [rect: assignedArc.rect, segs: LIST [NEW[OnionArc.SegRec _ [assignedArc.rect.y2, assignedArc.rect.y1, left, left]]]]], CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]+contactWidth] THEN assignedArc.rect.x1 _ innerRect.x1; IF OnionArc.NotOverlinsting[assignedArc, NEW[OnionArc.ArcRec _ [rect: assignedArc.rect, segs: LIST [NEW[OnionArc.SegRec _ [assignedArc.rect.y1, assignedArc.rect.y2, right, right]]]]], CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]+contactWidth] THEN assignedArc.rect.x2 _ innerRect.x2; IF OnionArc.NotOverlinsting[assignedArc, NEW[OnionArc.ArcRec _ [rect: assignedArc.rect, segs: LIST [NEW[OnionArc.SegRec _ [assignedArc.rect.x1, assignedArc.rect.x2, bottom, bottom]]]]], CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]+contactWidth] THEN assignedArc.rect.y1 _ innerRect.y1; IF OnionArc.NotOverlinsting[assignedArc, NEW[OnionArc.ArcRec _ [rect: assignedArc.rect, segs: LIST [NEW[OnionArc.SegRec _ [assignedArc.rect.x2, assignedArc.rect.x1, top, top]]]]], CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]+contactWidth] THEN assignedArc.rect.y2 _ innerRect.y2; CDProperties.PutInstanceProp[ PW.IncludeInCell[cell, inner, CDBasics.SubPoints[ CDBasics.BaseOfRect[innerRect], CDBasics.BaseOfRect[assignedArc.rect]]], $StopEnumerateDeepPins, $StopEnumerateDeepPins]; OnionArc.EnumerateSegBits[assignedArc, DrawRingBit]; TerminalIO.WriteF["Non routed nets: "]; [] _ SymTab.Pairs[nets, DepositOuterContacts]; TerminalIO.WriteF["\n"]; [] _ SymTab.Pairs[nets, DepositInnerWiresEtAl]; CDCells.SetInterestRect[cell, [0, 0, assignedArc.rect.x2-assignedArc.rect.x1, assignedArc.rect.y2-assignedArc.rect.y1]]; [] _ CDCells.RepositionCell[cell, NIL]; RETURN[cell, CDBasics.BaseOfRect[assignedArc.rect], doneOnce]; }; }; LRSRoute: PUBLIC PROC [inner, outer: CD.Object, innerPos: CD.Position, params: LayersParameters _ defaultLayersParameters] RETURNS [cell: CD.Object, status: Status] = { status _ doneOnce; WHILE status=doneOnce DO [inner, innerPos, status] _ LRSRouteOnce[inner, outer, innerPos, params]; ENDLOOP; cell _ inner; }; END.  OnionImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet, March 26, 1986 2:35:33 pm PST Last Edited by: Serlet, July 6, 1985 12:58:24 pm PDT Last Edited by: Sindhu, July 7, 1985 1:40:04 am PDT This type is internally used by the implementation and so does not instear in the interface Returns the innerPos needed for centering the inner in the outer Extends the wires of obj to make an proper inner. The extension takes into account the layer of outside pins. newApclass.properties _ CDProperties.CopyProps[inst.properties]; -- drole de stuff on layer Now the contact(s)! -- innerPos is the location of the origin of inner in the coord system of outer Returns the position of the innerPin in the coordinate system of the interestRect of the outer Returns the position of the outerPin in the coordinate system of the interestRect of the outer Returns the bi-projection on the correct side of the innerPin in the coordinate system of the interestRect of the outer. Size of the pin is taken into account so that the pin always represent an extension in the direct rotation. Returns the bi-projection on the correct side of the outerPin in the coordinate system of the interestRect of the outer. Size of the pin is taken into account so that the pin always represent an extension in the direct rotation. -- Procs for parsing the pins into nets -- Choice of possible nets Computation of the Arc of a Net -- Computation of the evaluation function of a Net, i.e. LAST[INT]/2+Length if there is an innerPin roughly (less than design rules) 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 else. Length is OnionArc.Length[arc]+ Perimeter[Arc.rect]. We look if a different net is facing -- Given two pins, checks if they faces each other -- Given two pins, checks if they faces each other, taking into account design rules -- Generation of the geometry Same as PW.IncludeInCell, but takes into account the size of the object and the side in which they are inserted. Also converts position which is given in the outer cell coord system. Add a contact and a pin Draws wires in metal for inner pins, and if the pin belongs to the net, then add a contact, else add a pin. can we find the minimal size of a contact -- Emergency break -- Parsing all the pins to sort them by nets -- We delete all nets containing only 1 pin -- We compute the Arc necessited by the net for being routed 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. 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. -- We now generate geometry Finished: now we extend all the wires using the wireExtendProc And we position the inner cell -- We shrink the assignedArc.rect if some sides are unused -- We position the inner cell -- We place the sides of the routing (in metal2) -- We deposit contacts facing the outer pins which touch the routing ring. By the way we print the names of non-chosen nets -- We deposit wires in metal for inner pins and if the pin belongs to the net, then add a contact, else add a pin. -- We reposition and include in the design Κ)˜– "Cedar" stylešœ™Jšœ Οmœ1™šžœžœž˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšžœžœ˜J˜——J˜Jšœ[™[JšŸœžœžœ ˜šœžœžœ˜Jšœžœžœ ‘˜:Jšœžœ‘˜2Jšœ žœ‘˜3Jš œžœžœžœ žœ‘˜CJ˜—J˜š£œžœžœžœ˜DJšœžœ˜Jšœ(˜(Jš œžœžœžœžœžœ ˜1J˜—J˜š£œžœžœ˜;Jšœ#˜#J˜—J˜š£ œžœžœžœžœ žœžœžœžœ žœ˜§Jšœ žœy˜…Jšœ)˜)Jšœ+˜+J˜—J˜š£œžœžœžœ,žœžœ žœžœ˜‘Jšœ žœ0˜;Jšœ žœ‘ ˜0Jšœžœžœ‘ ˜/šžœžœžœž˜$šœžœ˜Jšœ˜šžœž˜Jšœ1˜1Jšœ>˜>Jšœ2˜2Jšœ<˜žœ˜[JšœM˜MJšžœ˜—Jšžœ˜—J™J™™>Jšžœžœžœ)˜JJšœ™Jšœžœ&˜-Jšžœžœžœžœ$˜MJšœ"žœ˜'Jšžœ˜"Jšœ˜—šžœ˜Jšœ:™:šžœ'žœ2žœžœO˜ΆJšœHžœ$˜p—Jš žœ'žœ2žœžœ™žœ$˜¨Jš žœ'žœ2žœžœ›žœ$˜ͺJš žœ'žœ2žœžœ•žœ$˜€Jšœ™šœ˜šžœ/˜1Jšœ ˜ Jšœ(˜(—Jšœ0˜0—Jšœ0™0Jšœ4˜4J™{Jšœ'˜'Jšœ.˜.Jšœ˜J™rJšœ/˜/Jšœ*™*Jšœx˜xJšœ"žœ˜'Jšžœ8˜>J˜—J˜—J˜š£œžœžœžœžœ?žœžœ˜¨Jšœ˜šžœž˜JšœI˜IJšžœ˜—Jšœ ˜ Jšœ˜—J˜J˜Jšžœ˜——…—]š„Ο