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:
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:
New docs and scripts should spell out run explicitly.
run¶
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¶
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¶
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¶
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¶
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¶
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¶
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¶
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:
The surrogate is only for screening or gradient-based search; final feasibility should always be re-verified against the physical solver.
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¶
| 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.
runoutputs JSON;cornersoutputs CSV;exploreoutputs CSV/JSONL;datasetoutputs 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.