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-dq1-facing-cache.ts

/** Transplant one witnessed local D3 escape onto the replayed eleven-host board. */
import {readFileSync,writeFileSync,mkdirSync} 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]=process.argv.slice(2)
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-byte0-facing-progress.trace-paths.json')),exitContract=read(resolve(parentDir,'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.accepted||trial.captureHash!==captureHash||trial.parentCircuitSha256!==objectHash(parent)||trial.candidateCircuitSha256!==objectHash(candidate)||parentReport.candidateCircuitSha256!==objectHash(parent)||changes.invalidatedHostTraces.length!==1||changes.invalidatedHostTraces[0].source_trace_id!=='source_trace_576'||host.traces.length!==11)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=changes.invalidatedHostTraces[0],remaining=parent.filter((e:any)=>!(e.type==='pcb_trace'&&e.pcb_trace_id===retired.pcb_trace_id))
if(objectHash(parentHost.traces.find((t:any)=>t.pcb_trace_id===retired.pcb_trace_id))!==objectHash(retired)||objectHash(host)!==objectHash({...parentHost,traces:parentHost.traces.filter((t:any)=>t.pcb_trace_id!==retired.pcb_trace_id)})||objectHash(applyFacingExitReplacements(remaining,changes))!==objectHash(candidate))throw Error('Undeclared change or retirement')
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!=='ball_C7')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[0],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[0]),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||!['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:68,pathCount:72,paddingChangeMm:0,paddingChangeBySideMm:{left:0,right:0,top:0,bottom:0},priorCenterlineBounds:before,newCenterlineBounds:after,exits:[...exitContract.exits,{ball,terminal:'DQ1',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}],scope:'Isolated RAM0 DQ1 right-facing escape; eleven other hosts preserved, old overlong DQ1 host retired pending replacement. Four cache paths changed relative to frozen source; 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:11,preservedHostCount:11,physical,topology,allAngles,allJunctions,localContacts,cacheAngles,inputFileHashes:hashes,parentDirectory:resolve(parentDir),parentCandidateSha256:objectHash(parent),lengthBudget:trial.lengthBudget,scope:contract.scope}
 delete report.originalCopperReplacementsSha256
 write('candidate.circuit.json',candidate);write('host-bundle.json',host);write('routing-input.json',{...input,traces:host.traces});write('replacements.json',changes);write('ram-byte0-facing-progress.trace-paths.json',cache);write('exit-contract.json',contract);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'));if(power.launchQualified!==56||power.total!==60)throw Error('Power launch regression');write('report.json',{...report,launchAuditSha256:objectHash(power),launchQualified:56});console.log(JSON.stringify({accepted:true,ball,hosts:11,cache:cache.length,floor:trial.lengthBudget.optimisticTotalMm}))
}else throw Error('Current DQ1 escape failed full checks')