@tscircuit/fanout-solver 0.0.14 → 0.0.16

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/README.md CHANGED
@@ -198,6 +198,31 @@ parameters. Each sample has one shared boundary around all of its footprints,
198
198
  and component bounds come from the exact footprinter-generated copper pad
199
199
  extents.
200
200
 
201
+ ## SRJ19 benchmark
202
+
203
+ The repository also loads all 200 samples from
204
+ [`tscircuit/dataset-srj19`](https://github.com/tscircuit/dataset-srj19) as a
205
+ pinned development dependency. The adapter keeps the complete obstacle field
206
+ but selects only connections that touch the BGA, producing progressively larger
207
+ two-layer fanout problems with opposite-layer passive overlays.
208
+
209
+ Run the full benchmark with:
210
+
211
+ ```sh
212
+ ./benchmark.sh
213
+ ```
214
+
215
+ Use `--sample sample001`, `--limit 10`, or
216
+ `--max-layer-combinations 16` for shorter runs. Partial solutions are reported
217
+ as benchmark results instead of failing the command, making current completion
218
+ rates a baseline for solver improvements. `bun run benchmark:srj19` is an alias
219
+ for the same command.
220
+
221
+ Run `bun run start` and open the `datasets/srj19` Cosmos fixture to step the
222
+ selected sample through `GenericSolverDebugger`. The page has Previous/Next,
223
+ sample dropdown, and range controls and stores the selection in the `sample`
224
+ URL parameter.
225
+
201
226
  ## Dataset 02
202
227
 
203
228
  `datasets/dataset02.ts` is the four-layer BGA400 stress benchmark. It routes
package/lib/route-bus.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  } from "./geometry"
13
13
  import { getLayerSpan } from "./layer-names"
14
14
  import type {
15
+ Bounds,
15
16
  FanoutDirection,
16
17
  FanoutRoutePlan,
17
18
  Point2D,
@@ -147,6 +148,23 @@ function getConnectionRank(
147
148
  return connectionRank
148
149
  }
149
150
 
151
+ function getRoutableBounds(
152
+ srjBounds: SimpleRouteJson["bounds"],
153
+ sharedBoundary: Bounds,
154
+ ): SimpleRouteJson["bounds"] {
155
+ // Fanout routes must reach the shared boundary and terminate exactly on it.
156
+ // When that boundary sits outside srj.bounds -- which is what
157
+ // fanoutBoundaryPadding does, since it pads the boundary without widening
158
+ // the routing area -- containment has to follow the boundary, or every plan
159
+ // is rejected before its geometry is ever considered.
160
+ return {
161
+ minX: Math.min(srjBounds.minX, sharedBoundary.minX),
162
+ maxX: Math.max(srjBounds.maxX, sharedBoundary.maxX),
163
+ minY: Math.min(srjBounds.minY, sharedBoundary.minY),
164
+ maxY: Math.max(srjBounds.maxY, sharedBoundary.maxY),
165
+ }
166
+ }
167
+
150
168
  function pointIsInsideBounds(
151
169
  point: Point2D,
152
170
  bounds: SimpleRouteJson["bounds"],
@@ -668,15 +686,17 @@ function planIsClear(params: {
668
686
  plan: FanoutRoutePlan
669
687
  otherPlans: FanoutRoutePlan[]
670
688
  srj: SimpleRouteJson
689
+ sharedBoundary: Bounds
671
690
  clearance: number
672
691
  }): boolean {
673
- const { plan, otherPlans, srj, clearance } = params
692
+ const { plan, otherPlans, srj, sharedBoundary, clearance } = params
693
+ const routableBounds = getRoutableBounds(srj.bounds, sharedBoundary)
674
694
  if (
675
- !pointIsInsideBounds(plan.exitPoint, srj.bounds) ||
695
+ !pointIsInsideBounds(plan.exitPoint, routableBounds) ||
676
696
  plan.segments.some(
677
697
  (segment) =>
678
- !pointIsInsideBounds(segment.start, srj.bounds) ||
679
- !pointIsInsideBounds(segment.end, srj.bounds),
698
+ !pointIsInsideBounds(segment.start, routableBounds) ||
699
+ !pointIsInsideBounds(segment.end, routableBounds),
680
700
  )
681
701
  ) {
682
702
  return false
@@ -814,6 +834,7 @@ function routePlaneTerminatedBus(
814
834
  plan,
815
835
  otherPlans: [...acceptedPlans, ...candidatePlans],
816
836
  srj,
837
+ sharedBoundary: bus.sharedBoundary,
817
838
  clearance,
818
839
  })
819
840
  ) {
@@ -913,6 +934,7 @@ export function routeBus(params: RouteBusParams): FanoutRoutePlan[] | null {
913
934
  plan,
914
935
  otherPlans: [...acceptedPlans, ...candidatePlans],
915
936
  srj,
937
+ sharedBoundary: bus.sharedBoundary,
916
938
  clearance,
917
939
  })
918
940
  ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/fanout-solver",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "BGA fanout solver with coordinated bus-layer escapes for SimpleRouteJson",
5
5
  "module": "lib/index.ts",
6
6
  "type": "module",
@@ -28,6 +28,7 @@
28
28
  "typecheck": "bunx tsc --noEmit",
29
29
  "test": "bun test",
30
30
  "benchmark": "bun benchmarks/run-benchmark.ts",
31
+ "benchmark:srj19": "./benchmark.sh",
31
32
  "render:dataset": "bun scripts/render-dataset-pngs.ts",
32
33
  "format": "biome format --write .",
33
34
  "format:check": "biome format ."
@@ -39,10 +40,12 @@
39
40
  },
40
41
  "devDependencies": {
41
42
  "@biomejs/biome": "2.5.5",
43
+ "@tsci/tscircuit.dataset-srj19-bga-passive-overlays": "github:tscircuit/dataset-srj19#c1206f3",
42
44
  "@tscircuit/footprinter": "0.0.394",
43
45
  "@types/bun": "1.3.14",
44
46
  "@types/react": "19.2.14",
45
47
  "@types/react-dom": "19.2.3",
48
+ "bun-match-svg": "^0.0.15",
46
49
  "circuit-json": "0.0.455",
47
50
  "react": "19.2.8",
48
51
  "react-cosmos": "7.3.0",