DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDOrient, CDPinObjects, CDProperties, CDRects, CDSimpleRules, CMos, Core, CoreOps, IO, Onion, OnionArc, PW, PWCore, PWPins, RefTab, Rope, TerminalIO; OnionImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDOrient, CDPinObjects, CDProperties, CDRects, CDSimpleRules, CMos, CoreOps, IO, OnionArc, PW, PWCore, PWPins, RefTab, Rope, TerminalIO EXPORTS Onion = BEGIN OPEN Onion; defaultLayersParameters: PUBLIC LayersParameters = NEW [LayersParametersRec _ [ radialLayer: CMos.met, ringLayer: CMos.met2, ringWidth: RingWidthIs8, wireExtendProc: WireExtendMetToMet ]]; channelDefaultParameters: PUBLIC LayersParameters = NEW [LayersParametersRec _ [ radialLayer: CMos.met, ringLayer: CMos.met2, ringWidth: RingWidthIs8, wireExtendProc: WireExtendMetToMet ]]; WireExtendMetToMet: PUBLIC WireExtendProc = { wire _ CDRects.CreateRect[[length, width], CMos.met]; }; WireExtendPolToMetForPads: PUBLIC WireExtendProc = { nb: INT _ MAX[8, width]; -- for computing how many! wire _ CDCells.CreateEmptyCell[]; [] _ PW.IncludeInCell[wire, CDRects.CreateRect[[length-14, width], CMos.met], [0, 0]]; FOR i: INT IN [0 .. nb/8) DO [] _ PW.IncludeInCell[wire, CDSimpleRules.Contact[CMos.pol, CMos.met], [length-14, 8*i]] ENDLOOP; [] _ PW.IncludeInCell[wire, CDRects.CreateRect[[6, width], CMos.pol], [length-6, 0]]; CDCells.SetInterestRect[wire, [0, 0, length, width]]; [] _ CDCells.RepositionCell[wire, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, wire, "WireExtendPolToMetForPads"]; }; RingWidthIs8: PUBLIC RingWidthProc = {ringWidth _ 8}; Arc: TYPE = OnionArc.Arc; RotateSide: PROC [side: Side] RETURNS [Side] = { RETURN [SELECT side FROM bottom => right, right => top, top => left, left => bottom, ENDCASE => ERROR]; }; Net: TYPE = REF NetRec; NetRec: TYPE = RECORD [ name: ROPE _ NIL, -- name of the net. Unicity not guaranteed 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: RefTab.Ref, wire: Wire] RETURNS [net: Net] = { found: BOOL; val: RefTab.Val; [found, val] _ RefTab.Fetch[nets, wire]; net _ IF found THEN NARROW [val] ELSE NEW [NetRec]; }; IncludePin: PUBLIC PROC [cell: CD.Object, wire: Wire, layer: CD.Layer, size, position: CD.Position, orientation: CD.Orientation _ 0] RETURNS [newInst: CD.Instance] = { nets: RefTab.Ref _ NARROW [CDProperties.GetPropFromObject[cell, PWCore.netsProp]]; pins: LIST OF CD.Instance; newInst _ PW.IncludeInCell[cell: cell, obj: CDPinObjects.CreatePinOb[size], position: position, orientation: orientation].newInst; pins _ CONS [newInst, NARROW [RefTab.Fetch[nets, wire].val]]; [] _ RefTab.Store[nets, wire, pins]; CDPinObjects.SetLayer[newInst, layer]; CDPinObjects.SetName[newInst, CoreOps.GetShortWireName[wire]]; }; IncludeContact: PUBLIC PROC [cell: CD.Object, side: 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 [design: CD.Design, obj: CD.Object] RETURNS [inner: CD.Object] = { dist: INT _ 18; ---???? ExtendPinOnEdge: PWCore.EachNetProc = { FOR insts: LIST OF CD.Instance _ pins, insts.rest WHILE insts#NIL DO inst: CD.Instance _ insts.first; 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: Side _ PWPins.GetSide[obj, inst].side; newInst _ IncludePin[ inner, wire, CMos.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, CDPinObjects.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 CDPinObjects.GetLayer[inst] FROM CMos.met => {}; CMos.met2, CMos.pol => { IncludeContact[inner, side, CMos.met, CDPinObjects.GetLayer[inst], (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.WriteRopes["**** MakeInner: Layer unknown for extending pin ", CoreOps.GetShortWireName[wire], ". Extension WRONG!!!\n"]; ENDLOOP; }; inst: CD.Instance; inner _ CDCells.CreateEmptyCell[]; CDProperties.PutPropOnObject[inner, PWCore.netsProp, RefTab.Create[]]; inst _ PW.IncludeInCell[inner, obj]; CDProperties.PutPropOnInstance[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; [] _ PWCore.EnumerateNets[PWCore.FindNets[obj], ExtendPinOnEdge]; CDCells.SetInterestRect[inner, CDBasics.Extend[ CDBasics.RectAt[[0, 0], CDBasics.SizeOfRect[CD.InterestRect[obj]]], dist]]; [] _ CDCells.RepositionCell[inner, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, inner, Rope.Cat[CDDirectory.Name[obj], "@MadeInner"]]; }; LRSRouteOnce: PUBLIC PROC [design: CD.Design, 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: PWCore.EachNetProc = { net: Net _ FetchNet[nets, wire]; IF net.name=NIL THEN net.name _ CoreOps.GetShortWireName[wire]; FOR insts: LIST OF CD.Instance _ pins, insts.rest WHILE insts#NIL DO inst: CD.Instance _ insts.first; name: ROPE _ CDPinObjects.GetName[inst]; IF PWPins.GetSide[inner, inst]=none THEN ERROR; IF CDPinObjects.GetLayer[inst]#params.radialLayer THEN TerminalIO.WriteF["*** Inner Pin %g on net %g discarded: not of radialLayer material.\n", IO.rope[name], IO.rope[CoreOps.GetShortWireName[wire]]] ELSE net.innerPins _ CONS [inst, net.innerPins]; ENDLOOP; [] _ RefTab.Store[nets, wire, net]; }; AddOuterPinToNets: PWCore.EachNetProc = { net: Net _ FetchNet[nets, wire]; IF net.name=NIL THEN net.name _ CoreOps.GetShortWireName[wire]; FOR insts: LIST OF CD.Instance _ pins, insts.rest WHILE insts#NIL DO inst: CD.Instance _ insts.first; name: ROPE _ CDPinObjects.GetName[inst]; IF PWPins.GetSide[outer, inst]=none THEN ERROR; IF CDPinObjects.GetLayer[inst]#params.radialLayer THEN TerminalIO.WriteF["*** Outer Pin %g on net %g discarded: not of radialLayer material.\n", IO.rope[name], IO.rope[CoreOps.GetShortWireName[wire]]] ELSE net.outerPins _ CONS [inst, net.outerPins]; ENDLOOP; [] _ RefTab.Store[nets, wire, net]; }; ComputeArc: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; wire: Wire _ NARROW [key]; pitch: INT = MAX [contactWidth, params.ringWidth[wire]]+CDSimpleRules.MinDist[params.ringLayer, params.ringLayer]; quit _ FALSE; net.arc _ OnionArc.EmptyArc[CDBasics.Extend[innerRect, pitch]]; FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO side: 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: 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: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.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: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.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 RefTab.Pairs[nets, FindDifferentNetFacing] THEN {net.eval _ net.eval + LAST [INT] /2; RETURN}; ENDLOOP; }; Faces: PROC [innerPin, outerPin: CD.Instance] RETURNS [faces: BOOL] = { side: 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: 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: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL] -- = { net: Net _ NARROW [val]; wire: Wire _ NARROW [key]; 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[wire]#netRingWidth) THEN RETURN; minEval _ net.eval; minNet _ net; minKey _ wire; }; IncludeInCellSide: PROC [ob: CD.Object, side: 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 [wire: Wire, side: 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, wire, params.radialLayer, size, position]; }; IncludeContactSide: PROC [side: 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.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: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL] -- = { DrawOuterPin: PROC [inst: CD.Instance, wire: Wire] = { side: 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[wire, side, size, pos]; }; net: Net _ NARROW [val]; wire: Wire _ NARROW [key]; quit _ FALSE; IF ~net.chosen THEN {IF net.eval#LAST[INT] THEN TerminalIO.WriteRopes[net.name, " "]; RETURN}; FOR outerPins: LIST OF CD.Instance _ net.outerPins, outerPins.rest WHILE outerPins#NIL DO DrawOuterPin[outerPins.first, wire]; ENDLOOP; }; DepositInnerWiresEtAl: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL] -- = { DrawInnerPin: PROC [inst: CD.Instance, chosen: BOOL, wire: Wire] = { side: 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[wire, side, size, pos]; }; net: Net _ NARROW [val]; wire: Wire _ NARROW [key]; quit _ FALSE; FOR innerPins: LIST OF CD.Instance _ net.innerPins, innerPins.rest WHILE innerPins#NIL DO DrawInnerPin[innerPins.first, net.chosen, wire]; ENDLOOP; }; ExtendAllWires: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.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: 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[design, 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: RefTab.Ref _ RefTab.Create[]; minEval: INT; minNet: Net; minKey: Wire; -- for choosing the nets netRingWidth: INT _ 0; -- all nets on the same track have the same width cell _ CDCells.CreateEmptyCell[]; CDProperties.PutPropOnObject[cell, PWCore.netsProp, RefTab.Create[]]; IF CDSimpleRules.Contact[params.radialLayer, params.ringLayer]=NIL THEN { TerminalIO.WriteRope["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.WriteRope["**** Routing Impossible (Too big) ****\n**** Current state returned! ****\n"]; RETURN[inner, innerPos, impossible];}; [] _ PWCore.EnumerateNets[PWCore.FindNets[inner], AddInnerPinToNets]; [] _ PWCore.EnumerateNets[PWCore.FindNets[outer], AddOuterPinToNets]; BEGIN deletedNets: LIST OF Wire _ NIL; ToBeDeleted: RefTab.EachPairAction -- [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOL] -- = { wire: Wire _ NARROW [key]; 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 [wire, deletedNets]; }; [] _ RefTab.Pairs[nets, ToBeDeleted]; WHILE deletedNets#NIL DO TerminalIO.WriteRopes["*** Net: ", CoreOps.GetShortWireName[deletedNets.first], " has only 1 pin. Not routed\n"]; [] _ RefTab.Delete[nets, deletedNets.first]; deletedNets _ deletedNets.rest; ENDLOOP; END; [] _ RefTab.Pairs[nets, ComputeArc]; [] _ RefTab.Pairs[nets, ComputeEval]; TerminalIO.WriteRope["Allocating a new track\n"]; DO Count: PROC [pins: LIST OF CD.Instance] RETURNS [count: INT _ 0] = { WHILE pins#NIL DO count _ count+1; pins _ pins.rest ENDLOOP; }; minEval _ LAST [INT]; minNet _ NIL; [] _ RefTab.Pairs[nets, ChooseMinEval]; IF minEval=LAST [INT] THEN EXIT; IF minEval>=LAST [INT]/2 THEN TerminalIO.WriteRope["****** ROUTING IS WRONG: at least 2 different nets are facing each other. No cure possible until Dogleg is introduced in Onion!\n"]; IF assignedArc=NIL THEN netRingWidth _ params.ringWidth[minKey]; 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[minNet.name], IO.int[Count[minNet.innerPins]], IO.int[Count[minNet.outerPins]], IO.int[minNet.eval]]; ENDLOOP; IF assignedArc=NIL THEN { IF params.wireExtendProc#NIL THEN [] _ RefTab.Pairs[nets, ExtendAllWires]; [] _ PW.IncludeInCell[cell, inner, innerPos]; IF params.wireExtendProc#NIL THEN [] _ PW.IncludeInCell[cell, outer, [0, 0]]; [] _ CDCells.RepositionCell[cell, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, cell, "LastRoutingRing"]; 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.PutPropOnInstance[ PW.IncludeInCell[cell, inner, CDBasics.SubPoints[ CDBasics.BaseOfRect[innerRect], CDBasics.BaseOfRect[assignedArc.rect]]], $StopEnumerateDeepPins, $StopEnumerateDeepPins]; OnionArc.EnumerateSegBits[assignedArc, DrawRingBit]; TerminalIO.WriteRope["Non routed nets: "]; [] _ RefTab.Pairs[nets, DepositOuterContacts]; TerminalIO.WriteRope["\n"]; [] _ RefTab.Pairs[nets, DepositInnerWiresEtAl]; CDCells.SetInterestRect[cell, [0, 0, assignedArc.rect.x2-assignedArc.rect.x1, assignedArc.rect.y2-assignedArc.rect.y1]]; [] _ CDCells.RepositionCell[cell, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, cell, "RoutingRing-"]; RETURN[cell, CDBasics.BaseOfRect[assignedArc.rect], doneOnce]; }; }; LRSRoute: PUBLIC PROC [design: CD.Design, 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[design, inner, outer, innerPos, params]; ENDLOOP; cell _ inner; }; END. ”OnionImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet, November 14, 1985 6:45:33 pm PST Last Edited by: Sindhu, July 7, 1985 1:40:04 am PDT Barth, January 24, 1986 4:13:24 pm PST 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 SwitchBox: PUBLIC PROC [design: CD.Design, bottomOb, rightOb, topOb, leftOb: CD.Object, params: LayersParameters _ channelDefaultParameters] RETURNS [cell: CD.Object, status: Status] = { inner: CD.Object _ CDCells.CreateEmptyCell[]; outer: CD.Object _ CDCells.CreateEmptyCell[]; currentSide: Side; currentOb: CD.Object; size: CD.Position _ [ MAX[ CDBasics.SizeOfRect[CD.InterestRect[bottomOb]].x, CDBasics.SizeOfRect[CD.InterestRect[topOb]].x], MAX[ CDBasics.SizeOfRect[CD.InterestRect[rightOb]].y, CDBasics.SizeOfRect[CD.InterestRect[leftOb]].y]]; AddPin: PWPins.InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL _ FALSE] -- = { name: ROPE _ CDPinObjects.GetName[inst]; realSize: CD.Position _ CDOrient.OrientedSize[inst.ob.size, inst.orientation]; location: CD.Position _ CDBasics.SubPoints[inst.location, CDBasics.BaseOfRect[CD.InterestRect[currentOb]]]; IF PWPins.GetSide[currentOb, inst].side#RotateSide[RotateSide[currentSide]] THEN RETURN; IF CDPinObjects.GetLayer[inst]#params.radialLayer THEN { TerminalIO.WriteRope["*** Pin ", name, " discarded: not of radialLayer material.\n"] ; RETURN; }; [] _ IncludePin[outer, name, CDPinObjects.GetLayer[inst], realSize, SELECT currentSide FROM bottom => [location.x, 0], top => [location.x, size.y-realSize.y], left => [0, location.y], right => [size.x-realSize.x, location.y], ENDCASE => ERROR]; }; [] _ PW.IncludeInCell[inner, CDRects.CreateRect[[8, 8], params.ringLayer]]; [] _ CDCells.RepositionCell[inner, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, inner, "EmptyCellForHeartOfSwitchBox"]; currentSide _ bottom; currentOb _ bottomOb; [] _ PWPins.EnumerateEdgePins[currentOb, AddPin]; currentSide _ top; currentOb _ topOb; [] _ PWPins.EnumerateEdgePins[currentOb, AddPin]; currentSide _ left; currentOb _ leftOb; [] _ PWPins.EnumerateEdgePins[currentOb, AddPin]; currentSide _ right; currentOb _ rightOb; [] _ PWPins.EnumerateEdgePins[currentOb, AddPin]; CDCells.SetInterestRect[outer, [0, 0, size.x, size.y]]; [] _ CDCells.RepositionCell[outer, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, outer, "EmptyCellForSkinOfSwitchBox"]; [cell, status] _ LRSRoute[design, inner, outer, Center[inner, outer], params]; }; Channel: PUBLIC PROC [design: CD.Design, left, right: CD. Object, size: INT, params: LayersParameters _ channelDefaultParameters] RETURNS [cell: CD.Object, status: Status] = { top: CD.Object _ CDCells.CreateEmptyCell[]; [] _ PW.IncludeInCell[top, CDRects.CreateRect[[size, 8], params.ringLayer]]; [] _ CDCells.RepositionCell[top, NIL]; IF design#NIL THEN [] _ CDDirectory.Include[design, top, "EmptyTopForChannel"]; [cell, status] _ SwitchBox[design, top, right, top, left, params]; }; ΚΧ˜– "Cedar" stylešœ™Jšœ Οmœ1™˜>J˜—J˜š‘œžœžœžœ%žœžœ žœžœ˜šJšœ žœ0˜;Jšœ žœ  ˜0Jšœžœžœ  ˜/šžœžœžœž˜$šœžœ˜Jšœ˜šžœž˜Jšœ1˜1Jšœ>˜>Jšœ2˜2Jšœ<˜™>Jšžœžœžœ)˜JJšœ™Jšœžœ&˜-Jšžœžœžœžœ$˜MJšœ"žœ˜'Jšžœžœžœ;˜MJšžœ˜"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˜JJšžœ8˜>J˜—J˜—J˜š‘œžœžœ žœžœžœ?žœžœ˜»Jšœ˜šžœž˜JšœQ˜QJšžœ˜—Jšœ ˜ Jšœ˜—J˜š‘ œžœžœ žœ+žœ>žœžœ™ΊJšœžœ$™-Jšœžœ$™-Jšœžœ™(–? -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- šœžœ ™šžœ™Jšœžœ™2Jšœžœ™/—šžœ™Jšœžœ™1Jšœžœ™1——J™šŸœ 6œ™\Jšœžœ™(Jšœ žœC™OJšœ žœBžœ™kJ–*[ob: CD.ObPtr, pin: CD.ApplicationPtr]šžœJžœžœ™Xšžœ0žœ™8JšœV™VJšžœ™J™—šœDžœ ž™[Jšœ™Jšœ(™(Jšœ™Jšœ*™*Jšžœžœ™—J™—JšœžœD™KJšœ#žœ™(JšžœžœžœI™[J™šœ,™,Jšœ1™1—šœ&™&Jšœ1™1—šœ(™(Jšœ1™1—šœ*™*Jšœ1™1—J™Jšœ7™7Jšœ#žœ™(JšžœžœžœH™ZJ™JšœN™NJ™—J˜š‘œžœžœ žœžœžœ7žœžœ™―Jšœžœ$™+JšœžœE™LJšœ!žœ™&Jšžœžœžœ=™OJšœB™BJ™—J˜Jšžœ˜——…—aΪ—E