Openada
Discover, invoke, and interpret open-source EDA tools through OpenADA's versioned CLI contract. Use for semiconductor or electronics work involving Xschem schematics (.sch), SPICE simulation, GDS/KLayout DRC, Netgen LVS, Verilog/SystemVerilog lint, Yosys ASIC synthesis, OpenSTA timing, PDK discovery, or diagnosing an open EDA environment in Codex, Claude Code, or another terminal-capable agent.From its SKILL.md
npx -y skills add simra-tech/OpenADA --skill openadaAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 19 stars19 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
27.5 KB, as published. Nobody here has run it
OpenADA
Use the deterministic OpenADA CLI between agent reasoning and native EDA tools. Keep native design files, PDKs, and rule decks as the source of truth.
This is the plugin's execution and evidence skill. It maps a bounded intent to OpenADA operations and interprets their versioned results. Higher-level engineering skills may compose these operations into review or diagnosis workflows, but they must not duplicate backend commands or redefine contract status. Keep tool-native safety policy here or in the deterministic driver; keep reusable engineering judgment in a separate sibling skill.
Establish the workspace
- Identify the intended project root before running or modifying a design.
- Treat PDK trees, shared catalogs, and reference designs as read-only unless the user says otherwise.
- Put generated evidence under a task-local output directory. Do not overwrite source artifacts unless the user explicitly requests it.
Resolve the CLI
Prefer openada when it is on PATH.
Agent plugin managers install this skill bundle, not the OpenADA Python package or its jsonschema>=4.18 dependency. The recommended setup therefore installs the matching OpenADA Python release so openada is on PATH.
When this skill is loaded from a plugin checkout or cache, resolve the plugin root from this SKILL.md path and use <plugin-root>/bin/openada only if the command is not on PATH and that launcher's Python dependencies are available. Do not guess a different installation path. If a command returns provider.validation.unavailable, stop and tell the user to install the matching OpenADA Python release; do not present the failed profile/provider validation as an EDA result.
If neither entry point exists, stop the EDA operation and tell the user that the OpenADA executable is missing. Do not silently fall back to an unstructured raw-tool workflow while claiming OpenADA evidence.
Inspect before executing
For project work, map the user's immediate engineering intent to exactly one fixed assertion, then run one scoped preflight:
openada doctor --project-root /absolute/project \
--assertion spice-analysis-evidence-valid
Use these one-to-one mappings:
| User's immediate assertion | Preflight assertion | Target |
|---|---|---|
| Generate a resolved schematic netlist | schematic-netlist-generated | Xschem netlist |
| Run a SPICE analysis with valid evidence | spice-analysis-evidence-valid | ngspice simulate |
| Determine whether the supplied DRC deck is clean | drc-clean | KLayout drc |
| Determine whether two netlists match under the supplied setup | lvs-match | Netgen lvs |
| Elaborate RTL and pass structural checks | rtl-structural-check-passes | Yosys rtl-check |
| Lint SystemVerilog with no warnings or errors | rtl-lint-clean | Verilator rtl-lint |
| Produce a complete Liberty-mapped ASIC netlist | asic-netlist-synthesized | Yosys synthesize |
| Satisfy setup and hold constraints for one declared corner | timing-constraints-satisfied | OpenSTA timing-analyze |
If the request spans a chain, preflight only the smallest next assertion whose result is needed before later work. Do not run several preflights or recommend a whole flow at once. --project-root and --assertion are paired; do not add --tool or --require because the assertion selects and requires one tool.
Read data.preflight.target as the one recommendation. A preflight pass only establishes point-in-time root and tool readiness: data.preflight.assertion_evaluated remains false. It does not inspect the project, choose a PDK, or run the engineering assertion. An empty data.pdks means data.preflight.pdk.catalog_enumerated is false, not that no PDK exists. Do not search recursively to compensate.
Inspect portable operation parameters from the installed catalog, independent of the current working directory:
openada profile list
openada profile show openada.operation/result.series.extract/v1alpha1
openada profile show openada.operation/result.transfer.measure/v1alpha2
openada profile show openada.operation/result.osc.measure/v1alpha1
Preflight intentionally leaves pdk.selected and startup selected_files unresolved. Identify exact project-specific source, PDK, model, rcfile, init, rule deck, setup, top cell, and output paths from explicit user/project context. If more than one candidate is plausible, ask the user which is authoritative. Never guess a conventional filename, inspect $HOME startup files, crawl a PDK tree, or substitute generic collateral.
For environment diagnosis outside a concrete project assertion, a focused legacy probe remains available:
openada doctor --tool xschem --require xschem
openada doctor --tool ngspice --require ngspice
Put global runtime options before the command:
openada --profile native doctor
openada --profile iic-osic-tools doctor
openada --tool-path ngspice=/absolute/path/to/ngspice doctor --tool ngspice
Use the detected runtime and PDK roots; do not assume /foss exists. The IIC-OSIC-TOOLS layout is a reference profile, not a requirement.
Choose a semantic operation
Use the smallest operation that proves the requested engineering assertion:
mkdir -p evidence
# Xschem schematic -> SPICE; pass the project/PDK rcfile when library resolution depends on it
openada netlist design.sch --rcfile path/to/xschemrc --output evidence/design.spice
# simulate: ONE operation. The target is a deck or a published Simra artifact,
# and the model source is nothing, --models, or an installed PDK by name.
openada simulate testbench.spice --backend ngspice --output-dir evidence/sim
openada simulate path/to/schematic.artifact.json --backend ngspice \
--pdk <pdk-id> --pdk-root /foss/pdks --output-dir evidence/sim
openada simulate conformance/circuit-simulate-v0alpha2/fixtures/rc-transient.cir \
--backend xyce --output-dir evidence/shared-xyce
# native ngspice, for a deck whose collateral you own; not a semantic claim
openada simulate testbench.spice --execution-mode control \
--init-file path/to/pdk/.spiceinit \
--workdir path/to/writable-project-copy \
--expect-output raw=testbench.raw --output-dir evidence/simulation
# KLayout DRC with the project's real deck and one fresh exact report
mkdir -p /tmp/openada-drc-evidence
openada drc layout.gds \
--rules path/to/rules.drc \
--workdir path/to/project \
--top-cell TOP \
--provenance-input path/to/pdk/COMMIT \
--report /tmp/openada-drc-evidence/drc.lyrdb
# Netgen LVS with the project's real setup and fresh evidence basename
mkdir -p /tmp/openada-lvs-evidence
openada lvs layout.spice schematic.spice --cell top \
--setup path/to/setup.tcl \
--provenance-input path/to/pdk/COMMIT \
--report /tmp/openada-lvs-evidence/top.lvs.comp
# Yosys elaboration and structural checks
openada rtl-check rtl/top.sv rtl/block.sv --top top --output-dir evidence/rtl
# Strict SystemVerilog lint; ordered sources, includes, and defines are part of the evidence
openada rtl-lint rtl/package.sv rtl/top.sv --top top \
--include-dir rtl/include --define SYNTHESIS=1 \
--output-dir evidence/rtl-lint
# Flatten and map to one exact Liberty; retain generic inference and mapped statistics
openada synthesize rtl/package.sv rtl/top.sv --top top \
--frontend slang --include-dir rtl/include \
--liberty platform/typical.lib --techmap platform/cells_latch.v \
--abc-constraint platform/abc.constr --abc-delay-target-ns 2.0 \
--output-dir evidence/synthesis
# Single-corner synthesis-stage timing with exact mapped netlist, Liberty, and SDC
openada timing-analyze evidence/synthesis/mapped.v --top top \
--liberty platform/typical.lib --sdc constraints/top.sdc \
--output-dir evidence/timing
Never substitute a generic DRC deck, LVS setup, PDK, model library, or top cell merely to obtain a passing result. Ask for the missing project-specific input.
For digital commands, preserve source order, declared language dialect/revision, include directories, defines, top, Liberty, mapping policy, SDC, and tool identity as one comparison context. rtl-lint uses a strict policy: any recognized warning or error is an engineering fail. synthesize positively identifies and content-binds the exact external ABC executable under the same closed runtime environment as Yosys; operation-level evidence, not primary-tool preflight, is the authoritative ABC gate. synthesize passes only with fresh mapped netlist/statistics evidence, zero processes or memories after mapping, and no cell type outside the declared Liberty. Read data.inference_stats separately from data.stats; synthesis success does not establish behavioral equivalence, timing, area-budget, or power success.
timing-analyze is intentionally one corner with ideal interconnect and no SPEF. A negative WNS is a trustworthy constraint failure only when constraints_complete, reports_complete, inputs_stable, metric_consistency, and path-report agreement establish complete evidence. Even a timing pass is not MCMM or physical signoff. The timing connector accepts only openada-sdc-v1 declarative constraints and executes a fresh snapshot whose hash equals the declared SDC input; arbitrary Tcl, sourced files, environment access, and read_spef are unsupported. Its version probe and analysis share closed-opensta-runtime-v1 rather than inheriting ambient loader, interpreter, Tcl, OpenSTA, or shell-control state.
There is exactly one simulation operation, openada.operation/circuit.simulate/v1alpha2, and one verb, openada simulate. It accepts a bare deck or a published Simra artifact, detected by reading the file; it binds an installed PDK with --pdk; and when an artifact declares several analyses it derives one single-analysis deck per declaration, runs them all, and returns the weakest as one circuit.simulate/v1alpha2 envelope, naming every analysis and its own retained result in data.extensions["org.openada.simulation-dispatch"]. openada testbench-simulate is a deprecated alias that emits simulation.operation.deprecated and delegates.
A model-free deck must carry exactly one self-contained top-level .op, .dc, .ac, or .tran with parseable closed arguments, and no includes, native .measure directives, print directives, or control blocks. Require the selected driver's advertised feature: ngspice supports OP/DC/AC/TRAN; Xyce supports DC/AC/TRAN and rejects OP. Omitting --backend selects ngspice for an artifact, a --pdk or a --models request, and otherwise leaves the native ngspice interface active - which is a tool invocation, not a semantic claim, and reports no operation_profile.
Name the technology; never write it into the deck
A netlist carries devices, not technologies. Write each device as a canonical
role - nmos.core / pmos.core, and .svt / .lvt / .hvt / .io where a
threshold or oxide flavour is meant - with SI geometry (W=2u L=130n), and name
the PDK on the command line. The driver resolves the model name, instance
prefix, parameter spelling, geometry units, library prelude, corner and any
Verilog-A preload from a reviewed profile, so one deck binds to every installed
PDK with only --pdk changing.
A deck carrying pre_osdi, or a .lib/.include into an installed PDK's tree,
is refused with pdk.collateral.hand_bound even when its paths are correct,
because such a deck can only ask its question in one technology;
pdk.collateral.foreign when one PDK's incantation is applied to another, and
pdk.collateral.missing when it would bind nothing. A startup file binds
collateral the same way and earlier, so the rules cover --init-file too and
--pdk writes the ngspice startup file itself: no ambient spinit/.spiceinit
can bind another technology into the run. A failed preload is
simulation.collateral.unloadable, never a malformed result. openada simulate --help lists the PDKs that bind; platforms refuse with
pdk.analog.unsupported, and --unmanaged-collateral qualifies collateral no
profile covers yet, stamping a permanent provenance limitation.
Never hand-write model cards to get past a refusal: cards named after real
devices produce confident numbers unrelated to the technology. Adding a PDK is
a reviewed change to src/openada/pdk_bindings.py; --pdk and --models are
mutually exclusive.
Continue from native evidence to a specification
A shared-profile simulation pass feeds the typed evidence chain; never copy a
value out of a log. You rarely assemble this by hand: a completed simulate
retains its envelope as simulate.result.json, writes a ready-to-run
simulate.selection.json, and prints the exact openada extract command as
claim.measurement.typed_chain. Run it. A run reporting
claim.measurement.unsupported produced no supported scalar result; do not
report a value as simulated or verified. The selection is a closed document:
{
"selectors": [
{
"native_name": "v(out)",
"output_name": "v(out)",
"unit": "V",
"component": "real"
}
],
"conditions": [
{"name": "temperature", "value": 27, "unit": "degC"},
{"name": "corner", "value": "tt", "unit": "1"}
],
"extensions": {}
}
Then bind the exact retained simulation.result artifact named by the complete
simulation envelope:
openada extract \
--simulation evidence/simulation-result.json \
--artifact /absolute/evidence/simulation.raw \
--selection evidence/series-selection.json \
> evidence/series-extraction.json
The later measure, spectral, transfer, and transient oscillator commands
accept this complete passing extraction envelope directly;
data.extraction.series remains the
embedded canonical series for programmatic use. Extraction requires the exact
passing circuit.simulate/v1alpha2 envelope and matching
canonical path, byte count, and digest. Pass that envelope whole: it is
accepted exactly as simulate wrote it, including the
data.extensions["org.openada"].configuration record naming the collateral
that bound the devices. Never delete a field to get an envelope accepted -
what is deleted is the provenance of the evidence, and a refusal that a
deletion fixes is a bug worth reporting. It supports ngspice binary/ASCII and
Xyce ASCII padded Spice3 raw evidence. Select exact real or imaginary Cartesian
components; it never derives magnitude, phase, differential expressions, or
unit conversions. Conditions are caller-declared and digest-bound, not inferred
from simulator state. Retain the extraction envelope beside downstream results:
it carries the verified native binding that immutable result-operation lineage
still labels unverified.
For an ordinary scalar, write one closed result.measure request object and run:
openada measure \
--series evidence/series-extraction.json \
--measurement evidence/measurement-request.json \
> evidence/measurement-result.json
Advertised kinds are sample_at, minimum, maximum, mean, rms,
crossing, rise_time, fall_time, settling_time, and slope
(least-squares slope vs the axis, unit signal_unit/axis_unit). Inspect the
profile via openada profile show openada.operation/result.measure/v1alpha2
for the exact unit-bearing parameter shape. Do not use native .measure or an arbitrary expression as a substitute.
For a uniformly sampled coherent single-tone record, inspect the packaged spectral profile, write its complete method, and run:
openada spectral \
--series evidence/series-extraction.json \
--measurement evidence/spectral-request.json \
> evidence/spectral-result.json
The alpha supports only SNR, SINAD, signed-dB THD, and SFDR under its fixed power-of-two rectangular coherent-bin method. A candidate IEEE context records scope, not conformity.
For an AC analysis, inspect openada.operation/result.transfer.measure/v1alpha2 and run:
openada transfer \
--series evidence/ac-series-extraction.json \
--measurement evidence/transfer-request.json \
> evidence/transfer-result.json
transfer is the only operation that derives a ratio; measure reads one signal and has
no kind for a gain, a differential gain or an impedance. Metrics: low_frequency_gain_db,
low_frequency_impedance (ohms, output V over input A), bandwidth_3db, unity_gain_frequency,
phase_margin; ambiguous crossings are rejected and gain margin is absent. An operand is {real, imaginary} plus optional negative_real/negative_imaginary for a differential terminal; for
an output impedance name v(node) over i(vsource) from a 1 V AC source on that node.
For an oscillator transient, first inspect the experimental
openada.operation/result.osc.measure/v1alpha1 profile and use one complete
measurement request:
openada oscillator \
--series evidence/transient-series-extraction.json \
--measurement evidence/oscillator-transient-request.json \
> evidence/oscillator-transient-result.json
The request must explicitly name the differential terminals, VDD voltage and
current signals, current orientation, late crop, hysteresis, cycle count,
minimum amplitude, period-consistency tolerance, and startup hold interval.
Keep period relative deviation at or below 0.05 and amplitude relative
deviation at or below 0.20. Sustained evidence requires complete leading and
trailing crop coverage; a missing hysteresis confirmation or partial terminal
cycle is not collapse evidence.
Frequency, peak-to-peak differential amplitude, and average supply power bind
to the same source/window receipt. Treat sustained as the only verdict with a
measured frequency. Keep never_started, collapsed, not_sustained, and
multimode as typed non-results; beating or startup ringing is not permission
to select a convenient interval or tone. The assertion is
openada.assertion/oscillator.measurement.valid/v1alpha1.
Grid and perturbation requests compose the transient receipts directly and do
not take --series:
openada oscillator --measurement evidence/oscillator-grid-request.json \
> evidence/oscillator-grid-result.json
Require every control point. Read Kvco as the returned per-point endpoint- secant/unequal-spacing-central-difference curve alongside monotonicity and span, never as one fitted value. Verify each receipt's embedded request, fixed producer, and recomputable content hashes; those hashes provide integrity, not authorship authentication. A frequency-shift result retains signed and absolute supply/load perturbation shift. Phase noise and jitter are outside this profile and must remain not evaluated without a separate capability.
Finally evaluate a scalar result only against an already supplied explicit limit and exact conditions:
openada evaluate \
--measurement evidence/measurement-result.json \
--specification evidence/specification.json \
> evidence/specification-result.json
evaluate accepts ordinary, spectral, or transfer result envelopes. A
result-operation pass is not a specification pass, and a missing limit is not
permission to invent one.
Use one explicit external provider
The first provider boundary is opt-in and deliberately smaller than a marketplace:
openada provider validate path/to/driver-manifest.json
openada provider list --manifest path/to/driver-manifest.json
openada provider invoke \
--manifest path/to/driver-manifest.json \
path/to/openada-request.json
Invocation requires a complete openada.request/v0alpha1 with an exact
driver_selector. OpenADA validates the manifest and cross-references,
resolves one structured or workflow-validated local CLI capability, writes one
bounded JSON request to stdin without a shell, and validates the returned base
and operation-specific result plus request correlation and provider identity.
External dispatch is currently registered only for
openada.operation/circuit.simulate/v1alpha2. Its target and configuration
locators must be canonical absolute filesystem paths; its fresh evidence
destination must also be canonical and uses fail-if-present, with returned
artifacts confined beneath it.
The immutable v0alpha1 bridge does not carry a digest of the complete request;
do not describe correlation as cryptographic or complete request binding. The
default working directory is the manifest directory; pass --cwd only when
the provider contract requires another reviewed directory.
Manifest conformance records are self-declared metadata. The runtime checks their schema and cross-references but does not fetch their URI or independently rehash the referenced evidence, so do not present manifest validation as an independent conformance result.
There is no implicit provider discovery, installation, ranking, marketplace, MCP binding, credential model, session transport, or remote job transport in this command. Never describe an explicit manifest list as an EDA marketplace.
simulate runs from the netlist directory by default. An explicit --workdir
changes relative-path resolution; it is not a sandbox. A reviewed --pdk
binding captures its active closure in one content-addressed snapshot; arbitrary
transitive files in a caller-authored legacy deck remain unenumerated.
Use a task-local writable copy for caller-authored decks.
For the legacy ngspice interface, choose the mode explicitly when the default batch policy is not appropriate:
- Keep the default
batchmode for bounded streaming runs whose reviewed, flattened top-level deck has no.measure,.control, pure control script,.include,.inc, or.libdirective. - Use
controlfor.measureand.controldecks. If the deck callswriteorwrdata, repeat--expect-output raw=...or--expect-output wrdata=...for every required file. - Pass a real project/PDK init script with
--init-filewhen simulation depends on one. This disables local/user.spiceinitand records the init file as a hashed input; it does not disable systemspinit. - For a reproducible startup chain, also pass the runtime's reviewed system
spinitvia--system-init-file. OpenADA pins it by hash and selects its directory throughSPICE_SCRIPTS.
Never treat an undeclared file found by directory scanning as current-run
evidence. A declared deck output must be absent before launch and pass
requires OpenADA's structural validation, not just file presence.
The preview rejects logs over 16 MiB and raw/wrdata evidence over 256 MiB;
split or reduce evidence rather than treating a bounded-validation rejection as
an engineering failure.
For KLayout, the exact report and its sibling .openada.log transcript must be
absent before launch. OpenADA binds the report path through the deck variable
named report by default; use --report-variable NAME for a reviewed deck that
expects another variable. If the deck itself owns a fixed relative report path,
use --expect-report relative/path.lyrdb with --workdir instead of
--report; OpenADA then injects no report variable. Pass additional bounded
NAME=VALUE bindings with repeatable --deck-var and select the native top
cell with --top-cell when the deck supports topcell. Do not try to shadow
input, topcell, report, or the selected report-variable name with a deck
variable; those bindings are reserved by the connector.
KLayout automatically reads <report>.w. Do not leave that sidecar ambient:
either keep it absent or declare that exact existing file with --waiver-file
so it becomes a hashed, stability-checked configuration input. Use repeatable
--provenance-input for known %include, JSON, layer-map, or PDK revision files
loaded by the executable Ruby deck. OpenADA cannot infer arbitrary Ruby file
access, and --workdir controls relative paths but is not a sandbox. A stable
malformed report may be retained by hash for diagnosis, but only a bounded
native-shaped LYRDB with the executed deck generator, matching requested top
cell, a nonempty category catalog, declared cells, a native items section, and
interpretable multiplicity-weighted markers can support pass or fail.
For Netgen, keep the exact report, its native JSON path formed by replacing the
final suffix with .json, and <report>.openada.log absent before launch. Use a
fresh basename instead of deleting or reusing prior evidence. Treat setup Tcl as
caller-supplied executable code and run from an appropriate current working
directory; OpenADA records that directory but does not sandbox Tcl side effects.
Declare known sourced setup, layer-map, PDK, and revision files with repeatable
--provenance-input. Report the netgen.provenance_incomplete warning because
transitive Tcl access and ambient environment state remain unenumerated. The
preview rejects each declared input above 512 MiB before launch; report that
limit instead of attempting to bypass the stability check.
Accept Netgen pass or fail only from the normalized result. It requires
unchanged declared inputs, completed zero-exit execution, a complete clean
setup/completion transcript, and valid native report and JSON outcomes whose
device/net totals also agree. Accept stderr only when it is empty or every line
exactly matches the reviewed
Unable to permute model <token> pins <token>, <token>. grammar. Each token is
bounded ASCII text from A-Z a-z 0-9 _ . $ : + / @ -. Report accepted lines
through netgen.stderr_reviewed_warning; rely on normalized stderr_accepted
for classification. Inspect
data.report_output.capture, data.json_output.capture,
data.transcript.assessment (including stderr_policy, counts, and
stderr_accepted), and data.comparison.evidence_agrees when the result is
unknown. Never infer a match or mismatch from stale, linked, missing,
malformed, conflicting, unrecognized-stderr, or truncated evidence.
Interpret the contract
Read engineering.status separately from execution.status:
execution.status: completedmeans the native process ran; it does not mean DRC or LVS passed.engineering.status: passmeans the driver interpreted the requested check as passing.engineering.status: failis valid evidence of an engineering failure, such as violations, mismatch, or non-convergence.engineering.status: unknownmeans the evidence was insufficient or uninterpretable. Do not upgrade it to pass.
Use diagnostics, inputs, artifacts, and provenance before reading native logs. Open only the bounded log tail or a referenced artifact when the normalized result is insufficient. See references/result-contract.md for field and exit-code details.
For an explicit shared simulation backend, also read data.protocol,
data.analysis, and data.evidence. Those fields have the same closed meaning
for ngspice and Xyce; backend-native details remain under the namespaced
extension and native artifacts. A simulation-evidence pass proves fresh,
finite evidence for the selected OP, DC, AC, or transient analysis, not that
any circuit specification was met.
Report evidence
Return:
- The engineering conclusion and its status.
- The exact tool and version selected.
- The PDK, model, rule deck, setup, and top-cell assumptions that materially affect the conclusion.
- Diagnostics that explain failures or unknown results.
- Artifact paths and hashes from the contract.
- Any limitation that prevents signoff-level interpretation.
Do not describe a preview driver as foundry signoff. Preserve the distinction between tool execution, OpenADA normalization, and engineering review.