gokul/cm4-media-carrier

A tscircuit package created by gokul.

Version
0.1.0
License
unset
Stars
0

tools/audit-geometry.py

import json, math, sys
from collections import Counter
from pathlib import Path

path=Path(sys.argv[1] if len(sys.argv)>1 else 'dist/index/circuit.json')
elements=json.loads(path.read_text())
source={x['source_trace_id']: x for x in elements if x['type']=='source_trace'}
traces=[x for x in elements if x['type']=='pcb_trace']
errors=[x for x in elements if x['type'].endswith('_error')]
reports=[]
for sid,s in source.items():
    name=s.get('name','')
    if not name.startswith(('HDMI_', 'USB_DATA_')): continue
    routed=[t for t in traces if t.get('source_trace_id')==sid]
    length=0; widths=set(); layers=set(); vias=0
    for t in routed:
        route=t['route']
        for p in route:
            if p.get('route_type')=='wire':
                widths.add(p['width']); layers.add(p['layer'])
            elif p.get('route_type')=='via': vias+=1
        for a,b in zip(route,route[1:]):
            length+=math.hypot(a['x']-b['x'],a['y']-b['y'])
    reports.append({'name':name, 'trace_count':len(routed), 'planar_length_mm':round(length,6), 'widths_mm':sorted(widths), 'layers':sorted(layers), 'vias':vias,
        'width_matches_request':bool(routed) and all(abs(w-s['min_trace_thickness'])<1e-6 for w in widths),
        'top_only':bool(routed) and layers=={'top'} and vias==0})
pairs=[]
by_name={r['name']:r for r in reports}
for prefix in ['HDMI_D2','HDMI_D1','HDMI_D0','HDMI_CLK','USB_DATA']:
    p,n=(by_name.get(prefix+suffix) for suffix in ['_P','_N'])
    skew=abs(p['planar_length_mm']-n['planar_length_mm']) if p and n and p['trace_count'] and n['trace_count'] else None
    pairs.append({'pair':prefix,'skew_mm':round(skew,6) if skew is not None else None,'limit_mm':.15,'passes':skew is not None and skew<=.150001})
components=[e for e in elements if e['type']=='source_component']
result={'circuit_json':str(path),'pcb_trace_count':len(traces),'error_counts':dict(Counter(e['type'] for e in errors)), 'errors':[{'type':e['type'],'message':e.get('message')} for e in errors], 'high_speed_traces':reports, 'pair_lengths':pairs,'components_without_mpn':[e['name'] for e in components if not e.get('manufacturer_part_number')], 'electrical_geometry_gate_passes':not errors and len(traces)>0 and all(p['passes'] for p in pairs) and all(r['top_only'] and r['width_matches_request'] for r in reports), 'scope':'Checks exported centerline lengths, width metadata, layer use, MPN presence and reported DRC only. Does not establish impedance, coupling, current capacity, RF clearance, mechanical fit, or fabrication readiness.'}
print(json.dumps(result,indent=2))