Install
$ agentstack add skill-shenshan123-r2g-skills-signoff-loop ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
signoff-loop Skill
Execute a staged, artifact-first open-source EDA flow from specification to GDSII with full signoff checks using OpenROAD-flow-scripts (ORFS), and close the loop by learning from every run (the two memory DBs + engineer_loop) so DRC/LVS violations are eliminated and timing closes at the best Fmax. Prefer deterministic scripts for execution, keeping the agent focused on planning, generation, diagnosis, and iteration.
> Dataset construction lives in the companion def-graph skill. This skill produces > the clean, signed-off 6_final.def/.odb/.spef; converting those into PyG graph > datasets (the five views b–f, tech-lib/LEF parser, feature + label extraction) is > def-graph's job — see its SKILL.md.
Environment Setup
Every flow script sources scripts/flow/_env.sh on entry, which autodetects ORFS + tool paths and lets the user override any single value. You do not need to source anything manually.
Resolution order (first hit wins, per value)
- Variable already set in the caller's environment —
ORFS_ROOT=... run_orfs.sh ...wins unconditionally. - User env file — path in
$R2G_ENV_FILE(if set). - In-skill override file —
references/env.local.sh(copy fromreferences/env.local.sh.template). - ORFS-provided env —
$ORFS_ROOT/env.sh(onceORFS_ROOTis known). - System-wide env —
/opt/openroad_tools_env.sh(if present). - Autodetect —
command -von$PATH, then a list of well-known install paths (e.g.$ORFS_ROOT/tools/install/OpenROAD/bin/openroad,$HOME/oss-cad-suite/bin/yosys,/usr/local/bin/klayout).
Checking what the skill found
bash scripts/flow/check_env.sh
Prints the resolved ORFS_ROOT, every tool binary it picked, and the platforms it can see. Exits non-zero if a required tool is missing.
Overriding just a few values
# One-off override for a single run
ORFS_ROOT=/opt/ORFS OPENROAD_EXE=/opt/openroad/bin/openroad \
bash scripts/flow/run_orfs.sh design_cases/my_design nangate45
# Or persist overrides in a file
cp references/env.local.sh.template references/env.local.sh
# ...then edit the exports you care about; every subsequent flow picks them up.
Available platforms
nangate45, sky130hd, sky130hs, asap7, gf180, ihp-sg13g2 (default: asap7).
Workflow
1. Normalize the Specification First
- Convert free-form requirements into a structured specification before writing RTL.
- Read
references/spec-template.mdand produceinput/normalized-spec.yaml. - If clock/reset, IO, target flow, or timing targets are missing, stop and ask the user or record explicit assumptions.
2. Initialize a Project Directory
- Create a run folder under
design_cases//usingscripts/project/init_project.py. - The layout follows
references/workflow.md. - Directories created:
input/,rtl/,tb/,constraints/,lint/,sim/,synth/,backend/,drc/,lvs/,rcx/,reports/.
3. Generate RTL and Testbench Separately
- Write RTL to
rtl/design.v. - Write testbench to
tb/testbench.v. - Keep assumptions and design notes in
reports/rtl-notes.md.
4. Run Validation in Strict Order
- Run
scripts/project/validate_config.pybefore ORFS backend to catch config/RTL issues early. - Run lint/syntax checks before simulation.
- Run simulation before synthesis.
- Run synthesis before backend (ORFS).
- Do not skip failed stages unless the user explicitly requests it.
5. Run Backend with ORFS
- Prepare
constraints/config.mkandconstraints/constraint.sdc. - Use
scripts/flow/run_orfs.shto invoke the ORFS Makefile. - ORFS runs place-and-route natively (no Docker required).
- Collect results from the ORFS results directory.
5b. Check Timing Before Signoff (Tiered WNS + TNS)
After ORFS completes, extract PPA and run the timing gate:
- Run
scripts/extract/extract_ppa.py reports/ppa.jsonto extract timing metrics. - Run
scripts/reports/check_timing.pyto classify WNS and TNS and writereports/timing_check.json. - The script independently classifies WNS and TNS, then takes the worse of the two as the combined tier. A design with small WNS but large TNS (many slightly-violating paths) is caught.
- Read
reports/timing_check.jsonand act on thetier:
| Tier | Criteria | Agent Action | |------|----------|-------------| | clean | WNS >= 0, TNS >= 0 | Proceed to signoff. | | minor | WNS >= -2.0 AND TNS >= -10.0 | Auto-fix: update clk_period in constraint.sdc to suggested_clock_period from the JSON, then re-run backend. Report the fix to the user after the fact. | | moderate | WNS >= -5.0 AND TNS >= -100.0 (but not clean/minor) | Stop. Present the numbered options from the JSON to the user. Wait for their choice. | | severe | WNS 1e+30 | Stop. SDC clock port mismatch. Present options. Do NOT proceed. |
- The JSON includes
wns_tierandtns_tierfields so the agent can explain which metric triggered the tier (e.g., "TNS escalated this from minor to moderate"). - Only proceed to signoff checks (step 6) after timing is resolved.
5a. (Optional) Fmax search — find the fastest closing period
Before committing to a clock period, you can characterize the design's Fmax:
python3 scripts/reports/fmax_search.py [platform] [--verify]
Loose-first search using cheap placement-stage timing (each probe runs only ORFS_STAGES="synth floorplan place"). It reports a predicted-signoff Fmax (reports/fmax_search.json), corrected by a learned per-family slack-deterioration model. The number is a proxy (UNVERIFIED) — post-place timing is optimistic vs signoff. Pass --verify to confirm the winner with one full flow (and feed the result back to tighten the model). This does NOT replace the step-8 check_timing gate, which still runs on the final backend.
Knobs: --probe-timeout, --place-fast (whole-search conservative lower bound for hang-prone designs), --keep-variants. The search is sequential; cross-design parallelism is achieved by running multiple invocations concurrently.
6. Run Signoff Checks (DRC, LVS, RCX)
After a successful backend run, run signoff checks in order:
DRC (Design Rule Check)
Two tool options are available:
- KLayout DRC (default) —
scripts/flow/run_drc.sh [platform]
- Uses ORFS
make drctarget with platform.lydrcrules - Outputs:
drc/6_drc.lyrdb,drc/6_drc_count.rpt,drc/6_drc.log
- Magic DRC (sky130 only) —
scripts/flow/run_magic_drc.sh [platform]
- Uses Magic's built-in DRC engine with sky130A tech file
- Requires the sky130A PDK; the script reads
$PDK_ROOT/sky130A/libs.tech/magic/sky130A.tech
(set PDK_ROOT via references/env.local.sh — /opt/pdks is only the fallback default).
- Outputs:
drc/magic_drc.rpt,drc/magic_drc_count.rpt,drc/magic_drc_result.json - Supported platforms: sky130hd, sky130hs
LVS (Layout vs Schematic)
Two tool options are available:
- KLayout LVS (default) —
scripts/flow/run_lvs.sh [platform]
- Uses ORFS
make lvstarget with platform.lylvsrules + CDL netlist - Gracefully skips platforms without LVS rules (produces
lvs/lvs_result.jsonwith status "skipped") - Outputs:
lvs/6_lvs.lvsdb,lvs/6_lvs.log,lvs/6_final.cdl - nangate45: uses adapted FreePDK45 rules with
connect_implicit("VDD"/"VSS")for bulk merging andschematic.purgefor unused cell pins (e.g., QN on DFFR_X1) - Large design warning: KLayout LVS on designs >100K cells (black_parrot, swerv) takes >60 minutes. Use
LVS_TIMEOUT=7200for these designs. The default 3600s may not be enough.
- Netgen LVS (sky130 only) —
scripts/flow/run_netgen_lvs.sh [platform]
- Two-step flow: Magic extracts SPICE from GDS, then Netgen compares against Verilog netlist
- Requires the sky130A PDK (Magic tech +
$PDK_ROOT/sky130A/libs.tech/netgen/sky130A_setup.tcl).
Set PDK_ROOT via references/env.local.sh; /opt/pdks is only the fallback default.
- Outputs:
lvs/extracted.spice,lvs/netgen_lvs.rpt,lvs/netgen_lvs_result.json - Supported platforms: sky130hd, sky130hs
- This is the production sky130 LVS path — prefer it over KLayout LVS on sky130 (the
ORFS KLayout sky130 rule deck is not production-grade; see references/failure-patterns.md, "sky130 LVS").
- Antenna-diode designs are handled automatically: the script normalizes Magic's diode
X-subcircuit instances to D devices (perim=→pj=) and runs netgen with MAGIC_EXT_USE_GDS=1, so sky130_fd_sc_hd__diode_2 matches instead of flattening.
- Designs with port-to-port feedthroughs (
assign out_port = in_port) need
export POST_GLOBAL_PLACE_TCL = /scripts/flow/orfs_hooks/buffer_port_feedthroughs.tcl in config.mk before the backend run — SPICE cannot express two top-level ports on one net, so without the hook LVS fails "Top level cell failed pin matching". The hook is a no-op for designs without feedthroughs (safe to set everywhere); a backend re-run is required when adding it. See references/failure-patterns.md, "sky130 LVS" cause 5.
RCX (Parasitic Extraction)
- RCX —
scripts/flow/run_rcx.sh [platform]
- OpenRCX parasitic extraction via OpenROAD
- Generates Tcl script (
rcx/run_rcx.tcl) withdefine_process_corner,extract_parasitics,write_spef - Reads
6_final.odbfrom ORFS results, writes SPEF output - Outputs:
rcx/6_final.spef,rcx/rcx.log,rcx/run_rcx.tcl
Extract results into JSON for reporting and dashboard:
scripts/extract/extract_drc.py reports/drc.jsonscripts/extract/extract_lvs.py reports/lvs.jsonscripts/extract/extract_rcx.py reports/rcx.json- If DRC/LVS is
fail, attempt automated real-layout fixes:
scripts/flow/fix_signoff.sh [platform] [--check drc|lvs|both] (See references/signoff-fixing.md.)
- If the backend aborted at
route(congestion / DRT timeout, exit 124 —orfs_status=fail,
orfs_fail_stage=route), relieve it BEFORE signoff: scripts/flow/fix_signoff.sh sky130hd --check route (lowers CORE_UTILIZATION so DRT converges; learnable + A/B-validated route_relief). See references/failure-patterns.md "Routing Congestion".
Fix-Learning Loop
The skill learns from every fix attempt so candidate strategies are proposed in evidence-ranked order on the next similar violation.
- Record.
fix_signoff.shandcheck_timing.py --journalappend lossless,
session-keyed rows to reports/fix_log.jsonl (one per iteration: strategy, before/after counts, pre-fix violation class, verdict). fix_signoff.sh uses an adaptive budget (base 3 iters, hard cap 8, early-stop after 2 non-improving iters past the base).
- Ingest. Step-10 ingest (
knowledge/ingest_run.py) readsfix_log.jsonlinto the
Tier-1 fix_events table and writes a run_violations snapshot for every run — clean or not (the full violation landscape). It then auto-runs fix_log_manager.manage() (toggle R2G_FIX_AUTOLEARN, default on).
- Learn.
learn_heuristics.pyderives Tier-2fix_trajectories(per-episode path,
including abandoned episodes and failed strategies — negative learning) and folds them into Tier-3 fix_recipes inside heuristics.json.
- Apply. When a recipe exists for the design's family/platform/violation class,
diagnose_signoff_fix.py reorders the strategy list by empirical clearance — there is no hard gate, all real-fix strategies are always proposed, priority-ordered. diagnose_signoff_fix.py --check drc --list prints the evidence-ranked candidate set as JSON. Hard safety clamps are unchanged.
- Symptom index. Learned repair experience is keyed by a symptom signature
(knowledge/symptom.py: {check, class, predicates} → a stable symptom_id), NOT the design-family name. learn_heuristics.py emits a top-level symptoms[symptom_id] projection in heuristics.json (pooled across families/platforms, with by_platform + evidence_designs provenance); diagnose_signoff_fix.py looks recipes up by symptom and seeds an informed cross-platform prior for untried strategies (so a fix learned on nangate45 transfers to e.g. sky130hd). It also surfaces the matching active prose lesson (via search_failures.lessons_for_symptom) at the fix-decision point. monitor_health.py (degradation alerts) and analyze_execution.py (fix-proposal triage) are operator-invoked CLIs over the same store.
See references/signoff-fixing.md ("Fix-Learning Loop") and knowledge/README.md.
Engineer Loop (campaign mode)
Use campaign mode when you need to run the full flow unattended across many designs — or when you want the A/B-gated recipe-learning cycle to run autonomously. The campaign orchestrator (scripts/loop/engineer_loop.py) drives the flow scripts, ingests results, triggers learning, and manages A/B trials without human gates.
# Add a project to the campaign ledger
python3 scripts/loop/engineer_loop.py add \
--ledger design_cases/_batch/campaign.jsonl \
--project design_cases/my_design [--platform nangate45]
# Run the campaign (optionally limit to N designs)
python3 scripts/loop/engineer_loop.py run \
--ledger design_cases/_batch/campaign.jsonl [--max N]
# Inspect per-design state
python3 scripts/loop/engineer_loop.py status \
--ledger design_cases/_batch/campaign.jsonl
The ledger is JSONL (last-state-wins); kill/restart is safe — the campaign resumes where it left off. States: pending → flow → signoff → fixing → clean | escalated | abandoned.
Hard rules for campaign mode:
- Phase-1 runs workers=1 (single-process); do not run two campaigns sharing a
DESIGN_NAME
concurrently.
- Never run two configs with the same
DESIGN_NAME+FLOW_VARIANTconcurrently. - Never run more than one LVS job concurrently for designs > 100 K cells.
- Only
promotedrecipes affect live strategy ranking; shadow and candidate recipes are
inert until their A/B trial completes.
When the loop opens an escalation (unknown symptom, exhausted catalog, unseen crash, or repeated regression), drain it following the agent runbook in references/engineer-loop.md ("Escalation Drain"). That document also covers provenance queries (trace_provenance.py) and the full safety-invariant list.
Platform Support Matrix
| Platform | KLayout DRC | KLayout LVS | Magic DRC | Netgen LVS | RCX | |----------|-------------|-------------|-----------|------------|-----| | nangate45 | Yes | Yes | No | No | Yes | | sky130hd | Yes | Yes | Yes | Yes | Yes | | sky130hs | Yes¹ | Yes | Yes | Yes² | Yes | | asap7 | Yes | No | No | No | Yes | | gf180 | Yes | Yes | No | No | Yes | | ihp-sg13g2 | Yes | Yes | No | No | Yes |
¹ sky130hs has no ORFS-shipped DRC deck; run_drc.sh deliberately reuses the sibling sky130hd.lydrc (pure sky130A tech-layer rules, no hd-specific content) via KLAYOUT_DRC_FILE= on the make command line (failure-patterns.md #32). ² Requires the sky130hs.lyt lefdef repair (tools/patch_sky130hs_lyt.py, applied by eda-install's platform-rules step) — the stock file makes def2stream drop ALL DEF geometry, turning every Netgen LVS into a false top-pin mismatch; run_netgen_lvs.sh guards portless extractions as infra errors (failure-patterns.md #33).
7. Treat Artifacts as Source of Truth
- Save logs, reports, VCD waveforms, netlists, SPEF, configurations, and summary files.
- Prefer file outputs over GUI tools. GUI viewers like GTKWave/KLayout are optional helpers.
8. Diagnose Before Editing
- For failures, read
references/failure-patterns.md. - Classify the failure: specification gap, RTL bug, testbench bug, synthesis issue, backend/configuration issue, DRC violation, LVS mismatch, or RCX extraction error.
- Fix the smallest plausible cause first.
9. Summarize Each Stage Clearly
-
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ShenShan123
- Source: ShenShan123/r2g-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.