@tscircuit/fanout-solver 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/fanout-solver.ts
CHANGED
|
@@ -8,7 +8,10 @@ import { buildOutputSimpleRouteJson } from "./build-output"
|
|
|
8
8
|
import { distanceSegmentToObstacle } from "./geometry"
|
|
9
9
|
import { getCopperLayerColor } from "./layer-colors"
|
|
10
10
|
import { generateLayerAssignments, getCopperLayerNames } from "./layer-names"
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
prepareFanoutBuses,
|
|
13
|
+
resolveAvailableBoundaryRegions,
|
|
14
|
+
} from "./prepare-buses"
|
|
12
15
|
import { routeBus } from "./route-bus"
|
|
13
16
|
import { routeSingleLayerWithAdaptiveExits } from "./route-single-layer-adaptive-exits"
|
|
14
17
|
import { routeSingleLayerWithPushAndShove } from "./route-single-layer-push-shove"
|
|
@@ -404,9 +407,13 @@ export class FanoutSolver extends BaseSolver {
|
|
|
404
407
|
}
|
|
405
408
|
const singleLayerPlans =
|
|
406
409
|
routeSingleLayerWithPushAndShove(singleLayerParams) ??
|
|
407
|
-
(this.config.singleLayerAdaptiveExits
|
|
408
|
-
|
|
409
|
-
|
|
410
|
+
(this.config.singleLayerAdaptiveExits
|
|
411
|
+
? routeSingleLayerWithAdaptiveExits({
|
|
412
|
+
...singleLayerParams,
|
|
413
|
+
availableBoundaryRegions: resolveAvailableBoundaryRegions(
|
|
414
|
+
this.options.availableCornersAndSides,
|
|
415
|
+
),
|
|
416
|
+
})
|
|
410
417
|
: null)
|
|
411
418
|
if (singleLayerPlans) {
|
|
412
419
|
plans.push(...singleLayerPlans)
|
package/lib/prepare-buses.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
PreparedConnection,
|
|
18
18
|
} from "./types"
|
|
19
19
|
|
|
20
|
-
interface AvailableBoundaryRegion {
|
|
20
|
+
export interface AvailableBoundaryRegion {
|
|
21
21
|
direction: FanoutDirection
|
|
22
22
|
preferredExit: FanoutBorderTarget
|
|
23
23
|
}
|
|
@@ -407,7 +407,7 @@ function resolvePreferredExit(
|
|
|
407
407
|
return value
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
function resolveAvailableBoundaryRegions(
|
|
410
|
+
export function resolveAvailableBoundaryRegions(
|
|
411
411
|
value: readonly FanoutAvailableCornerAndSideInput[] | undefined,
|
|
412
412
|
): AvailableBoundaryRegion[] | undefined {
|
|
413
413
|
if (value === undefined) return undefined
|
|
@@ -768,7 +768,7 @@ function getDistanceToBoundary(
|
|
|
768
768
|
}
|
|
769
769
|
}
|
|
770
770
|
|
|
771
|
-
function getRegionAnchor(
|
|
771
|
+
export function getRegionAnchor(
|
|
772
772
|
region: AvailableBoundaryRegion,
|
|
773
773
|
boundary: Bounds,
|
|
774
774
|
): number {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
distanceSegmentToObstacle,
|
|
10
10
|
distanceSegmentToSegment,
|
|
11
11
|
} from "./geometry"
|
|
12
|
+
import { type AvailableBoundaryRegion, getRegionAnchor } from "./prepare-buses"
|
|
12
13
|
import type {
|
|
13
14
|
FanoutDirection,
|
|
14
15
|
FanoutRoutePlan,
|
|
@@ -23,6 +24,7 @@ interface FlowRoutingParams {
|
|
|
23
24
|
buses: PreparedBus[]
|
|
24
25
|
traceWidth: number
|
|
25
26
|
clearance: number
|
|
27
|
+
availableBoundaryRegions?: AvailableBoundaryRegion[]
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
interface FlowItem {
|
|
@@ -449,6 +451,7 @@ function createFlowGrid(params: {
|
|
|
449
451
|
|
|
450
452
|
function routeDirectionGroup(params: {
|
|
451
453
|
direction: FanoutDirection | "any"
|
|
454
|
+
availableDirections?: ReadonlySet<FanoutDirection>
|
|
452
455
|
items: FlowItem[]
|
|
453
456
|
grid: FlowGrid
|
|
454
457
|
obstacles: Obstacle[]
|
|
@@ -460,6 +463,7 @@ function routeDirectionGroup(params: {
|
|
|
460
463
|
}): DirectionGroupResult | null {
|
|
461
464
|
const {
|
|
462
465
|
direction,
|
|
466
|
+
availableDirections,
|
|
463
467
|
items,
|
|
464
468
|
grid,
|
|
465
469
|
obstacles,
|
|
@@ -695,10 +699,14 @@ function routeDirectionGroup(params: {
|
|
|
695
699
|
}
|
|
696
700
|
const isTarget =
|
|
697
701
|
(direction === "any" &&
|
|
698
|
-
(
|
|
699
|
-
column ===
|
|
700
|
-
|
|
701
|
-
|
|
702
|
+
(((!availableDirections || availableDirections.has("left")) &&
|
|
703
|
+
column === 0) ||
|
|
704
|
+
((!availableDirections || availableDirections.has("right")) &&
|
|
705
|
+
column === columnCount - 1) ||
|
|
706
|
+
((!availableDirections || availableDirections.has("down")) &&
|
|
707
|
+
row === 0) ||
|
|
708
|
+
((!availableDirections || availableDirections.has("up")) &&
|
|
709
|
+
row === rowCount - 1))) ||
|
|
702
710
|
(direction === "left" && column === 0) ||
|
|
703
711
|
(direction === "right" && column === columnCount - 1) ||
|
|
704
712
|
(direction === "down" && row === 0) ||
|
|
@@ -965,8 +973,19 @@ function routeWithAdaptiveExits(params: {
|
|
|
965
973
|
obstacles: Obstacle[]
|
|
966
974
|
traceWidth: number
|
|
967
975
|
clearance: number
|
|
976
|
+
availableBoundaryRegions?: AvailableBoundaryRegion[]
|
|
968
977
|
}): FanoutRoutePlan[] | null {
|
|
969
|
-
const {
|
|
978
|
+
const {
|
|
979
|
+
items,
|
|
980
|
+
grid,
|
|
981
|
+
obstacles,
|
|
982
|
+
traceWidth,
|
|
983
|
+
clearance,
|
|
984
|
+
availableBoundaryRegions,
|
|
985
|
+
} = params
|
|
986
|
+
const availableDirections = availableBoundaryRegions
|
|
987
|
+
? new Set(availableBoundaryRegions.map((region) => region.direction))
|
|
988
|
+
: undefined
|
|
970
989
|
const mergeItems = new Set(
|
|
971
990
|
items.filter(
|
|
972
991
|
(item) =>
|
|
@@ -985,6 +1004,7 @@ function routeWithAdaptiveExits(params: {
|
|
|
985
1004
|
) {
|
|
986
1005
|
const result = routeDirectionGroup({
|
|
987
1006
|
direction: "any",
|
|
1007
|
+
availableDirections,
|
|
988
1008
|
items: directlyRoutedItems,
|
|
989
1009
|
grid,
|
|
990
1010
|
obstacles,
|
|
@@ -1115,14 +1135,31 @@ function routeWithAdaptiveExits(params: {
|
|
|
1115
1135
|
plan.exitPoint,
|
|
1116
1136
|
grid.boundary,
|
|
1117
1137
|
)
|
|
1118
|
-
if (
|
|
1138
|
+
if (
|
|
1139
|
+
!direction ||
|
|
1140
|
+
(availableDirections && !availableDirections.has(direction))
|
|
1141
|
+
) {
|
|
1142
|
+
return null
|
|
1143
|
+
}
|
|
1119
1144
|
const item = items.find(
|
|
1120
1145
|
(candidate) =>
|
|
1121
1146
|
candidate.connection.connection.name === plan.connectionName,
|
|
1122
1147
|
)!
|
|
1123
1148
|
item.bus.direction = direction
|
|
1149
|
+
const compatibleRegions = availableBoundaryRegions?.filter(
|
|
1150
|
+
(region) => region.direction === direction,
|
|
1151
|
+
)
|
|
1152
|
+
const exitCoordinate =
|
|
1153
|
+
direction === "up" || direction === "down"
|
|
1154
|
+
? plan.exitPoint.x
|
|
1155
|
+
: plan.exitPoint.y
|
|
1124
1156
|
item.bus.preferredExit =
|
|
1125
|
-
|
|
1157
|
+
compatibleRegions?.toSorted(
|
|
1158
|
+
(first, second) =>
|
|
1159
|
+
Math.abs(exitCoordinate - getRegionAnchor(first, grid.boundary)) -
|
|
1160
|
+
Math.abs(exitCoordinate - getRegionAnchor(second, grid.boundary)),
|
|
1161
|
+
)[0]?.preferredExit ??
|
|
1162
|
+
(direction === "up" ? "top" : direction === "down" ? "bottom" : direction)
|
|
1126
1163
|
plan.direction = direction
|
|
1127
1164
|
}
|
|
1128
1165
|
const planByConnectionName = new Map(
|
|
@@ -1136,7 +1173,7 @@ function routeWithAdaptiveExits(params: {
|
|
|
1136
1173
|
export function routeSingleLayerWithAdaptiveExits(
|
|
1137
1174
|
params: FlowRoutingParams,
|
|
1138
1175
|
): FanoutRoutePlan[] | null {
|
|
1139
|
-
const { srj, buses, traceWidth, clearance } = params
|
|
1176
|
+
const { srj, buses, traceWidth, clearance, availableBoundaryRegions } = params
|
|
1140
1177
|
if (buses.some((bus) => bus.connections.length !== 1)) return null
|
|
1141
1178
|
const items = buses.flatMap((bus) =>
|
|
1142
1179
|
bus.connections.map(
|
|
@@ -1173,6 +1210,7 @@ export function routeSingleLayerWithAdaptiveExits(
|
|
|
1173
1210
|
obstacles: topObstacles,
|
|
1174
1211
|
traceWidth,
|
|
1175
1212
|
clearance,
|
|
1213
|
+
availableBoundaryRegions,
|
|
1176
1214
|
})
|
|
1177
1215
|
if (adaptivePlans) return adaptivePlans
|
|
1178
1216
|
return null
|