Skip to content

Signoff Campaigns

Documentation Home | CLI Reference | Circuit JSON Format | 中文版

circuit-opt signoff runs multiple circuit testbenches over one explicit process/voltage/temperature grid. It is intended for checks that cannot be represented honestly by one netlist, such as open-loop gain, differential and common-mode loop stability, closed-loop noise, and large-signal settling.

circuit-opt signoff examples/tsmc28hpcp_mdac_ota_signoff.json \
  --workers 4 --output results/tsmc28_mdac_signoff.json

The example contains 11 testbench cases over tt/ss/ff/sf/fs x -40/27/125 degC x 0.85/0.90/0.95 V, for 45 PVT points and 495 case runs. It covers open-loop gain, the differential loop, both CMFB loops, closed-loop input/output noise, five residue levels, and the 0111 to 1000 major-carry transition.

Manifest

Campaign paths are relative to the manifest file. Absolute paths and paths that escape the manifest directory are rejected, so a repository can be moved without editing machine-specific locations.

{
  "name": "ota_signoff",
  "pvt": {
    "corners": ["tt", "ss", "ff", "sf", "fs"],
    "temperatures_c": [-40, 27, 125],
    "supplies_v": [0.85, 0.9, 0.95],
    "nominal_supply_v": 0.9,
    "supply_bias_key": "VDD"
  },
  "cases": [
    {
      "name": "open_loop",
      "circuit": "ota_ac.json",
      "overrides": {
        "ac_drives": {"VINP": 0.5, "VINN": -0.5},
        "signoff": {
          "measurements": {},
          "constraints": {"gain": {"min": 80}}
        }
      }
    }
  ]
}

Each case deep-merges overrides into its base circuit. Objects merge recursively and arrays replace the base array. A numeric PVT expression is an explicit affine expression:

{"$pvt": {"vdd": 0.5, "temperature_c": 0.0, "constant": 0.225}}

This evaluates to 0.5 * VDD + 0.0 * temperature_c + 0.225. At each point the runner also binds section, MOS temperature in kelvin, the named supply bias, PMOS bulk voltage, numeric voltage-source levels, and DC seeds.

Margin Table

--margins prints one row per constraint instead of the single tightest measurement that worst_case names. A spec sitting at +0.02 of its limit is a design constraint even when another spec is at -0.5, and a worst-case view hides it entirely.

circuit-opt signoff campaign.json --margins

Each row carries the constraint's worst normalized margin and the PVT point that produced it, the observed minimum and maximum with their unit, the number of points evaluated, and every failing point. Rows are sorted tightest first. The same data is available programmatically from circuitopt.signoff_campaign.summarize_margins(result).

Passive Tolerance Sweep

A signoff that passes only at nominal component values is not a signoff. Poly resistors carry roughly 20% absolute tolerance and MOM capacitors roughly 10%, so a compensation network tuned on a knife edge will not survive fabrication.

circuit-opt signoff campaign.json --tolerance R=20,C=10

Values are percentages. A key of R or C perturbs that whole element class; any other key names a single element, for example --tolerance CC1=10. The sweep runs 1 + 2N campaigns for N entries — nominal, then each entry at 1 - tolerance and 1 + tolerance — and reports which constraints break in which direction. The result is robust only when every run passes.

Per-element perturbation answers a different question from class-wide perturbation: scaling one nulling resistor alone isolates the compensation network, while scaling every resistor together also moves the bias network that sets its target.

Result Contract

Every case must contain a circuit-level signoff block. The campaign stores that unit-bearing signoff envelope, not the raw waveform arrays. A model error, non-convergence, non-finite result, or invalid signoff configuration produces an invalid case; it is never converted to a passing fallback value.

Each point reports its case results and worst_case. The campaign-level worst_case includes case, corner, temperature_c, supply_v, measurement, and normalized margin. invalid dominates fail, and fail dominates pass. Point ordering is deterministic for every worker count.

The manifest schema is schemas/signoff_campaign.schema.json. The referenced testbenches continue to use schemas/circuit.schema.json.