Docs / FaultFlow ↔ OpenTestability Preflight Protocol

This document is for the FaultFlow session — it describes the machine interface OT exposes so FaultFlow can obtain structural reconvergence data before ATPG without inserting test points.


Overview

OT exposes an internal CLI subcommand _preflight (underscore prefix = not for end users). FaultFlow calls it as a subprocess, parses the stdout JSON line, and reads two output files:

opentest --yosys _preflight \
  -i /path/to/netlist.json \
  --scoap \
  -r \
  --reconv-algorithm advanced \
  -o /path/to/workspace

Recommended flags:


Stdout Contract

OT prints exactly one JSON object on stdout as the last output line:

{
  "status": "ok",
  "manifest": "/abs/path/to/tpi_manifest.json",
  "reconv_ids": "/abs/path/to/fanout_design_reconv_ids.json",
  "tech": "sky130"
}

On error:

{"status": "error", "message": "...reason..."}

FaultFlow should:

  1. Run the command, capture stdout
  2. Find the last line starting with {
  3. Parse JSON, check status == "ok"
  4. Use the returned manifest and reconv_ids paths

Output Files

tpi_manifest.json

Written at <output_dir>/tpi_manifest.json. Schema version "1.0".

Key fields for FaultFlow:

{
  "schema_version": "1.0",
  "session_id": "ot_1234567890_abcd1234",
  "iteration": 1,
  "top_module": "fanout_design",
  "netlist_path": "/abs/path/to/netlist.json",
  "inserted_test_points": [],
  "structural_hints": {
    "fanout_points": [
      {"name": "net_foo", "yosys_net_id": 42},
      {"name": "net_bar", "yosys_net_id": 107},
      {"name": "internal_ot_name", "yosys_net_id": null}
    ],
    "reconvergences": [...],
    "enabled": true,
    "algorithm": "advanced"
  },
  "awaiting_oracle": true,
  "response_path": "/abs/path/to/oracle_response.json"
}

structural_hints.fanout_points

list[dict] — each entry is:

Field Type Notes
name string OT signal name (from circuit graph)
yosys_net_id integer \| null netnames[name]["bits"][0] — first integer in Yosys bits list. null if signal not in Yosys netnames or if all bits are string constants ("0", "1")

Mapping: FaultFlow maps yosys_net_id → its internal compiled net index via the existing Yosys net-ID lookup it already uses for other purposes. Signals with null net_id are OT internal synthesis names — skip or ignore them.

FaultFlow Phase A action: before the ATPG round loop, push any fault whose net_id is in this set to the back of the ordering queue and skip the short-timeout tier (reconvergent-site faults are likely hard/redundant; don’t burn short attempts on them).


<design>_reconv_ids.json

Written at <output_dir>/<design>_reconv_ids.json. This is the algorithm output enriched with Yosys net IDs on every reconvergence record.

Each record in reconvergences has the following additional fields (any can be null):

Basic / Simple algorithm format

{
  "site": "gate_Y",
  "site_net_id": 42,
  "branch1": "sig_A",
  "branch1_net_id": 55,
  "branch2": "sig_B",
  "branch2_net_id": 56,
  "path1": ["sig_A", "mid_1", "gate_Y"],
  "path2": ["sig_B", "mid_2", "gate_Y"]
}
{
  "site": "gate_Y",
  "site_net_id": 42,
  "pairs": [
    {
      "branch1": "sig_A_br0",
      "branch1_net_id": 55,
      "branch2": "sig_A_br1",
      "branch2_net_id": 56,
      "stem": "sig_A",
      "stem_net_id": 50
    }
  ]
}

stem_net_id identifies the fanout source — the net that diverges into two paths and reconverges at site. This is the field needed for Phase B SAT pre-certification: two paths from stemsite with no common intermediate nodes means any single stuck-at fault on stem propagates through both paths and cancels at the XOR-equivalent merge site.

FaultFlow Phase B action: for each record where stem_net_id is non-null and the two paths are structurally disjoint, structurally certify any sa0/sa1 fault on stem as UNSAT (canceling paths) without running SAT at all.


Net ID Semantics

OT derives yosys_net_id as:

bits = netnames[signal_name]["bits"]
net_id = next((b for b in bits if isinstance(b, int)), None)

This matches Yosys’s internal bit numbering. String entries like "0" and "1" represent constant tie-offs and are skipped. The returned integer is directly usable as a Yosys net index.


Full Example Invocation

# Phase A + B preflight before ATPG
opentest --yosys _preflight \
  -i /workspace/design.json \
  --scoap \
  -r \
  --reconv-algorithm advanced \
  -o /workspace/preflight_out \
  --tech sky130

# Parse stdout to get paths
RESULT=$(opentest --yosys _preflight ... 2>/dev/null | tail -1 | python3 -c "
import sys, json
d = json.load(sys.stdin)
if d['status'] != 'ok':
    raise SystemExit(d['message'])
print(d['manifest'])
print(d['reconv_ids'])
")

Or in FaultFlow’s Rust/C++ subprocess handler:

  1. Spawn opentest --yosys _preflight ...
  2. Collect stdout lines
  3. Find last line matching /^\{/
  4. Parse JSON
  5. On status == "ok": read manifest and reconv_ids paths

Backward Compatibility


Files Written (summary)

File Content
<output_dir>/tpi_manifest.json Session manifest with enriched fanout_points
<output_dir>/<design>_reconv_ids.json Reconvergence records with *_net_id fields
<output_dir>/<design>_scoap.json SCOAP metrics (side-effect of DAG build)
<output_dir>/<design>_yosys_dag_advanced.json DAG with reconvergence data