kicad:EasyEDA→KiCad 工程(Board1/Board2)、库、脚本与评审文档(IC 引脚、风扇、热、EDL 供电、布局规则)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -0,0 +1,77 @@
|
||||
"""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()
|
||||
在新工单中引用
屏蔽一个用户