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/assemble-ddr-current-tuning.ts

/** Combine exact host-only timing proposals against one frozen current board. */
import{readFileSync,writeFileSync,mkdirSync,existsSync}from'node:fs'
import{resolve}from'node:path'
import{createHash}from'node:crypto'
import{verifyDdrCapture}from'./ddr-capture-provenance'
import{objectHash,validateDeclaredDdrReplacements}from'./improve-ddr-a9-power-launches'
import{auditCompositeHostTopology}from'./ddr-composite-routing-context'
import{auditRouteAngles}from'./check-route-angles'
import{auditDdrTraceJunctions}from'./check-ddr-system-copper'
import{checkHostTerminalContract}from'./route-ddr-sequential'
const[capture,parentDir,out,...trialDirs]=process.argv.slice(2);if(!out||!trialDirs.length)throw Error('Usage: capture parent output trial [trial...]')
if([parentDir,...trialDirs].some(d=>resolve(d)===resolve(out)))throw Error('Isolated output required')
const hashes:Record<string,string>={},fh=(p:string)=>createHash('sha256').update(readFileSync(p)).digest('hex'),read=(p:string)=>{p=resolve(p);hashes[p]=fh(p);return JSON.parse(readFileSync(p,'utf8'))}
const{captureHash}=verifyDdrCapture(capture),parent=read(resolve(parentDir,'candidate.circuit.json')),prior=read(resolve(parentDir,'report.json')),parentHost=read(resolve(parentDir,'host-bundle.json')),input=read(resolve(parentDir,'routing-input.json')),nominal=read(resolve(capture,'../../ddr-integrated-ten/dqlm-audit.json'))
if([prior,parentHost,nominal].some(x=>x.captureHash!==captureHash)||parentHost.layerSpace!=='physical'||prior.candidateCircuitSha256!==objectHash(parent))throw Error('Parent provenance mismatch')
const changes:any[]=[],evidence:any[]=[]
for(const dir of trialDirs){const manifest=read(resolve(dir,'original-copper-replacements.json')),report=read(resolve(dir,'report.json')),candidate=read(resolve(dir,'candidate.circuit.json')),host=read(resolve(dir,'host-bundle.json'));if(!report.accepted||manifest.captureHash!==captureHash||report.captureHash!==captureHash)throw Error('Timing trial provenance differs');const sameParent=manifest.parentCircuitSha256===objectHash(parent),trialParent=sameParent?parent:read(resolve(manifest.parentDirectory,'candidate.circuit.json')),trialParentHost=sameParent?parentHost:read(resolve(manifest.parentDirectory,'host-bundle.json'));if(objectHash(trialParent)!==manifest.parentCircuitSha256||trialParentHost.captureHash!==captureHash)throw Error('Source trial parent changed');validateDeclaredDdrReplacements(trialParent,candidate,manifest)
 for(const[p,h]of Object.entries(manifest.inputHashes??{})){if(fh(p)!==h)throw Error('Trial input changed');hashes[p]=h as string}
 for(const change of manifest.replacements){const before=parentHost.traces.find((t:any)=>t.pcb_trace_id===change.before.pcb_trace_id),{route:old,...om}=change.before,{route:next,...nm}=change.after;if(!before||objectHash(before)!==objectHash(change.before)||objectHash(om)!==objectHash(nm)||objectHash(old[0])!==objectHash(next[0])||objectHash(old.at(-1))!==objectHash(next.at(-1))||objectHash(old.filter((p:any)=>p.route_type==='via'))!==objectHash(next.filter((p:any)=>p.route_type==='via'))||next.filter((p:any)=>p.route_type==='wire').some((p:any)=>p.width!==.12)||changes.some(c=>c.before.pcb_trace_id===before.pcb_trace_id))throw Error('Invalid or duplicate host-only timing change');changes.push(change)}
 const expected={...trialParentHost,traces:trialParentHost.traces.map((t:any)=>manifest.replacements.find((c:any)=>c.before.pcb_trace_id===t.pcb_trace_id)?.after??t)};if(objectHash(expected)!==objectHash(host))throw Error('Trial host bundle mismatch');evidence.push({directory:resolve(dir),manifestSha256:objectHash(manifest),rebasedOntoCurrentParent:!sameParent,sourceParentSha256:objectHash(trialParent),report})
}
if(!changes.length)throw Error('Empty timing proposal')
const replay=(xs:any[])=>xs.map((e:any)=>e.type==='pcb_trace'?changes.find(c=>c.before.pcb_trace_id===e.pcb_trace_id)?.after??e:e),candidate=replay(parent),host={...parentHost,traces:replay(parentHost.traces)},planar=(r:any[])=>r.reduce((n:number,p:any,i:number)=>{const q=r[i-1];return n+(p.route_type==='wire'&&q?.route_type==='wire'&&p.layer===q.layer?Math.hypot(p.x-q.x,p.y-q.y):0)},0)
const full=(name:string)=>{const t=host.traces.find((t:any)=>t.connection_name===name),c=input.connections.find((c:any)=>c.name===name);if(!t||!c)throw Error('Missing actual host');return planar(t.route)+c.pointsToConnect.reduce((n:number,p:any)=>{const exit=candidate.find((e:any)=>e.pcb_breakout_point_id===p.pointId),saved=candidate.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(saved.length!==1)throw Error('Ambiguous saved escape');return n+planar(saved[0].route)},0)}
const timing=changes.map(change=>{const c=input.connections.find((c:any)=>c.name===change.after.connection_name);if(!c||!/^DQ[0-7]$|^DM$/.test(c.ramTerminal)||![0,1].includes(c.ramByte))throw Error('Only byte data/mask tuning supported');const pair=input.connections.filter((p:any)=>p.ramByte===c.ramByte&&['DQS_P','DQS_N'].includes(p.ramTerminal));if(pair.length!==2)throw Error('Missing strobe pair');const strobeLengths=pair.map((p:any)=>full(p.name)),targetMm=strobeLengths.reduce((a:number,b:number)=>a+b,0)/2,measuredMm=full(c.name),nominalMm=nominal.bytes.find((b:any)=>b.byte===c.ramByte).dqlmPairedDataMaximumMm;if(Math.abs(measuredMm-targetMm)>1e-7||[measuredMm,...strobeLengths].some(n=>!Number.isFinite(n)||n>nominalMm+1e-7))throw Error('Actual timing target/nominal failure');return{name:c.name,byte:c.ramByte,terminal:c.ramTerminal,measuredMm,targetMm,nominalMm,strobeLengths}})
const topology=auditCompositeHostTopology(candidate,host.traces,input.connections),angles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace')),junctions=auditDdrTraceJunctions(candidate,input.connections),terminal=checkHostTerminalContract(host.traces,input.connections.filter((c:any)=>host.traces.some((t:any)=>t.connection_name===c.name)))
if(!topology.valid||!angles.valid||!junctions.valid||!terminal.valid||topology.physical.connectivity.filter((c:any)=>c.connected).length!==host.traces.length)throw Error('Combined timing physical gates failed')
const copied:Record<string,any>={};for(const n of['ram-byte0-facing-progress.trace-paths.json','ram-byte1-facing-progress.trace-paths.json','exit-contract.json','ram-byte1-exit-contract.json'])if(existsSync(resolve(parentDir,n))){copied[n]=read(resolve(parentDir,n));if(n.includes('contract'))copied[n]={...copied[n],candidateCircuitSha256:objectHash(candidate)}}
const manifest={captureHash,parentDirectory:resolve(parentDir),parentCircuitSha256:objectHash(parent),candidateCircuitSha256:objectHash(candidate),replacements:changes,allOtherElementsExact:true,inputHashes:hashes},report={...prior,accepted:true,candidateCircuitSha256:objectHash(candidate),supportCircuitSha256:objectHash(candidate),hostTracesSha256:objectHash(host.traces),hostBundleSha256:objectHash(host),originalCopperReplacementsSha256:objectHash(manifest),currentTuningEvidence:timing,physical:topology.physical,topology,fullCandidateAngles:angles,fixedJunctionAudit:junctions,terminalContract:terminal,inputFileHashes:hashes,scope:'Host-only planar matching to actual byte strobe means. Remaining signals, unmatched data, power launches, reference transitions and full electrical qualification are incomplete.'}
const unchanged=()=>{verifyDdrCapture(capture);for(const[p,h]of Object.entries(hashes))if(fh(p)!==h)throw Error('Assembly input changed')};unchanged();mkdirSync(out,{recursive:true});const write=(n:string,v:any)=>writeFileSync(resolve(out,n),JSON.stringify(v,null,2)+'\n');write('candidate.circuit.json',candidate);write('host-bundle.json',host);write('routing-input.json',{...input,traces:host.traces,obstacles:undefined});write('original-copper-replacements.json',manifest);write('source-provenance.json',{captureHash,inputHashes:hashes,evidence});write('report.json',report);for(const[n,v]of Object.entries(copied))write(n,v)
for(const script of['audit-ddr-global-power-launches.ts','audit-ddr-host-reference-coverage.ts']){const p=Bun.spawn(['bun',`scripts/${script}`,resolve(out),resolve(capture)],{stdout:'inherit',stderr:'inherit'});if(await p.exited!==0)throw Error(`Failed ${script}`)}
const power=JSON.parse(readFileSync(resolve(out,'ram-power-launch-audit.json'),'utf8')),reference=JSON.parse(readFileSync(resolve(out,'host-reference-coverage.json'),'utf8'));if(power.launchQualified!==56||power.total!==60)throw Error('Power regression');unchanged();write('report.json',{...report,launchAuditSha256:objectHash(power),hostReferenceCoverageSha256:objectHash(reference),launchQualified:56});console.log(JSON.stringify({out,hosts:host.traces.length,timing,candidateHash:objectHash(candidate)}))