• 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. Need to reduce the height of a particular text layer inside...

Stats

  • Locked Locked
  • Replies 7
  • Subscribers 144
  • Views 15085
  • 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

Need to reduce the height of a particular text layer inside all layout views of a standard cell library

dwheeler
dwheeler over 5 years ago

I am using a std_cell library from Global Foundries for which all cells have text [on the ALPHA audit LPP] with a height of "1" [which extends far, far beyond the meaningful data extent].  This makes viewing/editing block layouts difficult, especially when trying to select a particular cell with so many overlapping data extents.

I'd like a skill script that would go [recursively] inside each std_cell layout of the library and reduce the height of this particular text layer from 1 to say, .01, or .001

Seems simple enough for a skill script, if so, please advise.

  • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago

    Not sure if you really meant to do this recursively, but if you wanted to do this for every cell in the library, something like this will do (no need for it to be recursive then):

    procedure(CCFfixText(libName layerName purpose newHeight @optional (saveAndClose t))
      let((lib master cv textLPP)
        lib=ddGetObj(libName)
        foreach(cell lib~>cells
          foreach(view cell~>views
            ; Check if the view is a layout viewType
            master=ddGetObj(libName cell~>name view~>name "*")
            when(master && ddMapGetFileViewType(master)=="maskLayout"
              printf("Updating %s %s %s\n" libName cell~>name view~>name)
              cv=dbOpenCellViewByType(libName cell~>name view~>name "" "a")
              ; find the layer purpose in this view and then fix
              ; the height of any labels
              textLPP=car(exists(lpp cv~>lpps lpp~>layerName==layerName && lpp~>purpose==purpose))
              foreach(shape textLPP~>shapes
                when(shape~>objType=="label"
                  shape~>height=newHeight
                )
              )
              when(saveAndClose
                dbSave(cv)
                dbClose(cv)
              )
            )
          )
        )
        t
      )
    )
    
    

    To use it, you'd then do:

    CCFfixText("std_cell" "ALPHA" "audit" 0.01)

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Sheppie
    Sheppie over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    You're using a combination of car() and exists() to test the existence of the specified layer in the layout.

    To me, this looks a bit complicated, it is possible to just use a when() and member() combination. Something like:

    lppList = list( '("ME1" "drawing") '("text" "drawing") '("ME2" "drawing") )
    (("ME1" "drawing")
        ("text" "drawing")
        ("ME2" "drawing")
    )
    lpp_lay = "text"
    "text"
    lpp_pur = "drawing"
    "drawing"
    when( member( list(lpp_lay "text") lppList ) printf("found\n") )
    nil
    when( member( list(lpp_lay lpp_pur) lppList ) printf("found\n") )
    found
    t

    Is there a particular reason why you use the car() and exists() combination?

    Thanks in advance.

    Sjoerd

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Sheppie

    Hi Sjoerd,

    I'm not just determining whether a specified layer purpose is present or not; I'm finding the layer-purpose object so that I can then find just the shapes on that LPP. The assumption is that you might have an enormous number of shapes in the layout, but relatively few on a specific layer, and so searching to find the layer-purpose object and then narrowing down the shapes on that LPP is more efficient than searching through every shape in the cellView which might be a label and on that LPP.

    The exists function (like member) returns the remainder of the list of LPP objects in the cellView (so it's not a list of sub-lists containing the layerName and purposeName), and will find the remainder from the point of the first match (there will only be one match since I'm checking the layer name and purpose name on that object); since I'm only interested in the first, I'm using the car.

    So I can't use the approach you suggest, because that wouldn't work...

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • dwheeler
    dwheeler over 5 years ago in reply to Andrew Beckett

    Thanks, Andrew-

      This is just what I needed. Thanks again!

    Cheers!

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Sheppie
    Sheppie over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    Sorry, I should have elaborated the example code a bit more. This is what I meant:

    ;;; first find out whether or not the lpp is used in the layout...
    when( member( list( layerName purpose ) cv~>lpps )
      ;;; Now go through all shapes that are labels and are in the right layer and purpose...
      foreach( shape setof(shapes cv~>shapes and( shapes~>objType == "label" shapes~>layerName == layerName shapes~>purpose == purpose )
        ;;; Adjust the height...
        shape~>height = newHeight
      ) ;;; end of foreach shape
    ) ;;; end of when

    Or is your solution quicker or "easier on the memory" than my solution?

    Thanks.

    Sjoerd

    ps: haven't tested the code, more an indication of how I would do it...

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Sheppie

    Hi Sjoerd,

    Other than the code not working because cv~>lpps is a list of dbObjects not a list of lists (of layer and purpose names), the pattern of first finding a list of all shapes which match the given layerName and purpose and objType will be slower and more memory consuming, unless there are a very small number of shapes in the cellView (even then I suspect it would not be quicker).

    The reasons are:

    1. Doing cv~>shapes has to build a list of objects for every shape in the design (whilst the database has all these shapes, the list construction takes time and memory)
    2. You then have to visit every single shape and then construct a new list (the setof) with just those which are labels on the right layer purpose
    3. Then you foreach over that reduced list (it would have been better to just do a foreach over all shapes and then have a when() instead of the setof to do something when the condition matched

    In my case, I traverse the layer-purpose objects (of which there are typically relatively few), and I only search until I find a match (so that means on average half the LPP objects). From there I directly get just the shapes that are on that layer-purpose pair - I don't need to visit all the shapes on layer-purposes that I don't care about - so no big list was generated with lots of things in it that don't matter.

    So my approach would be generally faster, take less memory, and produce less garbage to be collected. I think the code is actually simpler too!

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Sheppie
    Sheppie over 5 years ago in reply to Andrew Beckett

    Thanks Andrew,

    I understand your reasoning. I'm in the middle of writing code to the migration of a full chip design from one foundry to an other, and things like this will happen a lot in the code I'm writing. So thank you for taking the time to explain to me why you do what you do.

    Kind regards,

    Sjoerd

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

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