Examples

22 executable scripts in examples/, ordered from basic circuits to backend and testbench workflows. Run any with python examples/<name>.py (ngspice installed).

Basics

ScriptDemonstratesKey API
01_voltage_divider.pyResistive divider, DC operating pointSubcircuit, Testbench, R, V, operating_point()
02_rc_lowpass.pyRC filter: AC frequency response + transient stepac(), transient(), ac.frequency, tran.time, PulseVoltageSource
03_rlc_bandpass.pyRLC bandpass with coupled inductors (transformer)L, K, C, peak finding on numpy results
04_bjt_amplifier.pyCommon-emitter BJT amp with divider biasmodel(), Q, coupling/bypass caps
05_cmos_inverter.pyCMOS inverter transient switchingNMOS/PMOS model(), M, PulseVoltageSource
06_opamp_inverting.pyIdeal opamp via behavioral sourceBV with expression "1e6 * (V(inp) - V(inn))"
07_diode_rectifier.pyFull-bridge rectifier + filter capdiode model(), D, SinusoidalVoltageSource
08_differential_pair.pyMOSFET diff pair with tail currentM ×2, I, differential OP measurement

Elements tour

ScriptDemonstratesKey API
09_controlled_sources.pyAll four controlled sourcesE (VCVS), G (VCCS), F (CCCS), H (CCVS), 0 V sense source
10_subcircuit.pyHierarchy: define, nest, instantiateX, tb.add_subcircuit()
11_jfet_amplifier.pyJFET common-source amp, self-biasJ, NJF model()
12_transmission_line.pyLossless line, reflectionsT with Z0, TD
13_switches.pyV- and I-controlled switches with hysteresisS, W, SW/CSW model()
14_pwl_dac.py3-bit DAC staircase from PWL sourcePieceWiseLinearVoltageSource, programmatic waveform

Workflow

ScriptDemonstratesKey API
15_linting.pyCatching missing models / dangling nodes pre-simtb.check_backend(name)
16_simulator_config.pyFull simulator configurationtemperature, options(), save(), measure(), step(), initial_condition(), node_set()
17_veriloga_inline.pyInline Verilog-A → OSDI compile + instantiateveriloga(), raw_spice(); needs openvaf
18_verilog_digital.pyDigital Verilog co-sim with XSPICE bridgesA, adc/dac bridge model(); needs XSPICE + iverilog

Hot-swapping

ScriptDemonstratesKey API
19_backend_hotswap.pySame circuit on ngspice and vacasktb.with_backend(name) in a loop
20_pdk_hotswap.pySwap PDKs (sky130, gf180mcu), same topologyModelLibrary(path, corner=...), tb.use_pdk(); set PDK_ROOT, enable sims with DESPICE_RUN_PDK_EXAMPLES=1
21_combined_hotswap.pyMatrix sweep: PDKs × backendsModelLibrary with per-backend paths + with_backend()
22_design_testbenches.pyReusable analog testbench recipes + validationtestbenches module: amplifier_voltage_gain, CornerCase, MetricSpec, extract_metrics, validate_metrics

Backend hot-swap in full

import pyspice_rs as ps
from pyspice_rs.unit import u_V, u_kOhm

dut = ps.Subcircuit("divider", ["vin", "vout"])
dut.R(name="top", positive="vin", negative="vout", value=2 @ u_kOhm)
dut.R(name="bot", positive="vout", negative=dut.gnd, value=1 @ u_kOhm)

for backend in ["ngspice", "vacask"]:
    tb = ps.Testbench(dut)
    tb.V(name="supply", positive="vin", negative=dut.gnd, value=10 @ u_V)
    tb.with_backend(backend)          # the only line that changes
    op = tb.operating_point()
    print(backend, op["vout"])

PDK hot-swap in full

import os
import pyspice_rs as ps

PDK_ROOT = os.environ["PDK_ROOT"]

PDKS = {
    "sky130": {
        "lib": f"{PDK_ROOT}/sky130A/libs.tech/ngspice/sky130.lib.spice",
        "corner": "tt",
        "nmos": "sky130_fd_pr__nfet_01v8",
        "vdd": 1.8,
    },
    "gf180mcu": {
        "lib": f"{PDK_ROOT}/gf180mcuD/libs.tech/ngspice/sm141064.ngspice",
        "corner": "typical",
        "nmos": "nfet_03v3",
        "vdd": 3.3,
    },
}

for name, cfg in PDKS.items():
    dut = build_cs_amp(cfg["nmos"])           # same topology every time
    lib = ps.ModelLibrary(cfg["lib"], corner=cfg["corner"])

    tb = ps.Testbench(dut)
    tb.use_pdk(lib)
    tb.with_backend("ngspice")
    op = tb.operating_point()