Skip to content
Closed
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
51 changes: 48 additions & 3 deletions lib/solvers/HyperHighDensitySolver/HyperSingleIntraNodeSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import { SingleTransitionCrossingRouteSolver } from "../HighDensitySolver/TwoRou
import { SingleTransitionIntraNodeSolver } from "../HighDensitySolver/SingleTransitionIntraNodeSolver"
import { MultiHeadPolyLineIntraNodeSolver2 } from "../HighDensitySolver/MultiHeadPolyLineIntraNodeSolver/MultiHeadPolyLineIntraNodeSolver2_Optimized"
import { MultiHeadPolyLineIntraNodeSolver3 } from "../HighDensitySolver/MultiHeadPolyLineIntraNodeSolver/MultiHeadPolyLineIntraNodeSolver3_ViaPossibilitiesSolverIntegration"
import { HighDensitySolverA01 } from "@tscircuit/high-density-a01"
import {
HighDensitySolverA01,
HighDensitySolverA02 as HighDensityA02Solver,
} from "@tscircuit/high-density-a01"
import { FixedTopologyHighDensityIntraNodeSolver } from "../FixedTopologyHighDensityIntraNodeSolver"

export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
Expand All @@ -23,6 +26,7 @@ export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
| SingleTransitionCrossingRouteSolver
| SingleTransitionIntraNodeSolver
| FixedTopologyHighDensityIntraNodeSolver
| HighDensityA02Solver
> {
override getSolverName(): string {
return "HyperSingleIntraNodeSolver"
Expand Down Expand Up @@ -59,6 +63,7 @@ export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
["closedFormSingleTrace"],
// ["closedFormTwoTrace"],
["highDensityA01"],
["highDensityA02"],
["fixedTopologyHighDensityIntraNodeSolver"],
]
}
Expand Down Expand Up @@ -198,11 +203,22 @@ export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
},
],
},
{
name: "highDensityA02",
possibleValues: [
{
HIGH_DENSITY_A02: true,
},
],
},
]
}

