• 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. Using sweep names and values with famMap()

Stats

  • Locked Locked
  • Replies 5
  • Subscribers 144
  • Views 16288
  • 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

Using sweep names and values with famMap()

sgreenwo
sgreenwo over 10 years ago

The famMap() function can be used to extend a waveform-processing function to families of waveforms. I've found various examples on Support, Community, comp.cad.cadence, etc. on how to use this function to perform an operation on a family of waveforms, such as Andrew's nice explanation here. Rather than merely operating on data from each element in a family, I want to associate the sweep name and sweep value with data from each member of the family. Because the sweep depth can vary (i.e., length(sweepNames()) will vary), I tried to apply recursion with famMap().

The idea was that if the procedure argument was a waveform, I could strip off the sweep values from the waveform's XVec; if the argument was a family, I would use famGetSweepValues() and pass them into the function using famMap(). For simplicity, the code below is a stripped-down version of what I tried. This version attempts to print the "vds" parameter of FET instance "/Mn1" for each member of the family, while also printing the sweep values for each member.

-------------------------------------------------------------

;;; procedure to print vds

procedure( famVdsPrint( fileName cnrStr famVds)

cond(

  ; Waveform case - print the results
  (drIsWaveform(famVds)
  Xvec = drGetWaveformXVec(famVds)
  Xlen = drVectorLength(Xvec)
  Yvec_vds = drGetWaveformYVec(famVds)

  for(i 0 Xlen-1

    paramVal = strcat(cnrStr "_" sprintf(nil "%g" drGetElem(Xvec i)))
    vds = 1e3 * drGetElem(Yvec_vds i)
    fprintf(fileName "%s,%.1f\n" paramVal vds)
  )
)

; Waveform family case - apply recursion
(famIsFamily(famVds)
  foreach(sweepVal famGetSweepValues(famVds)
    famMap('famVdsPrint fileName strcat(sprintf(nil "%g" sweepVal) cnrStr) famValue(localFamVds sweepVal))
  ) 
)

; Error case
(t
  error("Error: procedure famVdsPrint can't handle %L\n" famVds)
)

)

)

-------------------------------------------------------------

[run a simulation with 3 nested parametric analyses, and open the results]

-------------------------------------------------------------

selectResult('dcOpInfo)

fam_vds = pv("/Mn1" "vds") ;

fileName = outfile("/myPath/myFileName.csv" "w")

famVdsPrint( fileName "" fam_vds)

-------------------------------------------------------------

That did not work. The waveform case works as intended, so the inner-most sweep is fine. The procedure correctly prints the "vds" values for each family member, but incorrectly prints only the outer-most sweep values as it loops through all the family members. Thinking that this might be a variable-scoping problem, I tried to make the variables local by modifying the family case as follows:

-------------------------------------------------------------

; Waveform family case - apply recursion

(famIsFamily(famVds)
  let( (localFamVds)
    localFamVds = famVds
    foreach(sweepVal famGetSweepValues(localFamVds)
      famMap('famVdsPrint fileName strcat(sprintf(nil "%g" sweepVal) cnrStr) famValue(localFamVds sweepVal))
    )
  )
)

-------------------------------------------------------------

Same failed result.

I am not set on any particular implementation. Another idea that occurred to me was to use famToList(fam_vds), but I could not figure out how to print the list elements recursively.

I would appreciate any help in associating family data with its sweep values. I did a fair amount of searching, but my apologies if this has been answered elsewhere. 

Best Regards,

Stephen Greenwood

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

    Stephen,

    You might find this useful too. It takes a family, and produces a list of abFamilySignal objects, for each leaf waveform. As part of doing this, it constructs a name which contains the sweep name and value. I did this as part of some code which generates a "VCSV" (ViVA CSV) file from arbitrary results - I've not included the entire code, but the key part is here. May not be quite what you want, but it may be illustrative of an approach you could take.

    Regards,

    Andrew.

    ;------------------------------------------------------------------------
    ; Container structure to keep the cleaned signal name,
    ; length, whether it's complex etc
    ;------------------------------------------------------------------------
    (defstruct abFamilySignal wave name len isComplex)
    
    /*****************************************************************
    *                                                                *
    * (abUnwrapFamily fam @optional topName top (level 0) (name "")) *
    *                                                                *
    *    Convert a family or waveform into a flat list of single     *
    *  waveforms, wrapped by an abFamilySignal container structure   *
    *                                                                *
    *****************************************************************/
    
    (defun abUnwrapFamily (fam @optional topName top (level 0) (name ""))
      (let (dim sweepName)
        (unless top (setq top fam))
        (setq dim (if (or (famIsFamily top) (drIsWaveform top))
                    (drWaveformGetDimension top)
                    0))
        (cond
          ((and (famIsFamily top) (lessp level (sub1 dim)))
           (setq sweepName (famGetSweepName top level))
           (foreach mapcan sweepValue (famGetSweepValues fam)
                    (abUnwrapFamily 
                      (famValue fam sweepValue) topName top (add1 level) 
                      (sprintf nil "%s (%s=%Y)" name sweepName sweepValue))
                    )
           )
          (t (list (make_abFamilySignal 
                     ?wave fam 
                     ; the messing with strcat in format is to stop SCCS doing 
                     ; keyword substitution!
                     ?name (sprintf nil (strcat "%Y" "%s")
                                    (or topName (famGetExpr top)) name))))
          )
        )
      )
    
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 10 years ago

    Stephen,

    You might find this useful too. It takes a family, and produces a list of abFamilySignal objects, for each leaf waveform. As part of doing this, it constructs a name which contains the sweep name and value. I did this as part of some code which generates a "VCSV" (ViVA CSV) file from arbitrary results - I've not included the entire code, but the key part is here. May not be quite what you want, but it may be illustrative of an approach you could take.

    Regards,

    Andrew.

    ;------------------------------------------------------------------------
    ; Container structure to keep the cleaned signal name,
    ; length, whether it's complex etc
    ;------------------------------------------------------------------------
    (defstruct abFamilySignal wave name len isComplex)
    
    /*****************************************************************
    *                                                                *
    * (abUnwrapFamily fam @optional topName top (level 0) (name "")) *
    *                                                                *
    *    Convert a family or waveform into a flat list of single     *
    *  waveforms, wrapped by an abFamilySignal container structure   *
    *                                                                *
    *****************************************************************/
    
    (defun abUnwrapFamily (fam @optional topName top (level 0) (name ""))
      (let (dim sweepName)
        (unless top (setq top fam))
        (setq dim (if (or (famIsFamily top) (drIsWaveform top))
                    (drWaveformGetDimension top)
                    0))
        (cond
          ((and (famIsFamily top) (lessp level (sub1 dim)))
           (setq sweepName (famGetSweepName top level))
           (foreach mapcan sweepValue (famGetSweepValues fam)
                    (abUnwrapFamily 
                      (famValue fam sweepValue) topName top (add1 level) 
                      (sprintf nil "%s (%s=%Y)" name sweepName sweepValue))
                    )
           )
          (t (list (make_abFamilySignal 
                     ?wave fam 
                     ; the messing with strcat in format is to stop SCCS doing 
                     ; keyword substitution!
                     ?name (sprintf nil (strcat "%Y" "%s")
                                    (or topName (famGetExpr top)) name))))
          )
        )
      )
    
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
No Data

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