Skip to content

CLI Reference

Documentation Home | Getting Started | Circuit JSON Format | 中文版

This document covers only the currently public commands. Treat the actual --help output as the final source of truth:

circuit-opt --help
python -m circuitopt --help

The two entry points are equivalent. The rest of this document uses circuit-opt throughout.

Command Overview

Command Purpose
run Run AC, noise, transient, PSS, PAC, PNoise per the JSON config
signoff Run multiple signoff testbenches over an explicit PVT grid
verify-engine Cross-check one signoff case between the native engine and ngspice
passive-bom Inventory passives with silicon-area estimates and the passive/active ratio
explore Sample, solve, filter by constraints, and generate the Pareto front from an explore block
corners Fixed typical/slow/fast process-corner sweep for AT4000TG
mc Per-device mismatch Monte Carlo for AT4000TG
chopper Ideal, static-phase, LPTV, PSS, PAC, PNoise, and transient flows for the AFE chopper
adc SAR ADC single conversion, static sweep, sine-wave dynamic test, mismatch MC, and design exploration
plot Render the built-in AFE/chopper waveform and Bode plots
dataset Build a surrogate dataset with provenance
serve Start the optional local FastAPI service
mcp Start the optional Model Context Protocol server

The legacy no-subcommand form still auto-routes to run:

circuit-opt examples/periodic_rc.json

New docs and scripts should spell out run explicitly.

run

circuit-opt run CIRCUIT.json [options]

Common examples:

# Run every analysis in the JSON analyses block
circuit-opt run examples/periodic_rc.json

# Run only AC and noise
circuit-opt run examples/periodic_rc.json --analysis ac,noise

# Override the process corner and write JSON output
circuit-opt run examples/tsmc28hpcp_5t_ota.json \
  --analysis ac,noise --corner ss --output results/tsmc28_ss.json

Flags:

Flag Description
-a, --analysis Comma-separated subset of analyses: ac,noise,transient,pss,pac,pnoise
--corner Process-corner override; typical/slow/fast for AT4000TG, silicon PDKs use their own supported corners
--noise-band LO HI Noise integration band for the CLI summary, default 0.05 100.0 Hz
-o, --output Write {status, results, signoff} JSON; signoff is the common unit-bearing acceptance contract
--engine {rust} Compute engine; only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists; use --engine rust instead
--quiet Suppress progress and summary output

run's specific numeric options come from the JSON top-level analyses block. See Circuit JSON Format for the fields. The output signoff object always contains status, measurements, constraints, passed, and worst_case. Gain, UGF, and total/per-source branch power are reported when AC is selected. Phase margin, settling, integrated noise, and saturation appear only when the JSON has an explicit top-level signoff.measurements definition; acceptance limits live in signoff.constraints. See Circuit JSON Format.

signoff

circuit-opt signoff CAMPAIGN.json [--workers N] [--margins] [--tolerance SPEC] [--output RESULT.json]

The command evaluates every configured testbench at every Cartesian PVT point, retains invalid cases, and emits deterministic per-point plus global worst-case metadata. See Signoff Campaigns for the manifest and result contracts.

Flag Purpose
--margins Print a per-constraint margin table (observed range, tightest corner, fail count) ordered tightest-first. The stock worst_case names one measurement; the table is what shows which other specs are also near their limits.
--tolerance SPEC Re-run the campaign with passives perturbed and report which constraints break. SPEC is comma-separated NAME=PERCENT, where NAME is a class (R, C) or a single element (CC1): --tolerance R=20,C=10. A signoff that holds only at nominal component values is not a signoff.

passive-bom

circuit-opt passive-bom CAMPAIGN.json [--exclude A,B] [--top N]
                        [--sheet-ohm-sq R] [--resistor-width-um W] [--cap-ff-um2 D]

Inventories every resistor and capacitor with a silicon-area estimate and reports the passive/active area ratio. Netlist review catches wrong values; nothing otherwise catches a value that is correct and unbuildable.

