文件
phonerail/kicad/scripts/check_power_paths.py

78 行
3.6 KiB
Python

"""Trace reviewed supply paths from fresh KiCad netlists; not an electrical rating check."""
import json
from check_hardware import Board
from schematic_maintenance import ROOT, children, parse, properties
OUT = ROOT / 'out/power-path-review'
def main():
OUT.mkdir(parents=True, exist_ok=True)
boards = {n: Board(n) for n in (1, 2)}
for b in boards.values():
b.compile('D:/KiCad/bin/kicad-cli.exe', OUT)
a, b = boards[1], boards[2]
checks = []
def same(number, *endpoints, net=None):
board = boards[number]
names = {board.net(*p) for p in endpoints}
assert len(names) == 1 and (net is None or names == {net}), (number, endpoints, names)
checks.append({'board': number, 'endpoints': endpoints, 'net': names.pop()})
same(1, ('J1', 1), net='GND')
same(1, ('J1', 2), ('F1', 1))
same(1, ('F1', 2), ('Q1', 1), ('Q1', 2), ('Q1', 3))
same(1, ('Q1', 5), ('Q1', 6), ('Q1', 7), ('Q1', 8), ('Rs6', 1))
same(1, ('Rs6', 2), ('U19', 3), ('U30', 3), net='+12V')
same(1, ('U19', 2), ('L2', 1))
same(1, ('L2', 2), ('U20', 2), net='+3V3')
same(1, ('U30', 2), ('L3', 1))
same(1, ('L3', 2), ('J24', 8), net='+5V')
for ch in range(1, 6):
same(1, (f'U{ch}', 4), (f'U{ch}', 5), (f'U{ch}', 6), net='+12V')
same(1, (f'U{ch}', 11), (f'U{ch}', 12), (f'L{ch}01', 1))
same(1, (f'L{ch}01', 2), *[(f'U{13+ch}', p) for p in range(9, 14)], net=f'VO{ch}')
same(2, (f'U{23+ch}', 1), ('U31', 3), net='+5V')
# The mechanical contract swaps odd/even physical pin numbers across the mating pair.
for lower, upper in [('J24', 'J31'), ('J25', 'J32')]:
for pin in range(1, 41):
mate = pin + 1 if pin % 2 else pin - 1
net = a.net(lower, pin)
assert net == b.net(upper, mate), (lower, pin, upper, mate)
if net in ('GND', '+5V'):
checks.append({'mating': [[1, lower, pin], [2, upper, mate]], 'net': net})
expected = {1: {'GND', '+3V3', '+12V', *[f'VO{ch}' for ch in range(1, 6)]},
2: {'GND', '+5V'}}
reported = {}
for number, board in boards.items():
report = json.loads((OUT / f'Board{number}-erc.json').read_text())
names = []
for sheet in report['sheets']:
for v in sheet['violations']:
if v['type'] != 'power_pin_not_driven':
continue
description = v['items'][0]['description'].split()
ref = description[1]
if ref.startswith('#PWR'):
path = board.path.parent / (sheet['path'].strip('/') + '.kicad_sch')
symbol = next(s for s in children(parse(path.read_text(encoding='utf-8')), 'symbol')
if properties(s)['Reference'][2] == ref)
net = properties(symbol)['Value'][2]
else:
net = board.net(ref, description[3])
names.append(net)
assert set(names) == expected[number] and len(names) == len(expected[number])
reported[number] = names
result = {'status': 'PASS', 'scope': 'Netlist topology and coverage of all 10 power ERC reports',
'power_erc_nets': reported, 'checks': checks,
'limits': ['No PWR_FLAG added; ERC remains visible',
'MOS gate operation, component ratings, startup and physical copper are not validated']}
(OUT / 'verification.json').write_text(json.dumps(result, indent=2) + '\n')
print(json.dumps({'status': 'PASS', 'checks': len(checks), 'power_erc_nets': reported}))
if __name__ == '__main__':
main()