Analog circuit IR (Intermediate Representation) and Spectre netlist generator
Project description
analogPy
Glossary
-
DSL (Domain-Specific Language): A mini-language focused on a specific problem domain. analogpy is a Python DSL for describing circuits — instead of writing raw Spectre netlists (
R1 vdd out 1k), you write Python (resistor("R1", p=vdd, n=out, r=1e3)). -
AST (Abstract Syntax Tree): A tree representation of code structure. When you write
resistor("R1", p=vdd, n=out, r=1e3), analogpy builds an internal tree representing the circuit hierarchy before generating netlist text. -
Codegen (Code Generation): Taking the internal AST and converting it to output code (Spectre or ngspice netlist).
generate_spectre(tb)walks the AST and outputs the netlist text.
Python code (your circuit) → analogpy builds AST → Codegen → Spectre netlist
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 (Spectre & 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 tmux4ssh
- this tool doesn't provide any simulator access, a demo with ngspice is available at analogpy website
-
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 tmux4ssh
- Result parsing: Use psf-utils for PSF ASCII files
- 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 │ │ psf-utils │ │ matplotlib │ │
│ │ (netlist) │ │ numpy │ │ plotly │ │
│ │ (command) │ │ scipy │ │ (visualization) │ │
│ │ │ │ (analysis) │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └─────────┬──────────-┘ │
└─────────┼────────────────┼───────────────────┼──────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌───────────┐
│ Spectre │ │ Post-process │ │ Plots │
│ Netlist │ │ (FFT, etc.) │ │ PNG/HTML │
└──────────┘ └──────────────┘ └───────────┘
Roadmap
- 0.1.x AST + netlist generation ✅
- 0.2.x Optimization / AI hooks
- 1.0.0 Stable IR
Installation
pip install analogpy
or git clone this repo and then
pip install -e .
Quick Start
from analogpy import Circuit, Testbench, nmos, pmos, vsource, generate_spectre
class Inverter(Circuit):
"""CMOS Inverter cell."""
def __init__(self, w_n: float = 1e-6, w_p: float = 2e-6,
l_n: float = 180e-9, l_p: float = 180e-9):
# Ports with optional direction using colon syntax:
# "inp:input" = input, "out:output" = output, default = inout
super().__init__(name="inverter", ports=["inp:input", "out:output", "vdd", "vss"])
# Short port names (d, g, s, b) or full names (drain, gate, source, bulk)
self.add_instance(pmos, "MP", d=self.net("out"), g=self.net("inp"),
s=self.net("vdd"), b=self.net("vdd"), w=w_p, l=l_p,
schematic_position={'relative_to': "MN", 'x_shift': 0, 'y_shift': 2.1})
# Equivalent using full names:
self.add_instance(nmos, "MN", drain=self.net("out"), gate=self.net("inp"),
source=self.net("vss"), bulk=self.net("vss"), w=w_n, l=l_n)
# Draw explicit wires between ports sharing the same net
self.draw_wires('out')
self.draw_wires('inp')
self.draw_wires('vdd', only=[('MP', 's'), ('MP', 'b')])
self.draw_wires('vss', only=[('MN', 's'), ('MN', 'b')])
# Customize transistor sizes directly in the constructor:
#inv_large = Inverter() # uses defaults: w_n=1u, w_p=2u, l_n=180n, l_p=180n
inv_large = Inverter(w_n=2e-6, w_p=4e-6, l_n=90e-9, l_p=90e-9)
# Create top-level circuit
#top = Testbench() # also works — auto-names from filename, ports=[] by default
top = Circuit("tb_inverter", ports=[])
# add_net() and net() are equivalent — use whichever you prefer
vin_net = top.net("vin") # short form
vout_net = top.add_net("vout") # explicit form
vdd_net = top.add_net("vdd")
gnd = top.add_gnd() # Global ground "0"; top.gnd() also works
# add_instance() and instance() are equivalent
vdd_inst = top.add_instance(vsource, "I_Vdd", p=vdd_net, n=gnd, dc=1.8)
x1_inst = top.instance(inv_large, "X1", inp=vin_net, out=vout_net, vdd=vdd_net, vss=gnd)
# Generate Spectre netlist
netlist = generate_spectre(top)
print(netlist)
Spectre netlist output:
subckt tb_inverter inp out vdd vss
I_Vdd (vdd 0) vsource dc=1.8
X1 (inp out vdd vss) inverter
ends tb_inverter
Two ways to define cells: The Quick Start above uses a class (
class Inverter(Circuit):), which is best when you need parameterized cells (different W/L per instance). For simpler cells, use a function instead — nosuper().__init__needed:def make_inverter(w_n=1e-6, w_p=2e-6, l_n=180e-9, l_p=180e-9): inv = Circuit(name="inverter", ports=["inp", "out", "vdd", "vss"]) inv.add_instance(nmos, "MN", d=inv.net("out"), g=inv.net("inp"), s=inv.net("vss"), b=inv.net("vss"), w=w_n, l=l_n) inv.add_instance(pmos, "MP", d=inv.net("out"), g=inv.net("inp"), s=inv.net("vdd"), b=inv.net("vdd"), w=w_p, l=l_p) return inv inv_large = make_inverter(w_n=2e-6, w_p=4e-6)See
examples/07_oled2.pyfor a full function-based example.
AST (Abstract Syntax Tree)
Inspect the circuit hierarchy as a tree:
print(Inverter().tree())
inverter [Circuit] ports=['inp', 'out', 'vdd', 'vss']
├── MP (pmos) [primitive] {w=2u, l=180n} d=out, g=inp, s=vdd, b=vdd
└── MN (nmos) [primitive] {w=1u, l=180n} d=out, g=inp, s=vss, b=vss
Schematic Visualization
Generate a schematic SVG and cell symbol:
from analogpy.visualization import render_schematic_svg, create_cell_symbol_standalone, drawing_to_svg
inverter = Inverter()
# Generate schematic view (with explicit wire routing)
svg = render_schematic_svg(cell=inverter)
with open("inverter.svg", "w") as f:
f.write(svg)
# Generate cell symbol view (port directions auto-extracted from cell)
drawing = create_cell_symbol_standalone(cell=inverter)
svg_symbol = drawing_to_svg(drawing)
with open("inverter_symbol.svg", "w") as f:
f.write(svg_symbol)
# Or render PDF (schematic only)
top.render_schematic("tb_inverter.pdf")
Inverter schematic and symbol:
| Schematic view | Symbol view |
Note: Spectre uses a different syntax than traditional SPICE:
- All instances start with
Iprefix (not R, C, L) - Nodes are in parentheses:
(node1 node2) - Parameters use
key=valuesyntax:dc=1.8,w=1u l=180n
Note on port naming: Avoid using Python reserved keywords (
in,for,class, etc.) as port names. For example,add_instance(inv, "X1", in=vin)is a syntax error becauseinis a reserved word. Useinpinstead. If you must match an existing netlist that usesinas a port name, use dict unpacking as a workaround:add_instance(inv, "X1", **{"in": vin, "out": vout, "vdd": vdd, "vss": gnd})
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/06_oled_dc.py- OLED DC simulation with Verilog-A LUTs (includes SpectreCommand reference)examples/07_oled2.py- Series OLED testbench using function-built cells
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.add_instance() - 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, vsource
tb = Testbench("tb_amp")
vdd = tb.add_net("vdd") # preferred; tb.net("vdd") is an alias
gnd = tb.add_gnd() # preferred; tb.gnd() is an alias
vdd_inst = tb.add_instance(vsource, instance_name="I_Vdd", p=vdd, n=gnd, dc=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))
Analysis extras and SimulatorOptions
All analysis classes and SimulatorOptions support an extras dict for arbitrary Spectre parameters not covered by named fields:
from analogpy import Transient, DC
# cmin is a named field on Transient (minimum capacitance per node for convergence)
tran = Transient(stop=1e-6, cmin=1e-18)
# Use extras for any other Spectre analysis parameter
tran = Transient(stop=1e-6, extras={"errpreset": "conservative", "method": "euler"})
dc = DC(extras={"homotopy": "all"})
Supported Analysis Types
analogpy supports the following analyses (verified against official documentation):
- Spectre: Cadence Spectre 23.10 reference
- ngspice:
https://ngspice.sourceforge.io/docs/ngspice-html-manual/manual.xhtml
⚠️ WARNING: Support status (✅/❌) is verified against official docs. The generated netlist syntax has NOT been verified with actual simulation runs. Some generated outputs may need correction.
| Spectre | analogpy Class | Spectre | ngspice | Notes |
|---|---|---|---|---|
dc |
DC |
✅ | ✅ | DC operating point / sweep |
ac |
AC |
✅ | ✅ | AC small-signal |
tran |
Transient |
✅ | ✅ | Transient time-domain |
noise |
Noise |
✅ | ✅ | Noise analysis |
stb |
STB |
✅ | ❌ | Stability/phase margin |
pss |
PSS |
✅ | ✅ | Periodic steady-state (ngspice: experimental) |
pac |
PAC |
✅ | ✅ | Periodic AC (ngspice: experimental) |
pnoise |
PNoise |
✅ | ✅ | Periodic noise (ngspice: experimental) |
pxf |
PXF |
✅ | ❌ | Periodic transfer function |
hb |
HB |
✅ | ❌ | Harmonic balance |
sp |
SP |
✅ | ❌ | S-parameter |
xf |
XF |
✅ | ✅ | Transfer function |
pz |
PZ |
✅ | ✅ | Pole-zero |
sweep |
Sweep |
✅ | ❌ | Parameter sweep |
dcmatch |
DCMatch |
✅ | ❌ | DC mismatch |
acmatch |
ACMatch |
✅ | ❌ | AC mismatch |
sens |
— | ✅ | ✅ | Sensitivity analysis |
disto |
— | ❌ | ✅ | Distortion analysis (ngspice-only) |
fft |
FFT |
❌ | ✅ | FFT analysis |
Two Syntax Options
Each analysis supports two equivalent syntaxes:
| Analysis | Explicit (add_analysis) | Convenience Method |
|---|---|---|
| DC | tb.add_analysis(DC()) |
tb.op() or tb.dc() |
| AC | tb.add_analysis(AC(start=1, stop=1e9)) |
tb.ac(start=1, stop=1e9) |
| Transient | tb.add_analysis(Transient(stop=1e-6)) |
tb.tran(stop=1e-6) |
| Noise | tb.add_analysis(Noise(output="v(out)", input="V1")) |
tb.noise(output="v(out)", input="V1") |
| STB | tb.add_analysis(STB(probe="v(out)")) |
tb.stb(probe="v(out)") |
| PSS | tb.add_analysis(PSS(fund=1e9)) |
tb.pss(fund=1e9) |
| PAC | tb.add_analysis(PAC(stop=1e9)) |
tb.pac(stop=1e9) |
| PNoise | tb.add_analysis(PNoise(stop=1e9)) |
tb.pnoise(stop=1e9) |
| PXF | tb.add_analysis(PXF(stop=1e9)) |
tb.pxf(stop=1e9) |
| SP | tb.add_analysis(SP(start=1e6, stop=1e9)) |
tb.sp(start=1e6, stop=1e9) |
| XF | tb.add_analysis(XF(stop=1e9)) |
tb.xf(stop=1e9) |
| PZ | tb.add_analysis(PZ()) |
tb.pz() |
| Sweep | tb.add_analysis(Sweep(param="R1", ...)) |
tb.sweep(param="R1", ...) |
| HB | tb.add_analysis(HB(funds=[1e9])) |
tb.hb(funds=[1e9]) |
| DCMatch | tb.add_analysis(DCMatch()) |
tb.dcmatch() |
| ACMatch | tb.add_analysis(ACMatch(start=1, stop=1e9)) |
tb.acmatch(start=1, stop=1e9) |
SimulatorOptions — tolerance fields (reltol, vabstol, iabstol, gmin) default to None and are not emitted, letting the command-line accuracy mode (++aps, +aps) control them. Set explicitly only when you need to override:
tb = Testbench("tb_amp")
tb.simulator_options.reltol = 1e-6 # Override tolerance
tb.simulator_options.gmin = 1e-15 # Tighter gmin
tb.simulator_options.extras = {"rforce": 1, "pivotdc": "yes"} # Convergence helpers
temp vs tnom:
temp— circuit simulation temperature (varies in PVT sweeps)tnom— temperature at which device model parameters were measured/extracted (usually fixed to match PDK characterization, e.g. 27 or 25)
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 - BJT/JFET:
bjt(),jfet()for bipolar and junction FETs - Passives:
resistor(),capacitor(),inductor(),mutual_inductor() - Sources:
vsource(),isource() - Controlled sources:
vcvs(),vccs(),ccvs(),cccs() - Other:
diode(),iprobe(),port()(for S-parameter)
Phase 5: SpectreCommand (Implemented)
- Command builder: Generate spectre commands without execution
- Minimal defaults: Only emits flags you explicitly set
- Configurable: Accuracy, threads, output format, 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 tmux4ssh
SpectreCommand Options Reference
| Method | Spectre Flag | Description |
|---|---|---|
.output_format(fmt) |
-format |
Raw data format: "psfascii" (default), "psfbin", "psfxl", "psfbinf", "nutbin", "nutascii", "sst2", "fsdb", "fsdb5", "wdf", "uwi", "tr0ascii". PSF ASCII files can be read with psf-utils |
.accuracy(level, mode) |
++aps, +aps, +errpreset |
Error tolerance and acceleration (see below) |
.threads(n) |
+mt=N |
Number of parallel threads (max 64) |
.include_path(*paths) |
-I |
Add include paths for model files |
.log_file(path) |
+log |
Log file path (default: Spectre writes <netlist>.log) |
.raw_dir(path) |
-raw |
Raw output directory (default: Spectre writes in current dir) |
.ahdl_libdir(path) |
-ahdllibdir |
Compiled Verilog-A model cache directory (default: raw output dir) |
.timeout(seconds) |
+lqtimeout |
License queue timeout — abort if license not acquired in time |
.max_warnings(n) |
-maxw |
Max warnings before Spectre aborts |
.max_notes(n) |
-maxn |
Max informational notes before suppression |
.logstatus() |
+logstatus |
Enable status logging for monitoring simulation progress |
.flag("+escchars") |
+escchars |
Allow backslash-escaped characters in paths/strings |
Accuracy modes — .accuracy(level, mode):
level:"liberal"(fast),"moderate","conservative"(accurate)mode(optional, default"++aps"):"++aps"— Uses a different time-step control algorithm for improved performance while satisfying error tolerances. Emits++aps=<level>"+aps"— Spectre APS mode, a different simulator engine from base Spectre. Emits+aps=<level>"errpreset"— Base Spectre error preset only, no APS acceleration. Emits+errpreset=<level>
# Examples
.accuracy("liberal") # ++aps=liberal (default mode)
.accuracy("liberal", "+aps") # +aps=liberal
.accuracy("moderate", "errpreset") # +errpreset=moderate
Note: Only .output_format() is emitted by default (-format psfascii). All other flags are opt-in — if not called, they are not included in the generated command, letting Spectre use its own defaults.
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 tmux4ssh {}
Phase 7: PDK Infrastructure (Implemented, not tested)
- 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)
Visualization Module (Experimental)
Generate schematic symbols and block diagrams for circuit documentation.
pip install analogpy[visualization] # Requires schemdraw, reportlab, pypdf
Port Type Inference
The visualization module automatically infers port placement on symbols based on naming conventions:
| Port Type | Position | Pattern Examples |
|---|---|---|
| POWER | Top | vdd, avdd, vcc, pwr, anode, *_vdd |
| GROUND | Bottom | vss, gnd, elvss, cathode, *_gnd |
| INPUT | Left | in, clk, en, rst, din, sel, *_in |
| OUTPUT | Right | out, q, y, dout, *_out |
| INOUT | Left (below inputs) | io, sda, scl, data, bus |
| UNKNOWN | Right (below outputs) | All other names |
Customizing Port Locations
Override the auto-inference using port_overrides:
from analogpy.visualization import draw_cell_symbol, PortType
import schemdraw
# Define your custom port types
port_overrides = {
"BIAS": PortType.INPUT, # Force BIAS to left side
"MONITOR": PortType.OUTPUT, # Force MONITOR to right side
}
# Draw symbol with overrides
with schemdraw.Drawing() as d:
d.config(unit=1, fontsize=10)
positions = draw_cell_symbol(
d, "my_cell",
ports=["VDD", "VSS", "IN", "OUT", "BIAS", "MONITOR"],
port_overrides=port_overrides
)
d.save("my_cell.png")
Standalone Symbol Generation
from analogpy.visualization import create_cell_symbol_standalone, drawing_to_svg
oled = Circuit(name="oled_cell", ports=["ANODE", "ELVSS"])
d = create_cell_symbol_standalone(oled)
svg = drawing_to_svg(d)
Note: This module is experimental. Block diagram connection routing still needs 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
Design Principles
- Netlist-focused: Generate netlists - 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
Naming Conventions
Following PEP 8:
- Files/modules:
snake_case—oled_1rc.py,circuit.py - Classes:
PascalCase—Oled1RC,Circuit,Testbench - Functions/variables:
snake_case—add_instance(),generate_spectre() - Device primitives:
lowercase—nmos,pmos,resistor,cccs
Example: from cells.oled_1rc import Oled1RC — file is snake_case, class is PascalCase.
Object Model: Python vs EDA Naming
In analogpy, a Python object represents an EDA cell definition (not an instance):
| Python | EDA Concept | Example |
|---|---|---|
Class (Inverter) |
Cell template — defines structure, parameters not yet set | class Inverter(Circuit): |
Object (inverter = Inverter(w_n=1u)) |
Parameterized cell — fully describes the netlist | nmos = Circuit(name="nmos", ...) |
add_instance(cell, "X0", ...) |
Instance — a placed copy with pin connections | self.add_instance(nmos, "MN", d=..., g=...) |
Why not Python class = cell, Python object = instance? Because in analog design, the same
cell with different W/L values produces a different netlist. Inverter(w_n=1u) and
Inverter(w_n=2u) are different cells. The Python object captures that parameterization.
Device primitives like nmos and pmos are pre-created objects (not classes) because they
have no user-configurable structure — their parameters (W, L) are passed at instantiation time
via add_instance().
Testing
pytest tests/ -v
Simulator Integration Tests
Some tests require a working Spectre simulator. These are marked with @pytest.mark.simulator and will be automatically skipped if no simulator is available.
Test levels:
- Syntax checks - Always run, use Python-based validation
- Basic simulation - Requires simulator, runs actual simulations
- Result validation - Compares results against expected values
Setting up simulator access:
Option 1: Config file (recommended for remote simulation)
# Copy template to ~/.analogpy/
mkdir -p ~/.analogpy
cp config.yaml.template ~/.analogpy/config.yaml
# Edit the config file to set remote spectre path
# Uncomment and modify the settings you need
Example ~/.analogpy/config.yaml:
simulator:
mode: remote
remote:
spectre_path: /tools/cadence/SPECTRE231/bin/spectre
workdir: /tmp/analogpy
Option 2: Local Spectre (if installed on your machine)
# Spectre in PATH
which spectre # Should return path
# Or set explicit path
export SPECTRE_PATH=/path/to/spectre
Option 3: Remote via tmux4ssh (auto-detected if config exists)
# Install tmux4ssh
pip install tmux4ssh
# Configure once (credentials are saved to ~/.tmux4ssh_config)
tmux4ssh user@your-spectre-server.com
# Now pytest will automatically use remote execution
pytest tests/test_simulation.py -v
Configuration precedence:
~/.analogpy/config.yaml(user config file)- Environment variables (override config file)
- Local Spectre (PATH or SPECTRE_PATH)
- Remote via tmux4ssh (reads ~/.tmux4ssh_config)
- Skip with helpful message
Environment variables:
| Variable | Description | Default |
|---|---|---|
SPECTRE_PATH |
Path to local spectre binary | Auto-detect from PATH |
ANALOGPY_WORKDIR |
Working directory for simulation files | /tmp/analogpy |
ANALOGPY_SKIP_SIMULATION |
Set to "1" to skip all simulation tests | Disabled |
License
Internal — requires company agreement before open source release.
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.2.17.tar.gz.
File metadata
- Download URL: analogpy-0.2.17.tar.gz
- Upload date:
- Size: 143.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6b651a54cb760c24e83456df3c3a3ba9147602bb4d2d572d06845e1f3ea2b45
|
|
| MD5 |
f708a56bfb98859aa3ee72cdf27f7383
|
|
| BLAKE2b-256 |
9eb08ad1f431eafb33a5ed6869a35491658056a4a8e7ec05472c1d0983f7f431
|
File details
Details for the file analogpy-0.2.17-py3-none-any.whl.
File metadata
- Download URL: analogpy-0.2.17-py3-none-any.whl
- Upload date:
- Size: 136.6 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 |
c19b8ee99e4a85fe64564b01236e7fa480c3a5d9f5019ea1ce1052193dbefd30
|
|
| MD5 |
10c030c920986aee382249fda9bba672
|
|
| BLAKE2b-256 |
10ce0abecc21291bfac5a812e2ea080ba2fef77f907f28d12c0959abf7a10b03
|