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-reuse.tsx
import{RootCircuit}from'@tscircuit/core'
import assert from 'node:assert/strict'
import {writeFileSync,readFileSync} from 'node:fs'
import Sample from '../src/ProfilePreview'
import{getAM3352TracePaths}from'../src/saved-paths'
import{assertLayoutProfile,getAM3352Bounds,LAYOUT_PROFILES}from'../src/profiles'
const profile=process.argv[2]??'native'
assertLayoutProfile(profile)
const am3352TracePaths=getAM3352TracePaths(profile)
const c=new RootCircuit();c.add(<Sample layoutProfile={profile} pcbX={2} pcbY={-1} pcbRotation={90} boardSize={Math.max(40,Math.max(...Object.values(LAYOUT_PROFILES[profile].fanoutBounds).map(Math.abs))*2+16)}/>);await c.renderUntilSettled()
const json=c.getCircuitJson()
assert.deepEqual(json.filter(e=>e.type.endsWith('_error')),[])
const bounds=getAM3352Bounds(profile),cx=(bounds.minX+bounds.maxX)/2,cy=(bounds.minY+bounds.maxY)/2
const region=json.find(e=>e.type==='pcb_group'&&e.name==='AM3352_SAVED')
assert.ok(region?.type==='pcb_group')
assert.ok(region.width!==undefined&®ion.height!==undefined)
assert.ok(Math.abs(region.center.x-(2-cy))<1e-6&&Math.abs(region.center.y-(-1+cx))<1e-6,'Asymmetric routing region must rotate about CPU center')
assert.ok(Math.abs(region.width-(bounds.maxY-bounds.minY))<1e-6&&Math.abs(region.height-(bounds.maxX-bounds.minX))<1e-6,'Rectangular routing region dimensions must rotate')
const cpuSource=json.find(e=>e.type==='source_component'&&e.name==='U1')
assert.ok(cpuSource?.type==='source_component')
const cpu=json.find(e=>e.type==='pcb_component'&&e.source_component_id===cpuSource.source_component_id)
assert.ok(cpu?.type==='pcb_component')
assert.ok(Math.hypot(cpu.center.x-2,cpu.center.y+1)<1e-6,'Public placement must stay at CPU center')
const traces=json.filter(e=>e.type==='pcb_trace')
for(const path of am3352TracePaths){
const first=path.route[0]!;const start={x:2-first.y,y:-1+first.x}
const expected=path.route.map(p=>({...p,x:2-p.y,y:-1+p.x}))
const trace=traces.find(t=>t.route.length===expected.length&&t.route.every((p,i)=>p.route_type !== "through_pad" && Math.hypot(p.x-expected[i]!.x,p.y-expected[i]!.y)<1e-5))
assert.ok(trace,`Changed route after rotation: ${path.connection}`)
for(const [i,p] of expected.entries()){
const q:any=trace.route[i]!
assert.equal(q.route_type,p.route_type)
if(p.route_type==='wire'&&q.route_type==='wire')assert.equal(q.layer,p.layer)
if(p.route_type==='via'&&q.route_type==='via'){assert.equal(q.from_layer,p.from_layer);assert.equal(q.to_layer,p.to_layer)}
}
}
const original=JSON.parse(readFileSync(`src/generated/${profile}.circuit.json`,'utf8'))
const fixedSources=original.filter((e:any)=>e.type==='source_trace'&&(/^(C\d+_(POWER|GROUND|LDO)|FIXED_DROP_)/.test(e.name??'')))
assert.equal(fixedSources.length,173)
for(const source of fixedSources){
const before=original.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===source.source_trace_id)
const rotatedSource=json.find((e:any)=>e.type==='source_trace'&&e.name===source.name) as any
const after=json.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===rotatedSource?.source_trace_id) as any
assert.ok(before&&after,`Missing fixed trace after rotation: ${source.name}`)
assert.equal(after.route.length,before.route.length)
for(let i=0;i<before.route.length;i++){
const p=before.route[i],q=after.route[i]
assert.ok(Math.hypot(q.x-(2-p.y),q.y-(-1+p.x))<1e-5,`Fixed waypoint did not rotate: ${source.name}`)
assert.equal(q.layer,p.layer)
}
}
writeFileSync('dist/rotated.circuit.json',JSON.stringify(json))
console.log(`All ${am3352TracePaths.length} saved paths and ${fixedSources.length} fixed supply/capacitor traces preserve geometry after translation and 90° rotation (${profile})`)