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-exit.ts
/** Merge a verified local exit experiment into a newer support candidate. */
import{readFileSync,writeFileSync,mkdirSync}from'node:fs'
import{resolve}from'node:path'
import{fanoutTracePath}from'@tscircuit/props'
import{assertRouteAngles}from'./check-route-angles'
import{verifyDdrCapture}from'./ddr-capture-provenance'
import{verifyDdrSystemCopper}from'./check-ddr-system-copper'
import{objectHash}from'./improve-ddr-a9-power-launches'
const[capture,support,experiment,out]=process.argv.slice(2)
if(!capture||!support||!experiment||!out)throw Error('Usage: capture support experiment output')
const read=(p:string)=>JSON.parse(readFileSync(p,'utf8')),write=(p:string,x:any)=>writeFileSync(resolve(out,p),JSON.stringify(x,null,2)+'\n')
const{captureHash,snapshot}=verifyDdrCapture(capture),original=read(resolve(capture,'unrouted.circuit.json')),parent=read(resolve(support,'candidate.circuit.json')),prior=read(resolve(support,'report.json')),host=read(resolve(support,'host-bundle.json')),changes=read(resolve(experiment,'replacements.json')),trial=read(resolve(experiment,'report.json')),trialCircuit=read(resolve(experiment,'candidate.circuit.json')),input=read(resolve(capture,'routing-input.json'))
if(prior.captureHash!==captureHash||trial.captureHash!==captureHash||host.captureHash!==captureHash||!trial.accepted||!trial.lengthBudget.nominalFloorPass||objectHash(trialCircuit)!==changes.candidateCircuitSha256)throw Error('Exit/support provenance mismatch')
if(changes.traces.length!==1||changes.breakoutPoints.length!==1)throw Error('Expected one declared exit replacement')
const trace=changes.traces[0],point=changes.breakoutPoints[0],candidate=structuredClone(parent)
for(const change of[trace,point]){const key=`${change.before.type}_id`,i=candidate.findIndex((e:any)=>e.type===change.before.type&&e[key]===change.before[key]);if(i<0||objectHash(candidate[i])!==objectHash(change.before))throw Error('Replacement does not match current support parent');candidate[i]=change.after}
const ids=new Set(host.traces.map((t:any)=>t.pcb_trace_id)),physical=verifyDdrSystemCopper(candidate.filter((e:any)=>!ids.has(e.pcb_trace_id)),host.traces,input.connections,{})
if(physical.errors.length||physical.violations.length||!physical.angles.valid||physical.joinedBends.length||physical.connectivity.filter((c:any)=>c.connected).length!==host.traces.length)throw Error('Full supported candidate failed')
// Independently check reuse against the original frozen component copper too.
const baseline=verifyDdrSystemCopper(original.filter((e:any)=>e.pcb_trace_id!==trace.before.pcb_trace_id),[trace.after],input.connections,{})
if(baseline.errors.length||baseline.violations.length||!baseline.angles.valid||baseline.joinedBends.length)throw Error('Variant needs additional original component changes')
const placement=snapshot.placements[0]
if(placement.pcbRotation!==180)throw Error('Expected frozen RAM0 rotation')
const localPaths=structuredClone(snapshot.pathsByByte[0]),index=localPaths.findIndex((p:any)=>p.connection==='U1.ball_B7')
if(index<0)throw Error('Missing frozen DM cache')
localPaths[index]={...localPaths[index],route:trace.after.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(const path of localPaths)fanoutTracePath.parse(path)
assertRouteAngles(localPaths)
const boundsOf=(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))}}
const priorBounds=boundsOf(snapshot.pathsByByte[0]),newBounds=boundsOf(localPaths)
if(newBounds.minX<priorBounds.minX-1e-7||newBounds.minY<priorBounds.minY-1e-7||newBounds.maxX>priorBounds.maxX+1e-7||newBounds.maxY>priorBounds.maxY+1e-7)throw Error('Variant extends the existing profile envelope')
mkdirSync(out,{recursive:true});write('candidate.circuit.json',candidate);write('host-bundle.json',host);write('original-component-physical-report.json',baseline);write('ram-byte0-facing-mask.trace-paths.json',localPaths)
write('report.json',{...prior,physical,parentSupportCircuitSha256:objectHash(parent),candidateCircuitSha256:objectHash(candidate),exitReplacement:changes,exitExperimentSha256:objectHash(trialCircuit),lengthBudget:trial.lengthBudget,scope:'Ten unchanged host nets plus one revised RAM mask exit. No mask host route, refreshed capture or complete timing approval; previous profiles remain available.'})
const end=trace.after.route.at(-1),prev=[...trace.after.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),tangentLength=Math.hypot(end.x-prev.x,end.y-prev.y),tangent={x:(end.x-prev.x)/tangentLength,y:(end.y-prev.y)/tangentLength}
write('exit-contract.json',{finalTangent:{world:tangent,local:{x:-tangent.x,y:-tangent.y}},captureHash,profile:'ram-byte0-facing-mask-experiment',pathCount:localPaths.length,changedBall:'B7',terminal:'DM',physicalLayerCount:10,localExit:localPaths[index].route.at(-1),worldExit:point.after,side:'local-left / world-right at180degrees',outwardDirection:{local:{x:-1,y:0},world:{x:1,y:0}},logicalViaTransition:'top->inner4',physicalViaSpan:'top through bottom, all10layers',traceWidthMm:.12,paddingChangeMm:0,priorCenterlineBounds:priorBounds,newCenterlineBounds:newBounds,scope:'Frozen72path cache with one changedpath. This is an experimental profile artifact; retain the original interiorCA/CK tap contract and explicitly use physical identity layer mapping. Default memory adapter remapping must not be applied.'})
console.log(JSON.stringify({connected:host.traces.length,profilePaths:localPaths.length,nominalFloorMm:trial.lengthBudget.optimisticTotalMm,nominalMm:trial.lengthBudget.nominalMm}))