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-dq4-current.ts

/** Small existing-template DQ4 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-dq4-retuned-current'),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=prior.strobePair.meanMm,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_579'),connection=input.connections.find((c:any)=>c.name==='source_trace_579'),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.accepted||prior.candidateCircuitSha256!==objectHash(parent)||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 DQ4host with one retained 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-20.148239586)>1e-6||delta<=0)throw Error('Actual DQ4 length differs')
const c=Math.SQRT1_2,rotate=(p:any)=>({...p,x:(p.x+p.y)*c,y:(p.y-p.x)*c}),unrotate=(p:any)=>({...p,x:(p.x-p.y)*c,y:(p.x+p.y)*c}),rotated={...before,route:[...before.route].reverse().map(rotate)},attempts:any[]=[],started=Date.now();let accepted:any=null
search:for(const entry of[-3.2,-4,-5])for(const exit of[-8,-9])for(const sign of[-1,1]){
 if(Date.now()-started>55000)break
 let detour:any;try{detour=addWestwardTuningExcursion(rotated,7,entry,exit,delta,sign,.1)}catch{continue}
 const after={...before,route:[...detour.route].reverse().map((p:any)=>{const original=before.route.find((q:any)=>{const r=rotate(q);return r.route_type===p.route_type&&r.layer===p.layer&&r.from_layer===p.from_layer&&r.to_layer===p.to_layer&&Math.hypot(r.x-p.x,r.y-p.y)<1e-8});return original??unrotate(p)})},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,violationDetails:r.violations,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,rotationDegrees:-45,bevelMm:.1}};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 DQ4 inner2 diagonal run; preserve existing through 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:'One DQ4 host retuned, all other retained 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}))