Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,491 changes: 7,491 additions & 0 deletions examples/features/keepoutsolver/keepoutsolver01-input.json

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions examples/features/keepoutsolver/keepoutsolver01.fixture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { GenericSolverDebugger } from "lib/testing/GenericSolverDebugger"
import { TraceKeepoutSolver } from "lib/solvers/TraceKeepoutSolver/TraceKeepoutSolver"
import { ConnectivityMap } from "circuit-json-to-connectivity-map"
import input from "./keepoutsolver01-input.json"

export default () => {
const createSolver = () => {
const data = input[0] as any

const connMap = new ConnectivityMap(data.connMap.netMap)

return new TraceKeepoutSolver({
hdRoutes: data.hdRoutes,
obstacles: data.obstacles,
connMap,
colorMap: data.colorMap,
keepoutRadiusSchedule: data.keepoutRadiusSchedule,
})
}

return <GenericSolverDebugger createSolver={createSolver} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { getGlobalInMemoryCache } from "lib/cache/setupGlobalCaches"
import { NetToPointPairsSolver2_OffBoardConnection } from "../../solvers/NetToPointPairsSolver2_OffBoardConnection/NetToPointPairsSolver2_OffBoardConnection"
import { RectDiffPipeline } from "@tscircuit/rectdiff"
import { TraceSimplificationSolver } from "../../solvers/TraceSimplificationSolver/TraceSimplificationSolver"
import { TraceKeepoutSolver } from "../../solvers/TraceKeepoutSolver/TraceKeepoutSolver"
import { AvailableSegmentPointSolver } from "../../solvers/AvailableSegmentPointSolver/AvailableSegmentPointSolver"
import {
PortPointPathingSolver,
Expand Down Expand Up @@ -102,6 +103,7 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
strawSolver?: StrawSolver
deadEndSolver?: DeadEndSolver
traceSimplificationSolver?: TraceSimplificationSolver
traceKeepoutSolver?: TraceKeepoutSolver
availableSegmentPointSolver?: AvailableSegmentPointSolver
portPointPathingSolver?: PortPointPathingSolver
multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer
Expand Down Expand Up @@ -244,14 +246,14 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
inputNodes,
capacityMeshNodes: cms.capacityNodes!,
colorMap: cms.colorMap,
numShuffleSeeds: 2000,
numShuffleSeeds: 10000,
minAllowedBoardScore: -1,
hyperParameters: {
// 1 = 60% maximum pf (see computeSectionScore)
// 5 = 99.3% maximum pf
// 10 = 99.995% maximum pf (1 - e**(-10))
// NODE_PF_MAX_PENALTY: 10,
// RANDOM_WALK_DISTANCE: 50,
MIN_ALLOWED_BOARD_SCORE: -1,
NODE_PF_FACTOR: 10000,
FORCE_OFF_BOARD_FREQUENCY: 0.3,
CENTER_OFFSET_DIST_PENALTY_FACTOR: 1,
Expand Down Expand Up @@ -296,19 +298,19 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
},
],
),
// definePipelineStep(
// "highDensityStitchSolver",
// MultipleHighDensityRouteStitchSolver,
// (cms) => [
// {
// connections: cms.srjWithPointPairs!.connections,
// hdRoutes: cms.highDensityRouteSolver!.routes,
// colorMap: cms.colorMap,
// layerCount: cms.srj.layerCount,
// defaultViaDiameter: cms.viaDiameter,
// },
// ],
// ),
definePipelineStep(
"highDensityStitchSolver",
MultipleHighDensityRouteStitchSolver,
(cms) => [
{
connections: cms.srjWithPointPairs!.connections,
hdRoutes: cms.simpleHighDensityRouteSolver!.routes,
colorMap: cms.colorMap,
layerCount: cms.srj.layerCount,
defaultViaDiameter: cms.viaDiameter,
},
],
),
definePipelineStep(
"traceSimplificationSolver",
TraceSimplificationSolver,
Expand All @@ -328,6 +330,14 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
},
],
),
definePipelineStep("traceKeepoutSolver", TraceKeepoutSolver, (cms) => [
{
hdRoutes: cms.traceSimplificationSolver?.simplifiedHdRoutes ?? [],
obstacles: cms.srj.obstacles,
connMap: cms.connMap,
colorMap: cms.colorMap,
},
]),
]

