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.
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
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.
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.
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:
Hope this is of any use to you.
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!
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...