seveibar/am3352-ram-dogbone-and-single-layer-route-test
AM3352BZCZ100 processor connected to a W631GG6MB-12 DDR3 memory chip through a routed, length-matched 16-bit DDR interface with clock/data-strobe pairs and control/address signals.
- Version
- 0.0.9
- License
- unset
- Stars
- 0
scripts/validate-rounded.py
"""Independent audit of phase handoff, angular continuity, and rounded geometry."""
import json,math
from pathlib import Path
root=Path(__file__).resolve().parents[1]
def read(phase):return json.loads((root/f'dist/autorouter-debug/phase-{phase}.output.traces.json').read_text())
def pieces(t):
ps=t['route'];vs=[i for i,p in enumerate(ps) if p['route_type']=='via'];assert len(vs)==2
return ps[:vs[0]+1],ps[vs[0]+1:vs[1]],ps[vs[1]:]
def metric(traces):
angles=[]
for t in traces:
_,ps,_=pieces(t)
for a,b,c in zip(ps,ps[1:],ps[2:]):
ux,uy=b['x']-a['x'],b['y']-a['y'];vx,vy=c['x']-b['x'],c['y']-b['y']
angles.append(abs(math.degrees(math.atan2(ux*vy-uy*vx,ux*vx+uy*vy))))
return dict(maximumHeadingChangeDeg=max(angles),cornersOver45Deg=sum(a>45.001 for a in angles),acuteInteriorCorners=sum(a>90.001 for a in angles))
before,after=read(2),read(3);lookup={t['source_trace_id']:t for t in before};assert len(after)==47
for t in after:
a,old,b=pieces(lookup[t['source_trace_id']]);p,new,q=pieces(t);assert a==p and b==q
assert all(x['route_type']=='wire' and x['layer']==old[0]['layer'] and x['width']==.1 for x in new)
a,b=metric(before),metric(after);assert b['maximumHeadingChangeDeg']<=5.001
report=dict(criteriaVersion=2,before=a,after=b,signals=47,preservedDogboneVias=94,addedVias=0,minimumRadiusGuaranteed=False)
(root/'validation/rounded-score.json').write_text(json.dumps(report,indent=2)+'\n');print(json.dumps(report,indent=2))