@tscircuit/fanout-solver 0.0.38 → 0.0.39
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 +7 -0
- package/lib/add-via-layer-metadata.ts +48 -0
- package/lib/complete-original-endpoints.ts +30 -2
- package/lib/fanout-solver.ts +636 -14
- package/lib/geometry.ts +21 -0
- package/lib/get-routed-trace-copper.ts +15 -6
- package/lib/index.ts +3 -0
- package/lib/layer-names.ts +40 -0
- package/lib/match-bus-lengths.ts +124 -14
- package/lib/match-component-dogbone-via-sites.ts +584 -0
- package/lib/route-bus.ts +872 -112
- package/lib/route-via-minimal-winding.ts +390 -74
- package/lib/types.ts +35 -7
- package/lib/validate-fanout-solution.ts +34 -6
- package/lib/validate-routed-copper-drc.ts +47 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,13 @@ and treats each bus-layer decision atomically.
|
|
|
86
86
|
- `allowSameNetMerges` lets grouped branches such as VCC or GND reuse connected
|
|
87
87
|
copper instead of reserving artificial clearance from one another. It is
|
|
88
88
|
opt-in; different electrical nets remain hard obstacles.
|
|
89
|
+
- `allowBlindAndBuriedVias` describes the host board's manufacturing rule. It
|
|
90
|
+
defaults to `true` for standalone compatibility; hosts that manufacture
|
|
91
|
+
through-all vias should pass `false`, which reserves every copper layer in
|
|
92
|
+
route planning and emitted-copper DRC while preserving each route's logical
|
|
93
|
+
layer transition.
|
|
94
|
+
- Via-in-pad remains opt-in through `SimpleRouteJson.allowViaInPad === true`.
|
|
95
|
+
Undefined or false uses an offset dogbone, including plane terminations.
|
|
89
96
|
- Audits route continuity, unique connection coverage, boundary exits, and
|
|
90
97
|
retained downstream endpoints before marking a solution complete.
|
|
91
98
|
- `completeOriginalEndpoints` adds a bounded fail-first completion stage after
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SimpleRouteJson } from "@tscircuit/capacity-autorouter"
|
|
2
|
+
import { getViaSpanLayers } from "./layer-names"
|
|
3
|
+
import type {
|
|
4
|
+
FanoutSimplifiedPcbTrace,
|
|
5
|
+
SimpleRouteJsonWithFanoutPlanes,
|
|
6
|
+
} from "./types"
|
|
7
|
+
|
|
8
|
+
export function addViaLayerMetadataToTrace(params: {
|
|
9
|
+
trace: FanoutSimplifiedPcbTrace
|
|
10
|
+
layerNames: string[]
|
|
11
|
+
allowBlindAndBuriedVias: boolean
|
|
12
|
+
}): FanoutSimplifiedPcbTrace {
|
|
13
|
+
const { trace, layerNames, allowBlindAndBuriedVias } = params
|
|
14
|
+
return {
|
|
15
|
+
...trace,
|
|
16
|
+
route: trace.route.map((routePoint) =>
|
|
17
|
+
routePoint.route_type === "via" && !allowBlindAndBuriedVias
|
|
18
|
+
? {
|
|
19
|
+
...routePoint,
|
|
20
|
+
layers: getViaSpanLayers({
|
|
21
|
+
fromLayer: routePoint.from_layer,
|
|
22
|
+
toLayer: routePoint.to_layer,
|
|
23
|
+
layerNames,
|
|
24
|
+
allowBlindAndBuriedVias,
|
|
25
|
+
}),
|
|
26
|
+
}
|
|
27
|
+
: { ...routePoint },
|
|
28
|
+
),
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function addViaLayerMetadataToSrj(params: {
|
|
33
|
+
srj: SimpleRouteJsonWithFanoutPlanes | SimpleRouteJson
|
|
34
|
+
layerNames: string[]
|
|
35
|
+
allowBlindAndBuriedVias: boolean
|
|
36
|
+
}): SimpleRouteJsonWithFanoutPlanes {
|
|
37
|
+
const { srj, layerNames, allowBlindAndBuriedVias } = params
|
|
38
|
+
return {
|
|
39
|
+
...srj,
|
|
40
|
+
traces: (srj.traces ?? []).map((trace) =>
|
|
41
|
+
addViaLayerMetadataToTrace({
|
|
42
|
+
trace,
|
|
43
|
+
layerNames,
|
|
44
|
+
allowBlindAndBuriedVias,
|
|
45
|
+
}),
|
|
46
|
+
),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
} from "./geometry"
|
|
13
13
|
import { obstacleSharesElectricalNet } from "./net-identity"
|
|
14
14
|
import type {
|
|
15
|
-
FanoutEndpointCompletionReport,
|
|
16
15
|
FanoutDownstreamRouter,
|
|
16
|
+
FanoutEndpointCompletionReport,
|
|
17
17
|
FanoutRoutePlan,
|
|
18
18
|
Point2D,
|
|
19
19
|
} from "./types"
|
|
@@ -267,6 +267,7 @@ function findLocalBranch(params: {
|
|
|
267
267
|
viaDiameter: number
|
|
268
268
|
viaHoleDiameter: number
|
|
269
269
|
clearance: number
|
|
270
|
+
allowBlindAndBuriedVias: boolean
|
|
270
271
|
}): {
|
|
271
272
|
trace?: SimplifiedPcbTrace
|
|
272
273
|
blockingConnectionNames: string[]
|
|
@@ -280,6 +281,7 @@ function findLocalBranch(params: {
|
|
|
280
281
|
viaDiameter,
|
|
281
282
|
viaHoleDiameter,
|
|
282
283
|
clearance,
|
|
284
|
+
allowBlindAndBuriedVias,
|
|
283
285
|
} = params
|
|
284
286
|
const { outward, perpendicular } = getTerminalDirections({ inputSrj, plan })
|
|
285
287
|
const branchStarts: Array<Point2D & { layer: string }> = [
|
|
@@ -414,6 +416,7 @@ function findLocalBranch(params: {
|
|
|
414
416
|
inputSrj,
|
|
415
417
|
routedSrj: candidateSrj,
|
|
416
418
|
clearance,
|
|
419
|
+
allowBlindAndBuriedVias,
|
|
417
420
|
})
|
|
418
421
|
if (!drc.valid) {
|
|
419
422
|
if (drc.issues.length < bestIssueCount) {
|
|
@@ -457,6 +460,7 @@ function runLocalCompletionPass(params: {
|
|
|
457
460
|
viaDiameter: number
|
|
458
461
|
viaHoleDiameter: number
|
|
459
462
|
clearance: number
|
|
463
|
+
allowBlindAndBuriedVias: boolean
|
|
460
464
|
}): CompletionAttempt {
|
|
461
465
|
const {
|
|
462
466
|
inputSrj,
|
|
@@ -466,6 +470,7 @@ function runLocalCompletionPass(params: {
|
|
|
466
470
|
viaDiameter,
|
|
467
471
|
viaHoleDiameter,
|
|
468
472
|
clearance,
|
|
473
|
+
allowBlindAndBuriedVias,
|
|
469
474
|
} = params
|
|
470
475
|
const traces: SimplifiedPcbTrace[] = []
|
|
471
476
|
const failedConnectionNames: string[] = []
|
|
@@ -480,6 +485,7 @@ function runLocalCompletionPass(params: {
|
|
|
480
485
|
viaDiameter,
|
|
481
486
|
viaHoleDiameter,
|
|
482
487
|
clearance,
|
|
488
|
+
allowBlindAndBuriedVias,
|
|
483
489
|
})
|
|
484
490
|
if (result.trace) {
|
|
485
491
|
traces.push(result.trace)
|
|
@@ -506,6 +512,7 @@ function runLocalCompletionPass(params: {
|
|
|
506
512
|
inputSrj,
|
|
507
513
|
routedSrj: simpleRouteJson,
|
|
508
514
|
clearance,
|
|
515
|
+
allowBlindAndBuriedVias,
|
|
509
516
|
}),
|
|
510
517
|
}
|
|
511
518
|
}
|
|
@@ -598,8 +605,16 @@ function acceptDownstreamTraces(params: {
|
|
|
598
605
|
localTraces: SimplifiedPcbTrace[]
|
|
599
606
|
candidates: SimplifiedPcbTrace[]
|
|
600
607
|
clearance: number
|
|
608
|
+
allowBlindAndBuriedVias: boolean
|
|
601
609
|
}): SimplifiedPcbTrace[] {
|
|
602
|
-
const {
|
|
610
|
+
const {
|
|
611
|
+
inputSrj,
|
|
612
|
+
fanoutSrj,
|
|
613
|
+
localTraces,
|
|
614
|
+
candidates,
|
|
615
|
+
clearance,
|
|
616
|
+
allowBlindAndBuriedVias,
|
|
617
|
+
} = params
|
|
603
618
|
const baselineTraces = [...(fanoutSrj.traces ?? []), ...localTraces]
|
|
604
619
|
const baselineSrj = { ...fanoutSrj, traces: baselineTraces }
|
|
605
620
|
const baselineConnectivity = validateOriginalEndpointConnectivity({
|
|
@@ -638,6 +653,7 @@ function acceptDownstreamTraces(params: {
|
|
|
638
653
|
inputSrj,
|
|
639
654
|
routedSrj: combinedSrj,
|
|
640
655
|
clearance,
|
|
656
|
+
allowBlindAndBuriedVias,
|
|
641
657
|
}).valid
|
|
642
658
|
) {
|
|
643
659
|
return usefulCandidates
|
|
@@ -655,6 +671,7 @@ function acceptDownstreamTraces(params: {
|
|
|
655
671
|
inputSrj,
|
|
656
672
|
routedSrj: candidateSrj,
|
|
657
673
|
clearance,
|
|
674
|
+
allowBlindAndBuriedVias,
|
|
658
675
|
})
|
|
659
676
|
if (!drc.valid) continue
|
|
660
677
|
const before = validateOriginalEndpointConnectivity({
|
|
@@ -729,6 +746,7 @@ function findDownstreamTerminalBranch(params: {
|
|
|
729
746
|
viaDiameter: number
|
|
730
747
|
viaHoleDiameter: number
|
|
731
748
|
clearance: number
|
|
749
|
+
allowBlindAndBuriedVias: boolean
|
|
732
750
|
}): SimplifiedPcbTrace | undefined {
|
|
733
751
|
const {
|
|
734
752
|
inputSrj,
|
|
@@ -739,6 +757,7 @@ function findDownstreamTerminalBranch(params: {
|
|
|
739
757
|
viaDiameter,
|
|
740
758
|
viaHoleDiameter,
|
|
741
759
|
clearance,
|
|
760
|
+
allowBlindAndBuriedVias,
|
|
742
761
|
} = params
|
|
743
762
|
const branchStart = {
|
|
744
763
|
x: plan.exitPoint.x,
|
|
@@ -782,6 +801,7 @@ function findDownstreamTerminalBranch(params: {
|
|
|
782
801
|
inputSrj,
|
|
783
802
|
routedSrj: candidateSrj,
|
|
784
803
|
clearance,
|
|
804
|
+
allowBlindAndBuriedVias,
|
|
785
805
|
}).valid
|
|
786
806
|
) {
|
|
787
807
|
return undefined
|
|
@@ -880,6 +900,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
880
900
|
viaDiameter: number
|
|
881
901
|
viaHoleDiameter: number
|
|
882
902
|
clearance: number
|
|
903
|
+
allowBlindAndBuriedVias?: boolean
|
|
883
904
|
effort?: number
|
|
884
905
|
routeDownstreamConnections?: FanoutDownstreamRouter
|
|
885
906
|
}): CompleteOriginalEndpointsResult {
|
|
@@ -891,6 +912,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
891
912
|
viaDiameter,
|
|
892
913
|
viaHoleDiameter,
|
|
893
914
|
clearance,
|
|
915
|
+
allowBlindAndBuriedVias = true,
|
|
894
916
|
effort = 1,
|
|
895
917
|
routeDownstreamConnections,
|
|
896
918
|
} = params
|
|
@@ -899,6 +921,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
899
921
|
inputSrj,
|
|
900
922
|
routedSrj: fanoutSrj,
|
|
901
923
|
clearance,
|
|
924
|
+
allowBlindAndBuriedVias,
|
|
902
925
|
})
|
|
903
926
|
const baselineConnectivity = validateOriginalEndpointConnectivity({
|
|
904
927
|
inputSrj,
|
|
@@ -952,6 +975,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
952
975
|
viaDiameter,
|
|
953
976
|
viaHoleDiameter,
|
|
954
977
|
clearance,
|
|
978
|
+
allowBlindAndBuriedVias,
|
|
955
979
|
})
|
|
956
980
|
searchPassCount++
|
|
957
981
|
if (
|
|
@@ -995,6 +1019,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
995
1019
|
viaDiameter,
|
|
996
1020
|
viaHoleDiameter,
|
|
997
1021
|
clearance,
|
|
1022
|
+
allowBlindAndBuriedVias,
|
|
998
1023
|
})
|
|
999
1024
|
if (terminalBranch) directDownstreamTraces.push(terminalBranch)
|
|
1000
1025
|
}
|
|
@@ -1052,6 +1077,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
1052
1077
|
downstreamConnectionNames.has(trace.connection_name),
|
|
1053
1078
|
),
|
|
1054
1079
|
clearance,
|
|
1080
|
+
allowBlindAndBuriedVias,
|
|
1055
1081
|
})
|
|
1056
1082
|
} catch (error) {
|
|
1057
1083
|
errors.push(
|
|
@@ -1102,6 +1128,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
1102
1128
|
viaDiameter,
|
|
1103
1129
|
viaHoleDiameter,
|
|
1104
1130
|
clearance,
|
|
1131
|
+
allowBlindAndBuriedVias,
|
|
1105
1132
|
})
|
|
1106
1133
|
if (terminalBranch) traces.push(terminalBranch)
|
|
1107
1134
|
}
|
|
@@ -1121,6 +1148,7 @@ export function completeOriginalEndpoints(params: {
|
|
|
1121
1148
|
inputSrj,
|
|
1122
1149
|
routedSrj: simpleRouteJson,
|
|
1123
1150
|
clearance,
|
|
1151
|
+
allowBlindAndBuriedVias,
|
|
1124
1152
|
})
|
|
1125
1153
|
if (!drc.valid) {
|
|
1126
1154
|
errors.push("Final endpoint-completion output failed emitted-copper DRC")
|