DUT-versus-testbench membership is derived: an element belonging to the amplifier appears in every deck the manifest names, while bias helpers, AC coupling and loop probes appear in some. The rule needs no annotation, so it stays correct as testbenches are added. Process constants are printed with the report and overridable — the useful output is the ranking and the order of magnitude, not three significant figures.

Accepts a signoff manifest (which already names every testbench) or two or more deck files.

verify-engine

circuit-opt verify-engine CAMPAIGN.json --case NAME --point CORNER/TEMP/SUPPLY
                          [--nodes A,B] [--tolerance-mv MV] [--top N]

Runs one signoff case through both the native BSIM4 engine and the ngspice model-card path and diffs the node trajectories. The verdict keys on the settled deviation: during a fast transition, step-placement differences between two solvers alone produce tens of millivolts, whereas a genuine disagreement about the circuit is still there at the end of the window. Nodes held by the stimulus and samples straddling an input discontinuity are excluded by default, because both compare a waveform with itself.

Use it whenever a design result looks structurally wrong rather than slightly off — that is the failure mode a single-engine toolchain cannot diagnose.

explore

circuit-opt explore CONFIG.json [options]

The config file must be a complete circuit JSON that includes an explore block.

circuit-opt explore examples/afe_explore.json -n 500 --seed 1
circuit-opt explore examples/sky130_5t_ota.json -n 200 --corner ss --workers 8
circuit-opt explore examples/tsmc28hpcp_5t_ota.json -n 200 --corner ff

Flags:

Flag Default Description
-n, --n 200 Number of candidates
--seed 0 RNG seed
--method lhs lhs or random
--corner no override Process corner used for solving
--workers 1 Rayon workers for eligible Rust CompiledCampaign batches
-o, --out, --output none Output prefix; writes <prefix>.csv and <prefix>.jsonl
--quiet off Don't print per-candidate progress
--engine {rust} rust Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists

See the explore field in the JSON documentation for explorable variables, constraints, and objectives.

corners

circuit-opt corners CIRCUIT.json [options]

The current implementation calls circuitopt.corners.corner_table, a fixed sweep over AT4000TG's typical/slow/fast. It is not a general-purpose silicon PVT campaign driver. For silicon PDKs, use signoff for a multi-testbench PVT grid, or run --corner for one circuit and corner.

circuit-opt corners examples/afe_explore.json \
  --freqs-start 0.01 --freqs-stop 10000 --freqs-num 121 \
  --noise-band 0.05 100 --output results/afe_corners.csv

Flags:

Flag Default Description
--freqs-start 0.01 Start frequency, Hz
--freqs-stop 10000 Stop frequency, Hz
--freqs-num 121 Number of log-spaced frequency points
--noise-band LO HI 0.05 100.0 IRN integration band
-o, --output none CSV output
--workers 1 Number of parallel corner workers (ThreadPoolExecutor; each solve releases the GIL independently); there are only 3 corners, so going beyond 3 has no benefit
--engine {rust} rust Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists
--quiet off Suppress per-corner output

mc

circuit-opt mc CIRCUIT.json [options]

The current general-purpose mc uses AT4000TG's mvt0/mbeta0 continuous mismatch model and the AFE latch criterion. It is not a general-purpose foundry mismatch engine.

circuit-opt mc examples/afe_explore.json \
  -n 300 --seed 1 --corner slow --output results/afe_mc.json

Flags:

Flag Default Description
-n, --n 200 Number of MC samples
--seed 0 RNG seed
--workers 1 Number of parallel MC workers (ThreadPoolExecutor; each solve releases the GIL independently); mismatch draws are pre-sampled before dispatch, so results are byte-identical regardless of worker count
--corner typical typical, slow, or fast
--freqs-start/stop/num 0.01/10000/121 AC/noise grid
--noise-band LO HI 0.05 100.0 IRN integration band
-o, --output none JSON summary
--engine {rust} rust Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists
--quiet off Suppress progress output

