ShiboSoftwareDev/am625sip-linux-board
This code defines the physical footprint and pin layout for an AM625 System-in-Package (SIP) component, detailing pad positions, pin labels, and package outline for hardware integration.
- Version
- 1.0.24
- License
- unset
- Stars
- 0
subcircuits/cached-soc-fanout-autorouter.ts
import { EventEmitter } from "node:events"
import cachedFanout from "./cache/soc-fanout-routes.json"
type SimpleRouteJson = any
type SimplifiedPcbTrace = any
const createCachedOutput = (input: SimpleRouteJson): SimpleRouteJson => {
const traces = cachedFanout.fanoutTraces as SimplifiedPcbTrace[]
const inputConnectionNames = new Set(
input.connections.map((connection: any) => connection.name),
)
if (
traces.length !== input.connections.length ||
traces.some((trace) => !inputConnectionNames.has(trace.connection_name))
) {
throw new Error(
`SOC fanout cache does not match input: ${traces.length} cached traces for ${input.connections.length} connections`,
)
}
const sourceComponentIds = new Set<string>()
const connections = input.connections.map((connection: any) => {
const trace = traces.find(
(candidate) => candidate.connection_name === connection.name,
)
if (!trace) throw new Error(`Missing cached SOC fanout ${connection.name}`)
const startPoint = trace.route.find(
(point: any) => point.route_type === "wire" && point.start_pcb_port_id,
)
const exitPoint = [...trace.route]
.reverse()
.find((point: any) => point.route_type === "wire")
const exitPointId = trace.connectsTo.find((id: string) =>
id.startsWith("fanout-exit:"),
)
const sourcePointIndex = connection.pointsToConnect.findIndex(
(point: any) => point.pcb_port_id === startPoint?.start_pcb_port_id,
)
if (!startPoint || !exitPoint || !exitPointId || sourcePointIndex < 0) {
throw new Error(`Invalid cached SOC fanout ${connection.name}`)
}
for (const obstacle of input.obstacles) {
if (
obstacle.componentId &&
obstacle.connectedTo?.includes(startPoint.start_pcb_port_id)
) {
sourceComponentIds.add(obstacle.componentId)
}
}
const pointsToConnect = connection.pointsToConnect.map((point: any) => ({
...point,
}))
pointsToConnect[sourcePointIndex] = {
x: exitPoint.x,
y: exitPoint.y,
layer: exitPoint.layer,
pointId: exitPointId,
}
return { ...connection, pointsToConnect }
})
const sourceKeepouts = [...sourceComponentIds].map((componentId) => {
const componentObstacles = input.obstacles.filter(
(obstacle: any) => obstacle.componentId === componentId,
)
const minX = Math.min(
...componentObstacles.map((obstacle: any) =>
obstacle.center.x - obstacle.width / 2,
),
)
const maxX = Math.max(
...componentObstacles.map((obstacle: any) =>
obstacle.center.x + obstacle.width / 2,
),
)
const minY = Math.min(
...componentObstacles.map((obstacle: any) =>
obstacle.center.y - obstacle.height / 2,
),
)
const maxY = Math.max(
...componentObstacles.map((obstacle: any) =>
obstacle.center.y + obstacle.height / 2,
),
)
return {
obstacleId: `fanout-source-keepout:${componentId}`,
componentId,
isFanoutSourceKeepout: true,
type: "rect",
layers: ["top", "inner1", "inner2", "bottom"],
center: { x: (minX + maxX) / 2, y: (minY + maxY) / 2 },
width: maxX - minX,
height: maxY - minY,
connectedTo: [],
}
})
const viaObstacles = traces.flatMap((trace) =>
trace.route.flatMap((point: any, viaIndex: number) =>
point.route_type === "via"
? [{
obstacleId: `fanout-via:${trace.connection_name}:${viaIndex}`,
type: "rect",
center: { x: point.x, y: point.y },
width: point.via_diameter,
height: point.via_diameter,
layers: point.layers ?? [point.from_layer, point.to_layer],
connectedTo: [trace.connection_name, trace.pcb_trace_id],
}]
: [],
),
)
return {
...input,
connections: connections.filter(
(connection: any) => connection.pointsToConnect.length > 1,
),
traces,
obstacles: [
...input.obstacles.filter(
(obstacle: any) => !sourceComponentIds.has(obstacle.componentId),
),
...sourceKeepouts,
...viaObstacles,
],
}
}
class CachedSocFanoutAutorouter extends EventEmitter {
isRouting = false
private readonly output: SimpleRouteJson
constructor(input: SimpleRouteJson) {
super()
this.output = createCachedOutput(input)
}
start() {
this.isRouting = true
queueMicrotask(() => {
if (!this.isRouting) return
this.isRouting = false
this.emit("complete", {
type: "complete",
traces: cachedFanout.fanoutTraces,
})
})
}
stop() {
this.isRouting = false
}
getOutputSimpleRouteJson() {
return this.output
}
}
export const createCachedSocFanoutAutorouter = async (
input: SimpleRouteJson,
) => {
console.log(
`[SOC_FANOUT cache] loading ${cachedFanout.fanoutTraces.length} cached traces for ${input.connections.length} connections`,
)
return new CachedSocFanoutAutorouter(input)
}