• 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. intances change to mosaic

Stats

  • Locked Locked
  • Replies 6
  • Subscribers 145
  • Views 10212
  • 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

intances change to mosaic

StanleyChiu
StanleyChiu over 3 years ago

i want to change multiple intances (same distance , same intances) to one mosaic

how to implement this function?

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

    I was interested by this - so wrote something. It's not entirely trivial because you need to check that all instances are the same object, have the same orientation, and have regular spacing - but the code below will do it (from my limited testing anyway). If the instances are selected, you can just do:

    abConvertInstancesToMosaic()

    or you can pass a list of instances to the function.

    Note: updated version to take into account the comments made by henker in his post below.

    /* abConvertInstancesToMosaic.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Jun 15, 2022 
    Modified   Jun 20, 2022 
    By         A.D.Beckett
    
    Convert a set of instances to be a mosaic. See comments
    in main function below.
    
    The code uses SKILL++ lexical scoping, so the file should
    keep the ".ils" suffix.
    
    ***************************************************
    
    SCCS Info: @(#) abConvertInstancesToMosaic.ils 06/20/22.15:39:05 1.2
    
    */
    
    /***************************************************************
    *                                                              *
    *      (abConvertInstancesToMosaic [instances] [verbose])      *
    *                                                              *
    *  Convert a list of instances (defaults to selected objects)  *
    *  to be a mosaic. Checks that all are the same object, same   *
    *   orientation and that spacing is regular before doing the   *
    *   conversion - returns either nil (if nothing was changed)   *
    *   or the new mosaic object. If the new mosaic was created,   *
    *             the original instances are deleted.              *
    *                                                              *
    ***************************************************************/
    
    (defun abConvertInstancesToMosaic (@optional (instances (geGetSelSet)) verbose)
      /***************************************************************
      *                                                              *
      *                       (lessXY xy1 xy2)                       *
      *                                                              *
      * Local (private) function to complete two coordinates. First  *
      *                compare x then y if x is equal                *
      *                                                              *
      ***************************************************************/
      (defun lessXY (xy1 xy2)
        (destructuringBind (x1 y1) xy1
          (destructuringBind 
            (x2 y2) xy2
            (or (lessp x1 x2)
                (and (equal x1 x2) (lessp y1 y2))))))
      /***************************************************************
      *                                                              *
      *                 (convertXYtoInt xy DBUPerUU)                 *
      *                                                              *
      * Local (private) function to convert xy coordinate to integer *
      *                            space                             *
      *                                                              *
      ***************************************************************/
      (defun convertXYtoInt (xy DBUPerUU)
        (mapcar (lambda (num) (round (times num DBUPerUU))) xy))
      /***************************************************************
      *                                                              *
      *                        (message text)                        *
      *                                                              *
      * Local (private) function to print explanation if verbose is  *
      *                             set                              *
      *                                                              *
      ***************************************************************/
      (defun message (text)
        (when verbose 
          (printf "%s\n" text)))
      ;----------------------------------------------------------------------
      ; Main body of function
      ;----------------------------------------------------------------------
      (let ((firstOrient (getq (car instances) orient))
            (firstMaster (getq (car instances) master))
            (cellView (getq (car instances) cellView))
            sorted firstOrigin origin DBUPerUU deltaX deltaY 
            llx lly urx ury mosaicOrigin
            diffX diffY col row
            (elementExists (makeTable 'elementExists nil))
            (cols 0)
            (rows 0)
            (count 1)
            irregular
            )
        ;--------------------------------------------------------------------
        ; First filter to check that all are instances and have the same 
        ; orientation and master
        ;--------------------------------------------------------------------
        (if (and instances
                 (forall inst instances
                         (and (equal (getq inst objType) "inst")
                              (equal (getq inst orient) firstOrient)
                              (equal (getq inst master) firstMaster))))
          ; then
          (progn
            ;----------------------------------------------------------------
            ; Sort to be ordered by x then y - uses copy to avoid 
            ; destructive modification of original list of instances
            ;----------------------------------------------------------------
            (setq sorted
                  (sort (copy instances)
                        (lambda (a b) (lessXY (getq a xy) (getq b xy)))))
            ;----------------------------------------------------------------
            ; All arithmetic on coordinates is in integer coordinate space
            ;----------------------------------------------------------------
            (setq DBUPerUU (getq cellView DBUPerUU))
            (setq firstOrigin (convertXYtoInt (getq (car sorted) xy) DBUPerUU))
            (destructuringBind (x y) (getq (car sorted) xy)
                               (setq llx (setq urx x))
                               (setq lly (setq ury y)))
            (setarray elementExists (list 0 0) t)
            (foreach inst (cdr sorted)
                     (destructuringBind (x y) (getq inst xy)
                                        (setq llx (min llx x))
                                        (setq lly (min lly y))
                                        (setq urx (max urx x))
                                        (setq ury (max ury y)))
                     (setq origin (convertXYtoInt (getq inst xy) DBUPerUU))
                     (setq diffX (difference (xCoord origin) (xCoord firstOrigin)))
                     (setq diffY (difference (yCoord origin) (yCoord firstOrigin)))
                     (setq col 0)
                     (setq row 0)
                     (unless (zerop diffX)
                       (if deltaX
                         (if (zerop (mod diffX deltaX))
                           (progn
                             (setq col (quotient diffX deltaX))
                             (setq cols (max cols col)))
                           (setq irregular t))
                         (progn
                           (setq deltaX diffX)
                           (setq col 1)
                           (setq cols 1))))
                     (unless (zerop diffY)
                       (if deltaY
                         (if (zerop (mod diffY deltaY))
                           (progn
                             (setq row (quotient diffY deltaY))
                             (setq rows (max rows row)))
                           (setq irregular t))
                         (progn
                           (setq deltaY diffY)
                           (setq row 1)
                           (setq rows 1)))) 
                     ;-------------------------------------------------------
                     ; Ensure that we only increment the count for each
                     ; unique row and column entry
                     ;-------------------------------------------------------
                     (unless (arrayref elementExists (list col row))
                       (setarray elementExists (list col row) t)
                       (postincrement count)
                       )
                     )
            ;----------------------------------------------------------------
            ; Convert to be 1-indexed
            ;----------------------------------------------------------------
            (postincrement rows)
            (postincrement cols)
            (unless deltaX (setq deltaX 0))
            (unless deltaY (setq deltaY 0))
            ;----------------------------------------------------------------
            ; Sort out origins and switch rows/cols and deltas based on
            ; orientation
            ;----------------------------------------------------------------
            (setq mosaicOrigin
                  (case firstOrient
                    (("R0" "MXR90") (list llx lly))
                    (("R90" "MY") (list urx lly))
                    (("R180" "MYR90") (list urx ury))
                    (("R270" "MX") (list llx ury))))
            (case firstOrient
              (("R90" "R270" "MYR90" "MXR90")
               (setq rows (prog1 cols (setq cols rows)))
               (setq deltaX (prog1 deltaY (setq deltaY deltaX)))
               ))
            (cond
              (irregular
                (message "Instance spacing is irregular")
                nil)
              ((nequal count (times rows cols))
               (message "Total unique instances not product of rows and columns")
               nil)
              (t
                (prog1
                  (dbCreateSimpleMosaic
                    cellView
                    firstMaster
                    ""
                    mosaicOrigin
                    firstOrient
                    rows cols (quotient deltaY DBUPerUU) (quotient deltaX DBUPerUU))
                  (foreach inst sorted
                           (dbDeleteObject inst))
                  )
                )
              )
            )
          ; else
          (message "Objects need to all be instances of the same master and orientation")
          )
        )
      )
    
    

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • henker
    henker over 3 years ago in reply to Andrew Beckett

    I think this only works if the original orientation is R0.
    For the other orientations it should be necessary to change the origin of the created mosaic from the current lowerLeft to another of the 4 corners of the detected array rectangle, and to swap the x/y arguments on 90/270 degree rotation, which would in sum correspond to the 8 possible orientations.
    Not sure if it would be easier to apply e.g. dbTransformPoint on the values and use the transformed result as base for the arguments of dbCreateSimpleMosaic or just to write all 8 variants as plain code.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • henker
    henker over 3 years ago in reply to Andrew Beckett

    I think this only works if the original orientation is R0.
    For the other orientations it should be necessary to change the origin of the created mosaic from the current lowerLeft to another of the 4 corners of the detected array rectangle, and to swap the x/y arguments on 90/270 degree rotation, which would in sum correspond to the 8 possible orientations.
    Not sure if it would be easier to apply e.g. dbTransformPoint on the values and use the transformed result as base for the arguments of dbCreateSimpleMosaic or just to write all 8 variants as plain code.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • Andrew Beckett
    Andrew Beckett over 3 years ago in reply to henker

    I realised this a couple of days ago that I'd not tested this with other orientations and had in my head the old CDB model of how orientation worked for mosaics rather than how it works in OA (where the whole mosaic is rotated). I've been away and haven't had a chance to fix it yet. The current code also still converts into an array when there are duplicate instances in one array location and a gap in another (i.e. if the total number of instances is correct). I'll fix both and re-post hopefully today.

    Andrew

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

    I updated the code above (I edited the post to avoid having two versions) to now take into account the orientation properly, plus cope with correctly (I think) counting the cells to ensure that it only counts non-overlapping cells.

    The new version works by finding the rows/cols and deltas and swapping them around based on the orientation, as well as finding the bounding box of the origins and picking the appropriate corner for the mosaic to be instantiated at. This was simpler than trying to transform everything into a particular orientation and transforming back afterwards.

    Andrew

    • 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