<> <> <> <> <> DIRECTORY Basics, CD, CDBasics, CDCells, CDRects, DABasics, D2Orient, Real, RefTab, Rope, Route, RoutePrivate, RouteChannel, RouteTechnology, RouteUtil, RTBasic; RouteUtilImpl: CEDAR PROGRAM IMPORTS Basics, CDBasics, CDCells, CDRects, Real, RefTab, Route, RouteTechnology, RouteUtil, RTBasic EXPORTS RouteUtil = BEGIN <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> RoutingLayerName: PUBLIC ARRAY RoutePrivate.RoutingLayerOrNone OF Rope.ROPE _ ["trunk", "branch", "none"]; <> <> <<>> <> <<};>> <<>> <> <> <<>> <> <> <> < RETURN[[pqPos.p, pqPos.q]];>> < RETURN[[pqPos.q, pqPos.p]];>> <> <> <<>> CompareResult: PUBLIC PROC [result1, result2: Route.ResultData] RETURNS [result: Basics.Comparison] = { result _ Basics.CompareInt[result1.numIncompletes, result2.numIncompletes]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.numTrunkTracks, result2.numTrunkTracks]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.polyLength, result2.polyLength]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.polyToMetal, result2.polyToMetal]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.metalToMetal2, result2.metalToMetal2]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.metalLength, result2.metalLength]; IF result # equal THEN RETURN; result _ Basics.CompareInt[result1.metal2Length, result2.metal2Length]; }; -- CompareResult Include: PUBLIC PROC [cell: CD.Object_NIL, ob: CD.Object, position: CD.Position_[0, 0], orientation: D2Orient.Orientation_original] RETURNS [application: CD.Instance] = { <> application _ CDCells.IncludeOb[design: NIL, cell: cell, ob: ob, trans: [off: position, orient: orientation], mode: dontResize].newInst}; GetVia: PUBLIC PROC [size: DABasics.Position, layer1, layer2: CD.Layer, cdLambda: DABasics.Number] RETURNS [cell: CD.Object _ NIL] = { <> <> minBigContact: CD.Object _ RouteTechnology.GetBigContact[[1, 1], layer1, layer2]; IF minBigContact = NIL THEN <> cell _ RouteTechnology.GetContact[layer1, layer2] ELSE { -- big contact exists, determine size to use contactSize: CD.Position _ CDBasics.SizeOfRect[minBigContact.bbox]; IF contactSize.x <= size.x AND contactSize.y <= size.y THEN { <> perim2x2: DABasics.Number _ Real.Round[size.x/(6*cdLambda)]*Real.Round[size.y/(6*cdLambda)]*8*cdLambda; -- 2x2 contacts go in a 6x6 square perim3x3: DABasics.Number _ Real.Round[size.x/(7*cdLambda)]*Real.Round[size.y/(7*cdLambda)]*12*cdLambda; -- 3x3 contacts go in a 7x7 square perim4x4: DABasics.Number _ Real.Round[size.x/(8*cdLambda)]*Real.Round[size.y/(8*cdLambda)]*16*cdLambda; -- 4x4 contacts go in a 8x8 square SELECT TRUE FROM perim4x4 >= perim2x2 AND perim4x4 >= perim3x3 => cell _ RouteTechnology.GetBigContact[[8*cdLambda, 8*cdLambda], layer1, layer2]; perim3x3 >= perim2x2 AND perim3x3 >= perim4x4 => cell _ RouteTechnology.GetBigContact[[7*cdLambda, 7*cdLambda], layer1, layer2]; perim2x2 >= perim4x4 AND perim2x2 >= perim3x3 => cell _ RouteTechnology.GetBigContact[[6*cdLambda, 6*cdLambda], layer1, layer2]; ENDCASE} ELSE -- big contact too big, must do it with small ones cell _ RouteTechnology.GetContact[layer1, layer2] }}; StitchVias: PUBLIC PROC [size: DABasics.Position, layer1, layer2: CD.Layer, cdLambda: DABasics.Number, viaTable: RefTab.Ref] RETURNS [obj: CD.Object] = { contact: CD.Object _ GetVia[size, layer1, layer2, cdLambda]; contactSize: CD.Position _ CDBasics.SizeOfRect[contact.bbox]; minSize: DABasics.Number _ 6*cdLambda; -- technology dependent!!! this needs to be fixed val: RefTab.Val _ IF viaTable = NIL THEN NIL ELSE RefTab.Fetch[viaTable, NEW[DABasics.Position _ size]].val; IF val # NIL THEN obj _ NARROW[val] ELSE IF contactSize.x >= size.x AND contactSize.y >= size.y THEN obj _ contact -- special case for performance ELSE { sizeX: DABasics.Number _ MAX[contactSize.x, minSize]; sizeY: DABasics.Number _ MAX[contactSize.y, minSize]; numYInts: DABasics.Number _ MAX[1, size.y/sizeY]; lastYLoc: DABasics.Number _ 0; lastXLoc: DABasics.Number; cover: DABasics.Position; obj _ CDCells.CreateEmptyCell[]; FOR index: DABasics.Number IN [1 .. numYInts] DO numXInts: DABasics.Number _ MAX[1, size.x/sizeX]; lastXLoc _ 0; FOR index: DABasics.Number IN [1 .. numXInts] DO [] _ RouteUtil.Include[obj, contact, [lastXLoc, lastYLoc]]; lastXLoc _ lastXLoc + sizeX; ENDLOOP; lastYLoc _ lastYLoc + sizeY; ENDLOOP; cover _ [lastXLoc - sizeX + contactSize.x, lastYLoc - sizeY + contactSize.y]; [] _ RouteUtil.Include[obj, CDRects.CreateRect[cover, layer1]]; [] _ RouteUtil.Include[obj, CDRects.CreateRect[cover, layer2]]; RTBasic.RepositionCell[obj]}}; LineToRect: PUBLIC PROC [pos1, pos2: DABasics.Position, width: DABasics.Number] RETURNS [position: CD.Position, size: CD.Position] = { <> SELECT TRUE FROM pos1.x = pos2.x => { -- line is vertical size _ [width, ABS[pos1.y - pos2.y]]; position _ [pos1.x - width/2, MIN[pos1.y, pos2.y]]}; pos1.y = pos2.y => { -- line is horizontal size _ [ABS[pos1.x - pos2.x], width]; position _ [MIN[pos1.x, pos2.x], pos1.y - width/2]}; ENDCASE => Route.Error[programmingError, "Diagional lines not allowed."]}; END.