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
19 changes: 16 additions & 3 deletions lib/solvers/SameNetViaMergerSolver/SameNetViaMergerSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { segmentToBoxMinDistance } from "@tscircuit/math-utils"

export interface SameNetViaMergerSolverInput {
inputHdRoutes: HighDensityRoute[]
/** Routed copper that participates in collision checks but is never changed. */
otherHdRoutes?: ReadonlyArray<HighDensityRoute>
obstacles: Obstacle[]
colorMap: Record<string, string>
layerCount: number
Expand All @@ -37,7 +39,11 @@ const getNetForRoute = (
connMap: ConnectivityMap,
route: HighDensityRoute,
): string => {
const net = connMap.idToNetMap[route.connectionName]
const net =
connMap.idToNetMap[route.connectionName] ??
(route.rootConnectionName
? connMap.idToNetMap[route.rootConnectionName]
: undefined)
if (!net) {
throw new Error(
`SameNetViaMergerSolver could not find net for route "${route.connectionName}"`,
Expand Down Expand Up @@ -170,6 +176,13 @@ export class SameNetViaMergerSolver extends BaseSolver {
obstacleSHI: ObstacleSpatialHashIndex
hdRouteSHI: HighDensityRouteSpatialIndex

private createHdRouteSpatialIndex(): HighDensityRouteSpatialIndex {
return new HighDensityRouteSpatialIndex([
...this.mergedViaHdRoutes,
...(this.input.otherHdRoutes ?? []),
])
}

constructor(private input: SameNetViaMergerSolverInput) {
super()
if (!input.connMap) {
Expand All @@ -192,7 +205,7 @@ export class SameNetViaMergerSolver extends BaseSolver {
"flatbush",
this.input.obstacles,
)
this.hdRouteSHI = new HighDensityRouteSpatialIndex(this.inputHdRoutes)
this.hdRouteSHI = this.createHdRouteSpatialIndex()
this.vias = []
this.offendingVias = []
this.connMap = input.connMap
Expand Down Expand Up @@ -444,7 +457,7 @@ export class SameNetViaMergerSolver extends BaseSolver {
}
}
this.rebuildVias()
this.hdRouteSHI = new HighDensityRouteSpatialIndex(this.mergedViaHdRoutes)
this.hdRouteSHI = this.createHdRouteSpatialIndex()
this.stats.mergedViaGroups = groups.length
this.stats.mergedViaCount = mergedViaCount
}
Expand Down
16 changes: 11 additions & 5 deletions lib/solvers/SimplifiedPathSolver/MultiSimplifiedPathSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class MultiSimplifiedPathSolver extends BaseSolver {
activeSubSolver: SingleSimplifiedPathSolver | null = null

unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]
otherHdRoutes: ReadonlyArray<HighDensityIntraNodeRoute>
obstacles: Obstacle[]
connMap: ConnectivityMap
colorMap: Record<string, string>
Expand All @@ -28,6 +29,8 @@ export class MultiSimplifiedPathSolver extends BaseSolver {

constructor(params: {
unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]
/** Routed copper that participates in collision checks but is never changed. */
otherHdRoutes?: ReadonlyArray<HighDensityIntraNodeRoute>
obstacles: Obstacle[]
connMap?: ConnectivityMap
colorMap?: Record<string, string>
Expand All @@ -38,11 +41,12 @@ export class MultiSimplifiedPathSolver extends BaseSolver {
this.MAX_ITERATIONS = 100e6

this.unsimplifiedHdRoutes = params.unsimplifiedHdRoutes
this.otherHdRoutes = params.otherHdRoutes ?? []
const inferredLayerCount =
Math.max(
2,
...params.unsimplifiedHdRoutes.flatMap((r) =>
r.route.map((p) => p.z + 1),
...[...params.unsimplifiedHdRoutes, ...this.otherHdRoutes].flatMap(
(r) => r.route.map((p) => p.z + 1),
),
) || 2
this.obstacles = createObjectsWithZLayers(
Expand All @@ -68,9 +72,11 @@ export class MultiSimplifiedPathSolver extends BaseSolver {

this.activeSubSolver = new SingleSimplifiedPathSolver5({
inputRoute: hdRoute,
otherHdRoutes: this.unsimplifiedHdRoutes
.slice(this.currentUnsimplifiedHdRouteIndex + 1)
.concat(this.simplifiedHdRoutes),
otherHdRoutes: this.otherHdRoutes.concat(
this.unsimplifiedHdRoutes
.slice(this.currentUnsimplifiedHdRouteIndex + 1)
.concat(this.simplifiedHdRoutes),
),
obstacles: this.obstacles,
connMap: this.connMap,
colorMap: this.colorMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ export class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {

TAIL_JUMP_RATIO: number = 0.8

private isSameNetRoute(otherRoute: HighDensityIntraNodeRoute): boolean {
const inputRouteIds = [
this.inputRoute.connectionName,
this.inputRoute.rootConnectionName,
].filter((id): id is string => id !== undefined)
const otherRouteIds = [
otherRoute.connectionName,
otherRoute.rootConnectionName,
].filter((id): id is string => id !== undefined)

return inputRouteIds.some((inputRouteId) =>
otherRouteIds.some(
(otherRouteId) =>
inputRouteId === otherRouteId ||
this.connMap.areIdsConnected(inputRouteId, otherRouteId),
),
)
}

constructor(
params: ConstructorParameters<typeof SingleSimplifiedPathSolver>[0],
) {
Expand Down Expand Up @@ -130,12 +149,7 @@ export class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {

this.filteredObstaclePathSegments = this.otherHdRoutes.flatMap(
(hdRoute) => {
if (
this.connMap.areIdsConnected(
this.inputRoute.connectionName,
hdRoute.connectionName,
)
) {
if (this.isSameNetRoute(hdRoute)) {
return []
}

Expand All @@ -158,12 +172,7 @@ export class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {
this.segmentTree = new SegmentTree(this.filteredObstaclePathSegments)

this.filteredVias = this.otherHdRoutes.flatMap((hdRoute) => {
if (
this.connMap.areIdsConnected(
this.inputRoute.connectionName,
hdRoute.connectionName,
)
) {
if (this.isSameNetRoute(hdRoute)) {
return []
}

Expand Down Expand Up @@ -256,12 +265,7 @@ export class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {

// Collect jumper pads from other routes as obstacles
this.filteredJumperPads = this.otherHdRoutes.flatMap((hdRoute) => {
if (
this.connMap.areIdsConnected(
this.inputRoute.connectionName,
hdRoute.connectionName,
)
) {
if (this.isSameNetRoute(hdRoute)) {
return []
}

Expand Down
37 changes: 37 additions & 0 deletions lib/solvers/TraceSimplificationSolver/TraceSimplificationSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class TraceSimplificationSolver extends BaseSolver {
* - defaultViaDiameter: Default diameter for vias
* - layerCount: Number of routing layers
* - minTraceToPadEdgeClearance: Minimum trace-edge clearance to pads/vias
* - otherHdRoutes: Immutable routed traces to avoid while simplifying
* - iterations: Number of complete simplification iterations (default: 2)
*/
constructor(
Expand All @@ -83,6 +84,7 @@ export class TraceSimplificationSolver extends BaseSolver {
readonly defaultViaDiameter: number
readonly layerCount: number
readonly minTraceToPadEdgeClearance?: number
readonly otherHdRoutes?: ReadonlyArray<HighDensityRoute>
},
) {
super()
Expand Down Expand Up @@ -229,6 +231,7 @@ export class TraceSimplificationSolver extends BaseSolver {
case "via_removal":
this.activeSubSolver = new UselessViaRemovalSolver({
unsimplifiedHdRoutes: this.hdRoutes,
otherHdRoutes: [...(this.simplificationConfig.otherHdRoutes ?? [])],
obstacles: [...this.simplificationConfig.obstacles],
colorMap: { ...this.simplificationConfig.colorMap },
layerCount: this.simplificationConfig.layerCount,
Expand All @@ -250,6 +253,7 @@ export class TraceSimplificationSolver extends BaseSolver {
case "via_merging":
this.activeSubSolver = new SameNetViaMergerSolver({
inputHdRoutes: this.hdRoutes,
otherHdRoutes: [...(this.simplificationConfig.otherHdRoutes ?? [])],
obstacles: [...this.simplificationConfig.obstacles],
colorMap: { ...this.simplificationConfig.colorMap },
layerCount: this.simplificationConfig.layerCount,
Expand All @@ -265,6 +269,7 @@ export class TraceSimplificationSolver extends BaseSolver {
case "path_simplification":
this.activeSubSolver = new MultiSimplifiedPathSolver({
unsimplifiedHdRoutes: this.hdRoutes,
otherHdRoutes: [...(this.simplificationConfig.otherHdRoutes ?? [])],
obstacles: [...this.simplificationConfig.obstacles],
connMap: this.simplificationConfig.connMap,
colorMap: { ...this.simplificationConfig.colorMap },
Expand Down Expand Up @@ -327,6 +332,38 @@ export class TraceSimplificationSolver extends BaseSolver {
})
}

// Draw immutable routed copper as subdued, dashed layer-colored peers.
for (const route of this.simplificationConfig.otherHdRoutes ?? []) {
for (let i = 0; i < route.route.length - 1; i++) {
const current = route.route[i]
const next = route.route[i + 1]
if (current.z !== next.z) continue

visualization.lines.push({
points: [
{ x: current.x, y: current.y },
{ x: next.x, y: next.y },
],
strokeColor:
current.z === 0
? "rgba(160, 32, 32, 0.55)"
: "rgba(32, 32, 160, 0.55)",
strokeWidth: route.traceThickness,
strokeDash: [0.08, 0.08],
label: `${route.connectionName} immutable (z=${current.z})`,
})
}

for (const via of route.vias) {
visualization.circles.push({
center: { x: via.x, y: via.y },
radius: route.viaDiameter / 2,
fill: "rgba(96, 96, 96, 0.45)",
label: `${route.connectionName} immutable via`,
})
}
}

// Draw output routes and vias
for (const route of this.hdRoutes) {
if (route.route.length === 0) continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import type { ConnectivityMap } from "circuit-json-to-connectivity-map"

export interface UselessViaRemovalSolverInput {
unsimplifiedHdRoutes: HighDensityRoute[]
/** Routed copper that participates in collision checks but is never changed. */
otherHdRoutes?: ReadonlyArray<HighDensityRoute>
obstacles: Obstacle[]
colorMap: Record<string, string>
layerCount: number
Expand Down Expand Up @@ -52,9 +54,10 @@ export class UselessViaRemovalSolver extends BaseSolver {
"flatbush",
this.input.obstacles,
)
this.hdRouteSHI = new HighDensityRouteSpatialIndex(
this.unsimplifiedHdRoutes,
)
this.hdRouteSHI = new HighDensityRouteSpatialIndex([
...this.unsimplifiedHdRoutes,
...(input.otherHdRoutes ?? []),
])
}

_step() {
Expand Down
Loading
Loading