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/retune-ddr-dq2.ts

/** Small existing-template DQ2 tuning with retained transition via. */
import{readFileSync,writeFileSync,mkdirSync}from'node:fs'
import{resolve}from'node:path'
import{createHash}from'node:crypto'
import{addWestwardTuningExcursion}from'./tune-ddr-data-mask'
import{objectHash,validateDeclaredDdrReplacements}from'./improve-ddr-a9-power-launches'
import{verifyDdrSystemCopper,auditDdrTraceJunctions}from'./check-ddr-system-copper'
import{auditCompositeHostTopology}from'./ddr-composite-routing-context'
import{auditHostSelfContacts}from'./audit-ddr-host-self-contacts'
import{auditRouteAngles}from'./check-route-angles'
import{checkHostTerminalContract}from'./route-ddr-sequential'
const dir=resolve(process.argv[2]??'dist/ddr-fifteen-reference-repaired'),out=resolve(process.argv[3]??'dist/ddr-dq2-retuned'),hashes=new Map<string,string>(),fh=(p:string)=>createHash('sha256').update(readFileSync(p)).digest('hex'),read=(p:string)=>{hashes.set(p,fh(p));return JSON.parse(readFileSync(p,'utf8'))},parent=read(`${dir}/candidate.circuit.json`),prior=read(`${dir}/report.json`),target=28.42315800048918,host=read(`${dir}/host-bundle.json`),input=read(`${dir}/routing-input.json`),before=parent.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id==='source_trace_577'),connection=input.connections.find((c:any)=>c.name==='source_trace_577'),planar=(r:any[])=>r.slice(1).reduce((n,p,i)=>n+(p.route_type==='wire'&&r[i].route_type==='wire'&&p.layer===r[i].layer?Math.hypot(p.x-r[i].x,p.y-r[i].y):0),0)
if(prior.captureHash!==host.captureHash||before.route.filter((p:any)=>p.route_type==='via').length!==1||objectHash(before)!==objectHash(host.traces.find((t:any)=>t.pcb_trace_id===before.pcb_trace_id)))throw Error('Expected exact DQ2host with one host via')
const fixedWitnesses=connection.pointsToConnect.map((p:any)=>{const exit=parent.find((e:any)=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===p.pointId),ts=parent.filter((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===exit?.source_trace_id&&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(ts.length!==1)throw Error('Expected unique actual CPU/RAM escape');return{exit,trace:ts[0],planarMm:planar(ts[0].route)}}),fixedMm=fixedWitnesses.reduce((n:number,w:any)=>n+w.planarMm,0),beforeMm=fixedMm+planar(before.route),delta=target-beforeMm
const actualStrobeLengths=['source_trace_564','source_trace_565'].map(name=>{const t=host.traces.find((t:any)=>t.connection_name===name),c=input.connections.find((c:any)=>c.name===name);return planar(t.route)+c.pointsToConnect.reduce((n:number,p:any)=>{const exit=parent.find((e:any)=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===p.pointId),saved=parent.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===exit?.source_trace_id&&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(!saved)throw Error('Missing actual strobe escape');return n+planar(saved.route)},0)}),actualStrobeMean=actualStrobeLengths.reduce((a,b)=>a+b,0)/2
if(!Number.isFinite(target)||Math.abs(actualStrobeMean-target)>1e-7)throw Error('Strobe target differs from actual copper')
if(Math.abs(beforeMm-24.496948698132)>1e-6||delta<=0)throw Error('Actual DQ2 length differs')
const rotated={...before,route:[...before.route].reverse()},attempts:any[]=[],started=Date.now();let accepted:any=null
search:for(const entry of[-2.95,-3])for(const exit of[-3.95,-3.9])for(const sign of[-1,1]){
 if(Date.now()-started>55000)break
 let detour:any;try{detour=addWestwardTuningExcursion(rotated,4,entry,exit,delta,sign,.2)}catch{continue}
 const after={...before,route:[...detour.route].reverse()},fixed=parent.filter((e:any)=>e.type!=='pcb_trace'||e.pcb_trace_id!==before.pcb_trace_id),r=verifyDdrSystemCopper(fixed,[after],[],{},0),self=auditHostSelfContacts([after]),clean=!r.errors.length&&!r.violations.length&&r.angles.valid&&!r.joinedBends.length&&self.valid
 attempts.push({entry,exit,sign,clean,errors:r.errors,violations:r.violations.length,selfContacts:self.contacts.length})
 if(!clean)continue
 const candidate=parent.map((e:any)=>e===before?after:e),traces=host.traces.map((t:any)=>t.pcb_trace_id===before.pcb_trace_id?after:t),topology=auditCompositeHostTopology(candidate,traces,input.connections),selfContacts=auditHostSelfContacts(traces),allAngles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace')),allJunctions=auditDdrTraceJunctions(candidate,input.connections),terminal=checkHostTerminalContract(traces,input.connections.filter((c:any)=>traces.some((t:any)=>t.connection_name===c.name))),measuredMm=fixedMm+planar(after.route)
 if(!topology.valid||!selfContacts.valid||!allAngles.valid||!allJunctions.valid||!terminal.valid)continue
 if(Math.abs(measuredMm-target)>1e-7||objectHash(after.route[0])!==objectHash(before.route[0])||objectHash(after.route.at(-1))!==objectHash(before.route.at(-1))||objectHash(after.route.filter((p:any)=>p.route_type==='via'))!==objectHash(before.route.filter((p:any)=>p.route_type==='via'))||after.route.filter((p:any)=>p.route_type==='wire').some((p:any)=>p.width!==.12))throw Error('Template changed actual endpoints/vias/width or target')
 accepted={candidate,traces,after,measuredMm,topology,selfContacts,allAngles,allJunctions,terminal,recipe:{entry,exit,sign,addedMm:delta,reversedForWestwardHelper:true,bevelMm:.2}};break search
}
mkdirSync(out,{recursive:true});const write=(n:string,v:any)=>writeFileSync(`${out}/${n}`,JSON.stringify(v,null,2));for(const[p,h]of hashes)if(fh(p)!==h)throw Error('Parent inputs changed')
if(accepted){const manifest={captureHash:host.captureHash,parentDirectory:dir,parentCircuitSha256:objectHash(parent),candidateCircuitSha256:objectHash(accepted.candidate),inputHashes:Object.fromEntries(hashes),fixedWitnesses,replacements:[{id:`pcb_trace:${before.pcb_trace_id}`,before,after:accepted.after,beforeSha256:objectHash(before),afterSha256:objectHash(accepted.after),reason:'Existing45degree excursion on DQ2 top horizontal run; preserve the existing host via and actual endpoints.'}]},preservation=validateDeclaredDdrReplacements(parent,accepted.candidate,manifest);write('candidate.circuit.json',accepted.candidate);write('host-bundle.json',{...host,traces:accepted.traces});write('original-copper-replacements.json',manifest);write('report.json',{captureHash:host.captureHash,accepted:true,beforeMm,actualStrobeLengths,actualStrobeMean,targetMm:target,measuredMm:accepted.measuredMm,attempts,recipe:accepted.recipe,preservation,topology:accepted.topology,selfContacts:accepted.selfContacts,allAngles:accepted.allAngles,allJunctions:accepted.allJunctions,terminal:accepted.terminal,scope:'OneDQ2host retuned, all other hosts/source copper exact. Planar matching only; viadelay/SI/fullbyte completeness remainunqualified.'})}else write('report.json',{accepted:false,attempts,inputHashes:Object.fromEntries(hashes)})
console.log(JSON.stringify({accepted:Boolean(accepted),attempts:attempts.length,beforeMm,targetMm:target,measuredMm:accepted?.measuredMm,candidateHash:accepted?objectHash(accepted.candidate):null}))