Skip to content

Commit 4dcfbf0

Browse files
committed
perf: optimize Bug 101 Pipeline 7 routing
1 parent d3e851f commit 4dcfbf0

27 files changed

Lines changed: 2058 additions & 53 deletions

fixtures/bug-reports/bugreport101-cm5-spi-routing-timeout/bugreport101-cm5-spi-routing-timeout.fixture.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default () => {
3030
...opts,
3131
cacheProvider: null,
3232
effort: 1,
33+
experimentalHighDensitySearchOptimization: true,
3334
})
3435
}
3536
/>

lib/autorouter-pipelines/AutoroutingPipeline7_MultiGraph/AutoroutingPipelineSolver7_MultiGraph.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ interface CapacityMeshSolverOptions {
8686
minNodeArea?: number
8787
visualizationTraceColorMode?: TraceColorMode
8888
powerTraceExpansion?: PowerTraceExpanderOptions
89+
/**
90+
* Enables bounded, output-changing high-density repair search. Enlarged
91+
* solutions may be retained as unvalidated seeds for later DRC repair.
92+
*/
93+
experimentalHighDensitySearchOptimization?: boolean
8994
}
9095
export type AutoroutingPipelineSolverOptions = CapacityMeshSolverOptions
9196

@@ -483,6 +488,7 @@ export class AutoroutingPipelineSolver7_MultiGraph extends BaseSolver {
483488
connections,
484489
layerCount: cms.srj.layerCount,
485490
effort: cms.effort,
491+
tinyPipelineStepsPerIteration: 1_000,
486492
preserveTerminalPcbPortIds: true,
487493
minViaPadDiameter: cms.viaDiameter,
488494
flags: {
@@ -536,6 +542,8 @@ export class AutoroutingPipelineSolver7_MultiGraph extends BaseSolver {
536542
cms.portPointPathingSolver?.getOutput().nodesWithPortPoints ?? []
537543
const nodePortPointsSource =
538544
uniformNodes.length > 0 ? uniformNodes : fallbackNodes
545+
const useExperimentalHighDensitySearchOptimization =
546+
cms.opts.experimentalHighDensitySearchOptimization === true
539547

540548
cms.highDensityNodePortPoints = structuredClone(nodePortPointsSource)
541549

@@ -559,6 +567,18 @@ export class AutoroutingPipelineSolver7_MultiGraph extends BaseSolver {
559567
obstacles: cms.srj.obstacles,
560568
layerCount: cms.srj.layerCount,
561569
useGrowShrinkHighDensityIntraNodeSolver: true,
570+
growShrinkMaxInitialScaleSupervisorIterations:
571+
useExperimentalHighDensitySearchOptimization ? 50_000 : undefined,
572+
growShrinkMaxTotalGrownScaleSupervisorIterations:
573+
useExperimentalHighDensitySearchOptimization ? 25_000 : undefined,
574+
// The enlarged solve is a fast seed; later DRC stages evaluate and
575+
// attempt to repair its coordinate-only post-shrink geometry.
576+
growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure:
577+
useExperimentalHighDensitySearchOptimization,
578+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion:
579+
useExperimentalHighDensitySearchOptimization,
580+
includeSyntheticPortBoundsForExternalSolvers:
581+
useExperimentalHighDensitySearchOptimization,
562582
preserveTerminalPcbPortIds: true,
563583
growShrinkFallbackToInvalidGeometryOnFailure: true,
564584
captureSearchDebug: false,

lib/autorouter-pipelines/AutoroutingPipeline7_MultiGraph/create-pipeline7-autorouting-drc-evaluator.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import {
44
type SimpleRouteJson as RepairSimpleRouteJson,
55
type SimplifiedPcbTraces as RepairSimplifiedPcbTraces,
66
} from "high-density-repair03/lib"
7+
import stableStringify from "fast-json-stable-stringify"
78
import type { SimpleRouteJson } from "lib/types"
9+
import type { HighDensityRoute } from "lib/types/high-density-types"
810
import { getViaDimensions } from "lib/utils/getViaDimensions"
911
import {
1012
type ConvertPipeline7HdRoutesOptions,
@@ -50,12 +52,36 @@ export const createPipeline7AutoroutingDrcEvaluator = (
5052
const convertCandidateRoutes =
5153
createPipeline7HdRoutesToSimplifiedPcbTracesConverter(conversionOptions)
5254
const originalTraces = conversionOptions.originalSrj.traces ?? []
55+
const routeGeometryIdByKey = new Map<string, number>()
56+
const resultByBoardGeometryKey = new Map<string, ReturnType<DrcEvaluator>>()
57+
let nextRouteGeometryId = 0
5358

54-
return ({ routes, hdRoutes }) => {
59+
const getRouteGeometryId = (route: HighDensityRoute): number => {
60+
const routeGeometryKey = stableStringify(route)
61+
const existingId = routeGeometryIdByKey.get(routeGeometryKey)
62+
if (existingId !== undefined) return existingId
63+
const routeGeometryId = nextRouteGeometryId
64+
nextRouteGeometryId += 1
65+
routeGeometryIdByKey.set(routeGeometryKey, routeGeometryId)
66+
return routeGeometryId
67+
}
68+
69+
const getBoardGeometryKey = (routes: HighDensityRoute[]): string => {
70+
const routeGeometryIds: number[] = []
71+
for (const route of routes) {
72+
routeGeometryIds.push(getRouteGeometryId(route))
73+
}
74+
return routeGeometryIds.join(",")
75+
}
76+
77+
const evaluator: DrcEvaluator = ({ routes, hdRoutes }) => {
5578
const evaluatedRoutes = routes ?? hdRoutes
5679
if (!evaluatedRoutes) {
5780
throw new Error("Pipeline7 autorouting DRC evaluation requires HD routes")
5881
}
82+
const boardGeometryKey = getBoardGeometryKey(evaluatedRoutes)
83+
const cachedResult = resultByBoardGeometryKey.get(boardGeometryKey)
84+
if (cachedResult !== undefined) return cachedResult
5985

6086
const candidateTraces = convertCandidateRoutes(evaluatedRoutes)
6187
const tracesToEvaluate = (
@@ -64,6 +90,10 @@ export const createPipeline7AutoroutingDrcEvaluator = (
6490
: candidateTraces
6591
) as RepairSimplifiedPcbTraces
6692

67-
return engine.evaluate(tracesToEvaluate)
93+
const result = engine.evaluate(tracesToEvaluate)
94+
resultByBoardGeometryKey.set(boardGeometryKey, result)
95+
return result
6896
}
97+
evaluator.consumesHdRoutesDirectly = true
98+
return evaluator
6999
}

lib/solvers/HighDensitySolver/HighDensitySolver.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ export class HighDensitySolver extends BaseSolver {
6060
useGrowShrinkHighDensityIntraNodeSolver: boolean
6161
preserveTerminalPcbPortIds: boolean
6262
growShrinkMaxInnerIterationsPerGrowthAttempt?: number
63+
growShrinkMaxInitialScaleSupervisorIterations?: number
64+
growShrinkMaxTotalGrownScaleSupervisorIterations?: number
65+
growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure: boolean
66+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion: boolean
67+
includeSyntheticPortBoundsForExternalSolvers: boolean
6368
growShrinkFallbackToInvalidGeometryOnFailure: boolean
6469
growShrinkSolutionValidator?: (routes: HighDensityIntraNodeRoute[]) => boolean
6570
captureSearchDebug: boolean
@@ -95,6 +100,11 @@ export class HighDensitySolver extends BaseSolver {
95100
useGrowShrinkHighDensityIntraNodeSolver,
96101
preserveTerminalPcbPortIds,
97102
growShrinkMaxInnerIterationsPerGrowthAttempt,
103+
growShrinkMaxInitialScaleSupervisorIterations,
104+
growShrinkMaxTotalGrownScaleSupervisorIterations,
105+
growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure,
106+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion,
107+
includeSyntheticPortBoundsForExternalSolvers,
98108
growShrinkFallbackToInvalidGeometryOnFailure,
99109
growShrinkSolutionValidator,
100110
captureSearchDebug,
@@ -111,6 +121,11 @@ export class HighDensitySolver extends BaseSolver {
111121
useGrowShrinkHighDensityIntraNodeSolver?: boolean
112122
preserveTerminalPcbPortIds?: boolean
113123
growShrinkMaxInnerIterationsPerGrowthAttempt?: number
124+
growShrinkMaxInitialScaleSupervisorIterations?: number
125+
growShrinkMaxTotalGrownScaleSupervisorIterations?: number
126+
growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure?: boolean
127+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion?: boolean
128+
includeSyntheticPortBoundsForExternalSolvers?: boolean
114129
growShrinkFallbackToInvalidGeometryOnFailure?: boolean
115130
growShrinkSolutionValidator?: (
116131
routes: HighDensityIntraNodeRoute[],
@@ -137,6 +152,16 @@ export class HighDensitySolver extends BaseSolver {
137152
this.preserveTerminalPcbPortIds = preserveTerminalPcbPortIds ?? false
138153
this.growShrinkMaxInnerIterationsPerGrowthAttempt =
139154
growShrinkMaxInnerIterationsPerGrowthAttempt
155+
this.growShrinkMaxInitialScaleSupervisorIterations =
156+
growShrinkMaxInitialScaleSupervisorIterations
157+
this.growShrinkMaxTotalGrownScaleSupervisorIterations =
158+
growShrinkMaxTotalGrownScaleSupervisorIterations
159+
this.growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure =
160+
growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure ?? false
161+
this.prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion =
162+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion ?? false
163+
this.includeSyntheticPortBoundsForExternalSolvers =
164+
includeSyntheticPortBoundsForExternalSolvers ?? false
140165
this.growShrinkFallbackToInvalidGeometryOnFailure =
141166
growShrinkFallbackToInvalidGeometryOnFailure ?? false
142167
this.growShrinkSolutionValidator = growShrinkSolutionValidator
@@ -156,6 +181,7 @@ export class HighDensitySolver extends BaseSolver {
156181
solverNodeCount: {} as Record<string, number>,
157182
difficultNodePfs: {} as Record<string, number[]>,
158183
highDensityResizeCount: 0,
184+
highDensityUnvalidatedRepairSeedCount: 0,
159185
}
160186
}
161187

@@ -283,6 +309,10 @@ export class HighDensitySolver extends BaseSolver {
283309
if (!(solver instanceof GrowShrinkHighDensityIntraNodeSolver)) return
284310
this.stats.highDensityResizeCount =
285311
(this.stats.highDensityResizeCount ?? 0) + solver.growthAttempts
312+
if (solver.stats.unvalidatedPostShrinkRepairSeed) {
313+
this.stats.highDensityUnvalidatedRepairSeedCount =
314+
(this.stats.highDensityUnvalidatedRepairSeedCount ?? 0) + 1
315+
}
286316
}
287317

288318
private getSolvedRoutesWithTerminalPcbPortIds(
@@ -383,6 +413,16 @@ export class HighDensitySolver extends BaseSolver {
383413
layerCount: this.layerCount,
384414
maxInnerIterationsPerGrowthAttempt:
385415
this.growShrinkMaxInnerIterationsPerGrowthAttempt,
416+
maxInitialScaleSupervisorIterations:
417+
this.growShrinkMaxInitialScaleSupervisorIterations,
418+
maxTotalGrownScaleSupervisorIterations:
419+
this.growShrinkMaxTotalGrownScaleSupervisorIterations,
420+
tryLargestScaleAsRepairSeedAfterInitialFailure:
421+
this.growShrinkTryLargestScaleAsRepairSeedAfterInitialFailure,
422+
prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion:
423+
this.prioritizeSolvedSegmentProgressBeforeAdaptiveExpansion,
424+
includeSyntheticPortBoundsForExternalSolvers:
425+
this.includeSyntheticPortBoundsForExternalSolvers,
386426
fallbackToInvalidGeometryOnFailure:
387427
this.growShrinkFallbackToInvalidGeometryOnFailure,
388428
growShrinkSolutionValidator: this.growShrinkSolutionValidator,

0 commit comments

Comments
 (0)