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/repair-ddr-joint-reference-void.ts
/** Isolated plane-only repair: replace an oversized generated joint signal void
* by the convex capsule of two minimum-clearance 64-gons. No signal is rerouted. */
import F from '@flatten-js/core'
import {readFileSync,writeFileSync,mkdirSync,copyFileSync,existsSync} from 'node:fs'
import {resolve} from 'node:path'
import {createHash} from 'node:crypto'
import {spawnSync} from 'node:child_process'
import {objectHash} from './improve-ddr-a9-power-launches'
import {refreshDdrPlaneContacts} from './ddr-plane-contact-audit'
import {auditCompositeHostTopology} from './ddr-composite-routing-context'
import {auditHostSelfContacts} from './audit-ddr-host-self-contacts'
import {auditRouteAngles} from './check-route-angles'
import {auditDdrTraceJunctions} from './check-ddr-system-copper'
import {checkHostTerminalContract} from './route-ddr-sequential'
type P={x:number,y:number}
const poly=(vs:P[])=>{const p=new F.Polygon(vs.map(p=>[p.x,p.y]));if([...p.faces][0]!.orientation()===1)p.reverse();return p},vertices=(f:any):P[]=>[...f.edges].map((e:any)=>({x:e.start.x,y:e.start.y}))
function hull(points:P[]){const p=[...points].sort((a,b)=>a.x-b.x||a.y-b.y),cross=(a:P,b:P,c:P)=>(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x),lo:P[]=[],hi:P[]=[];for(const a of p){while(lo.length>1&&cross(lo.at(-2)!,lo.at(-1)!,a)<=1e-12)lo.pop();lo.push(a)}for(const a of p.toReversed()){while(hi.length>1&&cross(hi.at(-2)!,hi.at(-1)!,a)<=1e-12)hi.pop();hi.push(a)}return [...lo.slice(0,-1),...hi.slice(0,-1)]}
/** Convex capsule consumes the entire subminimum web between these two antipads. */
export function minimalJointSignalVoid(centers:P[]){
if(centers.length!==2||centers.some(p=>!Number.isFinite(p.x)||!Number.isFinite(p.y))||Math.hypot(centers[1]!.x-centers[0]!.x,centers[1]!.y-centers[0]!.y)<1e-7)throw Error('Expected two distinct finite via centers')
const radius=(.4572/2+.1016)/Math.cos(Math.PI/64)
return hull(centers.flatMap(v=>Array.from({length:64},(_,i)=>({x:v.x+radius*Math.cos(i*Math.PI/32),y:v.y+radius*Math.sin(i*Math.PI/32)}))))
}
if(import.meta.main){
const parentDir=resolve(process.argv[2]??'dist/ddr-fourteen-shorter-strobes'),out=resolve(process.argv[3]??'dist/ddr-fourteen-reference-repaired'),hashes=new Map<string,string>(),fh=(p:string)=>createHash('sha256').update(readFileSync(p)).digest('hex'),read=(p:string)=>{hashes.set(p,fh(p));return JSON.parse(readFileSync(p,'utf8'))},write=(n:string,v:any)=>writeFileSync(`${out}/${n}`,JSON.stringify(v,null,2)+'\n')
if(parentDir===out)throw Error('Output must be isolated')
const original=read(`${parentDir}/candidate.circuit.json`),prior=read(`${parentDir}/report.json`),host=read(`${parentDir}/host-bundle.json`),input=read(`${parentDir}/routing-input.json`),source=read('dist/ddr-twelve-dq1-partial-timing/candidate.circuit.json')
if(!prior.accepted||prior.candidateCircuitSha256!==objectHash(original)||host.layerSpace!=='physical'||![14,15].includes(host.traces.length))throw Error('Parent mismatch')
const hostCount=host.traces.length,priorManifest=read(`${parentDir}/original-copper-replacements.json`),referenceParent=read('dist/ddr-fourteen-shorter-strobes/candidate.circuit.json')
const centers=[{x:-5.72,y:-10.06},{x:-5.68,y:-10.8}],newRing=minimalJointSignalVoid(centers),newVoid=poly(newRing),changes:any[]=[],diagnostics:any[]=[]
const copper:Array<{id:string,a:P,b:P,r:number,layer?:string}>=[]
for(const e of original){if(e.type==='pcb_via')copper.push({id:e.pcb_via_id,a:e,b:e,r:e.outer_diameter/2});if(e.type==='pcb_trace')for(let i=0;i<e.route.length;i++){const p=e.route[i],q=e.route[i-1];if(p.route_type==='via')copper.push({id:`${e.pcb_trace_id}:via:${i}`,a:p,b:p,r:p.via_diameter/2});else if(q?.route_type==='wire'&&q.layer===p.layer)copper.push({id:`${e.pcb_trace_id}:${i}`,a:q,b:p,r:Math.max(p.width,q.width)/2,layer:p.layer})}if(e.type==='pcb_smtpad'&&!['top','bottom'].includes(e.layer))throw Error('Unsupported internal pad');if(['pcb_plated_hole','pcb_cutout'].includes(e.type))throw Error('Unsupported internal geometry')}
const candidate=original.map((e:any)=>{
if(e.type!=='pcb_copper_pour')return e
const matches=e.brep_shape.inner_rings.map((h:any,i:number)=>({h,i})).filter(({h}:any)=>centers.every(v=>poly(h.vertices).contains(new F.Point(v.x,v.y))))
const referencePlane=referenceParent.find((p:any)=>p.type==='pcb_copper_pour'&&p.pcb_copper_pour_id===e.pcb_copper_pour_id),referenceHole=referencePlane.brep_shape.inner_rings.filter((h:any)=>centers.every(v=>poly(h.vertices).contains(new F.Point(v.x,v.y))))
if(referenceHole.length!==1||matches.length!==1||objectHash(referenceHole[0])!==objectHash(matches[0].h))throw Error('Joint void before-hash differs from verified original repair parent')
if(matches.length!==1)throw Error(`No unique joint void on ${e.layer}`)
const {h:old,i:index}=matches[0],oldVoid=poly(old.vertices),refill=F.BooleanOperations.subtract(oldVoid,newVoid),sourcePlane=source.find((s:any)=>s.type==='pcb_copper_pour'&&s.pcb_copper_pour_id===e.pcb_copper_pour_id)
if(!sourcePlane)throw Error('Missing baseline source plane')
for(const hole of sourcePlane.brep_shape.inner_rings)if(F.BooleanOperations.intersect(refill,poly(hole.vertices)).area()>1e-9)throw Error('Refill consumes baseline source void')
const otherWeb=Math.min(...e.brep_shape.inner_rings.filter((_:any,i:number)=>i!==index).map((h:any)=>newVoid.distanceTo(poly(h.vertices))[0]),...[...poly(e.brep_shape.outer_ring.vertices).edges].map(edge=>newVoid.distanceTo(edge.shape)[0]))
if(otherWeb<.1524-1e-7)throw Error(`Insufficient web ${otherWeb}`)
let minimumRefillCopperGapMm=Infinity;const failures:any[]=[]
for(const c of copper.filter(c=>!c.layer||c.layer===e.layer)){
const a=new F.Point(c.a.x,c.a.y),b=new F.Point(c.b.x,c.b.y),shape=Math.hypot(c.b.x-c.a.x,c.b.y-c.a.y)<1e-10?a:new F.Segment(a,b),distance=refill.contains(a)||refill.contains(b)?0:shape.distanceTo(refill)[0],gap=distance-c.r
minimumRefillCopperGapMm=Math.min(minimumRefillCopperGapMm,gap);if(gap<.1016-1e-7)failures.push({...c,gap})
}
diagnostics.push({layer:e.layer,minimumWebMm:otherWeb,minimumRefillCopperGapMm,refillAreaMm2:refill.area(),failures,baselineVoidsPreserved:true,scope:'Refilled copper checked against ALL original planar segments/full barrels, even same rail; no net exemption.'})
const after={...e,brep_shape:{...e.brep_shape,inner_rings:e.brep_shape.inner_rings.map((h:any,i:number)=>i===index?{vertices:newRing}:h)}}
changes.push({before:e,after,holeIndex:index,beforeHoleSha256:objectHash(old),afterHoleSha256:objectHash({vertices:newRing}),reason:'Replace generated enlarged joint antipad with minimum-clearance capsule; refill explicitly audited, all baseline holes preserved.'});return after
})
mkdirSync(out,{recursive:true});write('plane-repair-diagnostics.json',{diagnostics,changes,newRing,centers})
if(changes.length!==3||diagnostics.some(d=>d.failures.length))throw Error('Plane refill clearance failed; diagnostic only')
const planes=candidate.filter((e:any)=>e.type==='pcb_copper_pour'),planeAudit=refreshDdrPlaneContacts(prior.planeAudit,planes,candidate),topology=auditCompositeHostTopology(candidate,host.traces,input.connections),self=auditHostSelfContacts(host.traces),angles=auditRouteAngles(candidate.filter((e:any)=>e.type==='pcb_trace')),joins=auditDdrTraceJunctions(candidate,input.connections),terminal=checkHostTerminalContract(host.traces,input.connections.filter((c:any)=>host.traces.some((t:any)=>t.connection_name===c.name)))
if(!topology.valid||!self.valid||!angles.valid||!joins.valid||!terminal.valid||topology.physical.connectivity.filter(c=>c.connected).length!==hostCount)throw Error('Combined actual geometry gate failed')
for(const name of ['ram-byte0-facing-progress.trace-paths.json','ram-byte1-facing-progress.trace-paths.json','ram-byte1-exit-contract.json','source-provenance.json'].filter(name=>existsSync(`${parentDir}/${name}`))){read(`${parentDir}/${name}`);copyFileSync(`${parentDir}/${name}`,`${out}/${name}`)}
const contract=read(`${parentDir}/exit-contract.json`),manifest={captureHash:prior.captureHash,parentCircuitSha256:objectHash(original),candidateCircuitSha256:objectHash(candidate),replacements:changes.map(c=>({before:c.before,after:c.after})),inputHashes:Object.fromEntries(hashes)},report={...prior,accepted:true,candidateCircuitSha256:objectHash(candidate),supportCircuitSha256:objectHash(candidate),originalCopperReplacementsSha256:objectHash(manifest),parentReportSha256:objectHash(prior),planeAudit,topology,physical:topology.physical,fullCandidateAngles:angles,fixedJunctionAudit:joins,terminalContract:terminal,referenceRepair:{diagnostics,unchangedAllNonPlanes:true,unchangedHostBundleSha256:objectHash(host),parentDir},inputFileHashes:Object.fromEntries(hashes)}
write('candidate.circuit.json',candidate);write('report.json',report);write('host-bundle.json',host);write('routing-input.json',{...input,traces:host.traces});write('exit-contract.json',{...contract,candidateCircuitSha256:objectHash(candidate)});write('original-copper-replacements.json',manifest);write('parent-report.json',prior);write('parent-original-copper-replacements.json',priorManifest);write('host-self-contact-report.json',self);write('topology-report.json',topology);write('host-route-report.json',{captureHash:prior.captureHash,accepted:true,topology,selfContacts:self,allAngles:angles,allJunctions:joins,terminal,scope:'All retained hosts unchanged; current audits after explicit joint-plane-void repair.'})
for(const script of ['audit-ddr-global-power-launches.ts','audit-ddr-host-reference-coverage.ts']){const result=spawnSync(process.execPath,[resolve(`scripts/${script}`),out],{encoding:'utf8'});if(result.status!==0)throw Error(result.stderr||result.stdout)}
const power=JSON.parse(readFileSync(`${out}/ram-power-launch-audit.json`,'utf8')),reference=JSON.parse(readFileSync(`${out}/host-reference-coverage.json`,'utf8'));if(power.launchQualified!==56||reference.rows.some((r:any)=>['source_trace_564','source_trace_565'].includes(r.connection)&&r.uncoveredMm>1e-7))throw Error('Power/reference regression')
Object.assign(report,{launchAuditSha256:objectHash(power),hostReferenceCoverageSha256:objectHash(reference),hostBundleSha256:objectHash(host),hostTracesSha256:objectHash(host.traces),routingInputSha256:objectHash({...input,traces:host.traces}),sourceProvenance:{inheritedFile:'source-provenance.json',inheritedFileSha256:fh(`${out}/source-provenance.json`),parentCircuitSha256:objectHash(original),candidateCircuitSha256:objectHash(candidate),currentReplacementManifestSha256:objectHash(manifest)},referenceCoverageScope:reference.scope});write('report.json',report)
for(const[p,h]of hashes)if(fh(p)!==h)throw Error(`Input changed ${p}`)
console.log(JSON.stringify({out,candidateHash:objectHash(candidate),diagnostics,hosts:hostCount,power:56,dqs0Uncovered:0}))
}