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-dq1.ts
/** Small existing-template DQ1 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-twelve-dq1-connected'),out=resolve(process.argv[3]??'dist/ddr-dq1-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=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_576'),connection=input.connections.find((c:any)=>c.name==='source_trace_576'),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 DQ1host 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-27.373442852116924)>1e-6||delta<=0)throw Error('Actual DQ1 length differs')
const rotated={...before,route:[...before.route].reverse()},attempts:any[]=[],started=Date.now();let accepted:any=null
search:for(const entry of[.95,.9])for(const exit of[.55,.6])for(const sign of[-1,1]){
if(Date.now()-started>55000)break
let detour:any;try{detour=addWestwardTuningExcursion(rotated,7,entry,exit,delta,sign,.05)}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:.05}};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 DQ1 inner4 horizontal 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:'OneDQ1host retuned, all other11hosts/sourcecopper 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}))