SAR ADC has its own separate adc --mc flow, whose mismatch semantics come from the JSON adc.mismatch block.

chopper

circuit-opt chopper CIRCUIT.json --level LEVEL [options]

LEVEL:

Level Meaning
ideal Ideal square-wave LPTV
pmos PMOS switch static phase
lptv PMOS sideband folding
pss Shooting PSS
pac PAC on the PSS orbit
pnoise Periodic noise after PSS/PAC
transient Hard-switched transient
circuit-opt chopper examples/afe_explore.json --level ideal
circuit-opt chopper examples/afe_explore.json --level pnoise \
  --f-chop 225 --max-sideband 10
circuit-opt chopper examples/afe_explore.json --level transient \
  --n-periods 8 --n-points 121

Main flags:

Flag Default
--f-chop 225 Hz
--switch-w / --switch-l 5000 / 30 µm
--edge-time 20e-6 s
--max-harmonic 31
--max-sideband 10
--tstab-periods 2
--n-points 121
--n-periods 8
--freqs-start/stop/num 0.01/10000/121
--noise-band LO HI 0.05 100.0 Hz
-o, --output Write results to JSON
--engine {rust} Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists
--quiet Suppress summary output

This command is a wrapper around the project's AFE chopper; it is not the sole entry point for arbitrary JSON periodic circuits. For general periodic circuits, configure periodic and analyses in the JSON first, then use run.

adc

circuit-opt adc CIRCUIT.json MODE [options]

The modes are mutually exclusive:

# Single conversion
circuit-opt adc examples/freepdk45_sar3.json --vin 0.7

# Static ramp, DNL, INL, and missing codes
circuit-opt adc examples/freepdk45_sar6.json --sweep 64 --workers 8

# Coherent sine wave, SNDR, SFDR, and ENOB
circuit-opt adc examples/freepdk45_sar6.json \
  --sine 128 --tone-bin 13 --sample-rate 10e6 --workers 8

# MC using the adc.mismatch config
circuit-opt adc examples/freepdk45_sar6.json \
  --mc 32 --seed 1 --workers 8

# Design-space exploration
circuit-opt adc examples/freepdk45_sar6.json \
  --explore examples/freepdk45_sar6_explore.json -n 20 --workers 4

# Final-verification DNL: bisect the physical transition voltages at the
# binary major carries (0.05-LSB resolution, ~O(log 1/tol) conversions)
circuit-opt adc examples/freepdk45_sar6.json --transitions --workers 8

Main flags:

