Home
  • Products
  • Solutions
  • Support
  • Company

This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  • Products
  • Solutions
  • Support
  • Company
Community Custom IC Design How to access the result of a netcap info analysis in ADE...

Stats

  • Locked Locked
  • Replies 8
  • Subscribers 126
  • Views 5716
  • 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 to access the result of a netcap info analysis in ADE?

Zol
Zol over 1 year ago

Hello everybody,

Is there a way to print Ctotal of a net from the results of spectre's netcap info analysis? I hoped there is something like getData("/my_net" "Ctotal" ?result "netcap-info"), what I could add to the Results tab in ADE Explorer/Assembler.

I do not see any corresponding analysis names among the results in CIW:

results()
(dcOp dcOpInfo ac primitives subckts
asserts variables
)

Thanks,
Zoltan

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 1 year ago

    Zoltan,

    The netcap and allcap outputs from the info analysis don't save into a PSF database, but instead generate an SQL database that is used to populate the Capacitance view in ADE. You can look at the results from different sweep points, corners, and set up queries to look for particular nets and capacitances over certain values. You can't get to the data via OCEAN functions though - in some cases there is a PSF database produced (if where=rawfile is set) but it only contains some header information and no actual capacitance data.

    Regards,

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • ShawnLogan
    ShawnLogan over 1 year ago in reply to Andrew Beckett

    Dear Zoltan and Andrew,

    I am not sure f I am misunderstanding the Assembler manual regarding the use of net capacitance, but in the Feb 2023 version of the manual on page 1073, it states:

    "The net capacitance data is saved in the netlist.info.netcap file in ASCII format."

    If so, Zoltan, and you want to create either a single file or multiple files (one for each corner) containing the total capacitance, you might be able to using the following ocean script. The script traverses the results directory hierarchy and parses the netlist.info.netcap file in each netlist directory and saves the value for the net you specified ("my_net") in a unique filename. You could also modify the script to produce a single file with all the corner values of net "my_net" identified with the corner name. Hopefully, I've included enough comments for you to easily modify it for your results directory and number of corner simulations. To upload the file to the Forum, I had to change the extension from the normal ocean script extension of ".ocn" to ".txt". If you change the extension to ".ocn", you may run the script from the UNIX command line in your working directory using the command:

    ocean -nograph < sample_ocean_script_netcap.ocn > ocean_output.log

    or

    ocean -nograph -replay sample_ocean_script_netcap.ocn -log ocean_output.log

    The latter loads your .oceanrc file.

    or simply load the file if was placed in your working directory in the CIW using:

    load "sample_ocean_script_netcap.ocn"

    I could not test it, but modified a working script. If it is something you are interested in - but wanted to at least note the fact that it appears an ASCII file appears to be available with the netcap information that can be accessed using an ocean script.

    Shawn

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • ShawnLogan
    ShawnLogan over 1 year ago in reply to ShawnLogan

    The sample ocean file  with comments for you to modify it is attached.

    Fullscreen sample_ocean_script_netcap.txt Download
    ; Main routine
    
    simulator('spectre)
    
    base_results=strcat("<path_to_your_results>/results/data/Interactive.0/")
    sub_dir = strcat("<ADE test name>")
    
    TSTOP = 30e-09
    
    init_val = 1
    final_val = <number_of_corners>
    
    sim_case = init_val
    while( sim_case < (final_val + 1)
    
    printf("sim_case = %d\n" sim_case)
    sprintf(sim_case_val "%d" sim_case)
    
    ; Define unique output file for each ADE set of simulation results
    
    fname = strcat("<your output file name>" "_" sim_case_val ".csv")
    fp_params = outfile( fname "w")
    
    results = strcat( base_results sim_case_val sub_dir "psf")
    netlist_dir = strcat( base_results sim_case_val sub_dir "netlist")
    
    netcap_filename = strcat("netlist.info.netcap")
    
    ; Total cap appears to be 14th column of file netlist.info.netcap
    ; I'm not sure of the delimiter so am using a space - change this to
    ; the proper delimiter. I am also saving the net name which is in
    ; column 4
    
    sprintf(cut_field_14_command "cut -d\" \" -f4,14")
    
    sprintf(apply_cut_command "%s > ./tempfile\n" cut_field_14_command strcat(netlist_dir "/" netcap_filename) )
    sprintf(grep_net_command "grep my_net ./tempfile > %s\n" fname)
    
    system(apply_cut_command)
    system(grep_net_command)
    system("rm ./tempfile\n")
    close(fp_params)
    
    sim_case = sim_case + 1
    
    ) ; end sim_case loop
    
    
    exit()
    

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 1 year ago in reply to ShawnLogan

    Except this code won't actually work. I didn't try it out (because I could see it doesn't work). For a start, the cut command won't deal with the fact that there are multiple spaces between the columns - and I don't know where columns 4 and 14 came from in your code. The net name and total capacitance were in the 1st and 11th field in the example I tried. You could achieve that with:

    tr -s ' ' < input.info.netcap | cut -d ' ' -f 1,11

    but maybe better to do the search and find the final field in the same line using awk:

    awk '$1=="I0.pcasc"{print $NF}' input.info.netcap

    Of course, this could be built into the SKILL code. Or you could just parse the file using SKILL directly which wouldn't be that hard.

    (the bit about writing an ASCII file was correct; we covered that in Zoltan's other post).

    Andrew

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 1 year ago in reply to Andrew Beckett

    Zoltan,

    I went into a little bit of a rat hole on this and ended up writing a set of utilities to deal with ASCII net capacitance files. The details can be found in this SKILL code (examples of usage near the top):

    /* abParseNetCap.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Sep 20, 2023 
    Modified   
    By         
    
    Some utility functions for parsing the output of a spectre info analysis
    with what=netcap and where=file. The results are saved into an ASCII file
    (and in ADE that's usually in the netlist dir and called input.info.netcap)
    
    Note that these functions don't handle re-evaluation as in that case the
    asiGetCurrentSession() that is used is for the root of all the runs rather
    than for each individual run. 
    
    The file uses SKILL++ lexical scoping, so ensure that the file retains the
    suffix .ils. The file should be loaded in both your .cdsinit and .vdsinit
    by adding load("/path/to/abParseNetCap.ils")
    
    Examples of functions you can put in ADE outputs:
    
    ; note that the file read is cached so that it doesn't have to keep
    ; reading the file for each separate output
    abNetCap("OUTP")
    abNetCap("ibias")
    ; output Cestimated instead of Ctotal
    abNetCap("ibias" ?capacitance "Cestimated") 
    
    ; output a CSV in the netlist dir (the curly brackets are so that this returns
    ; 0 so nothing complains as ADE expects numerical outputs)
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv") 0}
    ; output a CSV just containing Ctotal
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv" 
      ?columns "Ctotal") 0}
    ; output a CSV just containing Ctotal and Cestimated
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv" 
      ?columns list("Ctotal" "Cestimated")) 0}
    
    ***************************************************
    
    SCCS Info: @(#) abParseNetCap.ils 09/20/23.13:57:50 1.1
    
    */
    
    /***********************************************************************
    *                                                                      *
    *                         abParseNetCap(file)                          *
    *                                                                      *
    *  Parse the ASCII netcap file from an info analysis with what=netcap  *
    * and return a table indexed by the net name, each entry of which is a *
    *                 table index by the column headings.                  *
    *                                                                      *
    ***********************************************************************/
    procedure(abParseNetCap(file)
      let((port line (netcaps makeTable('netcaps nil)) headers readingCaps 
          netcap data netName (spaceSuffixSpace pcreCompile(" ([a-zA-Z]) ")))
        when(port=infile(file)
          while(gets(line port)
            cond(
              (readingCaps
                ;----------------------------------------------------------
                ; Replace all suffixes with a space before them (with eng
                ; notation, spectre rather strangely adds a space before the
                ; suffix)
                ;----------------------------------------------------------
                line=pcreReplace(spaceSuffixSpace line "\\1 " 0)
                data=parseString(line)
                if(car(data) then
                  netName=car(data)
                  netcap=makeTable('capInfo nil)
                  foreach((field value) cdr(headers) cdr(data)
                    if(field=="NetType" then
                      netcap[field]=value
                    else
                      netcap[field]=aelNumber(value)
                    )
                  )
                  netcaps[netName]=netcap
                else
                  readingCaps=nil
                )
              )
              ;--------------------------------------------------------------
              ; using strncmp to compare as the common alternative causes
              ; issues with the forums! (sorry about being opaque about its name)
              ;--------------------------------------------------------------
              (zerop(strncmp(line "NetName" 7))
                headers=parseString(line)
                readingCaps=t
              )
            )
          )
          close(port)
          netcaps
        )
      )
    )
    
    /******************************************************************
    *                                                                 *
    *        abConvertNetCapToCSV(inFileName outFileName @key         *
    *                       columns (sorted t))                       *
    *                                                                 *
    *  Given an ASCII netcap file as input, output a CSV. Can either  *
    * have all columns (by default), or just the given column(s). The *
    *   column can be a single string (e.g. "Ctotal") or a list of    *
    *  column names. The default is that the net names are sorted in  *
    *                           output file                           *
    *                                                                 *
    ******************************************************************/
    procedure(abConvertNetCapToCSV(inFileName outFileName @key 
        columns (sorted t))
      let((outport netcaps netNames netcap)
        when(netcaps=abParseNetCap(inFileName)
          netNames=if(sorted sort(netcaps->? 'alphalessp) netcaps->?)
          cond(
            (stringp(columns) columns=list(columns))
            (!columns columns=sort(netcaps[car(netNames)]->? 'alphalessp))
          )
          when(outport=outfile(outFileName)
            fprintf(outport "NetName")
            foreach(column columns
              fprintf(outport ",%s" column)
            )
            fprintf(outport "\n")
            foreach(netName netNames
              fprintf(outport "%s" netName)
              netcap=netcaps[netName]
              foreach(column columns
                fprintf(outport ",%L" netcap[column])
              )
              fprintf(outport "\n")
            )
            close(outport)
          )
        )
      )
    )
    
    /***************************************************************
    *                                                              *
    *            abParseNetCapFromNetlistDir(file @key             *
    *              (session asiGetCurrentSession()))               *
    *                                                              *
    *     As abParseNetCap but relative to the netlist dir for     *
    *         the given asi session (defaults to current)          *
    *                                                              *
    ***************************************************************/
    procedure(abParseNetCapFromNetlistDir(file @key 
        (session asiGetCurrentSession()))
      let((netDir)
        when(netDir=asiGetNetlistDir(session)
          abParseNetCap(strcat(netDir "/" file))
        )
      )
    )
    
    /***********************************************************************
    *                                                                      *
    *    abConvertNetCapToCSVFromNetlistDir(inFileName outFileName @key    *
    *                          columns (sorted t)                          *
    *                  (session asiGetCurrentSession()))                   *
    *                                                                      *
    * As abConvertNetCapToCSV but with the input and output files relative *
    *         to the netlist directory for the given asi session.          *
    *                                                                      *
    ***********************************************************************/
    procedure(abConvertNetCapToCSVFromNetlistDir(inFileName outFileName @key 
        columns (sorted t)
        (session asiGetCurrentSession()))
      let((netDir)
        when(netDir=asiGetNetlistDir(session)
          abConvertNetCapToCSV(
            strcat(netDir "/" inFileName)
            strcat(netDir "/" outFileName)
            ?sorted sorted
            ?columns columns
          )
        )
      )
    )
    
    ;------------------------------------------------------------------------
    ; A lexical scope containing a single global function and some
    ; variables to manage the caching of the net cap info
    ;------------------------------------------------------------------------
    let((lastFullPath lastModTime lastNetcaps)
      /***************************************************************
      *                                                              *
      *         abNetCap(netName @key (capacitance "Ctotal")         *
      * (session asiGetCurrentSession()) (file "input.info.netcap")) *
      *                                                              *
      *  A convenient function to use in an ADE output which allows  *
      * you to retrieve the capacitance (default Ctotal) for a given *
      * net. Uses caching to avoid reading the file multiple times.  *
      *                                                              *
      ***************************************************************/
      globalProc(abNetCap(netName @key (capacitance "Ctotal") 
            (session asiGetCurrentSession()) (file "input.info.netcap")
          )
        let((netDir fullPath modTime)
          when(netDir=asiGetNetlistDir(session)
            fullPath=strcat(netDir "/" file)
            modTime=fileTimeModified(fullPath)
            when(fullPath!=lastFullPath || modTime!=lastModTime
              lastFullPath=fullPath
              lastModTime=modTime
              lastNetcaps=abParseNetCap(fullPath)
            )
          )
          when(lastNetcaps
            lastNetcaps[netName][capacitance]
          )
        )
      )
    )
    

    Andrew

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett over 1 year ago in reply to Andrew Beckett

    Zoltan,

    I went into a little bit of a rat hole on this and ended up writing a set of utilities to deal with ASCII net capacitance files. The details can be found in this SKILL code (examples of usage near the top):

    /* abParseNetCap.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Sep 20, 2023 
    Modified   
    By         
    
    Some utility functions for parsing the output of a spectre info analysis
    with what=netcap and where=file. The results are saved into an ASCII file
    (and in ADE that's usually in the netlist dir and called input.info.netcap)
    
    Note that these functions don't handle re-evaluation as in that case the
    asiGetCurrentSession() that is used is for the root of all the runs rather
    than for each individual run. 
    
    The file uses SKILL++ lexical scoping, so ensure that the file retains the
    suffix .ils. The file should be loaded in both your .cdsinit and .vdsinit
    by adding load("/path/to/abParseNetCap.ils")
    
    Examples of functions you can put in ADE outputs:
    
    ; note that the file read is cached so that it doesn't have to keep
    ; reading the file for each separate output
    abNetCap("OUTP")
    abNetCap("ibias")
    ; output Cestimated instead of Ctotal
    abNetCap("ibias" ?capacitance "Cestimated") 
    
    ; output a CSV in the netlist dir (the curly brackets are so that this returns
    ; 0 so nothing complains as ADE expects numerical outputs)
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv") 0}
    ; output a CSV just containing Ctotal
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv" 
      ?columns "Ctotal") 0}
    ; output a CSV just containing Ctotal and Cestimated
    {abConvertNetapToCSVFromNetlistDir("input.info.netcap" "netcap.csv" 
      ?columns list("Ctotal" "Cestimated")) 0}
    
    ***************************************************
    
    SCCS Info: @(#) abParseNetCap.ils 09/20/23.13:57:50 1.1
    
    */
    
    /***********************************************************************
    *                                                                      *
    *                         abParseNetCap(file)                          *
    *                                                                      *
    *  Parse the ASCII netcap file from an info analysis with what=netcap  *
    * and return a table indexed by the net name, each entry of which is a *
    *                 table index by the column headings.                  *
    *                                                                      *
    ***********************************************************************/
    procedure(abParseNetCap(file)
      let((port line (netcaps makeTable('netcaps nil)) headers readingCaps 
          netcap data netName (spaceSuffixSpace pcreCompile(" ([a-zA-Z]) ")))
        when(port=infile(file)
          while(gets(line port)
            cond(
              (readingCaps
                ;----------------------------------------------------------
                ; Replace all suffixes with a space before them (with eng
                ; notation, spectre rather strangely adds a space before the
                ; suffix)
                ;----------------------------------------------------------
                line=pcreReplace(spaceSuffixSpace line "\\1 " 0)
                data=parseString(line)
                if(car(data) then
                  netName=car(data)
                  netcap=makeTable('capInfo nil)
                  foreach((field value) cdr(headers) cdr(data)
                    if(field=="NetType" then
                      netcap[field]=value
                    else
                      netcap[field]=aelNumber(value)
                    )
                  )
                  netcaps[netName]=netcap
                else
                  readingCaps=nil
                )
              )
              ;--------------------------------------------------------------
              ; using strncmp to compare as the common alternative causes
              ; issues with the forums! (sorry about being opaque about its name)
              ;--------------------------------------------------------------
              (zerop(strncmp(line "NetName" 7))
                headers=parseString(line)
                readingCaps=t
              )
            )
          )
          close(port)
          netcaps
        )
      )
    )
    
    /******************************************************************
    *                                                                 *
    *        abConvertNetCapToCSV(inFileName outFileName @key         *
    *                       columns (sorted t))                       *
    *                                                                 *
    *  Given an ASCII netcap file as input, output a CSV. Can either  *
    * have all columns (by default), or just the given column(s). The *
    *   column can be a single string (e.g. "Ctotal") or a list of    *
    *  column names. The default is that the net names are sorted in  *
    *                           output file                           *
    *                                                                 *
    ******************************************************************/
    procedure(abConvertNetCapToCSV(inFileName outFileName @key 
        columns (sorted t))
      let((outport netcaps netNames netcap)
        when(netcaps=abParseNetCap(inFileName)
          netNames=if(sorted sort(netcaps->? 'alphalessp) netcaps->?)
          cond(
            (stringp(columns) columns=list(columns))
            (!columns columns=sort(netcaps[car(netNames)]->? 'alphalessp))
          )
          when(outport=outfile(outFileName)
            fprintf(outport "NetName")
            foreach(column columns
              fprintf(outport ",%s" column)
            )
            fprintf(outport "\n")
            foreach(netName netNames
              fprintf(outport "%s" netName)
              netcap=netcaps[netName]
              foreach(column columns
                fprintf(outport ",%L" netcap[column])
              )
              fprintf(outport "\n")
            )
            close(outport)
          )
        )
      )
    )
    
    /***************************************************************
    *                                                              *
    *            abParseNetCapFromNetlistDir(file @key             *
    *              (session asiGetCurrentSession()))               *
    *                                                              *
    *     As abParseNetCap but relative to the netlist dir for     *
    *         the given asi session (defaults to current)          *
    *                                                              *
    ***************************************************************/
    procedure(abParseNetCapFromNetlistDir(file @key 
        (session asiGetCurrentSession()))
      let((netDir)
        when(netDir=asiGetNetlistDir(session)
          abParseNetCap(strcat(netDir "/" file))
        )
      )
    )
    
    /***********************************************************************
    *                                                                      *
    *    abConvertNetCapToCSVFromNetlistDir(inFileName outFileName @key    *
    *                          columns (sorted t)                          *
    *                  (session asiGetCurrentSession()))                   *
    *                                                                      *
    * As abConvertNetCapToCSV but with the input and output files relative *
    *         to the netlist directory for the given asi session.          *
    *                                                                      *
    ***********************************************************************/
    procedure(abConvertNetCapToCSVFromNetlistDir(inFileName outFileName @key 
        columns (sorted t)
        (session asiGetCurrentSession()))
      let((netDir)
        when(netDir=asiGetNetlistDir(session)
          abConvertNetCapToCSV(
            strcat(netDir "/" inFileName)
            strcat(netDir "/" outFileName)
            ?sorted sorted
            ?columns columns
          )
        )
      )
    )
    
    ;------------------------------------------------------------------------
    ; A lexical scope containing a single global function and some
    ; variables to manage the caching of the net cap info
    ;------------------------------------------------------------------------
    let((lastFullPath lastModTime lastNetcaps)
      /***************************************************************
      *                                                              *
      *         abNetCap(netName @key (capacitance "Ctotal")         *
      * (session asiGetCurrentSession()) (file "input.info.netcap")) *
      *                                                              *
      *  A convenient function to use in an ADE output which allows  *
      * you to retrieve the capacitance (default Ctotal) for a given *
      * net. Uses caching to avoid reading the file multiple times.  *
      *                                                              *
      ***************************************************************/
      globalProc(abNetCap(netName @key (capacitance "Ctotal") 
            (session asiGetCurrentSession()) (file "input.info.netcap")
          )
        let((netDir fullPath modTime)
          when(netDir=asiGetNetlistDir(session)
            fullPath=strcat(netDir "/" file)
            modTime=fileTimeModified(fullPath)
            when(fullPath!=lastFullPath || modTime!=lastModTime
              lastFullPath=fullPath
              lastModTime=modTime
              lastNetcaps=abParseNetCap(fullPath)
            )
          )
          when(lastNetcaps
            lastNetcaps[netName][capacitance]
          )
        )
      )
    )
    

    Andrew

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Children
  • ShawnLogan
    ShawnLogan over 1 year ago in reply to Andrew Beckett

    Dear Andrew,

    Andrew Beckett said:

    For a start, the cut command won't deal with the fact that there are multiple spaces between the columns - and I don't know where columns 4 and 14 came from in your code. The net name and total capacitance were in the 1st and 11th field in the example I tried. You could achieve that with:

    tr -s ' ' < input.info.netcap | cut -d ' ' -f 1,11

    I included a comment regarding the delimiter and choice of fields in lines 29-32 of the codet, I do not have access to the documentation your do Andrew, so I could not determine the ASCII format of the netlist.info.netcap file. Hence, my only resort was to make an educated guess based on the order of the file contents from the Assembler manual:

    From pages 1034 and 1035, the net is the fourth listed item and Ctotal is the 14th. Hence, I guessed the net and Ctotall were in field 4 and field 14 of the the netlist.info.netcap file.

    I also did not know the delimiter used in the file. Since white space is often used in some Cadence ASCII files, I guessed it was a space and made the comment in the code that the delimiter should be changed to the proper delimiter if it is not a space.

    Handling multiple spaces can be easily handled using the tr command with cut. Here is an example of a text file whose first, second, and third lines use a single, two, and three spaces as field delimiters respectively. The example I show chooses the 3rd field. Note that for a single, two, or three white space field delimiters, the third field is chosen from each line.

    $
    $ cat test_multiple_spaces.txt
    1 2 3 4 5 6
    1  2  3  4  5  6
    1   2   3   4   5   6

    $ tr -s ' ' <  test_multiple_spaces.txt | cut -d" " -f3
    3
    3
    3

    Shawn

    • 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