78 行
3.6 KiB
Python
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()
|