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-system-copper.test.ts
import {test,expect}from'bun:test'
import {verifyDdrSystemCopper}from'../scripts/check-ddr-system-copper'
const wire=(x:number,y:number)=>({route_type:'wire',x,y,layer:'top',width:.1016})
function fixture(){const original:any[]=[{type:'source_trace',source_trace_id:'net',connected_source_port_ids:['a','b']}];for(const [i,x]of [0,4].entries()){original.push({type:'pcb_port',pcb_port_id:`p${i}`,source_port_id:i?'b':'a',x,y:0,layers:['top']},{type:'pcb_smtpad',pcb_smtpad_id:`pad${i}`,pcb_port_id:`p${i}`,shape:'circle',x,y:0,radius:.2,layer:'top'},{type:'pcb_breakout_point',pcb_breakout_point_id:`e${i}`,source_port_id:i?'b':'a',source_trace_id:'net',x:x+(i?-1:1),y:0,layer:'top'},{type:'pcb_trace',pcb_trace_id:`t${i}`,source_trace_id:'net',route:[wire(x,0),wire(x+(i?-1:1),0)]})}return {original,connections:[{name:'net',pointsToConnect:[{pointId:'e0'},{pointId:'e1'}]}]}}
test('full pad chains must connect, not only nominal endpoint identities',()=>{const {original,connections}=fixture();const missing=verifyDdrSystemCopper(original,[],connections,{},1);expect(missing.valid).toBe(false);expect(missing.connectivity[0]!.connected).toBe(false);const joined=verifyDdrSystemCopper(original,[{pcb_trace_id:'host',connection_name:'net',route:[wire(1,0),wire(3,0)]}],connections,{},1);expect(joined.valid).toBe(true);expect(verifyDdrSystemCopper(original,[],connections).valid).toBe(false)})
test('foreign copper and bends at saved lead joins are rejected',()=>{const {original,connections}=fixture();original.push({type:'pcb_smtpad',pcb_smtpad_id:'foreign',shape:'circle',x:2,y:.22,radius:.1,layer:'top'});const r=verifyDdrSystemCopper(original,[{pcb_trace_id:'host',connection_name:'net',route:[wire(1,0),wire(3,0)]}],connections,{},1);expect(r.violations.length).toBeGreaterThan(0);const bend=verifyDdrSystemCopper(fixture().original,[{pcb_trace_id:'host',connection_name:'net',route:[wire(1,0),wire(1,1)]}],connections,{},1);expect(bend.joinedBends.length).toBeGreaterThan(0)})
test('Y splits admit a 45-degree incoming direction while T splits do not',()=>{
const {original,connections}=fixture()
const y=[{pcb_trace_id:'y1',connection_name:'net',route:[wire(1,0),wire(2,1)]},{pcb_trace_id:'y2',connection_name:'net',route:[wire(1,0),wire(2,-1)]}]
expect(verifyDdrSystemCopper(original,y,connections,{},1).joinedBends).toEqual([])
const t=[{pcb_trace_id:'t1',connection_name:'net',route:[wire(1,0),wire(1,1)]},{pcb_trace_id:'t2',connection_name:'net',route:[wire(1,0),wire(1,-1)]}]
expect(verifyDdrSystemCopper(original,t,connections,{},1).joinedBends).toHaveLength(1)
})
test('only a coincident same-net via terminates the planar junction rule',()=>{
const {original,connections}=fixture(),host=[{pcb_trace_id:'turn',connection_name:'net',route:[wire(1,0),wire(1,1)]}]
const via={type:'pcb_via',pcb_via_id:'v',source_trace_id:'net',x:1,y:0,outer_diameter:.4572,layers:['top','inner1']}
expect(verifyDdrSystemCopper([...original,via],host,connections,{},1).joinedBends).toHaveLength(0)
expect(verifyDdrSystemCopper([...original,{...via,x:1.01}],host,connections,{},1).joinedBends).toHaveLength(1)
})
test('new signals cannot use reference layers',()=>{
const {original,connections}=fixture()
const report=verifyDdrSystemCopper(original,[{pcb_trace_id:'forbidden',connection_name:'net',route:[{...wire(1,0),layer:'inner1'},{...wire(3,0),layer:'inner1'}]}],connections,{},1)
expect(report.valid).toBe(false)
expect(report.errors).toContain('New signal on forbidden layer inner1')
})
test('spatial sweep is identical to brute force for mixed pads, barrels, crossings and disconnected nets',()=>{
let seed=7193
const random=()=>((seed=(Math.imul(seed,1664525)+1013904223)>>>0)/4294967296)
for(let trial=0;trial<12;trial++){
const {original,connections}=fixture(),fresh:any[]=[]
for(let i=0;i<36;i++){
const x=(random()-.5)*30,y=(random()-.5)*30,layer=i%3?'top':'inner2',source_trace_id=i%5?'foreign'+i:'net'
original.push(i%2?{type:'pcb_smtpad',pcb_smtpad_id:`r${i}`,source_trace_id,shape:'rect',x,y,width:.1+random()*3,height:.1+random()*3,layer,ccw_rotation:i%4?0:90}:{type:'pcb_via',pcb_via_id:`v${i}`,source_trace_id,x,y,outer_diameter:.2+random()*2,layers:['top','inner2']})
fresh.push({pcb_trace_id:`h${i}`,connection_name:i%4?'net':'foreign'+i,route:[{...wire(x,y),layer},{...wire(x+random()*8,y),layer}]})
}
expect(verifyDdrSystemCopper(original,fresh,connections,{},1)).toEqual(verifyDdrSystemCopper(original,fresh,connections,{},1,{pairSearch:'brute-force'}))
}
})
test('spatial sweep preserves exact minimum clearance beyond the collision threshold',()=>{
const {original,connections}=fixture()
original.push({type:'pcb_smtpad',pcb_smtpad_id:'far',shape:'rect',x:2,y:40,width:1,height:1,layer:'top'})
const host=[{pcb_trace_id:'host',connection_name:'net',route:[wire(1,0),wire(3,0)]}]
const report=verifyDdrSystemCopper(original,host,connections,{},1)
expect(report.minClearanceMm).toBeGreaterThan(30)
expect(report).toEqual(verifyDdrSystemCopper(original,host,connections,{},1,{pairSearch:'brute-force'}))
expect(verifyDdrSystemCopper(fixture().original,[],connections,{},1)).toEqual(verifyDdrSystemCopper(fixture().original,[],connections,{},1,{pairSearch:'brute-force'}))
})
test('via lookup preserves exact coincidence tolerance across bucket boundaries',()=>{
const {original,connections}=fixture(),host=[{pcb_trace_id:'turn',connection_name:'net',route:[wire(1,0),wire(1,1)]}]
const via={type:'pcb_via',pcb_via_id:'near',source_trace_id:'net',x:1-0.5e-6,y:-0.5e-6,outer_diameter:.4572,layers:['top']}
expect(verifyDdrSystemCopper([...original,via],host,connections,{},1).joinedBends).toHaveLength(0)
expect(verifyDdrSystemCopper([...original,{...via,x:1-0.9e-6,y:-0.9e-6}],host,connections,{},1).joinedBends).toHaveLength(1)
expect(verifyDdrSystemCopper([...original,{...via,source_trace_id:'foreign'}],host,connections,{},1).joinedBends).toHaveLength(1)
})
const square=(left:number,bottom:number,right:number,top:number)=>({vertices:[{x:left,y:bottom},{x:right,y:bottom},{x:right,y:top},{x:left,y:top}]})
function holedPour(layer='inner1',source_net_id='GND'){
return {type:'pcb_copper_pour',pcb_copper_pour_id:'pour',shape:'brep',layer,source_net_id,brep_shape:{outer_ring:square(-2,-2,2,2),inner_rings:[square(-.5,-.5,.5,.5)]}}
}
const holeVia=(x:number,y=0)=>({pcb_trace_id:'host-via',connection_name:'signal',route:[{route_type:'via',x,y,from_layer:'top',to_layer:'inner2',via_diameter:.4572,via_hole_diameter:.254}]})
test('full barrel checks exact pour holes, copper edges and filled regions',()=>{
const clear=verifyDdrSystemCopper([holedPour()],[holeVia(0)],[],{},0)
expect(clear.errors).toEqual([])
expect(clear.violations).toEqual([])
expect(clear.minClearanceMm).toBeCloseTo(.5-.4572/2,8)
const near=verifyDdrSystemCopper([holedPour()],[holeVia(.2)],[],{},0)
expect(near.violations).toHaveLength(1)
expect(near.violations[0].layer).toBe('inner1')
const deeper=verifyDdrSystemCopper([holedPour('inner5')],[holeVia(.2)],[],{},0)
expect(deeper.violations[0].layer).toBe('inner5') // Through barrel continues past logical inner2 exit.
expect(near.minClearanceMm).toBeCloseTo(.5-.2-.4572/2,8)
const copper=verifyDdrSystemCopper([holedPour()],[holeVia(1)],[],{},0)
expect(copper.violations).toHaveLength(1)
const outside=verifyDdrSystemCopper([holedPour()],[holeVia(3)],[],{},0)
expect(outside.violations).toEqual([])
expect(outside.minClearanceMm).toBeCloseTo(1-.4572/2,8)
})
test('new track inside a hole is clear while a track crossing the filled annulus fails',()=>{
const host=(a:number,b:number)=>[{pcb_trace_id:'host',connection_name:'signal',route:[wire(a,0),wire(b,0)]}]
const hole=verifyDdrSystemCopper([holedPour('top')],host(-.2,.2),[],{},0)
expect(hole.violations).toEqual([])
expect(hole.minClearanceMm).toBeCloseTo(.3-.1016/2,8)
expect(verifyDdrSystemCopper([holedPour('top')],host(-3,3),[],{},0).violations).toHaveLength(1)
})
test('same-net pour joins real pads through filled copper but not pads isolated inside its hole',()=>{
const original:any[]=[{type:'source_trace',source_trace_id:'net',connected_source_net_ids:['GND'],connected_source_port_ids:['a','b']},holedPour()]
for(const [i,x]of [-1.5,1.5].entries())original.push({type:'pcb_port',pcb_port_id:`p${i}`,source_port_id:i?'b':'a'},
{type:'pcb_smtpad',pcb_smtpad_id:`pad${i}`,pcb_port_id:`p${i}`,shape:'rect',x,y:0,width:.1,height:.1,layer:'inner1'})
const connections=[{name:'net',pointsToConnect:[{pointId:'p0'},{pointId:'p1'}]}]
expect(verifyDdrSystemCopper(original,[],connections,{},1).connectivity[0]!.connected).toBe(true)
const isolated=structuredClone(original);isolated.find(e=>e.pcb_smtpad_id==='pad1')!.x=0
expect(verifyDdrSystemCopper(isolated,[],connections,{},1).connectivity[0]!.connected).toBe(false)
})
test('nonconvex pour outer boundary is not replaced by its bounding box',()=>{
const pour=holedPour('top');pour.brep_shape={outer_ring:{vertices:[{x:0,y:0},{x:2,y:0},{x:2,y:1},{x:1,y:1},{x:1,y:2},{x:0,y:2}]},inner_rings:[]}
const report=verifyDdrSystemCopper([pour],[{pcb_trace_id:'host',connection_name:'signal',route:[wire(1.5,1.5),wire(1.8,1.5)]}],[],{},0)
expect(report.errors).toEqual([])
expect(report.violations).toEqual([])
expect(report.minClearanceMm).toBeCloseTo(.5-.1016/2,8)
})
test('pour representation, degenerate rings and overlapping holes fail closed',()=>{
for(const pour of [{...holedPour(),shape:'rect'}, {...holedPour(),brep_shape:{outer_ring:{vertices:[{x:0,y:0},{x:1,y:1}]},inner_rings:[]}}, {...holedPour(),brep_shape:{outer_ring:square(-2,-2,2,2),inner_rings:[square(-.5,-.5,.5,.5),square(0,0,1,1)]}}]){
expect(verifyDdrSystemCopper([pour],[],[],{},0).errors.length).toBeGreaterThan(0)
}
})
test('pour-hole sweep and brute force produce identical connectivity and clearance reports',()=>{
const pours=[holedPour(),{...holedPour('inner2','other'),pcb_copper_pour_id:'p2'}]
const traces=[holeVia(0),{...holeVia(.2),pcb_trace_id:'near',connection_name:'other'}, {...holeVia(3),pcb_trace_id:'far'}]
expect(verifyDdrSystemCopper(pours,traces,[],{},0)).toEqual(verifyDdrSystemCopper(pours,traces,[],{},0,{pairSearch:'brute-force'}))
})
test('rendered via inherits only a geometrically verified explicit parent trace owner',()=>{
const {original,connections}=fixture(),inline={route_type:'via',x:1,y:0,from_layer:'top',to_layer:'inner2',via_diameter:.4572,via_hole_diameter:.254}
original.find(e=>e.pcb_trace_id==='t0').route.push(inline)
const via={type:'pcb_via',pcb_via_id:'owned',pcb_trace_id:'t0',x:1,y:0,outer_diameter:.4572,hole_diameter:.254,layers:['top','inner2']},host=[{pcb_trace_id:'host',connection_name:'net',route:[wire(1,0),wire(3,0)]}]
const check=(v:any,aliases:Record<string,string>={})=>verifyDdrSystemCopper([...original,v],host,connections,aliases,1)
expect(check(via).valid).toBe(true)
for(const invalid of[{...via,x:1.01},{...via,outer_diameter:.5},{...via,hole_diameter:.2}]){
expect(check(invalid).valid).toBe(false)
expect(check(invalid).errors.some(e=>e.includes('Unverified via parent ownership'))).toBe(true)
}
expect(check({...via,pcb_trace_id:'invented'},{invented:'net'}).errors.some(e=>e.includes('Unverified via parent ownership'))).toBe(true)
expect(check({...via,source_net_id:'foreign'}).errors.some(e=>e.includes('Conflicting explicit via ownership'))).toBe(true)
})