computeG(solver: IntraNodeRouteSolver) {
if ((solver as any) instanceof HighDensitySolverA01) {
if (
(solver as any) instanceof HighDensitySolverA01 ||
(solver as any) instanceof HighDensityA02Solver
) {
return (solver as any).iterations / 1_000_000
}
if (solver?.hyperParameters?.MULTI_HEAD_POLYLINE_SOLVER) {
Expand Down Expand Up @@ -238,6 +254,32 @@ export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
solver.MAX_ITERATIONS = 10_000_000
return solver as any
}
if (hyperParameters.HIGH_DENSITY_A02) {
const solver = new HighDensityA02Solver({
nodeWithPortPoints: this.nodeWithPortPoints,
outerGridCellSize: 0.1,
outerGridCellThickness: 2,
innerGridCellSize: 0.4,
viaDiameter: this.constructorParams.viaDiameter ?? 0.3,
viaMinDistFromBorder: 0.15,
traceMargin: 0.15,
enableDeferredConflictRepair: true,
maxDeferredRepairPasses: 48,
edgePenaltyStrength: 0.2,
// This likely needs to be corrected to use the actual trace width-
// but using anything but 0.1 for traceThickness is causing issues
// needs more debugging- repro01 in the high-density-a01 repo
// has a good reproduction
traceThickness: 0.1, // this.constructorParams.traceWidth ?? 0.15,
hyperParameters: {
greedyMultiplier: 1.2,
shuffleSeed: hyperParameters.SHUFFLE_SEED ?? 0,
ripCost: 1,
},
})
solver.MAX_ITERATIONS = 20_000_000 * this.effort
return solver as any
}
if (hyperParameters.CLOSED_FORM_TWO_TRACE_SAME_LAYER) {
return new TwoCrossingRoutesHighDensitySolver({
nodeWithPortPoints: this.nodeWithPortPoints,
Expand Down Expand Up @@ -282,7 +324,10 @@ export class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<

onSolve(solver: SupervisedSolver<IntraNodeRouteSolver>) {
let routes: HighDensityIntraNodeRoute[]
if ((solver.solver as any) instanceof HighDensitySolverA01) {
if (
(solver.solver as any) instanceof HighDensitySolverA01 ||
(solver.solver as any) instanceof HighDensityA02Solver
) {
routes = (solver.solver as any).getOutput()
} else {
routes = solver.solver.solvedRoutes
Expand Down
133 changes: 98 additions & 35 deletions lib/testing/AutoroutingPipelineDebugger.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
import { useState, useEffect, useMemo, useRef } from "react"
import { GraphicsObject, Line, Point, Rect } from "graphics-debug"
import {
InteractiveGraphics,
InteractiveGraphicsCanvas,
} from "graphics-debug/react"
import { BaseSolver } from "lib/solvers/BaseSolver"
import { combineVisualizations } from "lib/utils/combineVisualizations"
import { SimpleRouteJson } from "lib/types"
import { AssignableAutoroutingPipeline1Solver } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline1/AssignableAutoroutingPipeline1Solver"
import { AssignableAutoroutingPipeline2 } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline2/AssignableAutoroutingPipeline2"
import { AssignableAutoroutingPipeline3 } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline3/AssignableAutoroutingPipeline3"
import { AutoroutingPipeline1_OriginalUnravel } from "lib/autorouter-pipelines/AutoroutingPipeline1_OriginalUnravel/AutoroutingPipeline1_OriginalUnravel"
import {
AutoroutingPipelineSolver2_PortPointPathing,
CapacityMeshSolver,
} from "lib/autorouter-pipelines/AutoroutingPipeline2_PortPointPathing/AutoroutingPipelineSolver2_PortPointPathing"
import { AutoroutingPipelineSolver3_HgPortPointPathing } from "lib/autorouter-pipelines/AutoroutingPipeline2_PortPointPathing/AutoroutingPipelineSolver3_HgPortPointPathing"
import { AssignableAutoroutingPipeline1Solver } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline1/AssignableAutoroutingPipeline1Solver"
import { AutoroutingPipeline1_OriginalUnravel } from "lib/autorouter-pipelines/AutoroutingPipeline1_OriginalUnravel/AutoroutingPipeline1_OriginalUnravel"
import { GraphicsObject, Line, Point, Rect } from "graphics-debug"
import { limitVisualizations } from "lib/utils/limitVisualizations"
import { getNodesNearNode } from "lib/solvers/UnravelSolver/getNodesNearNode"
import { filterUnravelMultiSectionInput } from "./utils/filterUnravelMultiSectionInput"
import { convertToCircuitJson } from "./utils/convertToCircuitJson"
import { getDrcErrors } from "./getDrcErrors"
import { addVisualizationToLastStep } from "lib/utils/addVisualizationToLastStep"
import { SolveBreakpointDialog } from "./SolveBreakpointDialog"
import { CacheDebugger } from "./CacheDebugger"
import {
getGlobalInMemoryCache,
getGlobalLocalStorageCache,
} from "lib/cache/setupGlobalCaches"
import { CacheProvider } from "lib/cache/types"
import { BaseSolver } from "lib/solvers/BaseSolver"
import { getNodesNearNode } from "lib/solvers/UnravelSolver/getNodesNearNode"
import { SimpleRouteJson } from "lib/types"
import { addVisualizationToLastStep } from "lib/utils/addVisualizationToLastStep"
import { combineVisualizations } from "lib/utils/combineVisualizations"
import { limitVisualizations } from "lib/utils/limitVisualizations"
import { useEffect, useMemo, useRef, useState } from "react"
import {
AutoroutingPipelineMenuBar,
PIPELINE_OPTIONS,
type PipelineId,
EFFORT_LEVELS,
type EffortLevel,
LAYER_OVERRIDE_OPTIONS,
type LayerOverride,
PIPELINE_OPTIONS,
type PipelineId,
} from "./AutoroutingPipelineMenuBar"
import { AssignableAutoroutingPipeline2 } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline2/AssignableAutoroutingPipeline2"
import { AssignableAutoroutingPipeline3 } from "lib/autorouter-pipelines/AssignableAutoroutingPipeline3/AssignableAutoroutingPipeline3"
import { CacheDebugger } from "./CacheDebugger"
import { SolveBreakpointDialog } from "./SolveBreakpointDialog"
import { getDrcErrors } from "./getDrcErrors"
import { convertToCircuitJson } from "./utils/convertToCircuitJson"
import { filterUnravelMultiSectionInput } from "./utils/filterUnravelMultiSectionInput"

const PIPELINE_SOLVERS = {
AutoroutingPipelineSolver2_PortPointPathing,
Expand All @@ -48,6 +50,26 @@ const PIPELINE_SOLVERS = {

const PIPELINE_STORAGE_KEY = "selectedPipeline"
const EFFORT_STORAGE_KEY = "selectedEffort"
const LAYER_OVERRIDE_STORAGE_KEY = "selectedLayerOverride"

const parseLayerOverride = (value: string | null): LayerOverride => {
if (value === "auto") return "auto"
const parsed = value ? parseInt(value, 10) : Number.NaN
return LAYER_OVERRIDE_OPTIONS.includes(parsed as LayerOverride)
? (parsed as LayerOverride)
: "auto"
}

const applyLayerOverrideToSrj = (
srj: SimpleRouteJson,
layerOverride: LayerOverride,
): SimpleRouteJson => {
if (layerOverride === "auto") return srj
return {
...srj,
layerCount: layerOverride,
}
}

const sanitizeParamsForDownload = (
value: any,
Expand Down Expand Up @@ -199,23 +221,47 @@ export const AutoroutingPipelineDebugger = ({
}
}

const [layerOverride, setLayerOverrideState] = useState<LayerOverride>(() =>
parseLayerOverride(localStorage.getItem(LAYER_OVERRIDE_STORAGE_KEY)),
)

const setLayerOverride = (newLayerOverride: LayerOverride) => {
setLayerOverrideState(newLayerOverride)
try {
localStorage.setItem(LAYER_OVERRIDE_STORAGE_KEY, String(newLayerOverride))
} catch (e) {
console.warn("Could not save layer override to localStorage:", e)
}
}

const createNewSolver = (
opts: {
cacheProvider?: CacheProvider | null
pipelineId?: PipelineId
effort?: EffortLevel
layerOverride?: LayerOverride
} = {},
) => {
const cacheProviderToUse = opts.cacheProvider ?? cacheProvider
if (createSolverProp) {
return createSolverProp(srj, { cacheProvider, effort, ...opts })
return createSolverProp(
applyLayerOverrideToSrj(srj, opts.layerOverride ?? layerOverride),
{
cacheProvider: cacheProviderToUse,
effort: opts.effort ?? effort,
},
)
}
const pipelineToUse = opts.pipelineId ?? selectedPipelineId
const effortToUse = opts.effort ?? effort
const srjToUse = applyLayerOverrideToSrj(
srj,
opts.layerOverride ?? layerOverride,
)
const SolverClass = PIPELINE_SOLVERS[pipelineToUse]
return new SolverClass(srj, {
cacheProvider,
return new SolverClass(srjToUse, {
cacheProvider: cacheProviderToUse,
effort: effortToUse,
...opts,
})
}

Expand All @@ -232,29 +278,33 @@ export const AutoroutingPipelineDebugger = ({
const initialEffort = storedEffort
? (parseInt(storedEffort, 10) as EffortLevel)
: 1
const initialLayerOverride = parseLayerOverride(
localStorage.getItem(LAYER_OVERRIDE_STORAGE_KEY),
)
const initialSrj = applyLayerOverrideToSrj(srj, initialLayerOverride)
const SolverClass = PIPELINE_SOLVERS[initialPipelineId]

if (!SolverClass) {
// Fallback to default pipeline if stored ID is invalid
const fallbackClass =
PIPELINE_SOLVERS["AutoroutingPipelineSolver2_PortPointPathing"]
PIPELINE_SOLVERS.AutoroutingPipelineSolver2_PortPointPathing
return createSolverProp
? createSolverProp(srj, {
? createSolverProp(initialSrj, {
cacheProvider: initialCacheProvider,
effort: initialEffort,
})
: new fallbackClass(srj, {
: new fallbackClass(initialSrj, {
cacheProvider: initialCacheProvider,
effort: initialEffort,
})
}

return createSolverProp
? createSolverProp(srj, {
? createSolverProp(initialSrj, {
cacheProvider: initialCacheProvider,
effort: initialEffort,
})
: new SolverClass(srj, {
: new SolverClass(initialSrj, {
cacheProvider: initialCacheProvider,
effort: initialEffort,
})
Expand Down Expand Up @@ -296,6 +346,11 @@ export const AutoroutingPipelineDebugger = ({
useEffect(() => {
let intervalId: ReturnType<typeof setInterval> | undefined

if (isSolvingToBreakpointRef.current) {
setIsAnimating(false)
return
}

if (isAnimating && !solver.solved && !solver.failed) {
const speedDef = SPEED_DEFINITIONS[speedLevel]
// For speeds >= 1x (index 4+), we might still want to respect the passed-in animationSpeed prop
Expand All @@ -320,11 +375,6 @@ export const AutoroutingPipelineDebugger = ({
clearInterval(intervalId)
}
}

// Stop animation if breakpoint solving is active
if (isSolvingToBreakpointRef.current) {
setIsAnimating(false)
}
}, [isAnimating, speedLevel, solver, animationSpeed])

// Manual step function
Expand Down Expand Up @@ -755,8 +805,13 @@ export const AutoroutingPipelineDebugger = ({
selectedPipelineId={selectedPipelineId}
onSetPipelineId={(pipelineId: PipelineId) => {
setSelectedPipelineId(pipelineId)
const SolverClass = PIPELINE_SOLVERS[pipelineId]
setSolver(new SolverClass(srj, { cacheProvider, effort }))
setLayerOverride("auto")
setSolver(
createNewSolver({
pipelineId,
layerOverride: "auto",
}),
)
setDrcErrors(null)
setDrcErrorCount(0)
}}
Expand All @@ -767,6 +822,14 @@ export const AutoroutingPipelineDebugger = ({
setDrcErrors(null)
setDrcErrorCount(0)
}}
layerOverride={layerOverride}
defaultLayerCount={srj.layerCount}
onSetLayerOverride={(newLayerOverride: LayerOverride) => {
setLayerOverride(newLayerOverride)
setSolver(createNewSolver({ layerOverride: newLayerOverride }))
setDrcErrors(null)
setDrcErrorCount(0)
}}
/>
<div className="flex gap-2 mb-4 text-xs">
<button
Expand Down
Loading
Loading