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/measure-routing.mjs
import fs from 'node:fs'
const c=JSON.parse(fs.readFileSync('dist/index/circuit.json','utf8'))
const netById=new Map(c.filter(e=>e.type==='source_net').map(e=>[e.source_net_id,e.name]))
const traceById=new Map(c.filter(e=>e.type==='source_trace').map(e=>[e.source_trace_id,e]))
const lengths={},vias={}
for(const t of c.filter(e=>e.type==='pcb_trace')) {
let n=netById.get(t.connection_name)
if (!n && t.source_trace_id) n=netById.get(traceById.get(t.source_trace_id)?.connected_source_net_ids?.[0])
if (!n) continue
let length=0,count=0
for(let i=1;i<t.route.length;i++) {
const a=t.route[i-1],b=t.route[i]
if (a.route_type==='wire' && b.route_type==='wire' && a.layer===b.layer) length+=Math.hypot(b.x-a.x,b.y-a.y)
if (b.route_type==='via') count++
}
lengths[n]=(lengths[n]??0)+length;vias[n]=(vias[n]??0)+count
}
const skew=names=>({names,lengths:names.map(n=>lengths[n]??null),vias:names.map(n=>vias[n]??null),xySkew:names.every(n=>lengths[n]!==undefined)?Math.max(...names.map(n=>lengths[n]))-Math.min(...names.map(n=>lengths[n])):null})
const groups=[0,1].map(b=>({name:`DDR_BYTE${b}`,limit:0.635,...skew([...Array.from({length:8},(_,i)=>`DDR_D${b*8+i}`),`DDR_DQM${b}`,`DDR_DQS${b}`,`DDR_DQSn${b}`])}))
for(const [name,pos,neg] of [['DDR_CK','DDR_CK','DDR_CKn'],['DQS0','DDR_DQS0','DDR_DQSn0'],['DQS1','DDR_DQS1','DDR_DQSn1'],['USB0','USB0_DP','USB0_DM']]) groups.push({name,limit:0.127,...skew([pos,neg])})
const result={note:'Planar copper length only; via barrel delays and stackup must be included in timing signoff.',groups}
fs.writeFileSync('design/routing-lengths.json',JSON.stringify(result,null,2)+'\n');console.log(JSON.stringify(result,null,2))