seveibar/am3352-dev-board
A 324-ball TI AM3352 ARM processor with DDR3, LCD, USB, Ethernet, storage, serial, analog, clock, reset, power, and JTAG interfaces, paired with configurable JST-GH board connectors and constrained PCB routing.
- Version
- 1.0.2
- License
- unset
- Stars
- 0
scripts/resume-router.py
"""Merge a routed SES checkpoint into its DSN to continue routing without losing copper.
Usage: python3 scripts/resume-router.py input.dsn checkpoint.ses output.dsn
"""
import re,json,sys
from pathlib import Path
def parse(text):
stack=[];root=None
for t in re.findall(r'"(?:\\.|[^"\\])*"|[()]|[^\s()]+',text.replace('(string_quote ")','')):
if t=='(':
a=[]
if stack:stack[-1].append(a)
stack.append(a)
elif t==')':root=stack.pop()
else:stack[-1].append(t)
return root
def walk(node,key):
if isinstance(node,list):
if node and node[0]==key:yield node
for x in node:
if isinstance(x,list):yield from walk(x,key)
def child(node,key):return next((x for x in node if isinstance(x,list) and x and x[0]==key),None)
def value(s):return json.loads(s) if s.startswith('"') else s
def emit(n):return '('+' '.join(map(emit,n))+')' if isinstance(n,list) else n
board=parse(Path(sys.argv[1]).read_text());ses=parse(Path(sys.argv[2]).read_text());r=next(walk(ses,'resolution'));factor=float(r[2])
assert r[1]=='um','Only micrometre SES units are supported'
def number(s):return str(round(float(s)/factor,6))
lib=child(board,'library');known={value(x[1]) for x in lib if isinstance(x,list) and x[0]=='padstack'}
for p in walk(ses,'padstack'):
if value(p[1]) in known:continue
for circle in walk(p,'circle'):circle[2:]=[number(v) for v in circle[2:]]
lib.append(p)
wiring=['wiring'];count=0
for net in walk(ses,'net'):
for wire in net[2:]:
if not isinstance(wire,list):continue
if wire[0]=='wire':
path=child(wire,'path')
if not path:continue
item=['wire',['path',path[1]]+[number(v) for v in path[2:]],['net',net[1]]]
elif wire[0]=='via':item=['via',wire[1],number(wire[2]),number(wire[3]),['net',net[1]]]
else:continue
item.append(child(wire,'type') or ['type','route']);wiring.append(item);count+=1
board=[x for x in board if not isinstance(x,list) or x[0]!='wiring']+[wiring]
Path(sys.argv[3]).write_text(emit(board)+'\n');print('Saved resumable DSN with',count,'wire/via records')