文件

54 行
2.5 KiB
Python

"""Inject violations into a disposable board to check R2 rules actually fire."""
import json
import shutil
import pcbnew as pcb
from bootstrap_pcb import xy, rounded_rect
from optimize_pcb_layout import ROOT, OUT
from verify_pcb_layout import run, routing
def main():
folder=OUT/'rule-probe'
folder.mkdir(exist_ok=True)
path=folder/'RuleProbe.kicad_pcb'
b=pcb.BOARD(); b.SetCopperLayerCount(4)
rounded_rect(b,50,50,220,135,5)
def net(name):
item=pcb.NETINFO_ITEM(b,name); b.Add(item); return item
usb,sw,control=net('USB_DP'),net('Net-(C105-Pad2)'),net('SDA')
def track(a,z,layer,n,width=.25):
t=pcb.PCB_TRACK(b); t.SetStart(xy(*a));t.SetEnd(xy(*z));t.SetLayer(layer)
t.SetWidth(pcb.FromMM(width));t.SetNet(n);b.Add(t)
track((60,60),(65,60),pcb.F_Cu,usb,.8)
track((70,70),(80,70),pcb.In1_Cu,control)
track((90,80),(90,81.5),pcb.F_Cu,control)
track((90,81.5),(90,83),pcb.F_Cu,control)
track((100,90),(101.5,90),pcb.B_Cu,control)
track((101.5,90),(103,90),pcb.B_Cu,control)
v=pcb.PCB_VIA(b);v.SetPosition(xy(120,100));v.SetWidth(pcb.FromMM(.6))
v.SetDrill(pcb.FromMM(.3));v.SetLayerPair(pcb.F_Cu,pcb.B_Cu);v.SetNet(sw);b.Add(v)
pcb.SaveBoard(str(path),b)
for ext in ('.kicad_pro','.kicad_dru'):
shutil.copy2(ROOT/'PhoneRail-Board1'/('PhoneRail-Board1'+ext),path.with_suffix(ext))
drc=folder/'drc.json'
run(['pcb','drc','--format','json','-o',str(drc),str(path)],drc)
data=json.loads(drc.read_text(encoding='utf-8'))
descriptions='\n'.join(v['description'] for v in data['violations'])
expected=['R2 USB differential target','R2 inner layers reserved','R2 switch copper stays']
checks={s:s in descriptions for s in expected}
contract=json.loads((ROOT/'pcb-routing-rules.json').read_text(encoding='utf-8'))
audit=routing(b,contract,1)
direction=[v for v in audit['errors'] if v['kind']=='direction']
checks['Split transverse tracks rejected on both outer layers']=len(direction)==2
checks['Inner signal track rejected']=any(v['kind']=='inner_signal_track' for v in audit['errors'])
checks['Explicit nonstandard USB pair skew checked']=any(v['kind']=='usb_skew' for v in audit['errors'])
result={'checks':checks,'all_passed':all(checks.values()),'routing':audit}
(folder/'verification.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(checks)
assert result['all_passed'],descriptions
if __name__=='__main__':
main()