How to use magic with Open PDKs
How to start Magic with nice colors
How to deal with search paths for cells
How to run basic extraction
How to run parasitic extraction
By far, the process technologies most commonly used with magic are the open-source PDKs, which at the time of this writing (October 2025) are three in number: SkyWater sky130, GlobalFoundries GF180MCU, and IHP sg13g2.To use magic with one of these open-source PDKs, you will first need to install the PDK. Installing an open source PDK can be a painful process, much like trying to compile a large and complex piece of software from source. Most people would prefer just a package manager to take care of it. And there is a package manager for the open PDKs! It's called ciel and can be found here:
https://github.com/fossi-foundation/cielThe "README.md" file will tell you how to download and run ciel. Once you decide on a PDK to use and install it using ciel, it will be placed in your home directory under ~/.ciel/, followed by a symbolic link with the PDK variant name (e.g., "sky130A") pointing to a location with a long hash value tied to the version of the PDK.I have developed magic techfiles for all of the open PDKs. The proper way to run magic on one of these technologies is to invoke the startup script, not the technology file itself. The startup script will run various commands to set up the layout environment correctly for the given PDK, including adding menus to the layout window to access the parameterized device generators.
Read the entry below on How to start Magic with nice colors. That is, options above should include the preferred graphics interface, and you can put the name of the layout you want to edit on the command line as well.
magic -rcfile ~/.ciel/sky130A/libs.tech/magic/sky130A.magicrc [options]
magic -rcfile ~/.ciel/gf180mcuD/libs.tech/magic/gr180mcuD.magicrc [options]
magic -rcfile ~/.ciel/ihp-sg13g2/libs.tech/magic/ihp-sg13g2.magicrc [options]
Each process technology comes in different variants which represent different sets of options provided by the foundry for the process. The PDK does not necessarily represent all possible option sets. Both SkyWater and IHP have relatively straightforward process stacks with all process features included in the price of manufacture. SkyWater has one option, ReRAM, which is not available in the standard PDK and incurs an extra charge for manufacture. So the sky130 PDK has been divided into two variants, sky130A (without ReRAM), and sky130B (with ReRAM). As of this writing, IHP's process is fixed and there are no options above and beyond the existing process definition, and so there is only the single process variant (Note that the process itself has many options, but the open PDK is defined for a single selection of options. This may change in the future). GlobalFoundries has many options for the GF180MCU process. However, the files that GlobalFoundries provided for the open PDK fall into three main stackups: 3-metal, 4-metal, and 5-metal back-ends. The process variants gf180mcuA, gf180mcuB, and gf180mcuD correspond to the 3-, 4-, and 5-metal stackups, respectively. The gf180mcuC is an "historic" variant used by Efabless and Google for the first open MPW runs. The difference is that GlobalFoundries advised us that the top metal was too thin and had a tendency to delaminate on pads, and they recommended a thicker top metal. So gf180mcuD defines the top metal thickness recommended by GlobalFoundries, and gf180mcuC is effectively deprecated.
Each of the open PDKs has an additional technology file for magic that is designed to view layers exactly as they are defined in the GDS. If you want GDS-exact rendering, you may want to just use klayout, but if you prefer the graphics rendering in magic, you may prefer to view the layers using this technology file. There is no startup script associated with this technology file, so use "-T tech_file" on the command line instead of "-rcfile startup_script". Note that the GDS-exact rendering does not properly capture either layout connectivity or do netlist extraction. Sometimes the GDS-exact tech file implements DRC rules for layers that are implicitly defined in magic, and therefore cannot be checked directly using the regular tech file.
For the advanced user, it is possible to build all the open PDKs from sources using https://github.com/RTimothyEdwards/open_pdks. For details, see the open_pdks repository above, or see http://opencircuitdesign.com/analog_flow.
magic -T ~/.ciel/sky130A/libs.tech/magic/sky130A-GDS.tech [options]
magic -T ~/.ciel/gf180mcuD/libs.tech/magic/gr180mcuD-GDS.tech [options]
magic -T ~/.ciel/ihp-sg13g2/libs.tech/magic/ihp-sg13g2-GDS.tech [options]
When building a PDK from source, the location of the PDK will by default be found in /usr/local/share/pdk/. Note that this requires root access to install, although the target can be relocated elsewhere, and the built PDK can be used from inside the open_pdks repository without installing. The IHP PDK, however, has been defined in the format used by open_pdks and so it is not necessary to build it at all---It comes pre-built and ready to use. Putting it in the same place as the other PDKs makes it easier for all the open source EDA tools to find it, but it is not necessary.
A convenience (and sometimes a necessity) for using all the open source PDKs is to define an environment variable called $PDK_ROOT which points to the directory above where the PDKs are located, which is another reason to put them all in the same place, so you don't have to redefine $PDK_ROOT for each one. It may also be useful or necessary to set an environment variable $PDK set to the name of the PDK.
For bash-like shells, for example:
export PDK_ROOT=~/.cielor for csh-like shells:
export PDK=sky130A
setenv PDK_ROOT ~/.ciel
setenv PDK sky130AFinally: Since typing in a long command line is tedious, I recommend creating an alias that can be put in your home directory's .bashrc file or .cshrc or .tcshrc file, depending on what kind of Linux shell you use. Regardless of the shell, the alias command is the same. I like to use the following:
alias magicsky 'magic -d OGL -rcfile ~/.ciel/sky130A/libs.tech/magic/sky130A.magicrc'Then all I need to do is run the command magicsky, magicgf, or magicihp, depending on which process I am designing something for. The same technique can be used for other open source EDA tools like xschem or klayout:
alias magicgf 'magic -d OGL -rcfile ~/.ciel/gf180mcuD/libs.tech/magic/gf180mcuD.magicrc'
alias magicihp 'magic -d OGL -rcfile ~/.ciel/ihp-sg13g2/libs.tech/magic/ihp-sg13g2.magicrc'
alias xschemsky 'xschem --rcfile ~/.ciel/sky130A/libs.tech/xschem/xschemrc'
alias xschemgf 'xschem --rcfile ~/.ciel/gf180mcuD/libs.tech/xschem/xschemrc'
alias xschemihp 'xschem --rcfile ~/.ciel/ihp-sg13g2/libs.tech/xschem/xschemrc'
alias klayoutsky 'setenv KLAYOUT_PATH ~/.ciel/sky130A/libs.tech/klayout ; klayout -e'
alias klayoutgf 'setenv KLAYOUT_PATH ~/.ciel/gf180mcuD/libs.tech/klayout ; klayout -e'
alias klayoutihp 'setenv KLAYOUT_PATH ~/.ciel/ihp-sg13g2/libs.tech/klayout ; klayout -e'
I often find people sending me screenshots of magic using the horrible default colors and stipples. The history of magic's graphics display is that it was originally (or at least early in its existence) designed to work with graphics cards on early workstations; these graphics cards had a "pseudocolor" visual in which colors could be defined as a look-up table indexed to an 8-bit number. It was then possible to get full 24-bit color with only 8 bits, with the drawback that only 256 colors could be made available at a time. Magic made use of the 8 bits to define "planes" of colors, and then the look-up table could be defined to represent "blends" of overlapping colors. The effect was quite striking. Unfortunately, though, eight planes is quite limiting. It worked reasonably well for the time that magic was first written, in the mid-1980s, when processes were large (e.g., 2 micron feature size) and back-end metallization was limited (e.g., 2 layers of metal). Even at three metal layers in the back-end process, the available pseudocolor planes ran out of space, and the pseudocolor system started to break down. Some graphics cards were fancy enough to have 16-bit pseudocolor, but those were not common.Eventually, fabrication processes started having four, five, six, and up metal layers, and the whole pseudocolor system was untenable. One solution was to switch from pseudocolor visuals to 24-bit "true color" visuals. But "true color" has no look-up tables, no indexing, so no concept of color blending. The only solution is to make use of stippling and cross-hatching so that layers will "show through" other layers. This is how most layout tools do rendering, and it is (in my opinion) awful, and makes layout practically impossible to understand at a glance. It is a huge impediment to doing good layout work.
I thought about this problem for a while and realized that 3D graphics accelerator hardware was common and becoming reasonably well integrated into Linux systems, and all the graphics drivers had OpenGL implementations, and OpenGL could do color blending in hardware, making it as fast as the pseudocolor planes, but without the limitations.
I wrote a new graphics interface for magic to use OpenGL, and with a few tricks and a lot of work, was able to get a perfect emulation of the pseudocolor graphics. Later, when the Cairo 2D hardware-accelerated graphics library became popular, I (with the help of a very talented intern, Chuan Chen) created a graphics interface for Cairo, which also overcame some issues with OpenGL graphics implementations not supporting off-screen (i.e., Pixmap) rendering.
Because it is not really possible to know or figure out whether a system supports Cairo 2D graphics or OpenGL 3D graphics, and what features or limitations they have, magic will default to the 24-bit "true color" X11 graphics interface. Which is the one I called "awful" (and which I never use, myself). But if you want the "nice" graphics, you will need to try the OpenGL and Cairo interfaces and figure out which one works best for you.
Starting magic with the "good" graphics is easy enough:
Important note: Because of the issue where graphics cards' implementation of OpenGL does not support off-screen (pixmap) rendering, and because magic depends on off-screen rendering to draw layers into the icons for the list of layers on the right-hand side of the layout window, a pure OpenGL interface will draw garbage (or nothing) into the icons, making the layer map useless. The workaround for this is to use Cairo graphics for the off-screen rendering, even if OpenGL is being used for the main layout window. Making this happen must be done at compile-time. When configuring magic prior to compiling, use:
magic -d OGL [options]
magic -d XR [options]
where:
- -d OGL
- Select the OpenGL graphics interface at runtime.
- -d XR
- Select the Cairo graphics interface at runtime.
- options
- All the rest of the usual options passed to magic on the command line.
When should you choose OpenGL vs. Cairo? Every implementation for every graphics card is a bit different, and they all have their quirks. If you see weird artifacts or get unusually slow rendering, you might consider switching from one interface to the other. Otherwise, the interfaces are nearly indistinguishable from each other.
./configure --enable-cairo-offscreen OpenGL libraries are usually packaged with graphics card drivers; the X11 open source implementation of OpenGL is "mesa" and the dependent libraries are (for Ubuntu/Debian-like systems) "mesa-common-dev", "libgl-dev", and "libglu1-mesa-dev"; and (for Fedora/CentOS-like systems) "mesa-libGL-devel" and "mesa-libGLU-devel".
Cairo has only one library; this is (for Ubuntu/Debian-like systems) "libcairo2-dev" and (for Fedora/CentOS-like systems) "cairo-devel".
Magic's methods of finding cells is rather complicated. Magic keeps a list of paths to search for layout files. This list can be accessed with thepath searchcommand, and modified with theaddpath path_namecommand.In addition to the search paths, magic keeps track of where layout cells are found on disk when loading, and saves this information when it writes the layout file for the parent cell that instantiates the cell in question. There is an order of precedence to how it saves the references to those cells. It tries to save references in a way that makes the layout more portable, if possible. The order of precedence for saving cells is:
This method generally works when all layout for a project is confined to a single project directory and a PDK directory; the PDK directory is recognized by magic from the path for the startup script or the technology file.
- The current working directory
- Anything in a subdirectory of the current working directory (for which it uses the relative path)
- Anything in the user home directory path (for which it uses "~/")
- Anything in the PDK path (for which it uses $PDKPATH)
- The path exactly as specified (for which it uses the absolute path).
If you have libraries that exist outside your project, this is considered bad practice, as it makes the project non-portable. The generally accepted way to access dependent libraries other than the PDK itself is to put them under the current working directory of the project. If the library is a git repository, then it should be made a sub-repository of the project. By making the dependent library a sub-repository, when it is initialized with git submodule init --recursive, then the library will be cloned in the state that it exists and any further changes to the library will not be reflected in the submodule unless you do git submodule update --recursive. This is a form of version control, because a project will not get invalidated by a library change, but as the designer, you can choose to update to a new library as needed and then fix your design as necessary to work with the library updates.
However, having libraries outside the project is not prohibited, but bear in mind that libraries outside the project make the project non-portable. If you moved the layout file elsewhere such that the library directory no longer exists, then what you need to do is start magic and issue the command
addpath /new/path/to/libraryto make sure that magic knows where the new location of the library is, and has it in its search path; and then do:load parent_cell -dereferencewhich should be sufficient for magic to find the library. Actually the "-dereference" option isn't needed if the path to the file is in magic's search path, and the layout doesn't exist anywhere else. Magic will just spit out a warning that it couldn't find the file in the path saved in the parent cell's .mag file but that it found it in the search path.If you have libraries in locations you use often, but are not using git submodules then just add the addpath line to your startup script (.magicrc in the layout directory of the project) so that magic will always have that location in its search path.
This example shows how to write an extraction script for automatically extracting a magic layout. The example shown is for the GF gf180mcuD open PDK. However, note that the "$PDK" environment variable can be set before calling this routine, and it will use the existing value of $PDK.Create the following script and name it "run_extract.sh". Set it to executable (chmod a+x run_extract.sh).
The general flow of the script is:
#!/bin/bash # Usage: run_extract.sh <cellname> # where <cellname> is a magic layout (<cellname>.mag) echo ${PDK_ROOT:=~/.ciel} > /dev/null echo ${PDK:=gf180mcuD} > /dev/null magic -dnull -noconsole -rcfile ${PDK_ROOT}/${PDK}/libs.tech/magic/${PDK}.magicrc > magic.log << EOF drc off locking disable crashbackups stop box 0 0 0 0 load $1 select top cell extract path extfiles extract all ext2spice lvs ext2spice -p extfiles quit -noprompt EOF rm -r extfiles echo "Done!" exit 0
In some cases, additional commands will need to be added to the script. For instance, to read from GDS, you might want to have the first command argument ($1) be the GDS filename, and add a second command-line argument($2) for the cell name. Then, the script looks like:
- The $PDK_ROOT and $PDK environment variables are set to default values if they don't exist in the environment. If they do already exist in the environment, then the existing values will be used.
- Magic is called with "-dnull -noconsole". That turns off all graphics, forcing magic to operate in batch mode. The tkcon console window is not used, so all output is passed back to the terminal, where it is captured and placed in a log file "magic.log".
- Shell input redirection is used to pass an entire set of commands to magic's Tcl interpreter as it runs. This involves using "<< EOF" to start the redirection, then putting all of the input into the file, and then ending with "EOF" on its own line. After the "EOF", control returns to the shell.
- The first lines of the script turn off DRC and prevent generating a crash backup file. A simple "box" command is issued to make sure that the cursor box is in the layout window (which is a "virtual" window since there are no graphics in batch mode).
- The magic layout is loaded (from the script command line's argument).
- Extraction is set up with a path set to a directory "extfiles/". This directory will be created if it doesn't exist. This causes magic to put all of its intermediate ".ext"-format files in this subdirectory. It is especially important that PDK-level extractions of cells that belong to the PDK (I/O cells, standard cells, etc.) end up in the project directory and not back in the PDK, especially since when using "ciel", the PDK is in a user-writeable directory path.
- Magic has a progressive "extract" command. To make sure a circuit is completely extracted from the top, use "extract all".
- Magic has a two-step extraction method. The "extract" command does not create a netlist; it creates an intermediate ".ext" file that contains more information than is used by any single netlist file, and has one file per subcell.
- "ext2spice" is used to create the actual netlist file. The options for "ext2spice" determine what optional information goes into the netlist. There are a confusing array of options, so there is a convenience option "ext2spice lvs" that sets a lot of options appropriately for LVS, and is good for most purposes. Even for target netlists used for purposes other than LVS, I use this command first to set "sane" options and then set additional options as needed.
- "ext2spice" requires a "-p" option switch to match the "extract path" command, so that it knows where to find the .ext files.
- The script cleans up afterward by removing all of the .ext files and the "extfiles/" subdirectory.
- I always like to print an exit message, particularly for tasks like extraction that can be quite long, depending on the input.
Sometimes a PDK will require additional commands. The IHP sg13g2 process has two different extraction methods depending on the target. For LVS, the target is a CDL-format file, and for simulation, the target is a SPICE netlist. The default extraction style is for ngspice, and the ext2spice lvs command sets up options for simulation output for ngspice, so the scripts above will work with the IHP PDK for simulation extraction. For LVS, however, the following changes are needed to the script:
#!/bin/bash # Usage: run_extract.sh <filename> <cellname> # where <filename> is a GDS layout file and <cellname> is the name of the top-level cell to extract. echo ${PDK_ROOT:=~/.ciel} > /dev/null echo ${PDK:=gf180mcuD} > /dev/null magic -dnull -noconsole -rcfile ${PDK_ROOT}/${PDK}/libs.tech/magic/${PDK}.magicrc > magic.log << EOF drc off locking disable crashbackups stop box 0 0 0 0 gds read $1 load $2 select top cell extract path extfiles extract all ext2spice lvs ext2spice -p extfiles quit -noprompt EOF rm -r extfiles echo "Done!" exit 0
Note the two added lines:
#!/bin/bash # Usage: run_extract.sh <cellname> # where <cellname> is the name of the magic layout to extract. echo ${PDK_ROOT:=~/.ciel} > /dev/null echo ${PDK:=ihp-sg13g2} > /dev/null magic -dnull -noconsole -rcfile ${PDK_ROOT}/${PDK}/libs.tech/magic/${PDK}.magicrc > magic.log << EOF drc off locking disable crashbackups stop box 0 0 0 0 load $1 select top cell extract path extfiles extract style ngspice(lvs) extract all ext2spice lvs ext2spice format cdl ext2spice -p extfiles quit -noprompt EOF rm -r extfiles echo "Done!" exit 0
Other useful extract options are:
- extract style ngspice(lvs) sets the "extraction style" which is defined in the technology file.
- ext2spice fomat cdl generates an output that has various aspects of CDL format. (Note that CDL format is not well defined, and magic's CDL format is designed to match the format of the CDL files in IHP's open PDK.)
- extract unique
- Layout nets can be tagged with a label, and it is possible to tag completely unrelated parts of the circuit with labels having the same text, which then translates into two nets in the netlist having the same name, and therefore effectively being the same net. This may be done on purpose, and is very common in abstract views where there may be multiple ports to, say, a standard cell, but the details of the standard cell (including the net connecting the two ports) are not present in the abstract view. Sometimes it is done as a shortcut to match a schematic (which is bad practice, but I have seen it done many times). Most of the time it is accidental, and can result in a circuit that passes LVS but is in fact completely broken. Running "extract unique" will force all unique nets to have unique names. Note that "extract unique" does not do any extraction itself; rather, it rewrites labels in the cell to force them to be unique. Avoid doing this on a cell that is actively being edited, as it may modify the cell. If the cell will not be re-written after modification, such as in the extraction scripts above, then there is no issue.
- extract unique notopports
- In cases where there are purposefully multiple nets with the same name, such as multiple pins named "VDD" that are all connected together in a way that is not immediately apparent to magic when extracting the cell (nets are connected together in a subcell, for example), this command will prevent magic from giving them separate names. Usually it is best to do this only on the top level cell. There is a command extract unique noports that will ignore ports in all subcircuits. While that may improve LVS output readability, it risks connecting unconnected nets within subcells, so use it with caution.
- extract no all
- This command is not the opposite of extract all. There is a set of extract option settings which take "do" or "no" to turn on or off. For example, "extract no capacitance" will disable parastic capacitance extraction, which can speed up extraction significantly when parasitics are not required, as is usually the case for LVS. However, most of the option settings are either for parasitics or are obscure, so the most common usage is either to keep them all (when doing parasitic extraction) or turn them all off (when extracting for LVS). "extract no all" turns them all off.
The one line that was added was "ext2spice cthresh 0.1". This tells magic to set a threshold of 0.1fF; values above this amount will be output. "ext2spice cthresh 0" also works but may output some zero-valued capacitors; this will not have any appreciable effect on the simulation but will produce a longer output file than necessary.
#!/bin/bash # Usage: run_extract.sh <cellname> # where <cellname> is a magic layout (<cellname>.mag) echo ${PDK_ROOT:=~/.ciel} > /dev/null echo ${PDK:=gf180mcuD} > /dev/null magic -dnull -noconsole -rcfile ${PDK_ROOT}/${PDK}/libs.tech/magic/${PDK}.magicrc > magic.log << EOF drc off locking disable crashbackups stop box 0 0 0 0 load $1 select top cell extract path extfiles extract all ext2spice lvs ext2spice cthresh 0.1 ext2spice -p extfiles quit -noprompt EOF rm -r extfiles echo "Done!" exit 0
Other useful ext2spice options are:
When done with a script, the complexity of full R-C extraction is largely invisible to the end-user, and there are fewer ways to mess it up. Here is an example script for the sky130A process. Name the script "run_rcx.sh" and set it to be executable. Making this script operate on GDS is similar to what was done in the section on basic extraction, above, and is left as an exercise for the reader.
One very important thing to understand about R-C extraction is that the command option ext2spice rthresh is unrelated: It produces something called a "lumped model" resistance in the .ext file that is unknown to any tools; it only appears in .sim file output but is not relevant for SPICE simulation (it can, in theory, be used by a switch-level simulator such as IRSIM).
The flow of the file is as follows:
#!/bin/bash # Usage: run_rcx.sh <cellname> # where <cellname> is a magic layout (<cellname>.mag) echo ${PDK_ROOT:=~/.ciel} > /dev/null echo ${PDK:=sky130A} > /dev/null magic -dnull -noconsole -rcfile ${PDK_ROOT}/${PDK}/libs.tech/magic/${PDK}.magicrc > magic.log << EOF drc off locking disable crashbackups stop box 0 0 0 0 load $1 select top cell flatten myflat load myflat cellname delete $1 cellname rename myflat $1 select top cell extract path extfiles extract unique notopports extract all ext2sim labels on ext2sim -p extfiles extresist tolerance 10 extresist ext2spice lvs ext2spice cthresh 0.1 ext2spice extresist on ext2spice -p extfiles quit -noprompt EOF rm -r extfiles echo "Done!" exit 0

| email: |
|
Last updated: October 29, 2025 at 10:31am