64 行
2.5 KiB
Python
64 行
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""对账 4:封装库完整性。
|
|
|
|
三项:
|
|
1. 原理图里每个元件引用的封装,库里都有;
|
|
2. 封装的焊盘号集合 ⊇ 符号的引脚号集合(少一个焊盘 = 网络接不上,PCB 里才会暴露);
|
|
3. 文件能被 KiCad 解析(交给 kicad-cli 做)。
|
|
"""
|
|
import json, os, re, sys, collections
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from k_netlist import parse_pads
|
|
|
|
ROOT = os.path.dirname(os.path.abspath(__file__))
|
|
SRC = os.path.join(ROOT, "eda_src")
|
|
PRETTY = os.path.join(os.path.dirname(ROOT), "kicad", "lib", "PhoneRail.pretty")
|
|
|
|
|
|
def fp_pads(path):
|
|
s = open(path, encoding="utf-8").read()
|
|
return {m.group(1) for m in re.finditer(r'\(pad "([^"]*)"', s)}
|
|
|
|
|
|
def main():
|
|
have = {}
|
|
for f in os.listdir(PRETTY):
|
|
if f.endswith(".kicad_mod"):
|
|
have[f[:-10]] = fp_pads(os.path.join(PRETTY, f))
|
|
ok = True
|
|
for board in ("Board1", "Board2"):
|
|
base = parse_pads(os.path.join(SRC, board, "netlist.asc"))
|
|
want = collections.Counter(base["parts"].values())
|
|
missing = sorted(n for n in want if n and n not in have)
|
|
print(f"[{board}] 引用封装 {len(want)} 种", end="")
|
|
if missing:
|
|
print(f" ✘ 库里缺 {len(missing)}: {missing[:6]}"); ok = False
|
|
else:
|
|
print(" ✔ 全部存在")
|
|
# 焊盘号 vs 引脚号
|
|
tree = json.load(open(os.path.join(SRC, "_tree.json"), encoding="utf-8"))
|
|
pages = next(x for x in tree["boards"] if x["board"] == board)["pages"]
|
|
bad = []
|
|
for p in pages:
|
|
g = json.load(open(os.path.join(SRC, board, p["name"] + ".geom.json"), encoding="utf-8"))
|
|
for c in (g["prims"]["Component"] or []):
|
|
if c["ComponentType"] != "part":
|
|
continue
|
|
fp = (c.get("Footprint") or {}).get("name")
|
|
if fp not in have:
|
|
continue
|
|
pins = {str(q["PinNumber"]) for q in (c.get("__pins") or [])}
|
|
miss = pins - have[fp]
|
|
if miss:
|
|
bad.append((c["Designator"], fp, sorted(miss)[:4]))
|
|
if bad:
|
|
print(f" ✘ 引脚号在封装里找不到对应焊盘 {len(bad)}: {bad[:4]}"); ok = False
|
|
else:
|
|
print(" ✔ 焊盘号覆盖全部引脚号")
|
|
print("\n" + ("封装库检查通过 ✔" if ok else "封装库有问题 ✘"))
|
|
sys.exit(0 if ok else 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|