Analog circuit IR (Intermediate Representation) and Spectre netlist generator
Project description
License: Apache-2.0
analog-py
Python DSL + AST + Codegen for Analog Circuit Design and Netlist Generation.
Project Goals
analogpy is a Python library for generating circuit netlists. It bridges the gap between Python programming and analog circuit simulation.
What analogpy DOES:
-
Generate netlists (MVP: Spectre, future: ngspice)
- Circuit topology in Python
- Hierarchical circuits
- Testbench with analyses
-
Build simulation commands (not execute)
- SpectreCommand builder with configurable options
- User executes via shell or tmux-ssh
-
Parse simulation results (planned)
- Read PSF/nutbin files
- Expose data as numpy arrays / pandas DataFrames
- Enable Python-native post-processing
-
Make Python loop design easy
- PVT corners: Python loop generates N netlists
- Monte Carlo: Python loop with different seeds
- Parameter sweeps: Python variables directly in netlist
What analogpy does NOT do:
- Job submission: Use shell or tmux-ssh
- Heavy analysis: Use numpy, scipy (FFT, filtering, etc.)
- Visualization: Use matplotlib, plotly (analogpy provides helpers)
- Replace Cadence ADE: analogpy is CLI/script-first, not GUI
Design Philosophy
┌─────────────────────────────────────────────────────────────┐
│ Python Script │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ analogpy │ │ numpy │ │ matplotlib │ │
│ │ (netlist) │ │ scipy │ │ plotly │ │
│ │ (parse) │ │ pandas │ │ (visualization) │ │
│ │ (expose) │ │ (analysis) │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └─────────┬──────────-┘ │
└─────────┼────────────────┼───────────────────┼──────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌───────────┐
│ Spectre │ │ Post-process │ │ Plots │
│ Netlist │ │ (FFT, etc.) │ │ PNG/HTML │
└──────────┘ └──────────────┘ └───────────┘
Roadmap
- 0.1.x AST + netlist generation ✅
- 0.2.x Result parser + data exposure
- 0.3.x Optimization / AI hooks
- 1.0.0 Stable IR
Installation
pip install -e .
Quick Start
from analogpy import Circuit, nmos, pmos, generate_spectre
# Define a reusable inverter circuit
inv = Circuit("inverter", ports=["in", "out", "vdd", "gnd"])
inv.add(nmos("MN", d=inv.net("out"), g=inv.net("in"),
s=inv.net("gnd"), b=inv.net("gnd"), w=1e-6, l=180e-9))
inv.add(pmos("MP", d=inv.net("out"), g=inv.net("in"),
s=inv.net("vdd"), b=inv.net("vdd"), w=2e-6, l=180e-9))
# Create top-level circuit (no ports = top level)
top = Circuit("tb_inverter", ports=[])
vin = top.net("vin")
vout = top.net("vout")
vdd = top.supply("vdd", 1.8)
gnd = top.gnd()
# Instantiate the inverter
top.instantiate(inv, "X1", **{"in": vin, "out": vout, "vdd": vdd, "gnd": gnd})
# Generate Spectre netlist
netlist = generate_spectre(top)
print(netlist)
Examples
See the examples/ folder for complete workflows:
examples/01_inverter_basic.py- Simple inverter netlistexamples/02_ota_testbench.py- OTA with DC/AC analysisexamples/03_pvt_sweep.py- PVT corner sweep with Python loopexamples/04_monte_carlo.py- Monte Carlo with Python loopexamples/05_result_processing.py- Parse results and plot (planned)
Features
Phase 1: Core Hierarchy (Implemented)
- Circuit: Reusable circuit blocks with defined ports (maps to Spectre
subckt) - Aliases:
SubcircuitandSubcktare aliases forCircuit - Instantiation: Hierarchical design with
circuit.instantiate() - Nested hierarchy: Circuits can contain other circuits
- Top-level: Use
Circuit("name", ports=[])orTestbenchfor simulation top
Phase 2: Testbench & Analysis (Implemented)
- Testbench: Test environment extending Circuit with simulation setup
- Analysis classes: DC, AC, Transient, Noise, STB
- Simulator options: Temperature, tolerances, convergence settings
- Behavioral models: Verilog-A include support
from analogpy import Testbench, DC, AC, Transient
tb = Testbench("tb_amp")
tb.supply("vdd", 1.8)
tb.set_temp(27)
tb.add_analysis(DC())
tb.add_analysis(AC(start=1, stop=1e9, points=100))
tb.add_analysis(Transient(stop=1e-6))
Phase 3: SaveConfig (Implemented)
- Hierarchical saves: Define saves at block level, apply with prefix
- Tagged signals: Filter saves by category
- Testbench control: Override, include, exclude saves
from analogpy import SaveConfig
# Define saves for OTA block
ota_saves = (SaveConfig("ota")
.voltage("out", "tail", tag="essential")
.op("M1:gm", "M2:gm", tag="op_params"))
# In testbench, apply with hierarchy prefix
tb.save(ota_saves.with_prefix("X_LDO.X_OTA"))
Phase 4: Device Primitives (Implemented)
- MOSFETs:
nmos(),pmos()with nf support - Passives:
resistor(),capacitor(),inductor() - Sources:
vsource(),isource(),vpulse(),vsin() - Controlled sources:
vcvs(),vccs(),ccvs(),cccs() - Other:
diode()
Phase 5: SpectreCommand (Implemented)
- Command builder: Generate spectre commands without execution
- Configurable: Accuracy, threads, timeouts, include paths
- Presets: Liberal (fast), conservative (robust), moderate
from analogpy import SpectreCommand
cmd = (SpectreCommand("input.scs")
.accuracy("liberal")
.threads(16)
.include_path("/path/to/models")
.build())
# User executes via shell or tmux-ssh
Phase 6: SimulationBatch (Implemented)
- PVT sweeps: Process/Voltage/Temperature corners
- Monte Carlo: Generate N runs with different seeds
- Runner scripts: Python scripts with CLI configuration
from analogpy import SimulationBatch
# Python loop generates multiple netlists
batch = SimulationBatch("ldo_pvt", "/sim/ldo_pvt")
batch.pvt_sweep(make_tb_ldo, corners=[
{"process": "tt", "voltage": 1.8, "temp": 27},
{"process": "ff", "voltage": 1.98, "temp": -40},
{"process": "ss", "voltage": 1.62, "temp": 125},
])
batch.command_options(accuracy="liberal", threads=16)
batch.generate()
batch.write_runner("run_pvt.py")
# User runs: python run_pvt.py commands | parallel tmux-ssh {}
Phase 7: PDK Infrastructure (Implemented)
- PDK loader: Load PDK configuration by name
- Multi-source config: Project, user, environment variables
- NDA-safe: PDK files never included in package
from analogpy.pdk import PDK
pdk = PDK.load("tsmc28") # Loads from config
mn1 = pdk.nmos("M1", d=vout, g=vin, s=gnd, b=gnd, w=1e-6, l=28e-9, nf=4)
Phase 8: Result Parsing (Planned)
- Parse PSF/nutbin: Read Spectre output files
- Expose as Python data: numpy arrays, pandas DataFrames
- Display config: Separate from save config
- Validation: Warn if display signal not in saved signals
# Planned API
from analogpy.results import load_results
results = load_results("/sim/ldo_pvt/tt_v1.8_t27/psf")
# Point query
vout_dc = results.dc["X_OTA.vout"]
# Waveform as numpy array
vout_tran = results.tran["vout"] # Returns (time, values) arrays
# At specific time
vgs_at_10ns = results.tran["M1:vgs"].at(10e-9)
# Use Python for analysis
import numpy as np
from scipy.fft import fft
spectrum = fft(vout_tran.values) # numpy/scipy does the work
Architecture
analogpy/
├── circuit.py # Circuit (Subcircuit, Subckt are aliases), Net, Instance
├── devices.py # nmos, pmos, resistor, capacitor, etc.
├── spectre.py # Spectre netlist generation
├── testbench.py # Testbench class
├── analysis.py # DC, AC, Transient, Noise, STB
├── save.py # SaveConfig for probe management
├── command.py # SpectreCommand builder
├── batch.py # SimulationBatch for PVT/MC
├── pdk/ # PDK loader infrastructure
└── results/ # Result parsing (planned)
Design Principles
- Netlist-focused: Generate netlists, expose results - that's it
- Python-native: Use Python variables, loops, data structures
- Don't reinvent: FFT? Use scipy. Plots? Use matplotlib.
- CLI-first: No GUI, scripts and commands
- AI-friendly: Simple patterns for LLM generation
Testing
pytest tests/ -v
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file analogpy-0.1.1.tar.gz.
File metadata
- Download URL: analogpy-0.1.1.tar.gz
- Upload date:
- Size: 42.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3701710689c85b16b0e078176976885c1ed8e2fc28a373883d220f68a5ffb059
|
|
| MD5 |
d7fe5c4069ab67804dec40a31a5f873d
|
|
| BLAKE2b-256 |
c0917130d56e7fb6d6d65bdaed5231193e5d2c14dcf3580340cce2f5b7a77301
|
File details
Details for the file analogpy-0.1.1-py3-none-any.whl.
File metadata
- Download URL: analogpy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 44.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2beb260a18ccf7d43ce5ed3e00f9fc640d7fbcb04603acdbddd3af7db222db7c
|
|
| MD5 |
475eaf181402ce087fcdef42a1b85b17
|
|
| BLAKE2b-256 |
6f11aa19ebf2741a3cf86edec163e8d705bf69d88b9230e7138b58e178f02055
|