文件
phonerail/.claude/k_check_extract.py
T

69 行
2.8 KiB
Python

#!/usr/bin/env python3
"""对账 1:几何提取结果 vs 网表基准(元件集合必须完全一致)。
只有 ComponentType == 'part' 且 AddIntoPcb 的实例才进网表;netflag/netport/sheet 不进。
对不上就说明提取漏了页或者取错了字段——必须在生成 KiCad 之前解决。
"""
import json, os, sys, collections
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from k_netlist import parse_pads
ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "eda_src")
def load_board(b):
tree = json.load(open(os.path.join(ROOT, "_tree.json"), encoding="utf-8"))
pages = next(x for x in tree["boards"] if x["board"] == b)["pages"]
comps, types = [], collections.Counter()
for p in pages:
g = json.load(open(os.path.join(ROOT, b, p["name"] + ".geom.json"), encoding="utf-8"))
for c in (g["prims"]["Component"] or []):
c["__page"] = p["name"]
types[c.get("ComponentType")] += 1
comps.append(c)
return comps, types
def main():
ok = True
for b in ("Board1", "Board2"):
comps, types = load_board(b)
base = parse_pads(os.path.join(ROOT, b, "netlist.asc"))
parts = [c for c in comps if c.get("ComponentType") == "part"]
inpcb = [c for c in parts if c.get("AddIntoPcb")]
geo_refs = collections.Counter(c.get("Designator") for c in inpcb)
base_refs = set(base["parts"])
print(f"[{b}] 实例 {len(comps)} {dict(types)}")
print(f" part 实例 {len(parts)},其中 AddIntoPcb {len(inpcb)};网表元件 {len(base_refs)}")
dupes = {r: n for r, n in geo_refs.items() if n > 1}
only_geo = sorted(set(geo_refs) - base_refs)
only_net = sorted(base_refs - set(geo_refs))
if dupes:
# 多单元器件(U1A/U1B)会合法地重复,先原样报出来看
print(f" ⚠ 位号重复 {len(dupes)}: {list(dupes.items())[:8]}")
if only_geo:
print(f" ⚠ 只在几何里 {len(only_geo)}: {only_geo[:10]}"); ok = False
if only_net:
print(f" ⚠ 只在网表里 {len(only_net)}: {only_net[:10]}"); ok = False
if not only_geo and not only_net:
print(f" ✔ 元件集合完全一致({len(base_refs)} 个)")
# 封装一致性
bad_fp = []
for c in inpcb:
fp = (c.get("Footprint") or {}).get("name")
want = base["parts"].get(c.get("Designator"))
if want and fp and fp != want:
bad_fp.append((c["Designator"], fp, want))
if bad_fp:
print(f" ⚠ 封装不符 {len(bad_fp)}: {bad_fp[:5]}"); ok = False
else:
print(f" ✔ 封装全部一致")
print()
sys.exit(0 if ok else 1)
if __name__ == "__main__":
main()