#!/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()