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/transplant-ddr-d3-escape.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 {loadAcceptedDq7Context,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,parent,ordered,dmHost,dqHost,experiment,out]=process.argv.slice(2)
if(!capture||!parent||!ordered||!dmHost||!dqHost||!experiment||!out)throw Error('Usage: capture parent ordered-exit DM-host DQ7-host D3-experiment output')
const context=await loadAcceptedDq7Context(capture,parent,ordered,dmHost,dqHost),hashes:Record<string,string>={}
const 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 trial=read(resolve(experiment,'report.json')),changes=read(resolve(experiment,'replacements.json')),ownPrior=read(resolve(experiment,'local-contact-audit.json'))
if(!trial.accepted||!ownPrior.valid||trial.captureHash!==context.captureHash||changes.invalidatedHostTraces.length)throw Error('Not a qualified isolated local replacement')
const t=changes.traces[0].after,source=context.candidate.find((e:any)=>e.type==='source_port'&&e.source_port_id===changes.breakoutPoints[0].before.source_port_id)
if(source?.name!=='ball_C8'||changes.breakoutPoints[0].before.pcb_breakout_point_id!=='pcb_breakout_point_363')throw Error('Expected authoritative D3/C8 source')
const candidate=applyFacingExitReplacements(context.candidate,changes),connections=context.input.connections.map((c:any)=>({...c,pointsToConnect:c.pointsToConnect.map((p:any)=>p.pointId===changes.breakoutPoints[0].after.pcb_breakout_point_id?{...p,x:changes.breakoutPoints[0].after.x,y:changes.breakoutPoints[0].after.y,layer:changes.breakoutPoints[0].after.layer}:p)})),fresh=[...context.host.traces,t],ids=new Set(fresh.map((t:any)=>t.pcb_trace_id))
const physical=verifyDdrSystemCopper(candidate.filter((e:any)=>!ids.has(e.pcb_trace_id)),fresh,connections,{}),topology=auditCompositeHostTopology(candidate,context.host.traces,connections),localContacts=auditDdrLocalEscapeContacts(candidate,t,connections),allAngles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace')),allJunctions=auditDdrTraceJunctions(candidate,connections)
const {snapshot}=verifyDdrCapture(capture),placement=snapshot.placements[0],cache=structuredClone(context.cache),index=cache.findIndex((p:any)=>p.connection==='U1.ball_C8')
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||end.layer!=='inner4')throw Error('Wrong D3 exit direction/layer')
const contract={...context.exitContract,candidateCircuitSha256:objectHash(candidate),ramCacheSha256:objectHash(cache),changedBalls:['B7','E7','C8'],unchangedPaths:69,pathCount:72,paddingChangeMm:0,paddingChangeBySideMm:{left:0,right:0,top:0,bottom:0},priorCenterlineBounds:before,newCenterlineBounds:after,exits:[...context.exitContract.exits,{ball:'C8',terminal:'DQ3',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->inner4',physicalViaSpan:'all ten layers',traceWidthMm:.12}],scope:'Experimental RAM0 cache: ordered DM0, DQ7, local D3 facing exit. Eleven existing hosts retained; D3 host transition not routed.'}
const planar=(route:any[])=>route.reduce((sum:number,p:any,i:number)=>{const q=route[i-1];return sum+(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 connection=connections.find((c:any)=>c.pointsToConnect.some((p:any)=>p.pointId===changes.breakoutPoints[0].after.pcb_breakout_point_id)),cpuPoint=connection.pointsToConnect[1],cpuExit=candidate.find((e:any)=>e.pcb_breakout_point_id===cpuPoint.pointId),cpuTrace=candidate.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===cpuExit.source_trace_id),dx=Math.abs(cpuPoint.x-end.x),dy=Math.abs(cpuPoint.y-end.y)
const lengthBudget={ramEscapeMm:planar(t.route),cpuEscapeMm:planar(cpuTrace.route),hostFloorMm:Math.max(dx,dy)+(Math.SQRT2-1)*Math.min(dx,dy),nominalMm:context.nominal.bytes.find((b:any)=>b.byte===connection.ramByte).dqlmPairedDataMaximumMm,optimisticTotalMm:0}
lengthBudget.optimisticTotalMm=lengthBudget.ramEscapeMm+lengthBudget.cpuEscapeMm+lengthBudget.hostFloorMm
const accepted=!physical.errors.length&&!physical.violations.length&&topology.valid&&localContacts.valid&&allAngles.valid&&allJunctions.valid&&cacheAngles.valid&&lengthBudget.optimisticTotalMm<=lengthBudget.nominalMm+1e-7&&context.host.traces.every((h:any)=>objectHash(candidate.find((e:any)=>e.pcb_trace_id===h.pcb_trace_id))===objectHash(h))
context.assertUnchanged();for(const[p,h]of Object.entries(hashes))if(hash(p)!==h)throw Error('Experiment input changed')
mkdirSync(out,{recursive:true});const write=(p:string,x:any)=>writeFileSync(resolve(out,p),JSON.stringify(x,null,2)+'\n')
write('report.json',{captureHash:context.captureHash,accepted,parentCandidateSha256:objectHash(context.candidate),candidateCircuitSha256:objectHash(candidate),ramCacheSha256:objectHash(cache),sourceProvenance:context.evidence,inputFileHashes:hashes,physical,topology,localContacts,allAngles,allJunctions,cacheAngles,lengthBudget,retainedHosts:context.host.traces.length,scope:contract.scope})
if(accepted){write('candidate.circuit.json',candidate);write('host-bundle.json',context.host);write('routing-input.json',{...context.input,connections,obstacles:undefined});write('replacements.json',changes);write('ram-byte0-facing-progress.trace-paths.json',cache);write('exit-contract.json',contract)}
console.log(JSON.stringify({accepted,hosts:context.host.traces.length,violations:physical.violations.length,ownContact:localContacts.valid,topology:topology.valid,cachePaths:cache.length,lengthBudget}));if(!accepted)process.exitCode=1