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')