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