• 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. Include external information/procedure in PCell

Stats

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

Include external information/procedure in PCell

maxaniertud
maxaniertud over 5 years ago

Hello,

Situation:

I  have created a PCell that generates a (transformer) layout based on the parameters.
All custom procedures are included (as lambda functions) inside the PCell body.

Currently, technology related information (which layers to use, etc.) is embedded in the body, the parameter default values (layer/metalstack options) as well as the cdf default values.
I would like to extract that information and move it into a dedicated file or at least a single place in the file. Thereby, it should be much easier porting the PCell to a different technology.

Furthermore, I would like to use some of the included functions/code in a different PCell. Currently, I just duplicate the code, but that is very annoying for code maintenance.

Issue:

If I move the information or these functions outside the PCell definition into separate procedures, it only works as long as they are loaded. Loading them in the CIW does not work for streaming out (for DRC etc.).

Do you have any idea how I could:

a) Copy/Attach already defined code to the PCell.

How this is meant:

I define a procedure/lambda function and somehow pass it to pcDefinePCell so it can be used in the body without loading the procedure again.

OR if this does not work

b) Specify a script that is always loaded when the PCell is evaluated

There is .cdsinit, but as far as I know that is only for the graphical tools.

There is libInit.il included in the PDK, but I don't think me (or the technology manager) can/should modify it.

Thank you very much for any input.

Using Virtuoso ICADV12.2

  • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago

    The right way to do this is to put it in the libInit.il (or libInit.ils) file within the library containing the PCell. If you have common functions, that's really the right way to do it. It would seem odd to have write permission to the library to define your own PCells, but not be able to update the libInit.il file...

    Note that every library can have a libInit.il file - so perhaps your pcells are in your own library? If so, define (or load) any relevant functions within your own library's libInit.il file.

    Regards,

    Andrew

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • maxaniertud
    maxaniertud over 5 years ago in reply to Andrew Beckett

    Thank you very much.

    I somehow assumed libInit files only exist for PDK libraries.

    I have created a libInit.il file in my own design library and it is being loaded.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Sheppie
    Sheppie over 5 years ago

    Hi,

    I had a similar issue where I had a lot of custom SKILL rocedures as part of a PDK I developed. In the end I settled on writing a procedure that would load many files at ones from a specified location. This location was a dedicated folder with all (and only) SKILL scripts in it. I put the special procedure at the beginning of the libInit.il file, and in this same libInit.il file I call this procedure. The scripts folder must not be in the same folder as the libInit.il file (it must not be in the Cadence Library folder). I decided to put it next to the library folder.

    This is the procedure I created:

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    unless( isCallable( 'loadAllFilesMatchingPattern )
        procedure( loadAllFilesMatchingPattern( rootDir pattern @optional (recursion t) (crucialFile nil) ( order nil ) ( skip nil ) ( verbose t ) "ttggllg" )
            let( ( file dirFiles fullFileName )

                dirFiles = sort( setof( file getDirFiles( rootDir ) file != "." && file != ".." ) nil )

                foreach( file order
                    when( file
                        fullFileName = buildString( list( rootDir file ) "/" )
                        when( isFile( fullFileName ) && member( file dirFiles )
                            when( verbose printf( "\tLoading the file: %s\n" fullFileName ) )
                            if( crucialFile
                            then
                                load( fullFileName )
                            else
                                loadi( fullFileName )
                            ) ;;; end of if
                        ) ;;; end of when
                    ) ;;; end of when
                ) ;;; end of foreach

                foreach( file dirFiles
                    unless( member( file order ) || member( file skip )
                        fullFileName = buildString( list( rootDir file ) "/" )
                        if( isDir( fullFileName )
                        then
                            recursion && loadAllFilesMatchingPattern( fullFileName pattern recursion crucialFile order skip verbose )
                        else
                            when( rexMatchp( pattern file )
                                when( verbose printf( "\tLoading the file: %s\n" fullFileName ) )
                                if( crucialFile then
                                    load( fullFileName )
                                else
                                    loadi( fullFileName )
                                ) ;;; end of if
                            ) ;;; end of when
                        ) ;;; end of if
                    ) ;;; end of unless
                ) ;;; end of foreach
            ) ;;; end of let
        ) ;;; end of procedure loadAllFilesMatchingPattern
    ) ;;; end of unless

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    Copy-past this piece of code into your libInit.il file (or any other file which gets loaded by Virtuoso, like the .cdsinit file).

    Then, in the libInit.il file do something like this:

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    when( isCallable( 'loadAllFilesMatchingPattern )
        loadAllFilesMatchingPattern( "../scripts/" "[.]il$" t t list( "pcellCode" "guardring.il" ) nil t )
    ) ;;; end of when

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    The arguments I specify:

    • "../scripts/"
      This is the path to the directory where all script files are located
    • "[.]il$"
      This is the pattern the filename must match, in this case the extension has to be .il (it is a regular expression)
    • t
      This means that, if you have sub-folders inside the ../scripts/ folder, it will look in those as well (recursive load). Specify nil to not go down sub-folders.
    • t
      All files in the ../scripts/ folder are crucial files. This will ensure all fie are loaded with the load() procedure (in stead of the loadi() procedure), which will generate errors/warnings if something is wrong.
    • list( "pcellCode" "guardring.il" )
      Any file/folder or files/folders that needs to be loaded first, should be specified here (the "order" argument of the procedure). In this example, if a folder called "pcellCode is found, it will recurse into it first, then it will look for a file called "guardring.il" and load it. After that, it will simply load all remaining files/folders. Only specify the file name, not the entire path.
    • nil
      It is possible to specify a list of files/folders which should not be loaded, the list should look like the "order" list. Only specify the file name, not the entire path.
    • t
      This will print a line in the CIW for every file it loads.

    Hope this is of any use to you.

    Kind regards,

    Sjoerd

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Sheppie

    Hi Sjoerd,

    Just a little thought - if the ../scripts dir is relative to the library containing the libInit.il that you're adding this code in, you could do this:

    when( isCallable( 'loadAllFilesMatchingPattern )
      let(((baseName pcreCompile("[^/]+$") scriptsDir))
        scriptsDir=simplifyFilename(pcreReplace(baseName get_filename(piport) "../scripts" 1)))
        loadAllFilesMatchingPattern( scriptsDir "[.]il$" t t list( "pcellCode" "guardring.il" ) nil t )
      )
    )

    What this does is use the filename for the libInit.il (found via get_filename(piport) at load time) and then remove the trailing part, and add on ../scripts - and then call your function with that.

    Might be helpful for future reference too!

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Sheppie
    Sheppie over 5 years ago in reply to Andrew Beckett

    Hi Andrew,

    Thanks for the suggested code. The example I gave was just to have a short root-folder, and showing how the procedure should be used. Having said that, I have gone through some of my code to change the way I load other files to include this neat implementation of yours. I'd like to make everything as fool-proof as possible...

    Kind regards,

    Sjoerd

    • 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