• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. how to use skill to do corner rounding for intersected ...

Stats

  • Locked Locked
  • Replies 5
  • Subscribers 144
  • Views 16729
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to use skill to do corner rounding for intersected paths

richardyuan
richardyuan over 11 years ago

I'm a skill-language beginner.

I created lots of poly lines using dbCreatePath. These lines intersected each other and forms right anlge or accute angle at the intersection.

I need to get corner rounding effect at the intersections. Can anybody help me? 

 

 

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 11 years ago

    Try this code as a starting point. The general algorithm that I used was:

    1. Classify paths as vertical or horizontal (the code only works for paths, and only single-segment paths; it's an exercise for you if you need it more general)
    2. Find the intersections of these two sets of paths
    3. Record all the vertices of the intersections
    4. Grow the intersections by twice the radius (to allow some margin and then AND with the original shapes to generate a cross polygon at each intersection.
    5. Modify all the corners that were identified in step 3 to be rounded (or chamfered)
    6. Optionally merge with the original shapes (or leave as additional shapes on top).

    Here's the code:

    /* CCFroundInternalCorners.il
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Nov 28, 2013 
    Modified   
    By         
    
    Example of rounding corners at intersections in a lattice structure.
    
    Can be used this way:
    
    shapes=CCFbuildStripes(?layer "Metal2" ?width 0.3 ?spacing 1.0 ?rows 5 ?columns 5)
    
    CCFroundInternalCorners(?shapes shapes ?distance 0.1)
    
    or:
    
    CCFroundInternalCorners(?shapes shapes ?distance 0.1 ?merge t)
    
    ***************************************************
    
    SCCS Info: @(#) CCFroundInternalCorners.il 11/28/13.13:09:05 1.1
    
    */
    
    /************************************************************************
    *                                                                       *
    *      CCFbuildStripes([?cv geGetEditCellView()] [?layer "Metal1"]      *
    *          [?width 0.2] [?spacing 1.5] [?rows 5] [?columns 4])          *
    *                                                                       *
    *    Function to build some test data for the function below. Allows    *
    * control over the layer used and width and spacing and number of paths *
    *                            in the lattice.                            *
    *                                                                       *
    ************************************************************************/
    
    procedure(CCFbuildStripes(@key (cv geGetEditCellView()) (layer "Metal1") 
            (width 0.2) (spacing 1.5) (rows 5) (columns 4))
        let((horizLength vertLength shapes ord)
            horizLength=(width+spacing)*columns+spacing
            vertLength=(width+spacing)*rows+spacing
            for(n 0 rows-1
                ord=(width+spacing)*n+width/2.0+spacing
                shapes=cons(dbCreatePath(cv layer list(0:ord horizLength:ord) width) shapes)
            )
            for(n 0 columns-1
                ord=(width+spacing)*n+width/2.0+spacing
                shapes=cons(dbCreatePath(cv layer list(ord:0 ord:vertLength) width) shapes)
            )
            shapes
        )
    )
    
    /***********************************************************************************
    *                                                                                  *
    * CCFroundInternalCorners([?shapes geGetSelSet()] [?tempLayer "y1"] [?chamfer nil] *
    *       [?distance 0.05] [?sides 20] [?outputLayer layerName] [?merge nil])        *
    *                                                                                  *
    *  Takes a bunch of horizontal and vertical paths, and then adds rounded corners   *
    *   at the intersections. Keyword arguments are added to allow control over the    *
    * list of shapes to work on (defaults to the selected set), whether to chamfer or  *
    *   round (default) the corners. The radius used for rounding or chamfering, how   *
    *   many sides to use in rounded corners. It also allows the output layer to be    *
    *    chosen (defaults to the layer of the first shape). By default the rounded     *
    *   crossovers are produced in addition, but with ?merge t it can merge all the    *
    *                                 shapes together.                                 *
    *                                                                                  *
    ***********************************************************************************/
    
    procedure(CCFroundInternalCorners(@key (shapes geGetSelSet()) (tempLayer "y1") chamfer 
            (distance 0.05) (sides 20) outputLayer merge)
        let((cv horizontal vertical vertexTable intersections points 
                grown crosses selVertexList new)
            unless(shapes error("No shapes provided\n"))
            unless(outputLayer outputLayer=car(shapes)~>layerName)
            cv=car(shapes)~>cellView
            ;----------------------------------------------------------------
            ; Split the shapes into horizontal and vertical paths
            ; (rather simplistic and with no error checking!)
            ;----------------------------------------------------------------
            foreach(shape shapes
                if(shape~>objType=="path" && shape~>nPoints==2 && 
                    xCoord(car(shape~>points))==xCoord(cadr(shape~>points)) then
                    vertical=cons(shape vertical)
                else
                    horizontal=cons(shape horizontal)
                )
            )
            ;----------------------------------------------------------------
            ; By anding the horizontal and vertical, can find the intersections.
            ; Record the coordinates of all the intersection shapes for later use
            ;----------------------------------------------------------------
            intersections=dbLayerAnd(cv tempLayer vertical horizontal)
            vertexTable=makeTable('vertexTable nil)
            foreach(shape intersections
                points=
                    if(shape~>objType=="rect" then
                        ; this is in IC615 onwards
                        destructuringBind(((llx lly) (urx ury)) shape~>bBox list(llx:lly llx:ury urx:ury urx:lly))
                    else
                        shape~>points
                    )
                foreach(point points
                    vertexTable[point]=t
                )
            )
            ;----------------------------------------------------------------
            ; originally tried merging all the layers and then using leModifyCorner - but the
            ; problem was that the "holes" in the lattice structure meant that some of the
            ; dividing lines meant that the modified corners ended up being rounded in the wrong
            ; direction, and some got omitted altogether. So instead, generate "crosses" by
            ; anding the grown intersections with the original shapes
            ;----------------------------------------------------------------
            grown=dbLayerSize(cv tempLayer intersections distance*2)
            crosses=dbLayerAnd(cv outputLayer grown shapes)
            foreach(shape intersections
                dbDeleteObject(shape)
            )
            foreach(shape grown
                dbDeleteObject(shape)
            )
            ;----------------------------------------------------------------
            ; Now modify the corners for the corners which we identified as "internal"
            ; corners in the lattice
            ;----------------------------------------------------------------
            foreach(shape crosses
                selVertexList=foreach(mapcar point shape~>points
                    vertexTable[point]
                )
                leModifyCorner(shape selVertexList chamfer distance sides)
            )
            ;----------------------------------------------------------------
            ; Optionally merge the shapes. Always return the generated objects
            ; though
            ;----------------------------------------------------------------
            if(merge then
                new=dbLayerOr(cv outputLayer shapes crosses)
                foreach(shape shapes
                    dbDeleteObject(shape)
                )
                foreach(shape crosses
                    dbDeleteObject(shape)
                )
                new
            else
                crosses
            )
        )
    )

     

    The picture below is the result of doing:

    shapes=CCFbuildStripes(?layer "Metal2" ?width 0.3 ?spacing 1.0 ?rows 5 ?columns 5)
    CCFroundInternalCorners(?shapes shapes ?distance 0.1 ?outputLayer "Metal3")

    I zoomed in to show the rounding, and intentionally output the cross-shapes on a different layer to make them stand out; most likely you'd omit the ?outputLayer argument, and possibly pass ?merge t instead.

    Kind Regards,

    Andrew.

     

    • crossover.png
    • View
    • Hide
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 11 years ago

    Try this code as a starting point. The general algorithm that I used was:

    1. Classify paths as vertical or horizontal (the code only works for paths, and only single-segment paths; it's an exercise for you if you need it more general)
    2. Find the intersections of these two sets of paths
    3. Record all the vertices of the intersections
    4. Grow the intersections by twice the radius (to allow some margin and then AND with the original shapes to generate a cross polygon at each intersection.
    5. Modify all the corners that were identified in step 3 to be rounded (or chamfered)
    6. Optionally merge with the original shapes (or leave as additional shapes on top).

    Here's the code:

    /* CCFroundInternalCorners.il
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Nov 28, 2013 
    Modified   
    By         
    
    Example of rounding corners at intersections in a lattice structure.
    
    Can be used this way:
    
    shapes=CCFbuildStripes(?layer "Metal2" ?width 0.3 ?spacing 1.0 ?rows 5 ?columns 5)
    
    CCFroundInternalCorners(?shapes shapes ?distance 0.1)
    
    or:
    
    CCFroundInternalCorners(?shapes shapes ?distance 0.1 ?merge t)
    
    ***************************************************
    
    SCCS Info: @(#) CCFroundInternalCorners.il 11/28/13.13:09:05 1.1
    
    */
    
    /************************************************************************
    *                                                                       *
    *      CCFbuildStripes([?cv geGetEditCellView()] [?layer "Metal1"]      *
    *          [?width 0.2] [?spacing 1.5] [?rows 5] [?columns 4])          *
    *                                                                       *
    *    Function to build some test data for the function below. Allows    *
    * control over the layer used and width and spacing and number of paths *
    *                            in the lattice.                            *
    *                                                                       *
    ************************************************************************/
    
    procedure(CCFbuildStripes(@key (cv geGetEditCellView()) (layer "Metal1") 
            (width 0.2) (spacing 1.5) (rows 5) (columns 4))
        let((horizLength vertLength shapes ord)
            horizLength=(width+spacing)*columns+spacing
            vertLength=(width+spacing)*rows+spacing
            for(n 0 rows-1
                ord=(width+spacing)*n+width/2.0+spacing
                shapes=cons(dbCreatePath(cv layer list(0:ord horizLength:ord) width) shapes)
            )
            for(n 0 columns-1
                ord=(width+spacing)*n+width/2.0+spacing
                shapes=cons(dbCreatePath(cv layer list(ord:0 ord:vertLength) width) shapes)
            )
            shapes
        )
    )
    
    /***********************************************************************************
    *                                                                                  *
    * CCFroundInternalCorners([?shapes geGetSelSet()] [?tempLayer "y1"] [?chamfer nil] *
    *       [?distance 0.05] [?sides 20] [?outputLayer layerName] [?merge nil])        *
    *                                                                                  *
    *  Takes a bunch of horizontal and vertical paths, and then adds rounded corners   *
    *   at the intersections. Keyword arguments are added to allow control over the    *
    * list of shapes to work on (defaults to the selected set), whether to chamfer or  *
    *   round (default) the corners. The radius used for rounding or chamfering, how   *
    *   many sides to use in rounded corners. It also allows the output layer to be    *
    *    chosen (defaults to the layer of the first shape). By default the rounded     *
    *   crossovers are produced in addition, but with ?merge t it can merge all the    *
    *                                 shapes together.                                 *
    *                                                                                  *
    ***********************************************************************************/
    
    procedure(CCFroundInternalCorners(@key (shapes geGetSelSet()) (tempLayer "y1") chamfer 
            (distance 0.05) (sides 20) outputLayer merge)
        let((cv horizontal vertical vertexTable intersections points 
                grown crosses selVertexList new)
            unless(shapes error("No shapes provided\n"))
            unless(outputLayer outputLayer=car(shapes)~>layerName)
            cv=car(shapes)~>cellView
            ;----------------------------------------------------------------
            ; Split the shapes into horizontal and vertical paths
            ; (rather simplistic and with no error checking!)
            ;----------------------------------------------------------------
            foreach(shape shapes
                if(shape~>objType=="path" && shape~>nPoints==2 && 
                    xCoord(car(shape~>points))==xCoord(cadr(shape~>points)) then
                    vertical=cons(shape vertical)
                else
                    horizontal=cons(shape horizontal)
                )
            )
            ;----------------------------------------------------------------
            ; By anding the horizontal and vertical, can find the intersections.
            ; Record the coordinates of all the intersection shapes for later use
            ;----------------------------------------------------------------
            intersections=dbLayerAnd(cv tempLayer vertical horizontal)
            vertexTable=makeTable('vertexTable nil)
            foreach(shape intersections
                points=
                    if(shape~>objType=="rect" then
                        ; this is in IC615 onwards
                        destructuringBind(((llx lly) (urx ury)) shape~>bBox list(llx:lly llx:ury urx:ury urx:lly))
                    else
                        shape~>points
                    )
                foreach(point points
                    vertexTable[point]=t
                )
            )
            ;----------------------------------------------------------------
            ; originally tried merging all the layers and then using leModifyCorner - but the
            ; problem was that the "holes" in the lattice structure meant that some of the
            ; dividing lines meant that the modified corners ended up being rounded in the wrong
            ; direction, and some got omitted altogether. So instead, generate "crosses" by
            ; anding the grown intersections with the original shapes
            ;----------------------------------------------------------------
            grown=dbLayerSize(cv tempLayer intersections distance*2)
            crosses=dbLayerAnd(cv outputLayer grown shapes)
            foreach(shape intersections
                dbDeleteObject(shape)
            )
            foreach(shape grown
                dbDeleteObject(shape)
            )
            ;----------------------------------------------------------------
            ; Now modify the corners for the corners which we identified as "internal"
            ; corners in the lattice
            ;----------------------------------------------------------------
            foreach(shape crosses
                selVertexList=foreach(mapcar point shape~>points
                    vertexTable[point]
                )
                leModifyCorner(shape selVertexList chamfer distance sides)
            )
            ;----------------------------------------------------------------
            ; Optionally merge the shapes. Always return the generated objects
            ; though
            ;----------------------------------------------------------------
            if(merge then
                new=dbLayerOr(cv outputLayer shapes crosses)
                foreach(shape shapes
                    dbDeleteObject(shape)
                )
                foreach(shape crosses
                    dbDeleteObject(shape)
                )
                new
            else
                crosses
            )
        )
    )

     

    The picture below is the result of doing:

    shapes=CCFbuildStripes(?layer "Metal2" ?width 0.3 ?spacing 1.0 ?rows 5 ?columns 5)
    CCFroundInternalCorners(?shapes shapes ?distance 0.1 ?outputLayer "Metal3")

    I zoomed in to show the rounding, and intentionally output the cross-shapes on a different layer to make them stand out; most likely you'd omit the ?outputLayer argument, and possibly pass ?merge t instead.

    Kind Regards,

    Andrew.

     

    • crossover.png
    • View
    • Hide
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
No Data

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information