• 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. Scheme vs Common Lisp style in SKILL++

Stats

  • Locked Locked
  • Replies 18
  • Subscribers 144
  • Views 22559
  • 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

Scheme vs Common Lisp style in SKILL++

tweeks
tweeks over 10 years ago

 While you can write your SKILL++ code like it is C, Maclisp, Scheme, or Common Lisp (or none of the above...), I've been experimenting with Common Lisp style lately.

Trying to write Common Lisp style code in SKILL++ can lead to curious situations like this:

(defvar first car)

The intention is to define FIRST as another name for CAR, as in Common Lisp.  In Scheme, we would write

(define first car)

which seems pretty natural, but using DEFVAR to define a function just feels.... wrong... somehow... :)

I guess I should use ALIAS:

 (alias second cadr)

 except ALIAS has weird limitations:

ILS-> (foo = first)
primop:car
ILS-> (foo '(1 2 3))
1
ILS-> (foo = second)
macro:evalalias
ILS-> (foo '(1 2 3))
*Error* evalalias: unknown alias - foo

  • Cancel
  • Andrew Beckett
    Andrew Beckett over 10 years ago

    Your mistake is that SKILL and SKILL++ are distinct dialects of LISP and are not either Scheme or Common Lisp or any of the others. They may share similar syntax to the other dialects, but they have different semantics. So whilst defvar and define both exist in SKILL, (defvar is nominally for SKILL mode rather than SKILL++ mode, although it works in both), in SKILL++ variables and functions are not distinct - it's an object bound to a name. So there's really no way that it can treat them differently.

    Aliases are different again - they are a very old mechanism in SKILL to alias two functions. They predate SKILL++ (or ils mode) by some considerable time, and they are not intended to be copied by assignment. In fact all aliases share the same definition - they are all calling the evalalias macro, which actually looks for the alias property on the symbol to find out what it is aliased to. So they are not "weird", but you are assuming that they can be assigned, which is not the case.

    So you'd have to do:

    foo=second
    foo.alias=second.alias

    And then it would work. However, this is an undocumented implementation detail which you should not rely upon (in case it changes in future).

    Regards,

    Andrew.

     

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tweeks
    tweeks over 10 years ago

    Andrew Beckett said:

    Aliases are different again - they are a very old mechanism in SKILL to alias two functions. They predate SKILL++ (or ils mode) by some considerable time, and they are not intended to be copied by assignment. In fact all aliases share the same definition - they are all calling the evalalias macro, which actually looks for the alias property on the symbol to find out what it is aliased to. So they are not "weird", but you are assuming that they can be assigned, which is not the case.

    So you'd have to do:

    foo=second
    foo.alias=second.alias

    And then it would work. However, this is an undocumented implementation detail which you should not rely upon (in case it changes in future).

    Thanks Andrew.  It sounds like aliases are basically depricated now.

    Someone should make a list somewhere of all the stuff in SKILL that is deprecated--only kept for backwards-compatibility--and what the preferred contemporary equivalents are.

    Andrew Beckett said:

    Your mistake is that SKILL and SKILL++ are distinct dialects of LISP and are not either Scheme or Common Lisp or any of the others. They may share similar syntax to the other dialects, but they have different semantics.

    It's nice that SKILL tries to look syntactically familiar by borrowing from Scheme and Common Lisp.  However, because the semantics of SKILL/SKILL++ are, as you said, profoundly different from these languages, one occasionally runs into these jarring situations like in my OP where something that looks familiar is in fact is very different.  Imagine a programming language where you write "+" for multiplication.  Yes, "2 + 2 = 4", but "2 + 3 = 6".  You might wonder, "why use the plus sign if it isn't really addition?"

    SKILL provides a defun which looks like Common Lisp, but in SKILL++ mode it actually behaves like Scheme's define, because it binds the function lexically rather than globally.  This means that flet and labels are unnecessary in SKILL++, because you can simply nest defuns.  However, nesting defuns is extremely rare in Common Lisp, so it looks peculiar to do so in SKILL++, which I assume is why flet and labels were added in the first place!  It seems that it would be stylistically better to use define if you want to bind lexical functions by nesting, as Scheme programmers do.

    However, SKILL++ define is different from Scheme's because SKILL doesn't have dotted pairs / improper lists (which I think was a wise improvement, BTW), so to define an n-ary function you need to use the CL-style @rest keyword, which looks out of place in an otherwise elegant and minimal define (not to mention the argument type-template string!).  IEEE Scheme doesn't have keyword and optional arguments either (though some implementations add them as an extension).  The biggest problem with using define in SKILL++ is that SKILL++ code looks otherwise more like Common Lisp than Scheme: you write t and nil for true and false rather than separate boolean objects #t and #f; there's no "else" keyword for cond; defmacro is unhygienic (and define_syntax doesn't work right); tail-call optimization is unreliable in Virtuoso (though it seems to work fine in standalone SKILL); there are no first-class continuations; you can't use an exclamation point suffix to denote destructive functions (e.g. set!) without an ugly backslash; many core builtins are named in a Common Lisp style (or worse: C style!) rather than a Scheme style.....

    I'm really struggling with this issue of what is good style for SKILL/SKILL++.  I'd say, over all, SKILL/SKILL++ (considering them as one big language with two evaluation modes) feels more like a streamlined Common Lisp than an enhanced Scheme, because some of the "enhancements" would be viewed as regressive by Scheme programmers, while many Common Lisp programmers would probably say SKILL / SKILL++ is a nice simplification, streamlining many clunky aspects (one namespace for functions and variables rather than two), removing old warts (no more "improper lists"!), and adding some innovative improvements to make the language more user-friendly (the foreach, forall, setof, and exists macros are wonderful). 

    Since I've concluded SKILL/SKILL++ is best viewed as a refinement of Common Lisp, it seems like using a refined Common Lisp style is a sensible approach.  However, you do find yourself doing curious things, like using defvar to define a global function.  Maybe I should use define for this use-case?

    I still haven't decided whether it's better to use flet / labels or nested defuns....

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tweeks
    tweeks over 10 years ago

    What's great about SKILL/SKILL++ is that there's so many ways to do things.

    What's annoying about SKILL/SKILL++ is that there's so many ways to do things.

    Define a procedure:

    (def square (lambda (x) (times x x)))
    (defun square (x) (times x x))
    (procedure square(x) (times x x))
    (define (square x) (times x x))
    (define square (lambda (x) (times x x)))
    (defvar square (lambda (x) (times x x)))
    (setq square (lambda (x) (times x x)))
    

    Define a global value:

    (define zero 0)
    (defvar zero 0)
    (setq zero 0)
    

    On the one hand, do we really need three semantically-identical ways to define a global variable, and seven to define a procedure?

    On the other hand, why not provide multiple redundant syntaxes if it helps make programmers from other languages feel more at home?

    On the third hand, SKILL is not Scheme or Common Lisp, so define, defun, and defvar only superficially resemble their namesakes: they are really very different animals. A Scheme programmer may feel at home with SKILL++'s define for a few minutes, but then be surprised later on by the differences. Likewise, a Common Lisp programmer will soon find that defun and defvar behave quite differently from CL. So in the short-run, the syntactic borrowing makes the language friendlier, but in the long-run these borrowings are "false-friends": familiar-looking words in a foreign language that actually mean quite different things from what you would expect.

    The differences are myriad: plus and append require two or more arugments; strings are immutable; improper and circular lists do not exist; the cdr of a cons must be a list; nil is not a symbol; environments are first-class; all free variable references are evaluated dynamically or lexically within a given block of code, depending on whether it's SKILL-mode or Scheme-mode; arithmetic with integers is inexact; rationals do not exist (but complex numbers are available in Virtuoso), and on and on and on.....

    What is SKILL/SKILL++'s philosophy? Scheme is minimalist and favors a functional style. Common Lisp is large and favors iteration over recursion. SKILL is large like Common Lisp, and seems to favor iteration like Common Lisp (foreach's default is mapc rather than mapcar; the gdmSpec interface is stateful; tail call optimization was not added until quite recently, and it still doesn't work reliably (for me anyway)...), but its documentation makes a big deal about being compatible with Scheme, and SKILL++ (with the plus-plus suggesting incremental improvement over the original) moved in the direction of Scheme's evaluation semantics rather than Common Lisp's, yet it added an object system patterned after CLOS!

    So what is SKILL/SKILL++'s philosophy? Is it trying to please everyone by pretending to be their favorite dialect? I like to think it is trying to create something new by taking the best features from both dialects. Scheme is the smallest, and CL is the biggest, so SKILL/SKILL++ is somewhere between. It's not as minimal and elegant as Scheme, and not as kitchen-sink and design-by-committee as CL. It has good support for pure functional programming like Scheme, but also good support for stateful iteration like CL. It supports unhygienic macros (which are widely regard as more powerful), while slowly adding support for hygienic macros (which are widely regard as much safer). It has an object system, but you are free to ignore it. It supports infix syntax, but you are free to (mostly) ignore that too.

    So SKILL appears to be a devil-may-care, happy-go-lucky language, lightheardedly doing its own thing rather than slavishly following the crowds. If Lisp is a language for non-conformists, SKILL is a dialect for non-comformists who refuse to conform to the other non-conformists! In this way it's a lot like Perl. If it had been free and open source back in the mid-80's, people might be using SKILL now instead of Perl, and Cadence might be a lot richer. :) But, like Xerox, Cadence wasn't in the software business (at least not that sort of software....)

    SKILL is so flexible, though, that it makes Perl look like Pascal. You can embed your own DSL's in SKILL very easily, because it's a Lisp.... Or you can pretend it's not Lisp (like my coworkers do) and write FORTRAN programs. It even has GOTO! SKILL just doesn't care. If Perl's motto is "there's more than one way to do it," and Python's is "there's only one (obvious) way to do it", then SKILL's motto is "whatever".

    Is SKILL supportive, or apathetic? Is it eager to please, or so code-weary that it can't even be bothered to care how you write your program?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tweeks
    tweeks over 10 years ago

    It's liberating that SKILL lets you adopt multiple styles, but it's also frustrating, because you can never follow any particular style completely. You can adopt some Scheme conventions, or Common Lisp conventions, or C conventions, but you can't use any one of them with complete consistency, even in a small program.

    So what do you do?  When there are seven ways to define a procedure (actually more if you include putd), which one do you choose? 

    I know def is a fossil from Franz Lisp, and is undocumented (although ironically it seems to be SKILL's primitive definitional construct that the others are built on), so one would not use that.  Besides, it's more verbose than the others.

    procedure and setq (the equals sign operator) are for infix programmers, so they're out, because I want to use one of Emacs' Lisp modes.

    defvar looks odd, and the forms with lambda are just needlessly verbose, so we're left with two practical contenders:

    (defun square (x) (times x x))
    (define (square x) (times x x))

    I've spent way too much time thinking about which one to use, and I've flip-flopped back and forth several times over the years.  (Some wag will say, "you should use defgeneric or defmethod!" but I'm ignoring that level of abstraction for now.)

    Choosing one or the other seems to be making a statement: "I am a Common Lisp programmer", or "I am a Scheme programmer". Of course it's not all-or-nothing, but once you choose one or the other, you naturally put Emacs in the mode that makes that particular keyword light up green, and then you're heading down that path.....  You choose whether to suffix your predicates with a "p" or a "?".  You choose whether to indicate destructive functions with an "n" or a "!".  You choose whether to use recursion or iteration, whether to embrace side-effects or to avoid them, whether to use keyword arguments liberally (like CL's core library) or prefer lots of smaller composable functions....

    SKILL doesn't care what you do.  You can mix and match in the same program!  You can alternate, define, defun, define, defun...   You can throw in a procedure here and there for variety.  You can avoid defining procedures entirely, stuff all your code in .il files, and just load them to run them!

    I like that SKILL is so supportive/apathetic about coding style, but at the same time it is a source of frustration, because there is no basis for choosing one way or the other on these stylistic issues, yet you must choose.  You must decide on conventions for your own code and stick to them, yet there's really no compelling reason to choose any particular one. 

    If I read Scheme books, I lean towards define.  If I read CL books, I lean towards defun.  Scheme is great because it's simple.  CL is great because it's complete.  Scheme is missing many things I want.  CL has a lot of things I don't want.  SKILL strikes a nice balance, but at the same time it takes no firm stand on even trivial things like how to define a procedure. 

    When should I use type-templates?  Are they always good?  Or can they be overdone?

    When should I use @key?  Is it always good?  Or can it be overused?

    Should I use docstrings?  Write Finder-compatible docs?  Should I include type information in a comment?  Should I include unit tests?  Specification-based tests?  Are there legitimate uses for go(to)?  When do I use error/errset and when do I use throw/catch?  When is it OK to define a macro?  When is it OK to define a macro-defining macro?

    There is no vast SKILL community publishing books and blogs to answer these sorts of questions.  The SKILL docs are very thin.  The SKILL community is small, and doesn't share much (with the exception of this forum).

    Basically SKILL programmers are given enough rope to hang themselves.  They're sent out into the world with very little guidance from the community at large as to how programs should be written, so they are free (good) to repeat others' mistakes over and over (bad).

    Naturally I look to the Common Lisp and Scheme and even Haskell communities for help in answering these questions, but they have their differences (due to differing philosophical presuppositions), so I get conflicting answers. 

    In the end, it seems human beings really can't agree on how programming ought to be done.  There is very little consensus on it, we just sort of make it up as we go.  The reason SKILL is such a big language with so much redudancy is no doubt because its developers were also making it up as they went.  Programmers worldwide cannot agree on how to use type information, unit tests, comments, macros, identifiers, and any other feature of a concrete programming language, simple or complex....  It is fitting that SKILL reflects humanity's confusion!

    fsck it, I'll use defun.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • theopaone
    theopaone over 10 years ago

     As kind of one of the "old" guys, having seen the development of EDA CAD from the 70's, user languages like SKILL were initially for the users, the programs were written by non programmers, layout designers and engineers who may have learned on Fortran (4 not 77) or pascal. We made it up as we went along, SKILL was a much more powerful language than its competitors but had to also cater to the layout designer who could barely use notepad or VI. As I lincreased my software engineering knowledge, I adopted certain styles and methodologies (Always used @key for optional arguments, extract the docStrings to create Finder docs, Unit tests - what's that? )

    Since I retired, I've been collecting what I think are the best practices of EDA programming, from the layout designer who wants to make a quick command to the developer writing a big application. I've considered writing a book, doing webinars on code quality, etc. I've looked at code written in multiple languages by hundreds of developers and it is so much easier to understand and debug when it adheres to a standard (any standard but is consistent).This is most important for maintainance, I had a customer developer from Moscow show up at my office in Austin with code I had written almost 12 years before and it was still readable and debuggable, except where they had made changes (and inserted the bug).  In another incarnation, I worked as part of a programming team where we all adopted the same style and you could not tell who wrote what, even the local variable naming was consistent. We all got the blame for any bugs.

    Adopt a style, document it (to share with others) and be consistent.

    Ted

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tweeks
    tweeks over 10 years ago

    Thanks Ted. :)

     Let me know if you write that book!  I recommend No Starch Press.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 10 years ago

    Lot's of things to answer here:

    tweeks said:
    It sounds like aliases are basically depricated now.

    No. Aliases are a SKILL mode thing rather than a SKILL++/Scheme mode thing - and in SKILL mode they can't be assigned anyway, in the same way that functions can't be assigned. So they are not deprecated.

    tweeks said:
    What is SKILL/SKILL++'s philosophy? Scheme is minimalist and favors a functional style. Common Lisp is large and favors iteration over recursion. SKILL is large like Common Lisp, and seems to favor iteration like Common Lisp (foreach's default is mapc rather than mapcar; the gdmSpec interface is stateful; tail call optimization was not added until quite recently, and it still doesn't work reliably (for me anyway)...), but its documentation makes a big deal about being compatible with Scheme, and SKILL++ (with the plus-plus suggesting incremental improvement over the original) moved in the direction of Scheme's evaluation semantics rather than Common Lisp's, yet it added an object system patterned after CLOS!

    Remember that SKILL is a pragmatic implementation where features are added because of demand rather than necessarily for idealistic reasons. A lot of the way it is are because of:

    1. history
    2. ensuring compatibilty - we do not want to break code that may have existed for 20 years

    On the history front, as you know, SKILL originated from a small LISP, Franz LISP. So it pre-dates both Common LISP and Scheme. Originally it was an interpreted language, which changed into a byte-code compiled (VM) language in the 4.3 release (in 1993, if my memory is correct). Around that time, there was an organization called CFI - the CAD Framework Initiative (I think) which had a goal of having Scheme as the customization language for lots of CAD tools. The "ils" mode of SKILL was an attempt to provide Scheme-like features within SKILL, without losing compatibility. There was initially a more aggressive Scheme implementation too, but the decision was made to adopt some of the concepts without the strict language compatibility with Scheme (such as case insensitivity, no infix operators, etc etc). At the same time there was an internal demand for an object system, primarily for the Analog Design Environment (aka Analog Artist) which had a home-grown object system but needed to be developed. This object system was based on CLOS, and so that was a logical choice for the implementation in SKILL. What was implemented was a much reduced version of CLOS, which only supported single inheritance, no multi-methods, and a few other restrictions. It wasn't deemed cost-effective to implement the whole of CLOS or other missing features from Common LISP on the off-chance that somebody might need it, when the vast majority of people writing SKILL were not programmers and certainly know little of either Scheme or Common LISP.

    As time went by, a few people asked for more Common LISP features to make their code simpler. Some of these add little value other than a different way of doing things - but some do add a valuable difference. For example, a number of the additions which came in for IC615 just add another way of doing something that was there already - flet and labels are the two I immediately debated their value. However, I have found myself using flet in the case where I intentionally wanted to wrap an existing function - doing this with nested defun/procedure feels a bit clunky. I'm so used to using nested defun/procedure because it's been there since 1995 when ils mode was added, that I didn't see any benefit in adoption some common LISP form that I'd not really used for many years. But flet has it's benefits. For example - here's an example I gave during a training class:

    let(((realarrayref arrayref))
      procedure(arrayref(arr ind)
        realarrayref(arr ind) || setarray(arr ind makeTable('tab nil))
      )
      a=makeTable('tab nil)
      a["hello"]["world"]["andrew"]=123
    )

    It shows a hash table that can have dimensions added automatically (a bit like perl - which was what the user on the course was saying was an advantage of perl that SKILL didn't have). It's in C-like syntax because it was an illustration for a user more comformatable with C syntax.

    However, with flet this clearer - none of this having to "rename" the arrayref via a local variable:

    flet(((arrayref (arr ind) arr[ind] || (arr[ind]=makeTable('tab nil))))
      a=makeTable('tab nil)
      a["hello"]["world"]["andrew"]=123
    )

    And then I can make this into a nice macro:

    defmacro(WithAutoHash (@rest body)
     `flet(((arrayref (arr ind) arr[ind] || (arr[ind]=makeTable('tab nil))))
       ,@body
      )
    )

    procedure(TrExampleArray()
      let(((arr makeTable('tab nil)))
        WithAutoHash(
          arr["my"]["big"]["test"]=7
          arr["my"]["other"]["test"]=9
          arr
        )
      )
    )

    However, I never find myself using labels. Two reasons - I find the name of the function counterintuitive - nothing in the name suggests to me that this defines functions using letrec semantic; secondly I can do all that just by declaring nested defuns.

    So with all of this, your mileage may vary. Coming up with a consistent style is a bit of a personal choice, as I think it is with any language. I have my own rules that I don't always stick to - for example, I tend to write most of my code in LISP-syntax, and I am pretty anal about not using operators but using functions - so I will write (times (plus a b) (difference a b)) rather than (a+b)*(a-b). I also tend to use defun when writing in LISP syntax. I won't mix and match LISP syntax and C syntax in the same file, but I will use C syntax if I know the target audience is more likely to want C syntax and also may want to understand and adapt the code - but then I use procedure rather than defun (usually). No good reasons for some of these, apart from trying some level of consistency. I never use define to define functions - only to define variables. And I never use defvar at all.

    I've learned that trying to suggest a set of global style guidelines is a thankless task which nobody will agree to (and quite probably I wouldn't agree to them myself!)

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tweeks
    tweeks over 10 years ago

    Thanks for clarifying the status of alias, and big thanks for the detailed history of Scheme mode and CLOS!  I had no idea CLOS was originally for ADE, but it makes sense (I noticed their class tree seems to be the largest).  Knowing the reasons why features were originally added to the language is very helpful in deciding when/how to use them, so this kind of background is invaluable.

    Thank you also for the good example of using flet over nested defuns.  I must show that WithAutoHash macro to my colleague who keeps talking up Perl over SKILL.  It should shut him up for a while. :)

    Andrew Beckett said:

    However, I never find myself using labels. Two reasons - I find the name of the function counterintuitive - nothing in the name suggests to me that this defines functions using letrec semantic; secondly I can do all that just by declaring nested defuns.

    The name probably derives from McCarthy's original Recursive Functions paper, where he introduced a primitive called label which made it possible to define recursive lambdas without resorting to deep lambda calculus trickery (i.e. the "Y-combinator").

    I think fletseq would have been a better name....

    Andrew Beckett said:

    I never use define to define functions - only to define variables. And I never use defvar at all.

    Do you use argument type templates?

    Do you use IL or ILS mode more often?

    Do you do anything special for constants (e.g. capitalize them)? 

    Do you favor iteration constructs like for, foreach, while, and do, or do you prefer recursion? 

    Have you ever used go? :)

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 10 years ago

     

    tweeks said:
    Do you use argument type templates?

    Sometimes. I'm a bit variable about this - sometimes I'll use them if I'm supplying an API which I am uncertain about the types that will be passed in.

    tweeks said:
    Do you use IL or ILS mode more often?

    If I'm writing single  functions which don't depend on lexical scoping or the object system, I probably tend to use IL mode. Mostly this is because I don't want people who pick up this code to be afraid of something that maybe they are less familiar with. However, for bigger code and bigger applications I'll nearly always use ILS mode. A quick analysis of the main SKILL files I've written over the last couple of years reveals something like 25-30% using ILS mode (I didn't check very carefully though).

    tweeks said:
    Do you do anything special for constants (e.g. capitalize them)? 

    No.

    tweeks said:
    Do you favor iteration constructs like for, foreach, while, and do, or do you prefer recursion? 

    I use both - so I wouldn't say I prefer one over the other. I certainly don't tend to use recursion when iteration is simple - I use recursion when it makes the algorithm more straightforward. Part of this is because of SKILL's limited stack size, and some is because there is a rich enough set of iteration functions in SKILL that mean that the recursive approach to a simple iteration doesn't add any value.

    tweeks said:
    Have you ever used go? :)

    What's go? (so that's no ;-> . I have a problem with goto in most languages having had structured programming drummed into me when I was at high school!)

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • theopaone
    theopaone over 10 years ago

     The only differences I have with Andrew are:

    1. Constants are a formal concept in my programs. They are write protected uppercase global symbols which have a value shared in SKILL and SKILL++.  Constants are common values such as rotations R0, R90, etc. Even the abutment function values are constants SERIES_CONNECT, PARALLEL_CONNECT, UN_ABUT, ... , ABUT_LEFT, ABUT_RIGHT etc. each resolving to their respective integer values. That way I don't have to remember what the actual value.

    2. recursion is a monster to debug, especially if the code is not directly recursive -> A calls B calls C calls A. I prefer the iteration constructs, they could be improved if they were real iterators instead of having to build a list in VM.

    3. Without a break or continue for loops, go is somewhat but seldom useful. My first language was Fortran IV with goto's, on punch cards, almost prehistoric school.

    Ted

    • 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