Files
Plasma-DMD/hardware/kicad/check_netlist.py
T

53 lines
1.8 KiB
Python
Raw Normal View History

2026-10-24 02:31:50 +02:00
"""Export the netlist with kicad-cli and compare it with PARTS in gen_kicad.py.
python hardware/kicad/check_netlist.py [path/to/kicad-cli]
"""
import re
import subprocess
import sys
from pathlib import Path
from gen_kicad import PARTS, PROJECT, pin_cache_for, read_sexpr_block
HERE = Path(__file__).parent
CLI = sys.argv[1] if len(sys.argv) > 1 else "C:/Users/patri/AppData/Local/Programs/KiCad/10.0/bin/kicad-cli.exe"
net_file = HERE / f"{PROJECT}.net"
subprocess.run([CLI, "sch", "export", "netlist", "-o", str(net_file), str(HERE / f"{PROJECT}.kicad_sch")],
check=True, capture_output=True)
text = net_file.read_text(encoding="utf-8")
net_file.unlink()
# actual: (ref, pin number) -> net name
actual = {}
for m in re.finditer(r"\(net\s+\(code", text):
blk = read_sexpr_block(text, m.start())
name = re.search(r'\(name "([^"]*)"\)', blk).group(1).lstrip("/")
for ref, pin in re.findall(r'\(node\s+\(ref "([^"]+)"\)\s+\(pin "([^"]+)"\)', blk):
actual[(ref, pin)] = name
errors = 0
expected = {}
for ref, lib_id, value, fp, conns, g in PARTS:
for num, name, *_ in pin_cache_for(lib_id):
key = num if num in conns else (name if name in conns else None)
if key is None or conns[key] is None:
continue
expected[(ref, num)] = conns[key]
for k, net in expected.items():
got = actual.get(k)
if got != net:
errors += 1
print(f"MISMATCH {k}: expected {net}, got {got}")
# every net should join at least two pins
by_net = {}
for k, net in actual.items():
by_net.setdefault(net, []).append(k)
for net, nodes in sorted(by_net.items()):
if len(nodes) < 2 and not net.startswith("unconnected"):
errors += 1
print(f"SINGLE-PIN NET {net}: {nodes}")
print(f"{len(expected)} pins checked, {len(by_net)} nets, {errors} problem(s)")
sys.exit(1 if errors else 0)