69 行
2.8 KiB
Python
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()
|