0hmX/am3352
This code suite comprises TypeScript scripts that analyze, verify, and assemble complex DDR memory interface hardware, focusing on physical routing, via and pad placement, electrical clearance, and physical constraints, often involving precise geometric calculations and consistent provenance tracking.
- Version
- 1.0.5
- License
- unset
- Stars
- 0
scripts/check-supply-decoupling.ts
import assert from 'node:assert/strict'
import {readFileSync,writeFileSync} from 'node:fs'
import {decouplingCaps} from '../src/DecouplingNetwork'
import {SUPPLY_DECOUPLING} from '../src/decoupling-requirements'
import {AM3352_PINS} from '../src/pin-map'
const json=JSON.parse(readFileSync('dist/six-layer-placed.circuit.json','utf8'))
assert.equal(decouplingCaps.length,82,'Complete native supply network must contain 82 capacitors')
const report=[]
for(const r of SUPPLY_DECOUPLING){
const caps=decouplingCaps.filter(c=>c.supply===r.supply)
assert.equal(caps.filter(c=>c.capacitance===r.smallValue).length,r.smallCount,`${r.supply} small capacitor count`)
assert.equal(caps.filter(c=>c.capacitance==='10uF').length,r.bulkCount,`${r.supply} bulk capacitor count`)
assert.ok(caps.every(c=>c.net===r.net),`${r.supply} connected to wrong rail`)
for(const c of caps){
const sc=json.find((e:any)=>e.type==='source_component'&&e.name===c.name)
assert.ok(sc,`Missing physical capacitor ${c.name}`)
for(const [suffix,net] of [['POWER',r.net],['GROUND','GND']]){
const trace=json.find((e:any)=>e.type==='source_trace'&&e.name===`${c.name}_${suffix}`)
const rail=json.find((e:any)=>e.type==='source_net'&&e.name===net)
assert.ok(trace?.connected_source_net_ids.includes(rail?.source_net_id),`${c.name} ${suffix} connectivity`)
}
}
report.push({supply:r.supply,net:r.net,smallValue:r.smallValue,smallCount:r.smallCount,bulk10uF:r.bulkCount,capacitors:caps.map(c=>c.name)})
}
assert.equal(decouplingCaps.filter(c=>c.ball&&c.capacitance==='1uF').length,4)
const ddr=decouplingCaps.filter(c=>c.supply==='VDDS_DDR'&&c.capacitance==='100nF')
assert.ok(ddr.filter(c=>c.x>=-3.6&&c.x<=-2.8&&c.y>=-1.2&&c.y<=2.8).length>=3,'At least three DDR HS capacitors must sit between the DDR supply column and the central ground cluster')
const key=(p:number[])=>p.map(n=>n.toFixed(4)).join(',')
for(const c of ddr){
for(const xy of [c.power,c.ground])assert.equal(decouplingCaps.flatMap(other=>[other.power,other.ground]).filter(p=>key(p)===key(xy)).length,1,`${c.name} DDR HS connection via must not be shared with another bottom capacitor`)
for(const supply of ['VDDS_DDR','VSS'])assert.ok(Math.min(...AM3352_PINS.filter(p=>p.name===supply).map(p=>Math.hypot(p.x-c.x,p.y-c.y)))<=10.16,`${c.name} exceeds TI DDR bypass distance`)
for(const suffix of ['POWER','GROUND']){
const st=json.find((e:any)=>e.type==='source_trace'&&e.name===`${c.name}_${suffix}`)
const pcb=json.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===st.source_trace_id)
const len=pcb.route.slice(1).reduce((sum:number,p:any,i:number)=>sum+Math.hypot(p.x-pcb.route[i].x,p.y-pcb.route[i].y),0)
assert.ok(len<=2.54,`${c.name} exceeds DDR cap pad-to-via length`)
}
}
const placements=decouplingCaps.map(c=>{
const sc=json.find((e:any)=>e.type==='source_component'&&e.name===c.name)
const pc=json.find((e:any)=>e.type==='pcb_component'&&e.source_component_id===sc.source_component_id)
const underPackage=Math.abs(pc.center.x)+pc.width/2<=7.5&&Math.abs(pc.center.y)+pc.height/2<=7.5
return {name:c.name,supply:c.supply,capacitance:c.capacitance,layer:pc.layer,x:c.x,y:c.y,underPackage,powerVia:c.power,groundVia:c.ground}
})
writeFileSync('src/generated/native.decoupling.json',JSON.stringify({datasheet:'SPRS717L',tables:['5-13','5-14','5-15','7-64','7-65'],capacitors:82,underPackage:placements.filter(p=>p.underPackage).length,withinPaddedBoundary:82,placements,supplies:report,ddrHsSeparateViaPairs:true},null,2)+'\n')
console.log('82 physical capacitors: all implemented supply groups covered; DDR HS capacitors have separate via pairs and pass proximity/connection-length checks')