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-routing.py
"""Assert routing topology and centerline skew independently of native DRC."""
import hashlib, json, math
from pathlib import Path
from shapely.geometry import LineString
root = Path(__file__).resolve().parents[1]
raw = (root / 'dist/index/circuit.json').read_bytes()
circuit = json.loads(raw)
errors = [e for e in circuit if 'error' in e['type']]
assert not errors, errors
traces = [e for e in circuit if e['type'] == 'pcb_trace']
vias = [e for e in circuit if e['type'] == 'pcb_via']
assert len(traces) == 47 and len(vias) == 94
lengths, layers = {}, {}
for trace in traces:
route = trace['route']
vi = [i for i,p in enumerate(route) if p['route_type'] == 'via']
assert len(vi) == 2, trace['source_trace_id']
middle = route[vi[0]+1:vi[1]]
signal_layers = {p['layer'] for p in middle}
assert len(signal_layers) == 1 and 'top' not in signal_layers
assert all(p['route_type'] == 'wire' for p in middle)
assert route[0].get('start_pcb_port_id') and route[-1].get('end_pcb_port_id')
assert LineString([(p['x'],p['y']) for p in middle]).is_simple, trace['source_trace_id']
total = 0
for a,b in zip(route,route[1:]):
if a['route_type'] == b['route_type'] == 'wire' and a['layer'] == b['layer']:
total += math.hypot(b['x']-a['x'],b['y']-a['y'])
lengths[trace['source_trace_id']] = total
layers[trace['source_trace_id']] = next(iter(signal_layers))
groups = []
for bus in [e for e in circuit if e['type'] == 'source_bus']:
members = bus['source_trace_ids']
assert len({layers[n] for n in members}) == 1
values = [lengths[n] for n in members]
skew = max(values)-min(values)
assert skew <= bus['max_length_skew'], (bus['name'],skew)
groups.append(dict(name=bus['name'],layer=layers[members[0]],signals=len(members),minimumPlanarLengthMm=min(values),maximumPlanarLengthMm=max(values),skewMm=skew,limitMm=bus['max_length_skew']))
report = dict(status='PASS',circuitSha256=hashlib.sha256(raw).hexdigest(),nativeDrcErrors=len(errors),signals=len(traces),dogboneVias=len(vias),signalRoutingVias=0,simpleCenterlines=True,groups=groups,scope='47 DDR signals only; power/reference/ground omitted. Pair skew checked here; measured spacing and bounded pin escapes checked independently in pair-coupling.json.')
(root / 'validation/summary.json').write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps(report,indent=2))