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-facing-progress.ts

/** Experimental composite: declared power56 + DM/DQ7 exits + the verified DM host. */
import{readFileSync,writeFileSync,mkdirSync}from'node:fs'
import{resolve}from'node:path'
import{createHash}from'node:crypto'
import{checkHostTerminalContract}from'./route-ddr-sequential'
import{fanoutTracePath}from'@tscircuit/props'
import{loadFacingContext,applyFacingExitReplacements}from'./ddr-facing-context'
import{verifyDdrCapture}from'./ddr-capture-provenance'
import{validateDeclaredDdrReplacements,objectHash}from'./improve-ddr-a9-power-launches'
import{verifyDdrSystemCopper}from'./check-ddr-system-copper'
import{assertRouteAngles,auditRouteAngles}from'./check-route-angles'
export function appendVerifiedFacingHost(candidate:any[],prior:any[],next:any[]){
 if(next.length!==prior.length+1)throw Error('Expected exactly one added host')
 const ids=new Set(prior.map(t=>t.pcb_trace_id));for(const t of prior)if(objectHash(next.find(n=>n.pcb_trace_id===t.pcb_trace_id))!==objectHash(t)||objectHash(candidate.find(e=>e.type==='pcb_trace'&&e.pcb_trace_id===t.pcb_trace_id))!==objectHash(t))throw Error('Existing host changed')
 const added=next.filter(t=>!ids.has(t.pcb_trace_id));if(added.length!==1||candidate.some(e=>e.type==='pcb_trace'&&e.pcb_trace_id===added[0].pcb_trace_id))throw Error('Ambiguous new host')
 return [...candidate,...added]
}
export function buildFacingRamCache(snapshot:any,replacements:Array<{ball:string,trace:any}>){
 if(replacements.length!==2||new Set(replacements.map(r=>r.ball)).size!==2||replacements.some(r=>!['B7','E7'].includes(r.ball)))throw Error('Expected exactly B7 and E7')
 const placement=snapshot.placements[0];if(placement.pcbRotation!==180||snapshot.pathsByByte[0].length!==72)throw Error('Expected frozen 72-path rotated RAM0')
 const paths=structuredClone(snapshot.pathsByByte[0]);for(const {ball,trace}of replacements){const i=paths.findIndex((p:any)=>p.connection===`U1.ball_${ball}`);if(i<0)throw Error('Missing changed RAM ball');paths[i]={...paths[i],route:trace.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<paths.length;i++){fanoutTracePath.parse(paths[i]);if(!['U1.ball_B7','U1.ball_E7'].includes(paths[i].connection)&&objectHash(paths[i])!==objectHash(snapshot.pathsByByte[0][i]))throw Error('Unrelated RAM cache path changed')}
 assertRouteAngles(paths)
 const bounds=(ps:any[])=>{const p=ps.flatMap(p=>p.route);return{minX:Math.min(...p.map(p=>p.x)),maxX:Math.max(...p.map(p=>p.x)),minY:Math.min(...p.map(p=>p.y)),maxY:Math.max(...p.map(p=>p.y))}},before=bounds(snapshot.pathsByByte[0]),after=bounds(paths)
 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')
 return{paths,before,after}
}
if(import.meta.main){
 const[capture,powerDir,dmDir,dqDir,hostDir,out]=process.argv.slice(2);if(!out)throw Error('Usage: capture power56 DM0-power54 DQ7-experiment DM0-host output')
 const inputHashes=new Map<string,string>(),fileHash=(p:string)=>createHash('sha256').update(readFileSync(p)).digest('hex'),read=(p:string)=>{p=resolve(p);if(!p.startsWith(resolve(out)+'/')){const h=fileHash(p);if(inputHashes.has(p)&&inputHashes.get(p)!==h)throw Error('Input changed while reading');inputHashes.set(p,h)}return JSON.parse(readFileSync(p,'utf8'))},assertInputsUnchanged=()=>{for(const[p,h]of inputHashes)if(fileHash(p)!==h)throw Error(`Assembly source changed: ${p}`)},write=(n:string,v:any)=>writeFileSync(resolve(out,n),JSON.stringify(v,null,2)+'\n'),{captureHash,snapshot}=verifyDdrCapture(capture),power=read(resolve(powerDir,'candidate.circuit.json')),powerReport=read(resolve(powerDir,'report.json')),powerManifest=read(resolve(powerDir,'original-copper-replacements.json')),powerParent=read(resolve(powerManifest.parentDirectory,'candidate.circuit.json')),context=await loadFacingContext(capture,powerManifest.parentDirectory,dmDir)
 if(powerReport.captureHash!==captureHash||powerReport.originalCopperReplacementsSha256!==objectHash(powerManifest))throw Error('Stale power56 report')
 const powerEvidence=validateDeclaredDdrReplacements(powerParent,power,powerManifest),dmChanges=context.report.exitReplacement,dqChanges=read(resolve(dqDir,'replacements.json')),dqTrial=read(resolve(dqDir,'report.json')),dqTrialCircuit=read(resolve(dqDir,'candidate.circuit.json')),newHost=read(resolve(hostDir,'host-bundle.json')),hostReport=read(resolve(hostDir,'report.json'))
 if(!dqTrial.accepted||!dqTrial.lengthBudget.nominalFloorPass||dqTrial.captureHash!==captureHash||dqChanges.candidateCircuitSha256!==objectHash(dqTrialCircuit)||!hostReport.accepted||hostReport.parentCandidateSha256!==objectHash(context.candidate)||hostReport.captureHash!==captureHash||newHost.captureHash!==captureHash||newHost.traces.length!==11||newHost.layerSpace!=='physical')throw Error('Experiment or host provenance mismatch')
 let candidate=applyFacingExitReplacements(applyFacingExitReplacements(power,dmChanges),dqChanges)
 candidate=appendVerifiedFacingHost(candidate,context.host.traces,newHost.traces)
 const connections=context.input.connections.map((c:any)=>({...c,pointsToConnect:c.pointsToConnect.map((p:any)=>{const e=candidate.find(e=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===p.pointId);if(!e)throw Error('Missing actual endpoint');return{...p,x:e.x,y:e.y,layer:e.layer}})})),changed=[dmChanges.traces[0].after,dqChanges.traces[0].after],fresh=[...newHost.traces,...changed],freshIds=new Set(fresh.map(t=>t.pcb_trace_id)),fixed=candidate.filter(e=>!freshIds.has(e.pcb_trace_id)),physical=verifyDdrSystemCopper(fixed,fresh,connections,{})
 if(physical.errors.length||physical.violations.length||!physical.angles.valid||physical.joinedBends.length||physical.connectivity.filter(c=>c.connected).length!==11)throw Error(`Composite check failed: ${physical.errors.length} errors/${physical.violations.length} violations`)
 const hostNames=new Set(newHost.traces.map((t:any)=>t.connection_name)),terminalContract=checkHostTerminalContract(newHost.traces,connections.filter((c:any)=>hostNames.has(c.name))),fullCandidateAngles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace'))
 if(!terminalContract.valid||!fullCandidateAngles.valid)throw Error('Actual host terminal contract or complete per-route angle audit failed')
 const dmHost=newHost.traces.find((t:any)=>!context.host.traces.some((p:any)=>p.pcb_trace_id===t.pcb_trace_id)),dmConnection=connections.find((c:any)=>c.name===dmHost.connection_name),ramExitId=dmChanges.breakoutPoints[0].after.pcb_breakout_point_id,cpuPoint=dmConnection.pointsToConnect.find((p:any)=>p.pointId!==ramExitId),cpuExit=candidate.find((e:any)=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===cpuPoint.pointId),cpuTrace=candidate.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===cpuExit.source_trace_id&&e.route.some((p:any)=>p.route_type==='wire'&&p.layer===cpuPoint.layer&&Math.hypot(p.x-cpuPoint.x,p.y-cpuPoint.y)<1e-7)),planar=(r:any[])=>r.reduce((s:number,b:any,i:number)=>{const a=r[i-1];return s+(a?.route_type==='wire'&&b.route_type==='wire'&&a.layer===b.layer?Math.hypot(a.x-b.x,a.y-b.y):0)},0)
 if(!cpuTrace)throw Error('Missing actual DM CPU escape')
 const nominalAudit=read(resolve(powerDir,'../ddr-integrated-ten/dqlm-audit.json'));if(nominalAudit.captureHash!==captureHash)throw Error('Nominal audit capture differs')
 const dmNominalMm=nominalAudit.bytes.find((b:any)=>b.byte===0)?.dqlmPairedDataMaximumMm,dmPlanar={ramMm:planar(changed[0].route),cpuMm:planar(cpuTrace.route),hostMm:planar(dmHost.route),nominalMm:dmNominalMm,totalMm:planar(changed[0].route)+planar(cpuTrace.route)+planar(dmHost.route),scope:'Remeasured actual complete planar copper; no via delay, stackup, or byte-matching qualification.'}
 if(!Number.isFinite(dmNominalMm)||dmPlanar.totalMm>dmNominalMm+1e-7)throw Error('Actual DM planar route exceeds nominal')
 const cache=buildFacingRamCache(snapshot,[{ball:'B7',trace:changed[0]},{ball:'E7',trace:changed[1]}]),planes=(c:any[])=>c.filter(e=>e.type==='pcb_copper_pour')
 if(objectHash(planes(candidate))!==objectHash(planes(power)))throw Error('Unexpected plane change')
 const contracts=changed.map((t,i)=>{const end=t.route.at(-1),prior=[...t.route].reverse().find(p=>p.route_type==='wire'&&p.layer===end.layer&&Math.hypot(p.x-end.x,p.y-end.y)>1e-7);if(!prior||end.x<=prior.x||end.layer!=='inner4')throw Error('Wrong exit tangent/layer');const d=Math.hypot(end.x-prior.x,end.y-prior.y),tangent={x:(end.x-prior.x)/d,y:(end.y-prior.y)/d};return{ball:i?'E7':'B7',terminal:i?'DQ7':'DM',side:'local-left / world-right at 180 degrees',worldExit:{x:end.x,y:end.y,layer:end.layer},localExit:{x:snapshot.placements[0].pcbX-end.x,y:snapshot.placements[0].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}})
 context.assertUnchanged();assertInputsUnchanged();mkdirSync(out,{recursive:true});write('candidate.circuit.json',candidate);write('host-bundle.json',newHost);write('routing-input.json',{...context.input,connections,obstacles:undefined,traces:newHost.traces,scope:'Updated physical endpoint connections; regenerate obstacle projection before routing.'});write('ram-byte0-facing-progress.trace-paths.json',cache.paths);write('exit-contract.json',{captureHash,changedBalls:['B7','E7'],unchangedPaths:70,pathCount:72,physicalLayerCount:10,identityLayerMappingRequired:true,paddingChangeMm:0,priorCenterlineBounds:cache.before,newCenterlineBounds:cache.after,exits:contracts,scope:'Experimental composite cache; not a fresh capture. Interior CA/CK contracts retained.'})
 write('report.json',{...powerReport,physical,terminalContract,fullCandidateAngles,dmPlanar,inputFileHashes:Object.fromEntries(inputHashes),fixedJunctionAudit:'Not covered by the per-route angle audit; unrelated existing CPU junctions require separate review.',aliases:{},externalAliasesUsed:false,candidateCircuitSha256:objectHash(candidate),supportCircuitSha256:objectHash(candidate),hostTracesSha256:objectHash(newHost.traces),hostBundleSha256:objectHash(newHost),preservedHostCount:10,connectedHostCount:11,powerEvidence,parentPowerCircuitSha256:objectHash(power),inheritedPlaneGeometrySha256:objectHash(planes(power)),planeAudit:powerReport.planeAudit,exitReplacements:[dmChanges,dqChanges],newHostEvidence:hostReport,ramCacheSha256:objectHash(cache.paths),scope:'Experimental composite power56, DM0/DQ7 CPU-facing exits and 11 connected hosts. No fresh capture, DQ7 host or DDR qualification.'})
 const audit=Bun.spawn(['bun','scripts/audit-ddr-global-power-launches.ts',resolve(out),resolve(capture)],{stdout:'inherit',stderr:'inherit'});if(await audit.exited!==0)throw Error('Power audit failed');const launch=read(resolve(out,'ram-power-launch-audit.json'));if(launch.launchQualified!==56||launch.total!==60)throw Error('Expected 56 qualified power launches');const finalReport=read(resolve(out,'report.json'));write('report.json',{...finalReport,launchAuditSha256:objectHash(launch),launchQualified:launch.launchQualified,totalRamPowerPads:launch.total})
 context.assertUnchanged();assertInputsUnchanged();
 console.log(JSON.stringify({out,connectedHosts:11,cachePaths:72,changedBalls:['B7','E7'],powerLaunches:launch.launchQualified,physicalViolations:0}))
}