seveibar/am3352-ram-dogbone-and-single-layer-route-test
AM3352BZCZ100 processor connected to a W631GG6MB-12 DDR3 memory chip through a routed, length-matched 16-bit DDR interface with clock/data-strobe pairs and control/address signals.
- Version
- 0.0.9
- License
- unset
- Stars
- 0
routing/algorithms.ts
import plan from "./coupled-route-plan.json"
import { materializePlan, checkTiming } from "./coupled-plan"
export const run = (fn: () => any) => {
const handlers: Record<string, (event:any)=>void> = {}
return { on(event:string,cb:any){handlers[event]=cb;return this}, stop(){},
start(){try{handlers.complete?.({traces:fn()})}catch(error){handlers.error?.({error})}} }
}
export function layerFor(_input:any, name:string) {
const route=plan.routes.find(r=>r.name===name)
if(!route)throw new Error(`No planned signal layer for ${name}`)
return route.layer
}
export const exitFor=(p:any)=>({x:p.x+0.4,y:p.y-0.4})
export function makeDogbones(input:any) {
return input.connections.flatMap((c:any)=>c.pointsToConnect.map((p:any,i:number)=>{
const layer=layerFor(input,c.name)
// Half-pitch diagonal: local dogbone only, never a package-boundary fanout.
const exit=exitFor(p)
return {type:"pcb_trace",pcb_trace_id:`dogbone_${c.name}_${i}`,connection_name:c.name,source_trace_id:c.source_trace_id??c.name,
route:[
{route_type:"wire",x:p.x,y:p.y,layer:"top",width:0.1,start_pcb_port_id:p.pcb_port_id},
{route_type:"wire",...exit,layer:"top",width:0.1},
{route_type:"via",...exit,from_layer:"top",to_layer:layer,via_diameter:0.3,via_hole_diameter:0.15},
{route_type:"wire",...exit,layer,width:0.1},
]}
}))
}
// A 1 um lateral bias avoids degenerate collinear top stubs in native geometry tests.
// The same translation is applied to every via and signal-layer route.
const ROUTE_X_BIAS = 0.001
export async function dogboneFanout(input:any) {
return run(()=>makeDogbones(input).map((t:any)=>({...t,route:t.route.map((p:any,i:number)=>i?{...p,x:p.x+ROUTE_X_BIAS}:p)})))
}
// Routes are explicit board-specific guides. They are not a general placement router.
export function createRoutingPhases(){
let routed=false,tuned=false
return {
singleLayerRoute:async(input:any)=>run(()=>{
const traces=materializePlan(input,"guide");routed=true;return traces
}),
coupledTuning:async(input:any)=>run(()=>{
if(!routed)throw new Error("Coupled tuning requires the guide-routing phase")
const traces=materializePlan(input,"tuned")
checkTiming(input,traces)
tuned=true
return traces
}),
ordinaryTurnCleanup:async(input:any)=>run(()=>{
if(!tuned)throw new Error("Turn cleanup requires the coupled-tuning phase")
const traces=materializePlan(input,"simplified")
checkTiming(input,traces)
return traces
})
}
}