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/sanitize-ddr-port-identities.ts

import {readFileSync,writeFileSync} from 'node:fs'

type Element=Record<string,any>
type EndpointField='start_pcb_port_id'|'end_pcb_port_id'
export interface DdrPortIdentityMismatch {
 pcbTraceId:string;pointIndex:number;field:EndpointField;portId:string
 reasons:string[];point:{x:number;y:number;layer:string|undefined}
 port:{x:number;y:number;layers:string[];sourcePortId?:string}|null
 sourceTraceId?:string
}
/** Remove only invalid inferred route-point port annotations. Physical copper,
 * trace ownership, and source connectivity are never edited or inferred here.
 * In particular, neither route annotations nor pcb_trace.connectsTo form unions.
 */
export function sanitizeDdrPortIdentities(original:readonly Element[],options:{coordinateToleranceMm?:number}={}) {
 const tolerance=options.coordinateToleranceMm??1e-6
 if(!Number.isFinite(tolerance)||tolerance<0)throw Error('Invalid coordinate tolerance')
 const parent=new Map<string,string>()
 const find=(id:string):string=>{const p=parent.get(id);if(!p){parent.set(id,id);return id}if(p===id)return id;const root=find(p);parent.set(id,root);return root}
 const join=(ids:unknown[])=>{const names=ids.filter((id):id is string=>typeof id==='string'&&id.length>0);for(const id of names)parent.set(find(id),find(names[0]!))}
 const sourcePorts=new Map(original.filter(e=>e.type==='source_port').map(e=>[e.source_port_id,e]))
 const sourceTraces=new Map(original.filter(e=>e.type==='source_trace').map(e=>[e.source_trace_id,e]))
 const ports=new Map(original.filter(e=>e.type==='pcb_port').map(e=>[e.pcb_port_id,e]))
 // Only explicit schematic membership is authoritative electrical evidence.
 for(const t of sourceTraces.values())join([t.source_trace_id,...t.connected_source_port_ids??[],...t.connected_source_net_ids??[]])
 for(const p of sourcePorts.values())if(p.source_net_id)join([p.source_port_id,p.source_net_id])
 for(const v of original)if(v.type==='source_manually_placed_via'&&v.source_net_id)join([v.source_net_id,...[...sourcePorts.values()].filter(p=>p.source_component_id===v.source_manually_placed_via_id).map(p=>p.source_port_id)])
 const circuit=structuredClone(original) as Element[],mismatches:DdrPortIdentityMismatch[]=[]
 let checkedAnnotations=0,preservedAnnotations=0
 for(const trace of circuit){if(trace.type!=='pcb_trace')continue
  for(const [pointIndex,p]of (trace.route??[]).entries())for(const field of ['start_pcb_port_id','end_pcb_port_id'] as const){
   if(p[field]===undefined)continue
   checkedAnnotations++
   const port=ports.get(p[field]),reasons:string[]=[]
   if(!port)reasons.push('unknown-pcb-port')
   else{
    if(![p.x,p.y,port.x,port.y].every((v:any)=>Number.isFinite(Number(v)))||Math.hypot(Number(p.x)-Number(port.x),Number(p.y)-Number(port.y))>tolerance)reasons.push('coordinate-mismatch')
    if(p.route_type!=='wire'||!Array.isArray(port.layers)||!port.layers.includes(p.layer))reasons.push('layer-mismatch')
    if(!sourceTraces.has(trace.source_trace_id))reasons.push('missing-explicit-source-trace')
    else if(!sourcePorts.has(port.source_port_id))reasons.push('missing-explicit-source-port')
    else if(find(trace.source_trace_id)!==find(port.source_port_id))reasons.push('source-net-mismatch')
   }
   if(!reasons.length){preservedAnnotations++;continue}
   mismatches.push({pcbTraceId:trace.pcb_trace_id,pointIndex,field,portId:p[field],reasons,point:{x:p.x,y:p.y,layer:p.layer},port:port?{x:port.x,y:port.y,layers:port.layers,sourcePortId:port.source_port_id}:null,sourceTraceId:trace.source_trace_id})
   delete p[field]
  }
 }
 return {circuit,report:{checkedAnnotations,preservedAnnotations,removedAnnotations:mismatches.length,coordinateToleranceMm:tolerance,mismatches,scope:'Only inferred start/end PCB port annotations removed; physical geometry and explicit source connectivity preserved.'}}
}
if(import.meta.main){
 const [input,output,reportPath]=process.argv.slice(2)
 if(!input||!output||!reportPath)throw Error('Usage: sanitize-ddr-port-identities.ts input.circuit.json sanitized.circuit.json report.json')
 if(input===output)throw Error('Use a separate sanitized output to retain the original capture')
 const {circuit,report}=sanitizeDdrPortIdentities(JSON.parse(readFileSync(input,'utf8')))
 writeFileSync(output,JSON.stringify(circuit,null,2)+'\n');writeFileSync(reportPath,JSON.stringify(report,null,2)+'\n')
 console.log(JSON.stringify({checked:report.checkedAnnotations,preserved:report.preservedAnnotations,removed:report.removedAnnotations}))
}