Flag Description
--vin VIN Single conversion; defaults to running one conversion at 0.5 V when no mode flag is given
--sweep N N uniformly spaced ramp inputs. Below 2**n_bits the sweep is subsampled: transition DNL/INL don't exist at that density, so metrics and the --plot figure switch to signed code errors (max_abs_code_err; |INL| at each sample is within 0.5 LSB of it) — the screening mode for 12-bit-class resolutions
--sine N N coherent sine-wave samples
--mc N N per-device mismatch MC trials
--sweep-points M mc only: subsample each trial's code-center sweep to M points (overrides adc.mismatch.sweep_points); yield then gates on code_err_threshold instead of the DNL/INL limits
--transitions [CODES] Locate physical code-transition voltages by lockstep bisection and report DNL/INL at them. Default carries targets both DNL bins around every binary major carry plus the offset transition; or pass a comma-separated code list. Each round batches every pending probe through one compiled call, so --workers parallelises across transitions. Resolves to --tol-lsb (default 0.05 — ten times finer than a full ramp's ±0.5 LSB quantization) from a --bracket-lsb window (default 2, auto-widened to full range if screening lied). The 12-bit final-verification mode: ~34 carries × ~9 probes ≈ 310 conversions instead of 4096
--explore CONFIG Standalone SAR-explore config JSON; runs ADC design-space exploration; mutually exclusive with --vin/--sweep/--sine/--mc
--tone-bin Coherent-input FFT bin, default 3
--sample-rate Sample rate reported in the results, default 10 MHz
--amplitude Sine peak amplitude, default 0.45*vref
--offset Sine DC offset, default 0.5*vref
--corner The current ADC CLI accepts nom/ss/ff
-n, --n Number of candidates in --explore mode, default 50
--seed RNG seed in --explore mode, default 0
--workers Concurrency for independent final transients, MC trials, or — in explore mode — each candidate's own conversion sweep (candidates run serially; the outer-thread-pool design it replaces topped out at 1.8x where the kernel's inner parallelism reaches 4.7x). Native-BSIM single conversions, sweeps, sine tests, MC, and exploration all use the compiled Rust SAR continuation kernel for bit decisions; each input then runs one final transient for waveform and power reporting. MC batches trials in one Rayon pool. Unsupported topologies or incomplete seeds explicitly fall back to Python replay.
--plot [DIR] Write the corresponding PNG; needs the plot extra
Not sure what --workers to pass on this machine? python tools/workers.py detects the topology and recommends per-workload counts; --calibrate measures the real saturation knee
--waveforms Record full per-conversion waveforms (t, input_waveforms, transient) and keep them in --output. Without it -o stores codes, bits, decision traces, and power/metric scalars only — kilobytes instead of tens of megabytes for a 64-code sweep — and a --sweep run skips trajectory recording entirely. Requires -o; rejected for --mc/--explore, whose rows never carried waveforms.
--csv / --jsonl ADC explore output
-o, --output JSON result (codes/metrics tier by default; see --waveforms)

The closed-loop bit-decision state machine runs in the Rust continuation kernel; Python handles workflow orchestration and final result/power assembly. The comparator, CDAC, and switches are still computed by transistor-level transient analysis. The flow is not equivalent to a full transistor-level digital SAR controller.

plot

circuit-opt plot [all|transient|bode|afe|chopper|ac|pac] [options]

This command renders the project's built-in AFE/chopper examples; it does not read an arbitrary circuit JSON.

uv pip install -e ".[plot]"
circuit-opt plot bode --npts 121 --out-dir results
circuit-opt plot chopper --f-chop 225 --input-diff 1e-3

Flags:

Flag Default Description
--f0 10 Hz AFE transient sine frequency
--amp 5e-4 V AFE transient differential half-amplitude
--f-chop 225 Hz Chopper frequency used by the chopper/pac plots
--input-diff 1e-3 V Chopper transient DC differential input
--npts per-plot default Number of Bode frequency points
--out-dir results Output directory
--engine {rust} rust Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists
--quiet off Suppress summary output

dataset

circuit-opt dataset CONFIG.json [options]

The input must be a complete circuit JSON with an explore block. Each sample retains its design variables, labels, failure status, and provenance.

circuit-opt dataset examples/single_stage.json \
  -n 500 --seed 1 --labels ac_noise --out results/datasets/single

circuit-opt dataset examples/sky130_chopper.json \
  -n 200 --labels pss,pac,pnoise --out results/datasets/sky_chopper

Flags:

Flag Default Description
-n, --n 200 Number of samples
--seed 0 RNG seed
--workers 1 Number of parallel candidate workers (ThreadPoolExecutor; each solve releases the GIL independently)
--method lhs lhs or random
--corner typical Solve corner; silicon PDKs may pass their own corner
--labels ac_noise Any combination of ac_noise,transient,pss,pac,pnoise
--freqs-start -2 AC start decade
--freqs-stop no override AC stop decade
--freqs-num 101 AC point count
--out automatic Output prefix
--no-npz off Don't write the dense NPZ
--parquet off Also write a Parquet table; needs the parquet extra
--quiet off Suppress progress
--engine {rust} rust Only rust as of v2.0.0 (omitting the flag defaults to rust)
--no-numba Removed in v2.0.0 (errors out): the numba engine no longer exists

Surrogate and Optimization

