• 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 Design
  3. metal (or any dummy fill layer) skill code that can run...

Stats

  • Replies 9
  • Subscribers 126
  • Views 1199
  • Members are here 0

metal (or any dummy fill layer) skill code that can run at the block or chip level and automatically fill dummy metal in vacant spaces.

yogeshjaiswalCAD
yogeshjaiswalCAD 20 days ago

Greetings Team,

I am grateful for your assistance whenever I am in need. I am working on TSMC 20nm with the IC 23.1 tool.

I need a metal (or any dummy fill layer) skill code that can run at the block or chip level and automatically fill dummy metal in vacant spaces.

Our form is the greatest spot for all experienced people.  Here is my code 

 In SKILL, we can check for empty space using dbFindAny or dbIntersect before creating a rectangle. This way, dummy metal is only added where nothing exists. Here's an updated, safe version of your metal fill procedure:

SKILL script: autoMetalFill.il

procedure(YOGI_metalFill(layerName fillSize spaceSize)
let((cv bBox xMin yMin xMax yMax x y fillWidth fillHeight space metalLayer)

;; Get active layout
cv = geGetEditCellView()
unless(cv
warn("No active layout window. Open a layout first!\n")
return()
)

;; Get layout bounding box
bBox = geGetBBox(cv) ;; replace with correct bbox function if needed
xMin = car(bBox)
yMin = cadr(bBox)
xMax = caddr(bBox)
yMax = cadddr(bBox)

fillWidth = car(fillSize)
fillHeight = cadr(fillSize)
space = spaceSize
metalLayer = list(layerName "drawing")

y = yMin
while(< y yMax)
progn
x = xMin
while(< x xMax)
progn
;; Check if the area is empty before creating rect
unless(dbFindAny(cv metalLayer (list (list x y) (list (+ x fillWidth) (+ y fillHeight))))
dbCreateRect(cv metalLayer (list (list x y) (list (+ x fillWidth) (+ y fillHeight))))
)
x = (+ x fillWidth space)
y = (+ y fillHeight space)
)
)

Since a tool-driven method is not ideal for addressing density concerns, kindly share any skill codes you may have.

I will be grateful for your help. Please help in!

 

With warm regards,

