文件
phonerail/kicad/scripts/review_edl_nc.py
T

103 行
4.8 KiB
Python

"""Verify the five reviewed EDL NC markers against a compiled pre-change baseline."""
import argparse
import json
import xml.etree.ElementTree as ET
from check_hardware import Board
from schematic_maintenance import ROOT
from unconnected_inventory import inventory, write_inventory
OUT = ROOT / 'out/edl-nc-review'
CLI = 'D:/KiCad/bin/kicad-cli.exe'
def snapshot(path):
root = ET.parse(path).getroot()
return ({c.attrib['ref']: ET.tostring(c) for c in root.findall('components/comp')},
{n.attrib['name']: {(p.attrib['ref'], p.attrib['pin']): dict(p.attrib)
for p in n.findall('node')} for n in root.findall('nets/net')})
def main():
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument('--baseline', action='store_true')
args = ap.parse_args()
out = OUT / ('before' if args.baseline else 'after')
if args.baseline and out.exists():
raise RuntimeError('Refusing to overwrite the baseline')
out.mkdir(parents=True, exist_ok=True)
results, rows = {}, []
for number in (1, 2):
b = Board(number)
b.compile(CLI, out)
if args.baseline:
continue
old_parts, old_nets = snapshot(OUT / 'before' / f'Board{number}.xml')
new_parts, new_nets = snapshot(out / f'Board{number}.xml')
assert old_parts == new_parts, 'Component metadata changed'
approved = {(f'U4{ch}', '3') for ch in range(1, 6)} if number == 2 else set()
changed = set()
assert old_nets.keys() == new_nets.keys(), 'Net names changed'
for name, endpoints in old_nets.items():
assert endpoints.keys() == new_nets[name].keys(), 'Connectivity changed'
for endpoint, attrs in endpoints.items():
expected = dict(attrs)
if endpoint in approved:
assert len(endpoints) == 1 and name.startswith('unconnected-')
assert attrs['pintype'] == 'passive'
expected['pintype'] = 'passive+no_connect'
actual = new_nets[name][endpoint]
assert actual == expected, (endpoint, actual, expected)
if actual != attrs:
changed.add(endpoint)
assert changed == approved
if number == 2:
for ch in range(1, 6):
u, j, r = f'U4{ch}', f'J6{ch}', f'R74{ch}'
assert b.net_members[b.net(u, 1)] == {(u, '1'), (j, '1')}
assert b.net_members[b.net(u, 4)] == {(u, '4'), (j, '2')}
assert b.net(u, 2) == 'GND' and b.net(u, 5) == '+3V3_HUB'
assert b.net(u, 6) == f'EDL_EN{ch}'
assert b.resistor(r) == 100000
assert {b.net(r, 1), b.net(r, 2)} == {'GND', b.net(u, 6)}
old_erc = json.loads((OUT / 'before' / f'Board{number}-erc.json').read_text())
new_erc = json.loads((out / f'Board{number}-erc.json').read_text())
for key in ('ignored_checks', 'included_severities'):
assert old_erc[key] == new_erc[key]
def violations(report):
# KiCad regenerates ERC pin UUIDs on each CLI load.
return sorted(json.dumps([s['path'], v['type'], v['severity'], v['description'],
[{k: value for k, value in item.items() if k != 'uuid'}
for item in v['items']]], sort_keys=True)
for s in report['sheets'] for v in s['violations'])
expected_erc = json.loads(json.dumps(old_erc))
removed = 0
for sheet in expected_erc['sheets']:
kept = []
for v in sheet['violations']:
is_target = (number == 2 and v['type'] == 'pin_not_connected'
and any(f'Symbol U4{ch} ' in v['items'][0]['description']
for ch in range(1, 6)))
if is_target:
removed += 1
else:
kept.append(v)
sheet['violations'] = kept
assert removed == len(approved)
assert violations(expected_erc) == violations(new_erc), 'Unexpected ERC change'
rows.extend(inventory(b))
results[number] = {'components_unchanged': len(new_parts),
'nets_unchanged': len(new_nets), 'reviewed_nc': sorted(approved),
'erc': b.erc}
if not args.baseline:
result = {'status': 'PASS', 'boards': results,
'inventory': write_inventory(OUT, rows),
'evidence': 'datasheets/ic/TS5A3157.pdf pages 3 and 16',
'scope': 'Unused switch port and powered default selection only; not power-off isolation qualification'}
(OUT / 'verification.json').write_text(json.dumps(result, indent=2) + '\n')
print(json.dumps(result))
if __name__ == '__main__':
main()