Skip to main content

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:

  1. Generate netlists (MVP: Spectre, future: ngspice)

    • Circuit topology in Python
    • Hierarchical subcircuits
    • Testbench with analyses
  2. Build simulation commands (not execute)

    • SpectreCommand builder with configurable options
    • User executes via tmux-ssh, LSCS, ICRP, or any job system
  3. Parse simulation results (planned)

    • Read PSF/nutbin files
    • Expose data as numpy arrays / pandas DataFrames
    • Enable Python-native post-processing
  4. 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 Python + tmux-ssh / LSCS / ICRP
  • 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, Subcircuit, nmos, pmos, generate_spectre

# Define a reusable inverter subcircuit
inv = Subcircuit("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 testbench
top = Circuit("tb_inverter")
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 netlist
  • examples/02_ota_testbench.py - OTA with DC/AC analysis
  • examples/03_pvt_sweep.py - PVT corner sweep with Python loop
  • examples/04_monte_carlo.py - Monte Carlo with Python loop
  • examples/05_result_processing.py - Parse results and plot (planned)

Features

Phase 1: Core Hierarchy (Implemented)

  • Circuit: Top-level circuit container with nets, instances, supplies
  • Subcircuit: Reusable circuit blocks with defined ports
  • Instantiation: Hierarchical design with circuit.instantiate()
  • Nested hierarchy: Subcircuits can contain other subcircuits

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: tmux-ssh "cmd" or submit to LSCS/ICRP

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, 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

  1. Netlist-focused: Generate netlists, expose results - that's it
  2. Python-native: Use Python variables, loops, data structures
  3. Don't reinvent: FFT? Use scipy. Plots? Use matplotlib.
  4. CLI-first: No GUI, scripts and commands
  5. AI-friendly: Simple patterns for LLM generation

Testing

pytest tests/ -v

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

analogpy-0.1.0.tar.gz (30.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

analogpy-0.1.0-py3-none-any.whl (31.2 kB view details)

Uploaded Python 3

File details

Details for the file analogpy-0.1.0.tar.gz.

File metadata

  • Download URL: analogpy-0.1.0.tar.gz
  • Upload date:
  • Size: 30.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for analogpy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 adfd0295ed1a81fbde39d0ca0ca7b03d8b71defb2fd0e8bc2e188c279d5ab0f9
MD5 f015dccb2567cf345f0badd7ef82efb8
BLAKE2b-256 8392f437845ab14c6cf3d07315ffc7d6b69d881274e7c4b414aabaff05b61a0e

See more details on using hashes here.

File details

Details for the file analogpy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: analogpy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for analogpy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 77f5d423de8ed5b13f177e9654485e3f95cc3ce60b29c168b563eb5a0f89a0de
MD5 fe62bc2004be73bf84025b753e1542af
BLAKE2b-256 cd9b6528ebf224f16c49801f5fe75fe9f1e1d6e1ffa5830b85f6b5a86bae32fe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page