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
tests/ddr-memory-board-profile.test.tsx
import{test,expect}from'bun:test'
import{RootCircuit}from'@tscircuit/core'
import{createHash}from'node:crypto'
import{readFileSync}from'node:fs'
import{compareDdrMemoryCachePathToBoard}from'../scripts/ddr-memory-cache-board-comparison'
import{DDR_MEMORY_BOARD_PROFILE_BINDING as binding,DDR_MEMORY_BOARD_PINS as pins,DdrMemoryBoardProfile,getDdrMemoryBoardPaths}from'../src/ddr-memory-board-profile'
import{auditRouteAngles}from'../scripts/check-route-angles'
const hash=(o:any)=>createHash('sha256').update(JSON.stringify(o)).digest('hex')
test('complete physical profiles bind immutable caches and explicitly disclose board power overrides',()=>{
for(const name of['current_e3_byte0','current_e3_byte1']as const){const paths=getDdrMemoryBoardPaths(name);expect(paths).toHaveLength(72);expect(hash(paths)).toBe(binding.profiles[name].pathsSha256);expect(auditRouteAngles(paths).valid).toBe(true);const profile=binding.profiles[name],candidate=JSON.parse(readFileSync(`${binding.acceptedArtifactDirectory}/candidate.circuit.json`,'utf8')),actualOverrides=paths.flatMap(path=>compareDdrMemoryCachePathToBoard(path,pins.find(pin=>path.connection===`U1.ball_${pin.ball}`)!,profile.byte,profile.placement,candidate));expect(profile.additionalBoardCopperOverrides.map(o=>o.ball).sort()).toEqual(actualOverrides.map(o=>o.ball).sort());expect(profile.additionalBoardCopperOverrides.every(o=>['VDD','VDDQ','VSS','VSSQ'].includes(pins.find(p=>p.ball===o.ball)!.signal))).toBe(true);paths[0]!.route[0]!.x=Number(paths[0]!.route[0]!.x)+1;expect(hash(getDdrMemoryBoardPaths(name))).toBe(binding.profiles[name].pathsSha256)}
expect(()=>getDdrMemoryBoardPaths('native'as any)).toThrow();expect(()=>DdrMemoryBoardProfile({name:'RAM',boardProfile:'current_e3_byte0',hostProfile:'am3352'}as any)).toThrow()
})
test('actual two-instance rendering preserves144 physical exits and through barrels without local pours',async()=>{
const circuit=new RootCircuit();circuit.add(<board width={50} height={40} layers={10} schematicDisabled allowBlindAndBuriedVias={false}><DdrMemoryBoardProfile name="RAM0" boardProfile="current_e3_byte0" pcbX={-12} pcbY={-6.5} pcbRotation={180}/><DdrMemoryBoardProfile name="RAM1" boardProfile="current_e3_byte1" pcbX={12} pcbY={6.5}/></board>);await circuit.renderUntilSettled();const json:any[]=circuit.getCircuitJson()
expect(json.filter(e=>e.type==='pcb_copper_pour')).toHaveLength(0);expect(json.filter(e=>e.type==='pcb_smtpad')).toHaveLength(156);expect(json.filter(e=>e.type==='pcb_breakout_point')).toHaveLength(144)
for(const[byte,name,x,y,sign]of[[0,'current_e3_byte0',-12,-6.5,-1],[1,'current_e3_byte1',12,6.5,1]]as const){for(const p of getDdrMemoryBoardPaths(name)){const ball=p.connection.slice('U1.ball_'.length),pin=pins.find(p=>p.ball===ball)!,last=p.route.at(-1)!,first=p.route[0]!,exit=json.filter(e=>e.type==='pcb_breakout_point'&&e.layer===(last as any).layer&&Math.hypot(e.x-(x+sign*Number(last.x)),e.y-(y+sign*Number(last.y)))<1e-7);expect(exit).toHaveLength(1);const sourcePort=json.find(e=>e.type==='source_port'&&e.source_port_id===exit[0].source_port_id);expect(sourcePort.name).toBe(`ball_${pin.ball}`);const traces=json.filter(e=>e.type==='pcb_trace'&&e.source_trace_id===exit[0].source_trace_id);expect(traces).toHaveLength(1);expect(traces[0].route).toHaveLength(p.route.length);for(let i=0;i<p.route.length;i++){const a=p.route[i]!,b=traces[0].route[i];expect(b.route_type).toBe(a.route_type);expect(b.x).toBeCloseTo(x+sign*Number(a.x),7);expect(b.y).toBeCloseTo(y+sign*Number(a.y),7);if(a.route_type==='wire')expect(b.layer).toBe(a.layer)}expect(json.some(e=>e.type==='pcb_smtpad'&&Math.hypot(e.x-(x+sign*Number(first.x)),e.y-(y+sign*Number(first.y)))<1e-7)).toBe(true)}}
const vias=json.filter(e=>e.type==='pcb_via');expect(vias.length).toBeGreaterThan(0);for(const via of vias){expect(via.outer_diameter).toBe(.4572);expect(via.hole_diameter).toBe(.254);expect(via.layers).toEqual(['top','inner1','inner2','inner3','inner4','inner5','inner6','inner7','inner8','bottom'])}
expect(auditRouteAngles(json.filter(e=>e.type==='pcb_trace')).valid).toBe(true);expect(json.filter(e=>e.type.endsWith('_error'))).toEqual([])
},30000)
test('quarter-turn placement preserves physical-layer exits',async()=>{
for(const rotation of[90,270]){const circuit=new RootCircuit();circuit.add(<board width={30} height={30} layers={10} schematicDisabled allowBlindAndBuriedVias={false}><DdrMemoryBoardProfile name="RAM" boardProfile="current_e3_byte0" pcbRotation={rotation}/></board>);await circuit.renderUntilSettled();const json:any[]=circuit.getCircuitJson(),exits=json.filter(e=>e.type==='pcb_breakout_point');expect(exits).toHaveLength(72);for(const path of getDdrMemoryBoardPaths('current_e3_byte0')){const end=path.route.at(-1)!,sign=rotation===90?1:-1;expect(exits.filter(e=>e.layer===(end as any).layer&&Math.hypot(e.x+sign*Number(end.y),e.y-sign*Number(end.x))<1e-7)).toHaveLength(1)}expect(auditRouteAngles(json.filter(e=>e.type==='pcb_trace')).valid).toBe(true);expect(json.filter(e=>e.type.endsWith('_error'))).toEqual([])}
},30000)