• 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 do I access the real value of a resistor used in a transient...

Stats

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

How do I access the real value of a resistor used in a transient simulation at a given PVT?

CADcasualty
CADcasualty over 6 years ago

I have a schematic that contains a "smart note" that evaluates a SKILL expression and displays the result on the schematic. The basis of this comes from Andrew Beckett's code that uses dynamic scoping to temporarily set ilInstPath which allows me to access information about instances via their cdsParams.

My schematic depicts a simple resistively loaded, differential amplifier whose gain is just gm*R and I want the smart note to display that gain after a transient sim completes. At the completion of the sim the skill code in the note interrogates the transistor and extracts it's gm (via transient operating point annotations) but I can't similarly extract the value of the resistor because TSMC annoyingly didn't provide transient operating point capability for resistors (or capacitors, but they did for transistors). The actual resistor value is a function of temperature and what process corner I'm in, but I don't know how to get the actual value so that I can calculate gm*R. I know R=V/I but the resistors don't appear to be enabled to provide transient current annotations either. Is there an alternative way access the value of a resistor used in a transient simulation?

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

    The issue is (probably) that it's not specifically a resistor but a subckt model - and so something needs to be done to compute the effective resistance with knowledge of what's inside it.

    Without seeing the specifics, I'm not sure I can advise more. Perhaps you could contact customer support and reference this post - I'd be happy to take a look with you on this (in other words, when they see this, they'll know it's OK to assign the case to me). By the way, that's not an open invitation to everyone on the forums to ask to assign their cases to me!

    Andrew.

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

    I'm on the road for a little while so I'll close the loop on this shortly. In the meantime, I'll look into your (correct) point about the resistor being a subckt - that may be enough of a clue for me to fix this. Thanks.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • CADcasualty
    CADcasualty over 6 years ago in reply to CADcasualty

    Some random thoughts until I get back:

    One thing I forgot to mention was that if I run a DC operating point sim and enable DC operating point annotations then the final resistance value I'm after is annotated on the resistor - my original post was because when I ran a transient sim and enabled transient operating point annotations the resistors didn't show any annotations at all. Because DC annotations do the right thing I'm now thinking this might not be a TSMC issue but rather a Cadence issue.

    A coworker got back to me and confirmed that the resistor I'm using is a indeed a subcircuit (it contains a 2 resistors in series - rmain and rend).

    The coworker was also running a transient simulation and within the environment he was using (I just make and run Ocean scripts) and was able to ask the tool to get the transient operating point information for the resistor e.g.
    value(OPT("stage1.ampm.rp.rmain" "res") 500n) -> 3798.053
    value(OPT("stage1.ampm.rp.rend" "res") 500n) -> 58.88665

    My "smart note" (which obviously shouldn't need to know the hierarchical level of the schematic that contains it) currently receives the ilInst of the resistor but I don't know how to get the final resistance from that.

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

    The way this would usually work is for the device which is implemented as a subckt to have opParamExprList defined in the CDF which then gives the expression needed to compute the effective resistance of the underlying components. Then you would be able to annotate that computed parameter on the instance, and your smart note ought to be able to access it to via the ilInstPath magic approach.

    That way your smart note doesn't need to know there's anything special - only the device itself needs to know that itself is special, which is the right place for it's awareness of how special it is to be stored.

    There are a few articles about setting this up (a bit in the documentation too), but the reason why transient operating points are not working is probably because the PDK also would need optParamExprList (as well as opParamExprList) to be defined. See ADE Transient operating points are not printed for devices defined within subcircuits

    Regards,

    Andrew.

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

    Thanks Andrew - I'll bet I now have enough information to get this working. You're the best!

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • CADcasualty
    CADcasualty over 6 years ago in reply to CADcasualty

    So I was able to get this working based on your guidance! It turns out that while the resistor did have a opParamExprList set in the CDF (for Spectre) it did not have optParamExprList set. I checked the parameters for the Hspice simulator and it DID have both set - in fact they both contained the exactly same text. So I took the Spectre opParamExprList text and just copied it into the optParamExprList field and it worked :-).

    So now all that remained was to effectively do all of that in my .cdsinit. When I copied the text into the optParamExprList field in the CDF editor window I saw the following in the CIW:

    opForm->tabField->topTab2->optParamExprListspectre->value="(\"res\" \"OP(mappedRoot(\\\".rend\\\") \\\"res\\\")+OP(mappedRoot(\\\".rmain\\\") \\\"res\\\")\") (\"i\" \"OP(mappedRoot(\\\".rend\\\") \\\"i\\\")\") (\"v\" \"OP(mappedRoot(\\\".rend\\\") \\\"i\\\")*(OP(mappedRoot(\\\".rend\\\") \\\"res\\\")+OP(mappedRoot(\\\".rmain\\\") \\\"res\\\"))\")"

    Based on other CDF parameters I've set in my .cdsinit I subsequently tried:

    cdfCreateUserCellCDF(ddGetObj("tsmc18" "rppo1rpo_pure5v"))->optParamExprListspectre = "(\"res\" \"OP(mappedRoot(\\\".rend\\\") \\\"res\\\")+OP(mappedRoot(\\\".rmain\\\") \\\"res\\\")\") (\"i\" \"OP(mappedRoot(\\\".rend\\\") \\\"i\\\")\") (\"v\" \"OP(mappedRoot(\\\".rend\\\") \\\"i\\\")*(OP(mappedRoot(\\\".rend\\\") \\\"res\\\")+OP(mappedRoot(\\\".rmain\\\") \\\"res\\\"))\")"

    but it didn't work. So I reckon we're really close here, but I don't know how to put the cherry on top...

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

    First of all, get the CCSdeepCopy function from Copies of disembodied property lists still have links to each other

    Then do:

    userCdf=cdfCreateUserCellCDF(ddGetObj("tsmc18" "rppo1rpo_pure5v"))
    baseCdf=cdfGetBaseCellCDF(ddGetObj("tsmc18" "rppo1rpo_pure5v"))
    userCdf->simInfo=CCSdeepCopy(baseCdf->simInfo)
    userCdf->simInfo->spectre->optParamExprList=copy(userCdf->simInfo->spectre->opParamExprList)

    Something like that. Note, this is not tested but something along those lines should be OK. With simInfo, you can't just incrementally add the different bits - you have to start off with the simInfo from the base and then tweak it - and the deepCopy and copy are done to prevent the lists interfering with each other (because -> is a destructive list operator). Otherwise strange things would probably happen...

    I'd try the above and then bring up the Effective CDF in the Tools->CDF->Edit form and see whether it looks OK.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 6 years ago in reply to CADcasualty

    First of all, get the CCSdeepCopy function from Copies of disembodied property lists still have links to each other

    Then do:

    userCdf=cdfCreateUserCellCDF(ddGetObj("tsmc18" "rppo1rpo_pure5v"))
    baseCdf=cdfGetBaseCellCDF(ddGetObj("tsmc18" "rppo1rpo_pure5v"))
    userCdf->simInfo=CCSdeepCopy(baseCdf->simInfo)
    userCdf->simInfo->spectre->optParamExprList=copy(userCdf->simInfo->spectre->opParamExprList)

    Something like that. Note, this is not tested but something along those lines should be OK. With simInfo, you can't just incrementally add the different bits - you have to start off with the simInfo from the base and then tweak it - and the deepCopy and copy are done to prevent the lists interfering with each other (because -> is a destructive list operator). Otherwise strange things would probably happen...

    I'd try the above and then bring up the Effective CDF in the Tools->CDF->Edit form and see whether it looks OK.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • CADcasualty
    CADcasualty over 6 years ago in reply to Andrew Beckett

    Yep - that fixed it and I'm all good to go! Thank you so much!

    The only lingering thing that puzzles me a bit was that for Hspice the CDFs for both opParamExprList and optParamExprList came preset to:

    ("res" "OP(mappedRoot(\"^rend\") \"res\")+OP(mappedRoot(\"^rmain\") \"res\")") ("i" "OP(mappedRoot(\"^rend\") \"i\")") ("v" "OP(mappedRoot(\"^rend\") \"i\")*(OP(mappedRoot(\"^rend\") \"res\")+OP(mappedRoot(\"^rmain\") \"res\"))")

    I've now just done the same thing for Spectre, but I would have thought that for both Hspice and Spectre the optParamExprList would have used OPT(stuff) instead of OP(stuff). Either way (for the stuff I'm doing) what you provided does what I want/need.

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

    That is a bit odd - I too would expect the expression to use OPT. I haven't experimented to make sure it's really annotating the transient operating point rather than the DC operating point, but I'm sure you can check that to be sure...

    Regards,

    Andrew.

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

    I just tried it - OP and OPT behave the same at different time points (and each time point actually has different operating point data). Curious... That likely means I probably should be using OPT for the optParamExprList parameter because there might be a use case I haven't tried yet that breaks when using OP.

    When I do userCdf->simInfo->spectre->opParamExprList I get:

    (("res" "OP(mappedRoot(\".rend\") \"res\")+OP(mappedRoot(\".rmain\") \"res\")")
    ("i" "OP(mappedRoot(\".rend\") \"i\")")
    ("v" "OP(mappedRoot(\".rend\") \"i\")*(OP(mappedRoot(\".rend\") \"res\")+OP(mappedRoot(\".rmain\") \"res\"))")
    )

    which is a list, and a little beyond my skill level (pun intended ;-) ) to figure out how to replace all the "OP(" bits with "OPT(" so I can subsequently stick that into

    userCdf->simInfo->spectre->optParamExprList

    Now I can fully appreciate that this topic is way too fringe to be of much use to anybody else in the forums, so if you decided to bail out at this point I'm OK (especially given that what you've provided already works and that I'm not even sure it's worth going down this road).

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

    With a bit of a recursive function and some pattern matching, it's not too bad - with this code:

    procedure(abCopyAndReplaceOpParamExprList(l1 @key pat (from "OP\\(") (to "OPT("))
      unless(pat
        pat=pcreCompile(from)
      )
      foreach(mapcar elem l1
        case(type(elem)
          (list abCopyAndReplaceOpParamExprList(elem ?pat pat ?to to))
          (string pcreReplace(pat elem to 0))
          (t elem)
        )
      )
    )

    You can then do:

    userCdf->simInfo->spectre->optParamExprList=abCopyAndReplaceOpParamExprList(userCdf->simInfo->spectre->opParamExprList)

    I don't know whether there is indeed some case where OPT is needed over OP, but at least the above code should do the mapping for you.

    Regards,

    Andrew.

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

    That code is just way beyond my pay grade...

    Speaking on behalf of this forum, you do know you're not allowed to ever retire, right? ;-)

    • 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