DSL for reverse engineering using KiCad

github.com · ryanm101 · 8 days ago · view on HN · tool
quality 4/10 · average
0 net
# revsch `revsch` is a Python tool for turning a small reverse-engineering DSL into a KiCad schematic. The DSL supports two closely related workflows: - schematic-style capture: declare parts, pins, and named nets explicitly - probe-first mapping: capture continuity quickly with `X -> Y, Z` traces, batch-generated parts, and sparse pin metadata The output is a valid `.kicad_sch` file that opens in KiCad and can be refined there by swapping symbols, improving layout, and adding drawing detail. For standard generic parts, the emitter now prefers official KiCad library symbols. For custom and unknown parts, it falls back to embedded generated symbols so the schematic remains self-contained. ## Install and Run This project uses `uv`. ```bash uv run revsch lint examples/basic_minimal.revsch uv run revsch compile examples/basic_minimal.revsch -o ~/tmp/basic_minimal.kicad_sch ``` Useful commands: ```bash uv run revsch lint input.revsch uv run revsch lint --mapping-mode input.revsch uv run revsch compile input.revsch -o output.kicad_sch uv run revsch compile --mapping-mode input.revsch -o output.kicad_sch uv run revsch compile input.revsch -o output.json --output-format json uv run revsch dump-ir input.revsch uv run revsch dump-json input.revsch uv run revsch format input.revsch ``` ## DSL Overview Supported statement types: - `part REFDES ...` - `pin REFDES.PIN ...` - `net NAME = REFDES.PIN, REFDES.PIN` - `alias ALT = NET` - `property TARGET KEY = VALUE` - `note TARGET = VALUE` - `PREFIX key=value ...` Used for batch generation, for example `IC name=PLA pincount=16 count=6` - `A -> B, C, D` Used for fast probe mapping Comments start with `#`. Quoted strings are supported. ### `` Batch Part Syntax `part REFDES ... count=N [start=S]` generates multiple identical parts. `` is replaced with an index for each generated part. `start` sets the first index (default `0`). For example, `part ENC count=2 start=1` creates `ENC1` and `ENC2`. Subsequent `pin`, `net`, `property`, `note`, and trace statements using `` in the reference designator expand across all generated parts. ## Schematic-Style Example ```text part U1 kind=IC value="STM32F103C8" package=LQFP48 pin U1.24 name=VDD type=power_in pin U1.32 name=PA11 type=bidirectional pin U1.33 name=PA12 type=bidirectional part J1 kind=CONN value="USB-C" package=USB_C_16 pin J1.A6 name=D+ pin J1.A7 name=D- net VCC_3V3 = U1.24 net USB_D+ = U1.33, J1.A6 net USB_D- = U1.32, J1.A7 alias +3V3 = VCC_3V3 ``` ## Probe-First Mapping Example This is the fast capture workflow for tracing a board with a continuity probe. ```text IC name=PLA pincount=16 count=6 C count=10 R count=5 J name=EDGE pincount=44 count=1 J1.1 -> +5V J1.2 -> C1, R3, IC1.3 C1 -> GND R3 -> GND ``` Behavior: - `IC name=PLA pincount=16 count=6` creates `IC1` through `IC6`, each with 16 pins - `C count=10` creates `C1` through `C10` with two pins each - `J1.2 -> C1, R3, IC1.3` creates one net containing `J1.2`, one implicit pin from `C1`, one implicit pin from `R3`, and explicit pin `IC1.3` - bare net names such as `+5V` or `GND` become canonical net names - if no net name appears in a trace statement, an automatic net name is created ## Sparse Capture For reverse engineering, most pin metadata can be omitted: ```text part U1 pin U1.6 pin U1.7 net ROW0 = U1.6 net COL0 = U1.7 ``` If a pin has no explicit `name`, the emitter falls back to the pin ID so the generated symbol is still usable. ## Mapping Mode `--mapping-mode` is intended for probe capture, where many pins are still untraced. It suppresses warnings that are usually noise during early reverse engineering: - missing `value` - missing `package` - unused pins - single-member nets It does not suppress structural errors such as undeclared pins, duplicate parts, or conflicting net assignments. ## No-Connect Handling Pins explicitly marked as no-connect emit real KiCad `no_connect` markers: ```text property U1.35 status=nc ``` Pins marked this way do not produce unused-pin warnings. ## Symbol Strategy The emitter uses two symbol strategies. Official KiCad library symbols are used for common standard parts: - resistor -> `Device:R_Small` - capacitor -> `Device:C_Small` - inductor / coil -> `Device:L_Small` - diode -> `Device:D` - LED -> `Device:LED` - crystal -> `Device:Crystal` - 2-pin switch -> `Switch:SW_SPST` - 3-pin switch -> `Switch:SW_SPDT` Embedded generated symbols are used for: - ICs - connectors that do not map cleanly to a stock symbol - unknown parts - anything else without a supported stock mapping This keeps standard parts recognizable in KiCad while preserving a self-contained fallback for reverse-engineered or custom devices. ## JSON Output There are two JSON export paths: - `dump-json` Exports the parsed DSL statement structure - `dump-ir` Exports the normalized internal representation used for validation and emission - `compile --output-format json` Writes the parsed DSL statement structure to a file Example: ```bash uv run revsch dump-json examples/mapping_probe.revsch uv run revsch dump-ir examples/mapping_probe.revsch uv run revsch compile examples/mapping_probe.revsch -o ~/tmp/mapping_probe.json --output-format json ``` `dump-json` and `compile --output-format json` are useful if another tool wants to consume the DSL without reimplementing the parser. ## Examples See [`examples/README.md`](file:///home/ryanm/workspace/kicad_dsl/examples/README.md) for the full example index. Included examples: - [`examples/basic_minimal.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/basic_minimal.revsch) - [`examples/metadata_and_aliases.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/metadata_and_aliases.revsch) - [`examples/sparse_reverse_capture.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/sparse_reverse_capture.revsch) - [`examples/mapping_probe.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/mapping_probe.revsch) - [`examples/mapping_probe_named_nets.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/mapping_probe_named_nets.revsch) - [`examples/esp_keyboard.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/esp_keyboard.revsch) - [`examples/ch579m_key12_v02.revsch`](file:///home/ryanm/workspace/kicad_dsl/examples/ch579m_key12_v02.revsch) ## Status Current implementation includes: - parser and semantic validation - KiCad `.kicad_sch` emission - deterministic UUID and symbol generation - mapping-mode warning profile - source-level and IR-level JSON exports - pytest coverage for parser, semantics, emitter, and CLI