constructor(
Expand Down Expand Up @@ -430,6 +440,7 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
const simpleHighDensityViz = this.simpleHighDensityRouteSolver?.visualize()
const highDensityStitchViz = this.highDensityStitchSolver?.visualize()
const traceSimplificationViz = this.traceSimplificationSolver?.visualize()
const traceKeepoutViz = this.traceKeepoutSolver?.visualize()
const problemOutline = this.srj.outline
const problemLines: Line[] = []

Expand Down Expand Up @@ -516,6 +527,7 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {
: null,
highDensityStitchViz,
traceSimplificationViz,
traceKeepoutViz,
this.solved
? combineVisualizations(
problemViz,
Expand Down Expand Up @@ -582,6 +594,7 @@ export class AssignableAutoroutingPipeline2 extends BaseSolver {

_getOutputHdRoutes(): HighDensityRoute[] {
return (
this.traceKeepoutSolver?.redrawnHdRoutes ??
this.traceSimplificationSolver?.simplifiedHdRoutes ??
this.highDensityStitchSolver?.mergedHdRoutes ??
this.simpleHighDensityRouteSolver?.routes ??
Expand Down
1 change: 1 addition & 0 deletions lib/data-structures/HighDensityRouteSpatialIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Segment = [Point, Point]

export type HighDensityIntraNodeRoute = {
connectionName: string // Assuming this is unique per route
rootConnectionName?: string // Parent connection for merged routes
traceThickness: number
viaDiameter: number // Now used in conflict calculation
route: Array<{ x: number; y: number; z: number }>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export class AvailableSegmentPointSolver extends BaseSolver {
const centerY = (overlap.start.y + overlap.end.y) / 2

if (maxPortPoints > 5) {
maxPortPoints = 5 + maxPortPoints / 4
maxPortPoints = 5 + Math.floor(maxPortPoints / 4)
}

// First pass: compute all XY positions and find which is closest to segment center
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ export class HyperPortPointPathingSolver extends HyperParameterSupervisorSolver<
...this.params.hyperParameters,
...hyperParameters,
MIN_ALLOWED_BOARD_SCORE:
this.params.minAllowedBoardScore ??
hyperParameters.MIN_ALLOWED_BOARD_SCORE ??
this.params.minAllowedBoardScore,
this.params.hyperParameters?.MIN_ALLOWED_BOARD_SCORE,
},
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function visualizePointPathSolver(

const red = Math.min(255, Math.floor(pf * 512))
const greenAndBlue = Math.max(0, 255 - Math.floor(pf * 512))
let color = `rgba(${red}, ${greenAndBlue}, ${greenAndBlue}, 0.3)`
let color = `rgba(${red}, ${greenAndBlue}, ${greenAndBlue}, ${pf < 0.001 ? "0.1" : "0.3"})`

if (node._containsObstacle) {
color = "rgba(255, 0, 0, 0.3)"
Expand All @@ -68,8 +68,8 @@ export function visualizePointPathSolver(

graphics.rects!.push({
center: node.center,
width: node.width * 0.9,
height: node.height * 0.9,
width: node.width - 0.2,
height: node.height - 0.2,
layer: `z${node.availableZ.join(",")}`,
fill: color,
label: `${node.capacityMeshNodeId}\npf: ${pf.toFixed(3)}, memPf: ${memPf.toFixed(3)}\nxSame: ${crossings.numSameLayerCrossings}, xLC: ${crossings.numEntryExitLayerChanges}, xTransition: ${crossings.numTransitionPairCrossings}\nobCmid: ${node._offBoardConnectedCapacityMeshNodeIds?.join(",")}\nobs: ${node._containsObstacle ? "yes" : "no"}`,
Expand Down
135 changes: 112 additions & 23 deletions lib/solvers/RouteStitchingSolver/MultipleHighDensityRouteStitchSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { mapLayerNameToZ } from "lib/utils/mapLayerNameToZ"
import { SingleHighDensityRouteStitchSolver } from "./SingleHighDensityRouteStitchSolver"
import { GraphicsObject } from "graphics-debug"
import { safeTransparentize } from "../colors"
import { ConnectivityMap } from "connectivity-map"
import { distance } from "@tscircuit/math-utils"

export type UnsolvedRoute = {
connectionName: string
Expand All @@ -14,6 +16,9 @@ export type UnsolvedRoute = {
end: { x: number; y: number; z: number }
}

const roundedPointHash = (p: { x: number; y: number; z: number }) =>
`${Math.round(p.x * 100)},${Math.round(p.y * 100)},${Math.round(p.z * 100)}`

export class MultipleHighDensityRouteStitchSolver extends BaseSolver {
unsolvedRoutes: UnsolvedRoute[]
activeSolver: SingleHighDensityRouteStitchSolver | null = null
Expand All @@ -22,39 +27,123 @@ export class MultipleHighDensityRouteStitchSolver extends BaseSolver {
defaultTraceThickness: number
defaultViaDiameter: number

constructor(opts: {
constructor(params: {
connections: SimpleRouteConnection[]
hdRoutes: HighDensityIntraNodeRoute[]
colorMap?: Record<string, string>
layerCount: number
defaultViaDiameter?: number
}) {
super()
this.colorMap = opts.colorMap ?? {}
this.colorMap = params.colorMap ?? {}

const firstRoute = opts.hdRoutes[0]
const firstRoute = params.hdRoutes[0]
this.defaultTraceThickness = firstRoute?.traceThickness ?? 0.15
this.defaultViaDiameter =
firstRoute?.viaDiameter ?? opts.defaultViaDiameter ?? 0.6

this.unsolvedRoutes = opts.connections.map((c) => ({
connectionName: c.name,
hdRoutes: opts.hdRoutes.filter((r) => r.connectionName === c.name),
start: {
...c.pointsToConnect[0],
z: mapLayerNameToZ(
getConnectionPointLayer(c.pointsToConnect[0]),
opts.layerCount,
),
},
end: {
...c.pointsToConnect[1],
z: mapLayerNameToZ(
getConnectionPointLayer(c.pointsToConnect[1]),
opts.layerCount,
),
},
}))
firstRoute?.viaDiameter ?? params.defaultViaDiameter ?? 0.6

const routeIslandConnectivityMap = new ConnectivityMap({})
const routeIslandConnections: Array<string[]> = []
const routeIslands = []

const pointHashCounts = new Map<string, number>()

for (let i = 0; i < params.hdRoutes.length; i++) {
const hdRoute = params.hdRoutes[i]
const start = hdRoute.route[0]
const end = hdRoute.route[hdRoute.route.length - 1]
routeIslandConnections.push([
`route_island_${i}`,
`${hdRoute.connectionName}:${roundedPointHash(start)}`,
`${hdRoute.connectionName}:${roundedPointHash(end)}`,
])
}
routeIslandConnectivityMap.addConnections(routeIslandConnections)
for (const routeIslandConnection of routeIslandConnections) {
for (const pointHash of routeIslandConnection.slice(1)) {
pointHashCounts.set(
pointHash,
(pointHashCounts.get(pointHash) ?? 0) + 1,
)
}
}

this.unsolvedRoutes = []

const uniqueNets = Array.from(
new Set(Object.values(routeIslandConnectivityMap.idToNetMap)),
)

for (const netName of uniqueNets) {
const netMembers =
routeIslandConnectivityMap.getIdsConnectedToNet(netName)

const hdRoutes = params.hdRoutes.filter((r, i) =>
netMembers.includes(`route_island_${i}`),
)
if (hdRoutes.length === 0) continue

const connection = params.connections.find(
(c) => c.name === hdRoutes[0].connectionName,
)!

const possibleEndpoints1 = hdRoutes.flatMap((r) => [
r.route[0],
r.route[r.route.length - 1],
])

const possibleEndpoints2 = []
for (const possibleEndpoint1 of possibleEndpoints1) {
const pointHash = `${hdRoutes[0].connectionName}:${roundedPointHash(possibleEndpoint1)}`
if (pointHashCounts.get(pointHash) === 1) {
possibleEndpoints2.push(possibleEndpoint1)
}
}
// Not sure why this happens
// If removing, make sure off-board-assignable2 doesn't break
if (possibleEndpoints2.length === 0) {
console.log("no possible endpoints, can't stitch")
continue
}

let start: { x: number; y: number; z: number }
let end: { x: number; y: number; z: number }

if (possibleEndpoints2.length !== 2) {
start = {
...connection.pointsToConnect[0],
z: mapLayerNameToZ(
getConnectionPointLayer(connection.pointsToConnect[0]),
params.layerCount,
),
}
end = {
...connection.pointsToConnect[1],
z: mapLayerNameToZ(
getConnectionPointLayer(connection.pointsToConnect[1]),
params.layerCount,
),
}
} else {
start = possibleEndpoints2[0]
end = possibleEndpoints2[1]

if (
distance(start, connection.pointsToConnect[1]) <
distance(end, connection.pointsToConnect[0])
) {
;[start, end] = [end, start]
}
}

this.unsolvedRoutes.push({
connectionName: hdRoutes[0].connectionName,
hdRoutes,
start,
end,
})
}

this.MAX_ITERATIONS = 100e3
}

Expand Down
Loading
Loading