- Python 100%
Verilog-A Distiller
Verilog-A Distiller converts SPICE3 device models from C to Verilog-A. It is intended primarily for converting Ngspice device models. The generated device models can be used in Ngspice itself or in VACASK. Since the generated device models are implemented in Verilog-A they should also work in other simulators. Due to varying support for Verilog-A $limit your mileage may vary, mostly in terms of convergence.
VADistiller uses the pycparser library for parsing the C code and producing the abstract syntax tree (AST). A toolbox for manipulating C ASTs is included with VADistiller. You will also have to install gcc because VADistiller uses its preprocessor (cpp). The preprocessor must be in the system PATH.
Which models does it convert and validate?
See the models directory for the converted device models. Older device models may change/improve with newer versions of the converter.
| Verilog-A device (SPICE) | File | Module |
|---|---|---|
| Linear resistor | resistor.va | sp_resistor |
| Linear capacitor | capacitor.va | sp_capacitor |
| Linear inductor | inductor.va | sp_inductor |
| Diode (levels 1 and 3) | diode.va | sp_diode |
| Gummel-Poon BJT | bjt.va | sp_bjt |
| JFET level 1 (Schichman-Hodges) | jfet1.va | sp_jfet1 |
| JFET level 2 (Parker-Skellern) | jfet2.va | sp_jfet2 |
| MESFET level 1 (Statz et. al.) | mes1.va | sp_mes1 |
| MOSFET level 1 (Schichman-Hodges) | mos1.va | sp_mos1 |
| MOSFET level 2 (Grove-Frohman) | mos2.va | sp_mos2 |
| MOSFET level 3 (empirical) | mos3.va | sp_mos3 |
| MOSFET level 6 (Sakurai-Newton) | mos6.va | sp_mos6 |
| MOSFET level 9 (modified level 3) | mos9.va | sp_mos9 |
| VDMOS | vdmos.va | sp_vdmos |
| BSIM3 3.3.0 | bsim3v3.va | sp_bsim3v3 |
| BSIM4 4.8.0, 4.8.1, 4.8.2, 4.8.3 | bsim4v8.va | sp_bsim4v8 |
Obtaining Ngspice sources
VADistiller works best on the device models in the Ngspice pre-master-46 branch. Because pre-master-46 is a fast moving target it is recommended to use a particular commit. For convenience there is a fork available at Sourceforge. The vadng-pre-46 branch is the one to use. This branch also contains some changes needed by VADistiller-generated device models. Until these changes are accepted in mainline Ngspice use the forked repository. Type
git clone -b vadng-pre-46 https://git.code.sf.net/u/arpadbuermen/ngspice ngspice-pre-46
This creates the ngspice-pre-46 directory and downloads the sources of the vadng-pre-46 branch which is based on the pre-master-46 branch. Next, you need to configure the sources. We assume the build directory will be named build and will reside in the sources directory. Enter the sources directory and type
./autogen.sh
mkdir build
cd build
../configure --with-x --with-readline=yes --enable-osdi --disable-debug --enable-nobypass --disable-openmp
--enable-nobypass disables element bypassing so that comparison of built-in and converted device models in various Ngspice benchmarks will be fair. OpenMP needs to be disabled (--disable-openmp) because it is used by all OSDI devices to parallelize instance evaluation. For small devices that evaluate quickly this actually slows down the simulation significantly due to OpenMP's overhead.
If you want to validate the converted device models you will need Ngspice pre-46 or newer. Therefore build it
make
and install it to /usr/local
sudo make install
Make sure /usr/local/bin is in the PATH.
Model variants
Under certain circumstances OpenVAF creates additional internal nodes during Verilog-A model compilation. Because these nodes make the system of equations larger and thus slower to solve it is of advantage to avoid the creation of internal nodes whenever possible.
Extra internal nodes are created in two cases:
- If a device exposes output variables (also referred to as opvars in OpenVAF) that cannot be computed directly from the solution vector (e.g. reactive currents).
- If the computation of a noise power spectral density (usually shot or flicker noise) is based on a reactive current.
The former case is avoided by not exposing certain output variables. The latter one, however, can be avoided only if a simplified noise model is used (i.e. one that uses DC currents for computing the power spectral density). This makes the noise model usable only in ordinary small-signal noise analysis.
Due to this several variants of each model are generated.
defaultvariant does not expose output variables that add internal nodes and uses the full noise modelsnvariant does not expose output variables that add internal nodes and uses the simplified noise modelfullvariant exposes all output variables and uses the full noise model
If the sn or the full variant of a model do not differ from the default variant they are not generated. E.g. the resistor model does not have output variables that would add extra internal nodes and its noise model is not based on a reactive current so the sn and the full variants are not generated.
The default variant is stored in the models directory while the sn and the full variants can be found in the models/sn and models/full directories, respectively.
Certain models need workarounds when used with Ngspice (e.g. BSIM4). If you intend to use a Verilog-A model generated by VADistiller with Ngspice compile it with the __NGSPICE__ macro defined (i.e. add -D__NGSPICE__ to the OpenVAF command line). This will enable all workarounds needed by Ngspice.
Running the conversion
Before running the conversion edit the configuration in xlat_cfg.py. The following settings in the config variable should be verified and possibly altered:
sources.. the path where the Ngspice sources are located,fake_libc.. the path where the pycparser's fake libc is located.
Also check the validation variable and edit the following settings:
compiler.. path to the OpenVAF-reloaded compiler,vacask.. path to the VACASK simulator, will replace $(VACASK) in command lines run by the validator.ngspice.. path to the Ngspice simulator, will replace $(NGSPICE) in command lines run by the validator.
You will need OpenVAF-reloaded for compiling the device models before they get validated. You can get the binaries here. Get the latest osdi_0.4 version because VACASK does not support older versions of the OSDI API. The osdi_0.4 version of the OpenVAF-reloaded binary is named openvaf-r.
If you install VACASK a nice summary of the compiled device model will be printed after the conversion. If you don't have VACASK the device model summary will not be printed. You can get the latest nightly build binary packages or you can compile it from the source code.
To start the conversion run
python3 xlat.py
VADistiller will read the SPICE3 device models, parse them, process them, and then dump the Verilog-A code in the models directory. After conversion each device model will be validated. For validation you will need OpenVAF-reloaded (the osdi_0.4 version) and Ngspice (pre-46 or newer).
Loading the SPICE3 device model source code is slow. To speed up the development of VADistiller the loaded device models and converter configuration are dumped to a .pck file. The next time you run the conversion the converter object with the SPICE3 sources is loaded from the corresponding .pck file which is much faster.
Each SPICE3 device model has its own configuration file. The names of the configuration files are xlat_<model_name>.py. All configured device models are listed in the xlat_cfg.py file in the what list. The xlat.py script has the following command line syntax:
python3 xlat.py [options] [model1 model2 ...]
If no device model is specified all configured device models are converted. If you change the configuration of a device the SPICE3 source files must be reloaded. Option -f forces loading of the device model sources even if a .pck file is available. To force source file loading you can also delete the .pck file before running the conversion.
The -o option specifies which variant of the models will be generated. If omitted, all variants are generated. By specifying the -c option the device model validation step is skipped. Similarly, specifying the -v option skips the conversion step and performs only device model validation. A short help is printed if you specify the -h option. The conversion process can be interrupted after the given conversion step is finished by supplying the -s options and the step name (pre, defs, structs, params, mapping, setup, temp, load, noise, post, valprep).
The converter has been tested under Debian 13. Your mileage may vary on other systems. Usually problems arise due to GCC extensions and system include files that can differ between operating systems. To fix these problems define dummy macros in xlat_cfg.py under the defines section of the config variable.
Notes
A call to $simparam in OpenVAF-generated device models is expensive (this is a weakness of OpenVAF) so it should be used sparingly. Some $simparam values are accessed as part of device model initialization code (in devsetup.c and devtemp.c). To reduce the number of $simparam calls they should be moved to compiled device model initialization code. To allow OpenVAF to do that $siparam calls must be assigned to constants in the device models generated by VADistiller. When compiling these device models OpenVAF issues warnings that a $simparam is accessed at constant initialization (which by the way is what we want). To disable this warning --allow variant_const_simparam is added to the OpenVAF command line.
Publications mentioning Verilog-A Distiller
- Á. Bűrmen, "VACASK: a Verilog-A Circuit Analysis Kernel", Free Silicon Conference 2024, Paris, June 2024.
- Á. Bűrmen, "OpenVAF - status update, ecosystem, and a roadmap", 17th International MOS-AK Workshop, Silicon Valley, December 2024."
- Á. Bűrmen, et. al. "Free software support for compact modelling with Verilog-A", Informacije MIDEM - Journal of Microelectronics, Electronic Components and Materials, 54 (2024), no. 4: 271-281.
- Á. Bűrmen, "VACASK and Verilog-A Distiller - building a device library for an analog circuit simulator", FOSDEM 2025, Brussels, February 2025.
- Á. Bűrmen, "Recent developments in the Verilog-A circuit analysis kernel", Free Silicon Conference 2025, Frankfurt (Oder), July 2025.
- Á. Bűrmen, "The OpenVAF Verilog-A Compiler for the OpenPDK Ecosystem", MOS-AK Workshop/ESSERC 2025, Munich, September 2025.
Acknowledgement
This project is partially funded through NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program. Learn more at the NLnet project page.