Skip to contents

spice runs SPICE3 circuit netlists from R and hands the results back as tidy data. The engine is Dune, a circuit simulator written in Rust and derived from Berkeley SPICE3f5 (with BSIM3v3.3, .sp, .measure and several revised routines derived from ngspice-47), checked circuit by circuit against ngspice.

  • Every SPICE3f5 analysis: operating point, DC sweep, transient, AC, pole-zero, noise, distortion, transfer function and sensitivity, plus periodic steady state (spice_pss()).
  • Every SPICE3f5 device, and BSIM3v3.
  • Long tibbles out (spice_tidy()), ready for ‘ggplot2’, or one column per variable (spice_wide()); plots picked by short name ("tran", "ac") and variables by node; autoplot() for a quick look.
  • Sessions and sweeps: alter a part and rerun without rebuilding (spice_session()), or sweep parameters across threads (spice_sweep()).
  • Decks as chunks: a knitr engine runs ```{spice} chunks in R Markdown and Quarto.
  • Circuits from figures: spice_pic() extracts the netlist of a schematic drawn in the pic language.
  • Rawfiles in SPICE3’s own format, to exchange with other simulators (spice_read_raw(), spice_write_raw()).

Installation

spice is not on CRAN yet. Install the development version from GitHub; it compiles Rust code, so it needs cargo and rustc (>= 1.88), from https://rust-lang.org/tools/install/.

# install.packages("remotes")
remotes::install_github("milkway/dune", subdir = "r")

A first circuit

library(spice)

deck <- "RLC low-pass
vin in 0 pulse(0 1 0 1u) ac 1
r1 in mid 50
l1 mid out 1m
c1 out 0 1u
.tran 2u 1m
.ac dec 50 100 100k
.end"

res <- spice_run(deck)
res |> spice_tidy("tran", "out")   # long: one row per point
res |> spice_tidy("ac", "out")     # complex plots carry mag, db, phase
res |> spice_wide("tran")          # wide: one column per variable

vignette("spice") walks through this deck end to end.

Faithful to SPICE, and better where it can be measured

Netlist syntax, device models and analyses are SPICE3f5’s. Where Dune departs from it by default, it is because the result is measurably closer to the converged answer at the same step: a transient integrates with TR-BDF2 instead of the trapezoidal rule, a switch flips at the instant its control crosses the threshold, a lossy line keeps the corners of the waves it carries. One option restores the SPICE3 behaviour of all of them:

spice_run(deck, options = list(compat = "spice3"))

vignette("defaults") shows the difference on a small circuit.

How it works

How a simulation runs: the deck is parsed and built into a circuit; for every point of an analysis the devices are linearized, the linear system is solved and convergence is tested, iterating until it holds; an accepted point goes to the results.

spice_run() hands the deck to the engine. It is parsed and built into a circuit, and every point of every analysis is a Newton-Raphson loop: linearize the devices, solve the linear system, test convergence at SPICE’s tolerances. The accepted points come back as the plots that spice_tidy() and spice_wide() turn into tibbles.

The same engine elsewhere

Architecture of Dune: a pic figure goes through dune-pic and a SPICE deck through dune-netlist into dune-core, the engine; dune-raw writes rawfiles; the command line and the Python, R, JavaScript and C interfaces all sit on that one engine.

spice is one of several front ends to Dune; a deck gives the same numbers in all of them.

package install
Python spice3 pip install spice3
JavaScript / WebAssembly @strategicprojects/dune-sim npm install @strategicprojects/dune-sim
Rust dune-core, with dune-netlist, dune-raw and dune-pic cargo add dune-core
Command line dune brew install milkway/tap/dune

The circuit gallery shows every circuit of the engine’s test corpus with its results, and rpic is the pic-language implementation behind spice_pic().

Credits

The engine is a derived work: it is translated from SPICE3f5 (© 1985–1991 The Regents of the University of California; Thomas L. Quarles and many others at UC Berkeley) and, for BSIM3v3.3, the .sp analysis, the operating-point fallback chain, .measure, the transient noise sources and the revisions of several device routines, from ngspice-47 (the ngspice team and contributors; BSIM3v3.3.0 by the UC Berkeley BSIM Research Group). The file inst/COPYRIGHTS of the package (NOTICE in the repository) lists the upstream files and reproduces their copyright and licence notices.

Dune is an independent project: it is not affiliated with, sponsored by or endorsed by the University of California, Berkeley, the UC Berkeley BSIM Research Group or the ngspice project. The names “SPICE”, “SPICE3” and “ngspice” are used only descriptively, to identify the programs whose netlist language and behaviour Dune implements.

Citing

Dune has a DOI: 10.5281/zenodo.24052213. citation("spice") gives the entry for the package.