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/adopt-ddr-current-e3.ts

/** Adopt current RAM E3 launches, preserving endpoints and restoring byte0 timing. */
import{readFileSync,writeFileSync,mkdirSync}from'node:fs'
import{resolve}from'node:path'
import{createHash}from'node:crypto'
import{verifyDdrCapture}from'./ddr-capture-provenance'
import{objectHash}from'./improve-ddr-a9-power-launches'
import{planDdrGroundAntipads}from'./ddr-ground-plane-antipads'
import{refreshDdrPlaneContacts}from'./ddr-plane-contact-audit'
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'
import{addWestwardTuningExcursion}from'./tune-ddr-data-mask'
import{fanoutTracePath}from'@tscircuit/props'
const[capture,parentDir,out]=process.argv.slice(2);if(!out)throw Error('Usage: capture current-board output')
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,snapshot}=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')),audit=read('dist/ddr-current-ram-compatibility-eighteen/report.json'),tuning=read('dist/ddr-dq4-retuned-current/original-copper-replacements.json'),tuningReport=read('dist/ddr-dq4-retuned-current/report.json'),webReview=read('dist/ddr-e3-plane-web-review/report.json')
if(prior.captureHash!==captureHash||parentHost.captureHash!==captureHash||prior.candidateCircuitSha256!==objectHash(parent)||!audit.nativeMatchesFrozen)throw Error('Parent/source provenance mismatch')
for(const[p,h]of Object.entries(audit.sourceHashes)){if(fh(p)!==h)throw Error('Current RAM source changed');hashes[p]=h as string}
const index=Object.keys(audit.sourceHashes).find(p=>p.endsWith('/src/index.tsx'));if(!index)throw Error('Missing RAM API binding');const{getRamFanoutTracePaths,adaptRamPathsToHost}=await import(index),native=getRamFanoutTracePaths('bus_grouped');if(objectHash(native)!==snapshot.sourceSha256)throw Error('Native RAM changed')
const changes:any[]=[],cacheEvidence:any[]=[],vias:any[]=[],same=(a:any,b:any)=>a.layer===b.layer&&Math.hypot(a.x-b.x,a.y-b.y)<1e-7,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)
for(const byte of[0,1]){const row=audit.rows.find((r:any)=>r.byte===byte&&r.ball==='ball_E3'),before=parent.find((e:any)=>e.type==='pcb_trace'&&e.pcb_trace_id===row.pcbTraceId),port=parent.find((e:any)=>e.type==='source_port'&&e.source_port_id===row.sourcePortId),p=snapshot.placements[byte],cache=read(resolve(parentDir,`ram-byte${byte}-facing-progress.trace-paths.json`)),contract=read(resolve(parentDir,byte?'ram-byte1-exit-contract.json':'exit-contract.json')),current=adaptRamPathsToHost(native,snapshot.hostProfiles[byte]).find((p:any)=>p.connection==='U1.ball_E3'),oldIndex=cache.findIndex((p:any)=>p.connection==='U1.ball_E3')
 if(!before||port?.name!=='ball_E3'||before.source_trace_id!==row.sourceTraceId||oldIndex<0||p.pcbRotation!==180)throw Error('E3 ownership mismatch')
 const route=current.route.map((q:any)=>({...q,x:p.pcbX-q.x,y:p.pcbY-q.y}));if(!same(route[0],before.route[0])||!same(route.at(-1),before.route.at(-1)))throw Error('E3 endpoint moved');route[0]=before.route[0];route[route.length-1]=before.route.at(-1)
 const after={...before,route},deltaMm=planar(route)-planar(before.route);if(Math.abs(deltaMm-.8)>1e-7)throw Error('Unexpected E3 adaptation delta');changes.push({id:`pcb_trace:${before.pcb_trace_id}`,before,after});const oldVia=before.route.find((q:any)=>q.route_type==='via'),newVia=route.find((q:any)=>q.route_type==='via'),standalone=parent.filter((e:any)=>e.type==='pcb_via'&&e.pcb_trace_id===before.pcb_trace_id);if(standalone.length!==1||Math.hypot(standalone[0].x-oldVia.x,standalone[0].y-oldVia.y)>1e-7)throw Error('Missing unique E3 via record');changes.push({id:`pcb_via:${standalone[0].pcb_via_id}`,before:standalone[0],after:{...standalone[0],x:newVia.x,y:newVia.y}});vias.push(...route.filter((q:any)=>q.route_type==='via').map((q:any)=>({x:q.x,y:q.y,net:`RAM${byte}_DQ4`})))
 const priorCache=structuredClone(cache);cache[oldIndex]=current;for(let i=0;i<72;i++){fanoutTracePath.parse(cache[i]);if(i!==oldIndex&&objectHash(cache[i])!==objectHash(priorCache[i]))throw Error('Other cache path changed')}
 const changedBalls=cache.filter((q:any,i:number)=>objectHash(q)!==objectHash(snapshot.pathsByByte[byte][i])).map((q:any)=>q.connection.slice('U1.ball_'.length)),e=route.at(-1),prev=[...route].reverse().find((q:any)=>q.route_type==='wire'&&q.layer===e.layer&&Math.hypot(q.x-e.x,q.y-e.y)>1e-7),d=Math.hypot(e.x-prev.x,e.y-prev.y),tx=(e.x-prev.x)/d,ty=(e.y-prev.y)/d
 cacheEvidence.push({byte,cache,contract:{...contract,changedBalls,unchangedPaths:72-changedBalls.length,scope:`Board-specific physical-layer RAM byte${byte} profile: ${changedBalls.length} paths changed and ${72-changedBalls.length} unchanged from the frozen capture. Current E3 launch adopted; other explicit board overrides retained. Exit direction and layer describe actual copper; full DDR qualification remains outstanding.`,exits:[...contract.exits.filter((x:any)=>x.ball!=='E3'),{ball:'E3',terminal:'DQ4',worldSide:'right',localSide:'left',worldExit:{x:e.x,y:e.y,layer:e.layer},localExit:{x:p.pcbX-e.x,y:p.pcbY-e.y,layer:e.layer},tangent:{world:{x:tx,y:ty},local:{x:-tx,y:-ty}},tangentDegrees:{world:Math.atan2(ty,tx)*180/Math.PI,local:Math.atan2(-ty,-tx)*180/Math.PI},logicalViaTransition:`top->${e.layer}`,physicalViaSpan:'all ten layers',traceWidthMm:.12,change:'Current adapter E3 launch; exit unchanged.'}]},deltaMm})
}
const oldChange=tuning.replacements[0],hostBefore=parentHost.traces.find((t:any)=>t.source_trace_id==='source_trace_579');if(objectHash(hostBefore)!==objectHash(oldChange.after))throw Error('Current DQ4 host differs from verified tuning recipe')
const short=oldChange.before,recipe=tuningReport.recipe,c=Math.SQRT1_2,rotate=(p:any)=>({...p,x:(p.x+p.y)*c,y:(p.y-p.x)*c}),unrotate=(p:any)=>({...p,x:(p.x-p.y)*c,y:(p.x+p.y)*c}),rotated={...short,route:[...short.route].reverse().map(rotate)},detour=addWestwardTuningExcursion(rotated,7,recipe.entry,recipe.exit,recipe.addedMm-cacheEvidence[0].deltaMm,recipe.sign,recipe.bevelMm),hostAfter={...short,route:[...detour.route].reverse().map((p:any)=>short.route.find((q:any)=>{const r=rotate(q);return r.route_type===p.route_type&&r.layer===p.layer&&r.from_layer===p.from_layer&&r.to_layer===p.to_layer&&Math.hypot(r.x-p.x,r.y-p.y)<1e-8})??unrotate(p))}
if(objectHash(hostAfter.route[0])!==objectHash(hostBefore.route[0])||objectHash(hostAfter.route.at(-1))!==objectHash(hostBefore.route.at(-1))||objectHash(hostAfter.route.filter((p:any)=>p.route_type==='via'))!==objectHash(hostBefore.route.filter((p:any)=>p.route_type==='via'))||Math.abs(planar(hostBefore.route)-planar(hostAfter.route)-.8)>1e-7)throw Error('E3 compensation changed host contracts')
changes.push({id:`pcb_trace:${hostBefore.pcb_trace_id}`,before:hostBefore,after:hostAfter})
const planes=parent.filter((e:any)=>e.type==='pcb_copper_pour'),plan=planDdrGroundAntipads(planes,vias,{minimumCopperWebMm:.127,clearanceMm:.107});for(const before of planes)changes.push({id:`pcb_copper_pour:${before.pcb_copper_pour_id}`,before,after:plan.planes.find((p:any)=>p.pcb_copper_pour_id===before.pcb_copper_pour_id)})
const candidate=parent.map((e:any)=>changes.find(ch=>ch.id===`${e.type}:${e[`${e.type}_id`]}`)?.after??e),host={...parentHost,traces:parentHost.traces.map((t:any)=>t.pcb_trace_id===hostBefore.pcb_trace_id?hostAfter:t)},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))),planeAudit=refreshDdrPlaneContacts(prior.planeAudit,plan.planes,candidate)
mkdirSync(out,{recursive:true});const write=(n:string,v:any)=>writeFileSync(resolve(out,n),JSON.stringify(v,null,2)+'\n');write('diagnostic.json',{topology,angles,junctions,terminal,addedAntipads:plan.added})
if(!topology.valid||!angles.valid||!junctions.valid||!terminal.valid||topology.physical.connectivity.filter((c:any)=>c.connected).length!==host.traces.length)throw Error('Current E3 migration fails actual board gates')
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),physical:topology.physical,topology,fullCandidateAngles:angles,fixedJunctionAudit:junctions,terminalContract:terminal,planeAudit,currentE3Migration:{planeWebPolicy:{minimumCopperWebMm:.127,scope:'Provisional5mil E3-only web policy: new .128781mm web uses external .107mm reference-pour clearance and remains above the explicit .127mm provisional threshold. Fabricator approval remains outstanding; inherited .003306mm inner3 webs are separately unresolved.',reviewSha256:objectHash(webReview)},sourceHashes:audit.sourceHashes,byte0HostShortenedMm:.8,cacheDeltas:cacheEvidence.map(e=>({byte:e.byte,deltaMm:e.deltaMm}))},inputFileHashes:hashes,scope:'Current RAM E3 launch updates adopted for both bytes, byte0 host compensation preserves planar matching. Current E1/E2/clock changes and full electrical qualification remain outstanding.'}
const unchanged=()=>{verifyDdrCapture(capture);for(const[p,h]of Object.entries(hashes))if(fh(p)!==h)throw Error('Migration input changed')};unchanged();write('candidate.circuit.json',candidate);write('host-bundle.json',host);write('routing-input.json',{...input,traces:host.traces,obstacles:undefined});write('report.json',report);write('original-copper-replacements.json',manifest);write('source-provenance.json',{captureHash,inputHashes:hashes,auditSha256:objectHash(audit)})
for(const e of cacheEvidence){write(`ram-byte${e.byte}-facing-progress.trace-paths.json`,e.cache);write(e.byte?'ram-byte1-exit-contract.json':'exit-contract.json',{...e.contract,candidateCircuitSha256:objectHash(candidate),[e.byte?'ramByte1CacheSha256':'ramCacheSha256']:objectHash(e.cache)})}
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'));if(power.launchQualified!==56||power.total!==60)throw Error('Power regression');unchanged();write('report.json',{...report,launchAuditSha256:objectHash(power),launchQualified:56,ramCacheSha256:objectHash(cacheEvidence[0].cache),ramByte1CacheSha256:objectHash(cacheEvidence[1].cache)});console.log(JSON.stringify({out,candidateHash:objectHash(candidate),hosts:host.traces.length,adoptedE3:2,hostShortenedMm:.8}))