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/export-ddr-d13-facing-cache.ts

/** Transplant one witnessed local D3 escape onto the replayed eleven-host board. */
import {readFileSync,writeFileSync,mkdirSync,copyFileSync} from 'node:fs'
import {resolve} from 'node:path'
import {createHash} from 'node:crypto'
import {fanoutTracePath} from '@tscircuit/props'
import {auditCompositeHostTopology} from './ddr-composite-routing-context'
import {verifyDdrCapture} from './ddr-capture-provenance'
import {applyFacingExitReplacements} from './ddr-facing-context'
import {objectHash} from './improve-ddr-a9-power-launches'
import {auditDdrLocalEscapeContacts} from './audit-ddr-local-escape-contacts'
import {verifyDdrSystemCopper,auditDdrTraceJunctions} from './check-ddr-system-copper'
import {auditRouteAngles} from './check-route-angles'
const [capture,parentDir,trialDir,out,signal='DDR_D13']=process.argv.slice(2)
if(!['DDR_D13','DDR_D15'].includes(signal))throw Error('Unsupported signal')
const expectedBall=signal==='DDR_D15'?'ball_E7':'ball_E8',terminal=signal==='DDR_D15'?'DQ7':'DQ5'
if(!out)throw Error('Usage: capture current-parent DQ1-trial output')
const hashes:Record<string,string>={},hash=(p:string)=>createHash('sha256').update(readFileSync(p)).digest('hex'),read=(p:string)=>{p=resolve(p);hashes[p]=hash(p);return JSON.parse(readFileSync(p,'utf8'))}
const {captureHash,snapshot}=verifyDdrCapture(capture),parent=read(resolve(parentDir,'candidate.circuit.json')),parentHost=read(resolve(parentDir,'host-bundle.json')),parentReport=read(resolve(parentDir,'report.json')),cacheBefore=read(resolve(parentDir,'ram-byte1-facing-progress.trace-paths.json')),exitContract=read(resolve(parentDir,'ram-byte1-exit-contract.json')),trial=read(resolve(trialDir,'report.json')),changes=read(resolve(trialDir,'replacements.json')),candidate=read(resolve(trialDir,'candidate.circuit.json')),host=read(resolve(trialDir,'host-bundle.json')),input=read(resolve(trialDir,'routing-input.json'))
if(!trial.collarPhysical||trial.collarPhysical.errors.length||trial.collarPhysical.violations.length||!trial.accepted||trial.captureHash!==captureHash||trial.parentCircuitSha256!==objectHash(parent)||trial.candidateCircuitSha256!==objectHash(candidate)||parentReport.candidateCircuitSha256!==objectHash(parent)||changes.invalidatedHostTraces.length!==0||host.traces.length!==parentHost.traces.length)throw Error('DQ1 trial identity/provenance mismatch')
for(const[p,h]of Object.entries(trial.inputHashes)){if(hash(p)!==h)throw Error('DQ1 trial inputs changed');hashes[p]=h as string}
const retired=null; if(objectHash(host)!==objectHash(parentHost)||objectHash(applyFacingExitReplacements(parent,changes))!==objectHash(candidate))throw Error('Undeclared D13change')
const t=changes.traces[0].after,source=candidate.find((e:any)=>e.type==='source_port'&&e.source_port_id===changes.breakoutPoints[0].before.source_port_id),connections=input.connections
if(source?.name!==expectedBall)throw Error('Expected DQ1 RAM C7')
const fresh=[...host.traces,t],ids=new Set(fresh.map((t:any)=>t.pcb_trace_id)),physical=verifyDdrSystemCopper(candidate.filter((e:any)=>!ids.has(e.pcb_trace_id)),fresh,connections,{}),topology=auditCompositeHostTopology(candidate,host.traces,connections),localContacts=auditDdrLocalEscapeContacts(candidate,t,connections),allAngles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace')),allJunctions=auditDdrTraceJunctions(candidate,connections)
const context={cache:cacheBefore,exitContract}
const placement=snapshot.placements[1],cache=structuredClone(context.cache),index=cache.findIndex((p:any)=>p.connection===`U1.${source.name}`)
if(index<0||cache.length!==72)throw Error('Missing complete inherited RAM cache')
cache[index]={...cache[index],route:t.route.map((p:any)=>p.route_type==='wire'?{route_type:'wire',x:placement.pcbX-p.x,y:placement.pcbY-p.y,layer:p.layer,width:p.width}:{route_type:'via',x:placement.pcbX-p.x,y:placement.pcbY-p.y,from_layer:p.from_layer,to_layer:p.to_layer,via_diameter:p.via_diameter,via_hole_diameter:p.via_hole_diameter})}
for(let i=0;i<72;i++){fanoutTracePath.parse(cache[i]);if(i!==index&&objectHash(cache[i])!==objectHash(context.cache[i]))throw Error('Unrelated inherited cache changed')}
const bounds=(paths:any[])=>{const points=paths.flatMap((p:any)=>p.route);return{minX:Math.min(...points.map((p:any)=>p.x)),maxX:Math.max(...points.map((p:any)=>p.x)),minY:Math.min(...points.map((p:any)=>p.y)),maxY:Math.max(...points.map((p:any)=>p.y))}},before=bounds(snapshot.pathsByByte[1]),after=bounds(cache),cacheAngles=auditRouteAngles(cache)
if(after.minX<before.minX-1e-7||after.maxX>before.maxX+1e-7||after.minY<before.minY-1e-7||after.maxY>before.maxY+1e-7)throw Error('RAM envelope grew')
const end=t.route.at(-1),prev=[...t.route].reverse().find((p:any)=>p.route_type==='wire'&&p.layer===end.layer&&Math.hypot(p.x-end.x,p.y-end.y)>1e-7),d=Math.hypot(end.x-prev.x,end.y-prev.y),tangent={x:(end.x-prev.x)/d,y:(end.y-prev.y)/d}
if(tangent.x<=0||!['inner2','inner4','inner6'].includes(end.layer))throw Error('Wrong DQ1 direction/layer')
const ball=source.name.slice(5),contract={...exitContract,candidateCircuitSha256:objectHash(candidate),ramCacheSha256:objectHash(cache),changedBalls:[...exitContract.changedBalls,ball],unchangedPaths:72-new Set([...exitContract.changedBalls,ball]).size,pathCount:72,paddingChangeMm:0,paddingChangeBySideMm:{left:0,right:0,top:0,bottom:0},priorCenterlineBounds:before,newCenterlineBounds:after,exits:[...exitContract.exits,{ball,terminal,worldSide:'right',localSide:'left',worldExit:{x:end.x,y:end.y,layer:end.layer},localExit:{x:placement.pcbX-end.x,y:placement.pcbY-end.y,layer:end.layer},tangent:{world:tangent,local:{x:-tangent.x,y:-tangent.y}},tangentDegrees:{world:Math.atan2(tangent.y,tangent.x)*180/Math.PI,local:Math.atan2(-tangent.y,-tangent.x)*180/Math.PI},logicalViaTransition:`top->${end.layer}`,physicalViaSpan:'all ten layers',traceWidthMm:.12,outwardCollarMm:.2,outwardCollarVerified:true}],scope:`Isolated RAM1 ${terminal} (${signal}) facing escape on ${end.layer}; all parent hosts preserved, new host pending. Exact changedBalls list and full72 cache are authoritative; no new padding.`}
if(!physical.errors.length&&!physical.violations.length&&topology.valid&&localContacts.valid&&allAngles.valid&&allJunctions.valid&&cacheAngles.valid&&trial.lengthBudget.optimisticTotalMm<=trial.lengthBudget.nominalMm+1e-7){
 for(const[p,h]of Object.entries(hashes))if(hash(p)!==h)throw Error('Input changed')
 mkdirSync(out,{recursive:true});const write=(n:string,v:any)=>writeFileSync(resolve(out,n),JSON.stringify(v,null,2)+'\n')
 const report={...parentReport,accepted:true,captureHash,candidateCircuitSha256:objectHash(candidate),supportCircuitSha256:objectHash(candidate),hostTracesSha256:objectHash(host.traces),hostBundleSha256:objectHash(host),ramCacheSha256:objectHash(cache),connectedHostCount:host.traces.length,preservedHostCount:host.traces.length,physical,topology,allAngles,allJunctions,localContacts,cacheAngles,inputFileHashes:hashes,parentDirectory:resolve(parentDir),parentCandidateSha256:objectHash(parent),lengthBudget:trial.lengthBudget,outwardCollarEvidence:{lengthMm:.2,physical:trial.collarPhysical},scope:contract.scope}
 const manifest={captureHash,parentDirectory:resolve(parentDir),parentCircuitSha256:objectHash(parent),candidateCircuitSha256:objectHash(candidate),replacements:[...changes.traces,...changes.breakoutPoints].map((r:any)=>({...r,beforeSha256:objectHash(r.before),afterSha256:objectHash(r.after)})),inputHashes:hashes};Object.assign(report,{originalCopperReplacementsSha256:objectHash(manifest),ramByte1CacheSha256:objectHash(cache),ramCacheSha256:parentReport.ramCacheSha256});
 write('original-copper-replacements.json',manifest);write('candidate.circuit.json',candidate);write('host-bundle.json',host);write('routing-input.json',{...input,traces:host.traces});write('replacements.json',changes);write('ram-byte1-facing-progress.trace-paths.json',cache);write('ram-byte1-exit-contract.json',contract);copyFileSync(resolve(parentDir,'ram-byte0-facing-progress.trace-paths.json'),resolve(out,'ram-byte0-facing-progress.trace-paths.json'));const inheritedContract=read(resolve(parentDir,'exit-contract.json'));write('exit-contract.json',{...inheritedContract,candidateCircuitSha256:objectHash(candidate)});write('report.json',report);write('source-provenance.json',{captureHash,inputFileHashes:hashes,parentReport,trial,retiredHost:retired})
 const p=Bun.spawn(['bun','scripts/audit-ddr-global-power-launches.ts',resolve(out),resolve(capture)],{stdout:'inherit',stderr:'inherit'});if(await p.exited!==0)throw Error('Power audit failed');const power=JSON.parse(readFileSync(resolve(out,'ram-power-launch-audit.json'),'utf8'));const parentPower=read(resolve(parentDir,'ram-power-launch-audit.json'));if(power.launchQualified<parentPower.launchQualified||power.total!==parentPower.total||parentPower.rows.filter((r:any)=>r.planeContact&&r.launchWithin1524Mm).some((r:any)=>!power.rows.some((q:any)=>q.byte===r.byte&&q.terminal===r.terminal&&q.padId===r.padId&&q.planeContact&&q.launchWithin1524Mm)))throw Error('Power launch regression');write('report.json',{...report,launchAuditSha256:objectHash(power),launchQualified:power.launchQualified});console.log(JSON.stringify({accepted:true,ball,hosts:host.traces.length,cache:cache.length,floor:trial.lengthBudget.optimisticTotalMm}))
}else throw Error('Current DQ1 escape failed full checks')