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/ddr-terminal-copper-obstacles.ts
/** Keep same-net escape copper blocked outside a short, explicitly bounded terminal join. */
import { supportCopperObstacles } from './ddr-support-routing-context'
type P={x:number;y:number;layer:string;pointId:string}
export function trimProjectionAtTerminal(trace:any,p:P,allowanceMm=.25){
if(!Number.isFinite(allowanceMm)||allowanceMm<=0||allowanceMm>.25)throw Error('Invalid terminal allowance')
const copy=structuredClone(trace),route=copy.route
const matches=(q:any)=>q?.route_type==='wire'&&q.layer===p.layer&&Math.hypot(q.x-p.x,q.y-p.y)<1e-7
if(!matches(route.at(-1)))throw Error('Expected actual saved escape endpoint')
let remaining=allowanceMm
while(route.length>1){const b=route.at(-1),a=route.at(-2);if(a.route_type!=='wire'||a.layer!==p.layer)throw Error('Terminal allowance would expose an original via or another layer')
const distance=Math.hypot(b.x-a.x,b.y-a.y)
if(distance<=remaining+1e-9){route.pop();remaining-=distance;if(remaining<1e-9)break}
else{const fraction=(distance-remaining)/distance;route[route.length-1]={...b,x:a.x+(b.x-a.x)*fraction,y:a.y+(b.y-a.y)*fraction};remaining=0;break}
}
if(remaining>1e-9)throw Error('Saved copper shorter than terminal allowance')
return copy
}
export function terminalOnlyFixedObstacles(fixed:any[],connection:any){
const terminals:P[]=connection.pointsToConnect
if(terminals.length!==2)throw Error('Terminal-only projection requires a two-terminal host signal')
const clipped=new Map<string,any>(),witnesses:any[]=[]
for(const p of terminals){
const exit=fixed.find(e=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===p.pointId)
if(!exit||exit.layer!==p.layer||Math.hypot(exit.x-p.x,exit.y-p.y)>1e-7)throw Error('Missing authoritative terminal')
const matches=fixed.filter(e=>e.type==='pcb_trace'&&e.source_trace_id===exit.source_trace_id&&e.route.at(-1)?.route_type==='wire'&&e.route.at(-1).layer===p.layer&&Math.hypot(e.route.at(-1).x-p.x,e.route.at(-1).y-p.y)<1e-7)
if(matches.length!==1||clipped.has(matches[0].pcb_trace_id))throw Error('Ambiguous saved endpoint copper')
const trace=matches[0],projected=trimProjectionAtTerminal(trace,p);clipped.set(trace.pcb_trace_id,projected);witnesses.push({pointId:p.pointId,traceId:trace.pcb_trace_id,allowanceMm:.25,actualEndpoint:p,projectedEndpoint:projected.route.at(-1)})
}
const obstacles=fixed.filter(e=>['pcb_trace','pcb_via','pcb_smtpad'].includes(e.type)).flatMap(original=>{
const e=clipped.get(original.pcb_trace_id)??original
return supportCopperObstacles([e]).map(o=>({...o,...((e.type==='pcb_smtpad'&&e.shape==='circle')||e.type==='pcb_via'||o.obstacleId.startsWith('fixed_via_')||o.obstacleId.endsWith('_cap')?{shape:'circle'}:{}),connectedTo:[`reserved:${e[`${e.type}_id`]}`]}))
})
// These selectors identify the solver launch; only this tiny endpoint cap is net-exempt.
for(const p of terminals)obstacles.push({type:'rect',shape:'circle',obstacleId:`terminal:${p.pointId}`,center:{x:p.x,y:p.y},width:.12,height:.12,layers:[p.layer],connectedTo:[connection.name]} as any)
return{obstacles,witnesses,scope:'Routing projection only: unchanged physical copper is checked independently. Every fixed conductor is reserved, including same-net saved paths; only the final0.25mm of each actual escape is omitted for its terminal join.'}
}