These are standalone module entry points, not subcommands of the main CLI:

uv pip install -e ".[ml]"

python -m circuitopt.surrogate train \
  results/datasets/single.npz --out results/models/single.pkl

python -m circuitopt.surrogate predict \
  results/models/single.pkl --x 2000,1500,25

python -m circuitopt.optimize \
  examples/single_stage.json results/models/single.pkl \
  --n-screen 100000 --top-k 20

PyTorch variant:

uv pip install -e ".[torch]"
python -m circuitopt.surrogate_torch --help

The surrogate is only for screening or gradient-based search; final feasibility should always be re-verified against the physical solver.

serve

uv pip install -e ".[serve]"
circuit-opt serve

Flags:

Flag Default Description
--host 127.0.0.1 Listen address
--port 8341 TCP port
--reload off uvicorn development auto-reload
--job-workers 1 Number of background workers for explore/mc

0.0.0.0 exposes the unauthenticated service to the network and should not be used as a default configuration. See Local Service API for the full protocol.

mcp

uv pip install -e ".[mcp]"
circuit-opt mcp --transport stdio --workspace .
Flag Default Description
--transport stdio stdio or streamable-http
--workspace . Only file tree exposed to MCP tools
--host 127.0.0.1 Streamable HTTP listen address; loopback only
--port 8342 Streamable HTTP port
--job-workers 1 Concurrent background explore/MC/signoff jobs

The equivalent dedicated entry point is circuit-opt-mcp. See MCP Server for tools, resources, and client configuration.

Analog Design Tools

Standalone tools in tools/, for the loop that sits around a signoff campaign rather than inside one.

# Sizing loop: override generator constants in memory, run the full PVT grid,
# print per-spec pass counts plus the corners behind every failing constraint.
python tools/design_iterate.py run --generator tsmc28_mdac_ota_gen \
    --manifest examples/tsmc28hpcp_mdac_ota_signoff.json CC=850e-15 SZ:M11=139.286/0.30

# Root cause: distribution of one measurement over the grid, its mean grouped
# along each PVT axis, and the optimal common trim for a signed error.
python tools/design_iterate.py map --generator tsmc28_mdac_ota_gen \
    --manifest examples/tsmc28hpcp_mdac_ota_signoff.json \
    --case residue_plus_fs16 --measurement checkpoint_error --scale 1e3 --unit mV --limit 20

# Trajectory anatomy at one point.
python tools/design_iterate.py trace --generator tsmc28_mdac_ota_gen \
    --manifest examples/tsmc28hpcp_mdac_ota_signoff.json \
    --case residue_plus_fs16 --point ff/27/0.85 --nodes OUTP,OUTN,CTRL2

The map grouping is the root-cause discriminator worth knowing: a spread that lives on the temperature axis is a device-level offset, one that lives on the supply axis is a reference or level-shift mismatch.

Calibration and Benchmarks

Calibration regression:

python -m circuitopt.calibration --all
python -m circuitopt.calibration --all --json
python -m circuitopt.calibration calibration/amp_design3_typical/ --analyses ac,noise

Performance benchmarks:

python -m benchmarks.bench_afe --warm-runs 3
python -m benchmarks.bench_model --warm-runs 3
python -m benchmarks.bench_periodic --warm-runs 3
python -m benchmarks.bench_chopper --warm-runs 3
python -m benchmarks.bench_sweep --n-candidates 200

Performance numbers are affected by Python, Numba, CPU, cold-start, and cache state. See Environment & Benchmarks for historical measurements.

Exit Codes and Output

  • Returns 0 on success; returns non-zero for argument errors, missing files, analysis failures, or failed calibration.
  • run outputs JSON; corners outputs CSV; explore outputs CSV/JSONL; dataset outputs JSONL/manifest/NPZ, with optional Parquet.
  • In numeric results, frequency is in Hz, time is in seconds, voltage is in V, and current is in A.
  • Noise integration results must always record the integration band alongside them.