Yogesh Jaiswal

  • Cancel
  • Sign in to reply
  • Andrew Beckett
    Andrew Beckett 20 days ago

    Yogesh,

    I see you updated the post above with an additional comment talking about dbFindAny or dbIntersect. I'm assuming this came out of ChatGPT or a similar LLM because these are invented functions that don't exist, and it also has progn appearing in strange places what aren't function calls. 

    My question would be why you would do this with SKILL? It's generally something that would be done with a physical verification tool such as Pegasus, and foundries provide rule decks for doing dummy fill. Doing this with a physical verification engine will be efficient and naturally handle hierarchical designs.

    It can also be done in-design with iPegasus too.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • yogeshjaiswalCAD
    yogeshjaiswalCAD 20 days ago in reply to Andrew Beckett

    Thanks Andrew,

    I understand your views; however, if you can debug the code above, it will solve my purpose. It would be kind of you to provide clean code for it. Once again thanks for warm gesture

    I will wait for your response. Have a pleasant day!

    Cheers & regards,

    Yogesh Jaiswal 

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 20 days ago in reply to yogeshjaiswalCAD
    yogeshjaiswalCAD said:
    I understand your views; however, if you can debug the code above, it will solve my purpose. It would be kind of you to provide clean code for it. Once again thanks for warm gesture

    I'm afraid I'm not going to debug code written by an LLM. Writing a proper dummy fill algorithm is far more complex than the framework you've got above, and writing something to do this when there are existing tools to do this job is not a good use of my time (given that this is done in my spare time, but even if it was my work time it wouldn't be a good use of that time).

    To spend 2 minutes listing what's wrong with the code above before even getting to the algorithm itself:

    1. There is no such function geGetBBox
    2. If there was, it wouldn't return the extent in a list (llx lly urx ury) which is what the code assumes with the car/cadr/caddr part
    3. while(< y yMax) is not valid syntax
    4. progn on its own makes no sense
    5. dbFindAny is not a valid function

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • yogeshjaiswalCAD
    yogeshjaiswalCAD 20 days ago in reply to Andrew Beckett

    Thanks Andew,

    I have sample code which needs correction. Please help in !

    ;=============================================================
    ; Density-Driven Metal Fill Script for Virtuoso IC23
    ;=============================================================

    (procedure (metalFillDensity layer targetDensity / sel bbox ll ur width spacing areaX areaY stepX stepY x y rectArea totalArea fillArea actualDensity)
    ;; layer: metal layer name as string, e.g., "M1"
    ;; targetDensity: fraction (0.3 = 30%) desired metal density

    ;; Get currently selected objects
    sel = geGetSel()
    unless(sel
    error("No objects selected. Please select the area to fill.")
    )

    ;; Get bounding box of selection
    bbox = dbGetBBox(car(sel)) ; bbox = ((llx lly) (urx ury))
    ll = car bbox
    ur = cadr bbox

    ;; Get tech DRC rules
    width = techGetProp(layer 'MINWIDTH)
    spacing = techGetProp(layer 'MINSPACING)

    ;; Fallbacks if techGetProp fails
    unless(width width = 0.14)
    unless(spacing spacing = 0.14)

    ;; Total area of selection
    areaX = (car ur) - (car ll)
    areaY = (cadr ur) - (cadr ll)
    totalArea = areaX * areaY

    ;; Compute spacing to achieve approximate target density
    ;; simple model: density = (width^2) / ((width + spacingX)^2)
    stepX = width / sqrt(targetDensity) ; spacingX + width = width / sqrt(density)
    spacingX = stepX - width
    stepY = width / sqrt(targetDensity)
    spacingY = stepY - width

    ;; Ensure spacing respects minSpacing
    if(spacingX < spacing) spacingX = spacing
    if(spacingY < spacing) spacingY = spacing

    ;; Fill rectangles
    x = car ll
    fillArea = 0
    while (<= x (car ur))
    y = cadr ll
    while (<= y (cadr ur))
    ;; Create rectangle
    dbCreateRect(layer list(x y) list(+ x width) (+ y width))
    fillArea = fillArea + (width * width)
    y = y + width + spacingY
    )
    x = x + width + spacingX
    )

    ;; Report achieved density
    actualDensity = fillArea / totalArea
    hiDisplay(sprintf(nil "Metal fill completed on %s. Achieved density: %.2f%%"
    layer (* 100 actualDensity)))
    )

    I will wait for your response. Have a pleasant day!

    Cheers & regards,

    Yogesh Jaiswal 

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 20 days ago in reply to yogeshjaiswalCAD
    yogeshjaiswalCAD said:

    I will wait for your response. Have a pleasant day!

    Clearly you didn't read my previous reply.  This new code is also generated by an LLM (well, if it wasn't, I'd be amazed) that doesn't know SKILL. It uses non-existent functions geGetSel, techGetProp (and it's unlikely the tech file would have things like 'MINSPACING in uppercase), dbGetBBox, hiDisplay; it has incorrect syntax for if() functions, it does things like "x = car ll" which is incorrect too. I'm not wasting my time on something you've asked an LLM to write and not even checked the results or attempted to get it working.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • yogeshjaiswalCAD
    yogeshjaiswalCAD 20 days ago in reply to Andrew Beckett

    Hello, Andrew.

    I've already supplied a link to this error, which is not created by LLM.

    Our colleague left throughout the process, which is why I am seeking assistance on his behalf. Hope we have a healthy relationship.

    Other people can help in if Andrew is busy with other tasks!

    Have a nice day!

    Cheers & regards,

    Yogesh Jaiswal

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • Aurel B
    Aurel B 19 days ago

    Hi Yogesh,

    I'm not exactly sure as I didn't exactly understood what your code is doing.

    As Andrew said, it is using functions that look like Cadence ones.

    If they are custom, this is a really bad habit as it can be really confusing for others (especially on the forum)...

    Aren't you trying to achieve something similar to what's done in:

    Cadence Community SKILL Forum - How to do a dbLayerAndNot from top-level through the whole hierarchy?

    If you want to fill the holes instead of generating the whole layer (regarding the code I made in the mentioned article):

    You can probably browse the ABE islands from the resulting layers and create rectangles inside each island.

    Also maybe rodFillBBoxWithRects can be useful in your case.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • yogeshjaiswalCAD
    yogeshjaiswalCAD 18 days ago in reply to Aurel B

    Greetings Aurel & Andrew

    It means a lot when you take time from your busy schedule to reply to such answers; 

    I have succeeded in this quest with your help.. I wrote the following code  ...  The code is functioning as expected.  

    procedure(and_not_fill_safe(@key (cv (geGetEditCellView)) existing_lpp filling_lpp (keepOut 0.1))
    let((tf boundary_points existing_abe shrunk_abe boundary_abe filling_abe)

    unless(cv
     warn("Warning️ No active layout window. Open a layout first!\n")
    then(return(nil))
    )

    tf = techGetTechFile(cv)

    unless(and(existing_lpp filling_lpp)
     warn("Warning️ Must provide both existing_lpp and filling_lpp as (layer purpose)\n")
    then(return(nil))
    )

    when(not(techGetLP(tf existing_lpp))
     warn("Warning️ Existing layer %L not found in tech file.\n" existing_lpp)
    )
    when(not(techGetLP(tf filling_lpp))
     warn("Warning️ Fill layer %L not found in tech file.\n" filling_lpp)
    )

    abeInit(cv)
    unwindProtect(
    progn(
    ;; --- Get boundary (prBoundary or bbox) ---
    boundary_points = nil
    when(cv~>prBoundary
    boundary_points = car(cv~>prBoundary)~>points
    )
    unless(boundary_points
    let((bb ll ur)
    bb = cv~>bBox
    ll = car(bb)
    ur = cadr(bb)
    boundary_points = list(
    list(car(ll) cadr(ll))
    list(car(ur) cadr(ll))
    list(car(ur) cadr(ur))
    list(car(ll) cadr(ur))
    )
    )
    )

    ;; --- Create ABE layers ---
    existing_abe = abeLayerFromCellView(car(existing_lpp) ?purpose cadr(existing_lpp))
    boundary_abe = abeNewLayer()
    filling_abe = abeNewLayer()
    shrunk_abe = abeNewLayer()

    abeLayerOrPtArray(boundary_points boundary_abe)

    ;; White check mark Replace abeLayerShrink with abeLayerSize (portable)
    abeLayerSize(existing_abe shrunk_abe (- keepOut))

    ;; Subtract shrunk metal area from boundary
    abeLayerAndNot(boundary_abe shrunk_abe filling_abe)
    abeLayerToCellView(filling_abe car(filling_lpp) ?purpose cadr(filling_lpp))

    printf("White check mark Safe dummy fill complete on %L avoiding %L (keepOut=%.3f)\n"
    filling_lpp existing_lpp keepOut)
    )
    abeDone()
    )
    )
    )

    Once again thanks for warm gesture , We are here for each other !

    Have a pleasant day!

    Cheers & regards,

    Yogesh Jaiswal 

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 18 days ago in reply to yogeshjaiswalCAD

    Yogesh,

    A small point - in your latest code, the checks at the beginning won't work correctly because they are trying to call return(). In order to use return(), you have to be within prog() - they won't work within a let(). You'd get:

    *Error* return: return can only be used within a prog

    Andrew

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • 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