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/route-ddr-winding.ts

/** One bounded existing winding-solver attempt; no generated router code. */
import {readFileSync,writeFileSync,mkdirSync} from 'node:fs'
import {resolve} from 'node:path'
const {routeViaMinimalWindingAlternativesSteps}=await import(resolve('node_modules/@tscircuit/fanout-solver/lib/route-via-minimal-winding.ts'))
import {prepareDdrHostSignalProjection} from './prepare-ddr-host-signal-projection'
import {verifyDdrCapture} from './ddr-capture-provenance'
import {selectVerifiedDdrSeed} from './ddr-verified-seed'
import {checkHostTerminalContract} from './route-ddr-sequential'
import {loadDdrSupportRoutingContext} from './ddr-support-routing-context'
import {verifyDdrSystemCopper} from './check-ddr-system-copper'
const [dir,seedPath,out,supportPath,signalArg,stateArg]=process.argv.slice(2)
const maximumSearchStates=stateArg===undefined?100000:Number(stateArg)
if(!Number.isInteger(maximumSearchStates)||maximumSearchStates<1000||maximumSearchStates>1000000)throw Error('Search state budget must be 1000–1000000')
const signalName=signalArg??'DDR_D1'
if(!/^DDR_D(?:[0-9]|1[0-5])$/.test(signalName))throw Error('Select DDR_D0 through DDR_D15')
if(!dir||!seedPath||!out)throw Error('Usage: capture seed output')
const read=(p:string)=>JSON.parse(readFileSync(p,'utf8')),write=(n:string,x:any)=>writeFileSync(resolve(out,n),JSON.stringify(x,null,2)+'\n')
mkdirSync(out,{recursive:true})
const started=Date.now(),{captureHash}=verifyDdrCapture(dir),original=read(resolve(dir,'unrouted.circuit.json')),physical=read(resolve(dir,'merged-routing-input.json')),signalMap=read(resolve(dir,'signal-map.json'))
const signal=signalMap.find((m:any)=>m.cpuSignal===signalName),connection=physical.connections.find((c:any)=>[c.name,...c.mergedConnectionNames??[]].includes(signal.sourceTraceId))
if(!connection||connection.pointsToConnect.length!==2)throw Error('Requires two-terminal data contract')
const targetLayer=connection.pointsToConnect[0].layer
if(!['inner2','inner4','inner6'].includes(targetLayer)||connection.pointsToConnect.some((p:any)=>p.layer!==targetLayer))throw Error('This adapter requires same-layer physical terminals')
const seed=selectVerifiedDdrSeed({captureHash,bundle:read(seedPath),original,leads:[],connections:physical.connections})
if(seed.connectedNetNames.includes(connection.name))throw Error(`${signalName} already present`)
write('candidate.physical.json',{captureHash,layerSpace:'physical',traces:seed.traces})
const projection=prepareDdrHostSignalProjection(dir),inverse:Record<string,string>={top:'top',inner1:'inner2',inner2:'inner4',bottom:'inner6'}
const srj:any={...physical,traces:seed.traces,obstacles:projection.input.obstacles.map((o:any)=>({...o,layers:o.layers.map((l:string)=>inverse[l])}))}
const support=supportPath?await loadDdrSupportRoutingContext(dir,supportPath,original,seed.traces,captureHash):null
const fixed=support?.fixed??original,aliases=support?.aliases??{}
if(support){srj.obstacles.push(...support.obstacles);write('support-provenance.json',support.evidence);const baseline=verifyDdrSystemCopper(fixed,seed.traces,physical.connections,aliases);if(baseline.errors.length||baseline.violations.length||!baseline.angles.valid||baseline.joinedBends.length)throw Error('Fresh full support/seed physical predicate failed')}
const [source,target]=[...connection.pointsToConnect].sort((a:any,b:any)=>a.x-b.x)
const exit=original.find((e:any)=>e.type==='pcb_breakout_point'&&e.pcb_breakout_point_id===source.pointId)
const saved=original.find((e:any)=>e.type==='pcb_trace'&&e.source_trace_id===exit?.source_trace_id&&e.route.at(-1)?.layer===source.layer&&Math.hypot(e.route.at(-1).x-source.x,e.route.at(-1).y-source.y)<1e-7)
if(!saved)throw Error('Missing exact RAM source copper')
const previous=[...saved.route].reverse().find((p:any)=>p.route_type==='wire'&&p.layer===source.layer&&Math.hypot(p.x-source.x,p.y-source.y)>1e-7)
if(!previous)throw Error('Missing source tangent')
const length=Math.hypot(source.x-previous.x,source.y-previous.y),collar={x:source.x+.2*(source.x-previous.x)/length,y:source.y+.2*(source.y-previous.y)/length}
const sourceObstacle=srj.obstacles.find((o:any)=>o.connectedTo.includes(connection.name)&&o.layers.includes(targetLayer)&&Math.abs(o.center.x-source.x)<=o.width/2+1e-7&&Math.abs(o.center.y-source.y)<=o.height/2+1e-7)
if(!sourceObstacle)throw Error('No real source copper obstacle at terminal')
const prefix={type:'pcb_trace',pcb_trace_id:`winding_${signalName}_fixed_prefix`,connection_name:connection.name,route:[source,collar].map(p=>({route_type:'wire',x:p.x,y:p.y,layer:targetLayer,width:.12}))}
const prefixCheck=verifyDdrSystemCopper(fixed,[...seed.traces,prefix],physical.connections,aliases)
if(prefixCheck.errors.length||prefixCheck.violations.length||!prefixCheck.angles.valid||prefixCheck.joinedBends.length)throw Error('Exact source-tangent collar fails physical predicate')
const prepared:any={connection,connectionIndex:0,sourcePoint:{...source,pcb_port_id:source.pointId},sourcePointIndex:connection.pointsToConnect.indexOf(source),sourceLayer:targetLayer,sourceObstacle,targetPoint:target}
const bus:any={busId:signalName,direction:'right',exitEdge:'right',termination:{type:'boundary'},connections:[prepared],componentId:'actual-RAM0-exit',componentObstacles:[sourceObstacle],componentBounds:physical.bounds,sharedBoundary:{...physical.bounds,maxX:target.x},xCoordinates:[source.x],yCoordinates:[source.y],pitchX:.8,pitchY:.8}
const params:any={srj,bus,targetLayer,terminals:[{connection:prepared,viaPoint:collar,exitPoint:target}],acceptedPlans:[],layerNames:['top','inner1','inner2','inner3','inner4','inner5','inner6','inner7','inner8','bottom'],traceWidth:.12,viaDiameter:.4572,viaHoleDiameter:.254,clearance:.1016,allowBlindAndBuriedVias:false,allowSourceLayerRouting:true,gridStep:.1,maximumRouteOrderAttempts:1,maximumSearchStates,heuristicWeight:1.2,sourceEscapePaths:new Map([[0,[source,collar]]])}
write('input-summary.json',{captureHash,signal:signalName,source,target,collar,obstacleCount:srj.obstacles.length,sourceObstacle,planningRegion:bus.sharedBoundary,gridStep:.1,maxSearchStates:maximumSearchStates,seedNetCount:seed.connectedNetNames.length,seedTraceHash:seed.seedTraceHash,scope:'Same-layer path; all original signal obstacles and full-depth via footprints retained. Full physical predicate after search.'})
const steps=routeViaMinimalWindingAlternativesSteps(params,1),progress:any[]=[]
let result:any
while(true){if(Date.now()-started>55000){steps.return([]);result=[];write('timeout.json',{elapsedMs:Date.now()-started});break}const next=steps.next();if(next.done){result=next.value;break}progress.push({...next.value,visualization:undefined});write('progress.json',progress)}
const traces=result[0]?.map((p:any)=>p.trace)??[]
const terminals=checkHostTerminalContract(traces,[connection]),final=verifyDdrSystemCopper(fixed,[...seed.traces,...traces],physical.connections,aliases)
if(supportPath&&support){const current=await loadDdrSupportRoutingContext(dir,supportPath,original,seed.traces,captureHash);if(current.evidence.candidateSha256!==support.evidence.candidateSha256||current.evidence.reportSha256!==support.evidence.reportSha256)throw Error('Support source changed during routing')}
const accepted=traces.length===1&&traces.every((t:any)=>t.route.every((p:any)=>p.route_type==='wire'&&p.layer===targetLayer))&&terminals.valid&&!final.errors.length&&!final.violations.length&&final.angles.valid&&!final.joinedBends.length&&final.connectivity.find((c:any)=>c.name===connection.name)?.connected
write('raw-candidate.physical.json',{captureHash,layerSpace:'physical',traces:[...seed.traces,...traces]})
if(accepted)write('candidate.physical.json',{captureHash,layerSpace:'physical',traces:[...seed.traces,...traces]})
write('physical-report.json',{captureHash,...final})
const report={captureHash,status:accepted?'new-net-geometrically-accepted':'no-accepted-new-net',elapsedSeconds:(Date.now()-started)/1000,alternatives:result.length,rawTraceCount:traces.length,seedNetCount:seed.connectedNetNames.length,terminalContract:terminals,errors:final.errors.length,violations:final.violations.length,angleViolations:final.angles.violations.length,joinedBends:final.joinedBends.length,progressCount:progress.length}
write('report.json',report);console.log(JSON.stringify(report))

if(!accepted)process.exitCode=1