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
| Script | Demonstrates | Key API |
01_voltage_divider.py | Resistive divider, DC operating point | Subcircuit, Testbench, R, V, operating_point() |
02_rc_lowpass.py | RC filter: AC frequency response + transient step | ac(), transient(), ac.frequency, tran.time, PulseVoltageSource |
03_rlc_bandpass.py | RLC bandpass with coupled inductors (transformer) | L, K, C, peak finding on numpy results |
04_bjt_amplifier.py | Common-emitter BJT amp with divider bias | model(), Q, coupling/bypass caps |
05_cmos_inverter.py | CMOS inverter transient switching | NMOS/PMOS model(), M, PulseVoltageSource |
06_opamp_inverting.py | Ideal opamp via behavioral source | BV with expression "1e6 * (V(inp) - V(inn))" |
07_diode_rectifier.py | Full-bridge rectifier + filter cap | diode model(), D, SinusoidalVoltageSource |
08_differential_pair.py | MOSFET diff pair with tail current | M ×2, I, differential OP measurement |
Elements tour
| Script | Demonstrates | Key API |
09_controlled_sources.py | All four controlled sources | E (VCVS), G (VCCS), F (CCCS), H (CCVS), 0 V sense source |
10_subcircuit.py | Hierarchy: define, nest, instantiate | X, tb.add_subcircuit() |
11_jfet_amplifier.py | JFET common-source amp, self-bias | J, NJF model() |
12_transmission_line.py | Lossless line, reflections | T with Z0, TD |
13_switches.py | V- and I-controlled switches with hysteresis | S, W, SW/CSW model() |
14_pwl_dac.py | 3-bit DAC staircase from PWL source | PieceWiseLinearVoltageSource, programmatic waveform |
Workflow
| Script | Demonstrates | Key API |
15_linting.py | Catching missing models / dangling nodes pre-sim | tb.check_backend(name) |
16_simulator_config.py | Full simulator configuration | temperature, options(), save(), measure(), step(), initial_condition(), node_set() |
17_veriloga_inline.py | Inline Verilog-A → OSDI compile + instantiate | veriloga(), raw_spice(); needs openvaf |
18_verilog_digital.py | Digital Verilog co-sim with XSPICE bridges | A, adc/dac bridge model(); needs XSPICE + iverilog |
Hot-swapping
| Script | Demonstrates | Key API |
19_backend_hotswap.py | Same circuit on ngspice and vacask | tb.with_backend(name) in a loop |
20_pdk_hotswap.py | Swap PDKs (sky130, gf180mcu), same topology | ModelLibrary(path, corner=...), tb.use_pdk(); set PDK_ROOT, enable sims with DESPICE_RUN_PDK_EXAMPLES=1 |
21_combined_hotswap.py | Matrix sweep: PDKs × backends | ModelLibrary with per-backend paths + with_backend() |
22_design_testbenches.py | Reusable analog testbench recipes + validation | testbenches 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()