• 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. dbGetTrueOverlaps with diagonals

Stats

  • Replies 5
  • Subscribers 135
  • Views 290
  • Members are here 0

dbGetTrueOverlaps with diagonals

RC202602061219
RC202602061219 9 days ago

I am trying debug a skill script which involves finding abutting shapes.

lpp = selectedObj~>lpp
bbox = selectedObj~>bBox
overlaps = dbGetTrueOverlaps(cv bbox lpp 0)

I found that shapes with diagonals don't work well. With object 'A' selected it returns 'B' as overlapping but not the other way round.

Is there an alternative that will cope with this situation? The script is meant to return the total length of a path.

  • Sign in to reply
  • Cancel
Parents
  • RC202602061219
    RC202602061219 8 days ago

    Script which can cope with diagonals. Hopefully someone will be along shortly to show how it should really be done.

    Fullscreen totalPathLength.txt Download
    ;  totalPathLength.il
    ;; Script from Google AI & tweaked to fix RJC
    ; Should calculate total path length of a path including touching segments
    ; select a path segment and run CalculateChainedPathLength()
    ; load("./skill/totalPathLength.il")  in CIW
    ;
    ; Need to have local writeable library called scratch
    ; Can get double counting where paths overlap
    
    procedure(CalculateChainedPathLength()
        let((selectedObj cv lpp shapesToVisit visitedShapes totalLength currentObj bbox overlaps newLength)
            selectedObj = car(geGetSelectedSet())
            cv = geGetEditCellView()
            
            if(!selectedObj || !(selectedObj~>objType == "pathSeg" || selectedObj~>objType == "path") then
                error("Please select a starting pathSeg or path object first.")
            )
            
            lpp = selectedObj~>lpp
            shapesToVisit = list(selectedObj)
            visitedShapes = makeTable("visited" nil)
            totalLength = 0.0
            
            while(shapesToVisit
                currentObj = car(shapesToVisit)
                shapesToVisit = cdr(shapesToVisit)
                
                unless(visitedShapes[currentObj]
                    visitedShapes[currentObj] = t
                    bbox = currentObj~>bBox
                    
                    ;; Calculate individual segment length
                    case(currentObj~>objType
                        ("pathSeg"
                            ;; dx or dy based on straight paths
                            totalLength = totalLength + dbGetSegLength(currentObj)
    			printf(">> Add getseglen : %f \n" dbGetSegLength(currentObj))
                        )
                        ("path"
                            ;; Fallback length calculation for multi-point paths
                            let((prevPt ptLen)
                                ptLen = 0.0
                                foreach(pt currentObj~>points
                                    if(prevPt then
                                        ptLen = ptLen + sqrt(expt(car(pt)-car(prevPt) 2) + expt(cadr(pt)-cadr(prevPt) 2))
                                        prevPt = pt
                                    else
                                        prevPt = pt
                                    )
                                )
                                totalLength = totalLength + ptLen
    			    printf(">> Add mltpntpath len : %f \n" ptLen)
                            )
                        )
                    )
                    
                    ;; Automatically find geometrically touching/overlapping segments on the same layer
    		;; As bbox is rectangle doesn't work well for diagonals
                    ; overlaps = dbGetTrueOverlaps(cv bbox lpp 0)
    		
    		;;improved search which copes with diagonals
    		overlaps = MyGetTrueNonOrthogonalOverlaps(cv currentObj lpp)
    		
                    foreach(overlap overlaps
                        when(overlap && (overlap~>objType == "pathSeg" || overlap~>objType == "path")
                            unless(visitedShapes[overlap]
                                shapesToVisit = cons(overlap shapesToVisit)
                            )
                        )
                    )
                )
            )
            
            printf(">>> Total Chained Path Length for the selected trace: %f microns on layer %L\n" totalLength lpp)
        )
    )
    
    ;; Helper function for single straight pathSeg calculation
    procedure(dbGetSegLength(seg)
        let((bPt ePt)
            bPt = seg~>beginPt
            ePt = seg~>endPt
            sqrt(expt(car(ePt)-car(bPt) 2) + expt(cadr(ePt)-cadr(bPt) 2))
        )
    )
    
    procedure(MyGetTrueNonOrthogonalOverlaps(cv searchShape lpp)
        let((overlaps scratchCv trueOverlaps searchShape_sized)
            ; 1. Coarse filtering using the bounding box of your search shape
            overlaps = dbGetTrueOverlaps(cv searchShape~>bBox lpp 0)
    
    	
            ; Create a scratch cellview in memory to perform the layer operation safely
            scratchCv = dbOpenCellViewByType("scratch" "temp" "layout" "maskLayout" "w")
    	; size operation to create some overlap - assumes there is layer "text"
    	searchShape_sized = dbLayerSize(scratchCv "text" list(searchShape) 0.001)
            
            foreach(overlap overlaps
                unless(overlap == searchShape
                    ; 2. Perform a boolean AND between the shapes
                    ; dbLayerAnd returns a list of resulting shapes if they truly overlap
    		;if(dbLayerAnd(scratchCv lpp list(searchShape overlap)) then
                    if(dbLayerAnd(scratchCv lpp searchShape_sized list(overlap)) then
                        trueOverlaps = cons(overlap trueOverlaps)
                    )
                )
            )
            
            ; Clean up the scratch cellview to avoid memory leaks
            dbClose(scratchCv)
            
            trueOverlaps
        )
    )
    
    ;; Bind the script to Shift + L
    hiSetBindKey("Layout" "Shift<Key>l" "CalculateChainedPathLength()")
    

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 6 days ago in reply to RC202602061219

    I meant to reply to this but obviously got distracted whilst doing so!

    Anyway, the mains ways of doing this are to do one of:

    1. dbLayerAnd of the shapes as you've done (you could use dbOpenScratchDesign as that doesn't require anything on disk))
    2. dbPolntArrayAnd - you could get the boundary of the pathSeg using obj~>boundary or if it was a path you'd use dbGetPathBoundary. For other shapes you'd have to compute them yourself
    3. abeLayerAnd - you can construct the ABE shapes from the original shapes and then the and is just done in memory. Note that these are constrained to 45-degree shapes (OK in this case)
    4. You could iterate over the points in one shape and use geIsPointInsidePolygon or leIsPointInsideFig - again you need to find the boundary. There's also abPointInPolygon in this post if you are in a context (e.g. in a PCell) that can't use ge or le functions.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • RC202602061219
    RC202602061219 6 days ago in reply to Andrew Beckett

    Hi Andrew,

    Thanks for that. I replaced the line
    scratchCv = dbOpenCellViewByType("scratch" "temp" "layout" "maskLayout" "w")

    by
    scratchCv = dbOpenScratchDesign("scratch" "maskLayout")
    and it still gives the expected answers

    Robin

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • RC202602061219
    RC202602061219 4 days ago in reply to RC202602061219

    p.s.

    I tried extending my script so it works across layers of hierarchy but my amateurish attempts got very messy and didn't work properly so I gave up for the time being.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 4 days ago in reply to RC202602061219

    Using the abe* functions would be the easiest way - these handle hierarchy directly without you needing to do the traversal yourself.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett 4 days ago in reply to RC202602061219

    Using the abe* functions would be the easiest way - these handle hierarchy directly without you needing to do the traversal yourself.

    Andrew

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

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

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