• 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 get marknet region when i use lemarknet function...

Stats

  • Replies 10
  • Subscribers 150
  • Views 843
  • Members are here 0

How to get marknet region when i use lemarknet function in skill script

Albertyu
Albertyu 27 days ago

hi all!

i want to get hightlight polygon region when i use leMarkNet function, Is here have many other function to achieve that. if you can reply with completed code that will be Appreciate!

thanks for reply

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

    You'd probably need to use leSaveMarkNet to save the data to a (temporary) cellView and then you could look at the resulting shapes there to identify the "region" of the resulting shapes.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Albertyu
    Albertyu 26 days ago in reply to Andrew Beckett

    i have already done it like you said, thanks for reply

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

    This is a draft of what you can do with the net tracer, it does not exactly does what you ask for but I think it is similar enough to be worth sharing :

    ;; Macro to group context S-expressions
    (defmacro cst_wrap ( in out @rest body) (list 'unwindProtect (constar 'progn in body) out))
    
    (defun cst_get_shapes_by_net ( @key ( window   (hiGetCurrentWindow) )
                                        ( cellview (geGetEditCellView)  )
                                        nets layers
                                   @rest _ "wdll" )
      "Return the list of polygons points from shapes in WINDOW/CELLVIEW connected to NETS whose layer is in LAYERS."
      (let ( ( tech_file (techGetTechFile cellview) )
             ( lib_name  cellview->libName          )
             ( cell_name cellview->cellName         )
             )
    
        ;; -------------------------------------------------------
        ;; Check inputs
        ;; -------------------------------------------------------
    
        ;; Nets
        (assert (and nets (forall net nets (stringp net))) "cst_get_shapes_by_net - ?nets should be a non-empty list of strings: %N" nets)
        (foreach net nets
          (assert (dbFindNetByName cellview net)
            "cst_get_shapes_by_net - Unable to find net %s in %s/%s/%s." net lib_name cell_name cellview->viewName
            ))
        ;; Layers
    
        (assert (and layers
                     (forall layer layers
                       (or (stringp layer)
                           (and (listp layer) (stringp (car layer)) (stringp (cadr layer)) (not (cddr layer)))
                           )))
          "cst_get_shapes_by_net - ?layers should be a non-empty list of layers and/or lpps: %N" layers)
        (foreach layer layers
          (cond
            ( (and (stringp layer) (techFindLayer tech_file layer)) )
            ( (and (listp layer)   (techGetLP     tech_file layer)) )
            ( t (error "cst_get_shapes_by_net - Not a valid layer or lpp: %N" layer))
            ))
    
        ;; Library
        ;; TODO - Creating a temporary library instead of a temporary view is better on many aspects:
        ;; - writable by default
        ;; - easier to cleanup
        ;; - `mktemp` (or `makeTempFileName`) can avoid name overlap
        (assert (ddIsObjWritable (ddGetObj lib_name))
          "cst_get_shapes_by_net - Library %s is not writable, this is not supported yet..." lib_name)
    
        ;; -------------------------------------------------------
        ;; Create net traces
        ;; -------------------------------------------------------
        (let ( ( tmp_view_name (strcat cellview->viewName (gensym '_tmp_trace)) )
               trace_ids
               tmp_cellview
               )
          (assert (not (ddGetObj lib_name cell_name tmp_view_name))
            "cst_get_shapes_by_net - LCV %s/%s/%s already exists." lib_name cell_name tmp_view_name)
          ;; Create traces and properly remove them afterwards 
          (cst_wrap (setq trace_ids (foreach mapcar net nets (car (lntAddTrace window net))))
                    (foreach trace_id trace_ids (errset (lntRemoveTrace trace_id window) t))
            ;; Save traces to temporary cellview and properly delete it afterwards
            (cst_wrap (lntSaveTraces window trace_ids lib_name cell_name tmp_view_name)
                      (ddDeleteObj (ddGetObj lib_name cell_name tmp_view_name))
              (cst_wrap (setq tmp_cellview (dbOpenCellViewByType lib_name cell_name tmp_view_name))
                        (dbClose tmp_cellview)
                (cst_wrap (abeInit cellview)
                          (abeDone)
                  ;; Return the polygons
                  (foreach mapcan layer layers
                    (let ( ( abe_iter (abeIslandIterator
                                        (if (stringp layer) (abeLayerFromCellView layer)
                                          (abeLayerFromCellView (car layer) ?purpose (cadr layer))
                                          )) )
                           points
                           polygons
                           )
                      (while (setq points abe_iter->next) (push points polygons))
                      polygons
                      ))
                  ));wrap abe ;wrap open tmp_cellview 
              ));wrap write tmp_cellview  ;wrap trace
          )
        ))
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Albertyu
    Albertyu 26 days ago in reply to Aurel B

    thanks for sharing, i will learn it!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 26 days ago in reply to Aurel B

    Aurel B  - for your information, lntSaveTraces can now be given a memory-only scratch cellView since (if my memory is correct, IC23.1 ISR11;  might be in ISR10 too):

    (sets sc (dbOpenScratchDesign lib_name "maskLayout"))
    (lntSaveTraces window trace_ids nil nil nil ?targetCV sc)

    Avoids you needing to create temporary libraries etc...

    This is as a consequence of a request from somebody you know!

    Andrew

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

    just as minor comment from a pedantic point of view:
    I would take the cst_wrap e.g. as:

    (defmacro cst_wrap (in out @rest body) (list 'progn in (list 'unwindProtect (cons 'progn body) out)))

    effectively placing the 'in' clause before the unwindProtect.
    Otherwise it risks calling the 'out' cleanup when an error is raised during the 'in', which usually is not required. But it may depend on the actual case, tough.

    Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Aurel B
    Aurel B 20 days ago in reply to henker

    Funny you say that.

    That is something I thought a long time about but I assume that my 'in' form might be destructive while the 'out' one is only for cleanup purposes (so it should be safe to call it even if it fails).

    This not something I have encountered often though.

    If I hade to make an example up : 

    'in' could create a temporary directory and populate it with a git repository.

    'out' would erase the temporary directory,

    Even if the checkout phase fails, I still want my directory to be cleaned up.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Aurel B
    Aurel B 20 days ago in reply to henker

    This is a separate post because I know it's gonna be caught by moderation...

    If you are interested in macros, I have plenty there : 

    skill-sharp/skill/macros at main · Da-Buche/skill-sharp · GitHub

    Mostly in patterns.scm and f-strings.scm

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • henker
    henker 15 days ago in reply to Aurel B


    Thanks for sharing code, got me some inspiration.

    Your remark on the 'in' form is fully understood, therefore I stated that it depends on the actual case.

    However, in your example with the folder:
    If you define the 'in' as "create a temporary directory and populate it", than ok, this has no own cleanup and thus, must be inside the unwindProtect.
    But actually, the 'in' clause is only the "create a temporary directory", the "populate" is already part of the body.
    If the directory creation fails, you have no reason to populate not to mention call the 'out' to delete the directory.
    The latter might even cause damage: Assume the directory already exists, trying to create fails, when you nevertheless call the 'out', it would delete a previously existing directory, potentially not related to what you are doing...

    The other examples from the code above are quite similar:

    cst_wrap (abeInit cellview) (abeDone) ...)
    abeInit retuens t/nil depending on success, but it also throws error when passed an invalid cellview, so it should be before the unwindProtect.
    Although it would be rather harmless here to have it inside because abeDone does not throw error when there was no successfull abeInit before (it just returns nil), but from a pedantic point of view, I'd not like to call abeDone if the abeInit failed.

    (cst_wrap (.. dbOpenCellViewByType ..) (dbClose ..) ...)
    might be more severe as dbOpenCellViewByType does not throw but warns/returns nil on failure; error is then thrown when the invalid cellview is first accessed later in the body, and it would also force dbClose on an invalid argument which will cause an error on its own.

    So on second thought, the usual initializer functions already return nil on failure, thus, it might be appropriate to test the return value of the 'in' clause and conditionally call the unwindProtect with body+out, e.g.

    (defmacro cst_wrap (in out @rest body) (list 'when in (list 'unwindProtect (if (cdr body) (cons 'progn body) body) out)))

    It can still be invoked as: (cst_wrap t out in body ...) if you want the 'in' as part of the body (and still have it written together with the 'out', just in reverse order), although I would have 'in' clauses in a proceeding conditional for all examples I could think of (e.g. abeInit->abeDone, dbOpenCellViewByType->dbClose, ddGetObj->ddReleaseObj, outfile/infile->close, createDir/createDirHier->deleteDir).

    Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Aurel B
    Aurel B 13 days ago in reply to henker

    To be honest, I use `@wrap` only with cases that are not already handled by the `@with` macro  (which is very similar to Python contexts): 

    (with ( (cv  (dbOpenCellViewByType ...)) )
      cv->??)

    It is a mix of `let` & `wrap` and calls `in` & `out` depending on the object type.

    • Cancel
    • Vote Up 0 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