• 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. [Solved] Trying to wrap a script in unwindProtect, progn...

Stats

  • Locked Locked
  • Replies 7
  • Subscribers 143
  • Views 13130
  • 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

[Solved] Trying to wrap a script in unwindProtect, progn complains: too many arguments

jriad
jriad over 4 years ago

My use case is that I'm trying to invoke some SKILL code from within Python. To that end, I'm spawning a "virtuoso -nograph" process and passing my skill code to its standard input.

To make sure the virtuoso process will exit no matter what (so that my Python script can continue), this is the SKILL code I'm sending it:

    (unwindProtect
      (progn
        ;; My code goes here
      )
    (exit))
The problem is, my code can be quite long so I sometimes get an error like:
      *Error* progn: too many arguments (at most 65535 expected, 174884 given)
How can I approach this so that my SKILL code always exits and doesn't hang around waiting for more input and hijacking control from my Python script?
I have also tried writing my code out to a file and tacking an (exit) at the end of it then invoking the process as "virtuoso -nograph -restore mycode.il", but the problem is, if there are any errors in the code, the (exit) call will never be reached and the REPL will keep waiting for input and not return control to the Python script.
Am I going about this all wrong? Is there a better approach to this?
  • Cancel
  • mbracht
    mbracht over 4 years ago

    Hi,

    This is a known bug of progn() - CCR# 1070771.
    Have you tried an errset() statement instead of the progn()? That way any potentially fatal errors will get caught, the program jumps to the end of the errset() block and exit() will be executed.

    Max

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • jriad
    jriad over 4 years ago in reply to mbracht

    Thanks for your reply.

    I wasn't aware of errset. From my understanding of the docs, it only accepts a single expression so I would need to wrap every single line of code in errset. Not only is this impractical (I have a single Python function to run SKILL and I invoke it multiple times with multiple scripts; using errset would require me to change the code for each Python function that produces SKILL not just for my single function that runs SKILL), but I also worry about its performance impact for a large script (again, I don't know much about errset, but I'm guessing it will add some overhead). Is there a better way of using it that I'm not seeing and that you can suggest?

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

    There are two issues here. I don't think the progn() issue is really a bug but more of a limitation - there's an upper limit to the number of arguments to a function. Similarly there is an upper limit to the size of the code. Both of these are related to the stack and the virtual machine implementation (how far it could jump, for example). let() would have the same problem, and errset won't help as it expects a single form.

    Those limits are never reached in human-written code. Whilst you could extend things a bit further by having two progn() within the progn(), you'll then hit other limits if you go beyond that and this causes a stack overflow.

    The general approach is to break long code into function definitions, and then call those functions from your code. 

    I'm assuming that your code is machine generated?

    Andrew

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

    Hi Andrew,

    Thank you for the clarifications. Yes, my code is machine-generated. I'm parsing information from a layout net and then annotating the layout in (many) relevant places. The code that generates the annotations is very short (about 4 function calls) so wrapping that in a function won't really work as I would still have to call that function many times if a net is large and has many such places. I'm guessing a better approach would be to simply test if the code is long and divide it up as follows:

    (unwindProtect
     (progn
         ;; Some code not exceeding the progn limit
      )
    t)
    ;; Repeat as many unwindProtects as needed
    (unwindProtect
      (progn
        ;; Final part of code
       )
    (exit))

    Does this approach make sense?

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

    Yes, that could work. I did have some code in the past that would rewrite an arbitrarily long piece of code into smaller functions (this was when the code size limit was much smaller, and it was a more common problem). I wasn't necessarily suggesting that you make these underlying functions sensible - they could just be blocks of work that you keep generating as you go along, and collect the functions to be called at the end. However, your approach should work too... if these blocks of code are all top-level in the file, then it should be OK.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • jriad
    jriad over 4 years ago in reply to Andrew Beckett
    Andrew Beckett said:
    if these blocks of code are all top-level in the file, then it should be OK.

    Yes, I've had to convert everything to top-level because I ran into a similar problem with a (let...) form before. I thought the limitation applied to (let...)  only because it created its own environment. I wasn't aware that this is a general limitation. Thank you, marking the issue as solved.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • jriad
    jriad over 4 years ago

    Update: I tried splitting the code into many (unwindProtect ...) forms to make sure the number of arguments to (progn...) never exceeded the limit but I still got a "literal stack overflow" error because the code size was too large.

    The approach I ended up taking was different: I made my Python script write out all the annotation info to a text file and then I wrote a SKILL function that reads the text file line by line and creates annotations in the layout based on the info it reads from each line. I was then able to wrap this function call in an (unwindProtect...) from within Python with no issues. Not only did this work without overflow errors, it was blazing fast: it created ~44k annotations in under 2 minutes.

    • 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