@tscircuit/core 0.0.1853 → 0.0.1855
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/dist/index.js +142 -43
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -18308,6 +18308,10 @@ function distanceSegmentToObstacle(segment2, obstacle) {
|
|
|
18308
18308
|
function segmentsAreClear(first, second, clearance) {
|
|
18309
18309
|
if (first.layer !== second.layer) return true;
|
|
18310
18310
|
const requiredDistance = (first.width + second.width) / 2 + clearance;
|
|
18311
|
+
const broadPhaseDistance = requiredDistance + EPSILON;
|
|
18312
|
+
if (Math.min(first.start.x, first.end.x) - Math.max(second.start.x, second.end.x) > broadPhaseDistance || Math.min(second.start.x, second.end.x) - Math.max(first.start.x, first.end.x) > broadPhaseDistance || Math.min(first.start.y, first.end.y) - Math.max(second.start.y, second.end.y) > broadPhaseDistance || Math.min(second.start.y, second.end.y) - Math.max(first.start.y, first.end.y) > broadPhaseDistance) {
|
|
18313
|
+
return true;
|
|
18314
|
+
}
|
|
18311
18315
|
return distanceSegmentToSegment(
|
|
18312
18316
|
first.start,
|
|
18313
18317
|
first.end,
|
|
@@ -21755,6 +21759,13 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21755
21759
|
}));
|
|
21756
21760
|
const boundaryDirection = getDirectionForExitEdge(bus.exitEdge);
|
|
21757
21761
|
const sharesNet = (first, second) => first === second || allowSameNetMerges && connectionsShareElectricalNet(srj, first, second);
|
|
21762
|
+
const boundedBlockingSegments = blockingSegments.map((blocker) => ({
|
|
21763
|
+
...blocker,
|
|
21764
|
+
minX: Math.min(blocker.segment.start.x, blocker.segment.end.x),
|
|
21765
|
+
maxX: Math.max(blocker.segment.start.x, blocker.segment.end.x),
|
|
21766
|
+
minY: Math.min(blocker.segment.start.y, blocker.segment.end.y),
|
|
21767
|
+
maxY: Math.max(blocker.segment.start.y, blocker.segment.end.y)
|
|
21768
|
+
}));
|
|
21758
21769
|
const allBlockingVias = [...blockingVias, ...terminalVias];
|
|
21759
21770
|
const maximumViaToTraceDistance = allBlockingVias.reduce(
|
|
21760
21771
|
(maximum, { via }) => Math.max(maximum, via.diameter / 2 + traceWidth / 2 + clearance),
|
|
@@ -21776,6 +21787,10 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21776
21787
|
const segmentIsClear = (params2) => {
|
|
21777
21788
|
const { segment: segment2, terminal, acceptedAttemptSegments } = params2;
|
|
21778
21789
|
const connectionName = terminal.connection.connection.name;
|
|
21790
|
+
const segmentMinX = Math.min(segment2.start.x, segment2.end.x);
|
|
21791
|
+
const segmentMaxX = Math.max(segment2.start.x, segment2.end.x);
|
|
21792
|
+
const segmentMinY = Math.min(segment2.start.y, segment2.end.y);
|
|
21793
|
+
const segmentMaxY = Math.max(segment2.start.y, segment2.end.y);
|
|
21779
21794
|
const requiredObstacleClearance = segment2.width / 2 + clearance;
|
|
21780
21795
|
for (const obstacle of targetLayerObstacleIndex.querySegment(
|
|
21781
21796
|
segment2,
|
|
@@ -21788,21 +21803,25 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21788
21803
|
return false;
|
|
21789
21804
|
}
|
|
21790
21805
|
}
|
|
21791
|
-
for (const blocker of
|
|
21806
|
+
for (const blocker of boundedBlockingSegments) {
|
|
21792
21807
|
if (sharesNet(connectionName, blocker.connectionName)) continue;
|
|
21808
|
+
const margin = (segment2.width + blocker.segment.width) / 2 + clearance;
|
|
21809
|
+
if (segmentMaxX + margin < blocker.minX || segmentMinX - margin > blocker.maxX || segmentMaxY + margin < blocker.minY || segmentMinY - margin > blocker.maxY) {
|
|
21810
|
+
continue;
|
|
21811
|
+
}
|
|
21793
21812
|
if (distanceSegmentToSegment(
|
|
21794
21813
|
segment2.start,
|
|
21795
21814
|
segment2.end,
|
|
21796
21815
|
blocker.segment.start,
|
|
21797
21816
|
blocker.segment.end
|
|
21798
|
-
) <
|
|
21817
|
+
) < margin - EPSILON7) {
|
|
21799
21818
|
return false;
|
|
21800
21819
|
}
|
|
21801
21820
|
}
|
|
21802
21821
|
for (const blocker of acceptedAttemptSegments) {
|
|
21803
21822
|
if (sharesNet(connectionName, blocker.connectionName)) continue;
|
|
21804
21823
|
const margin = (segment2.width + blocker.segment.width) / 2 + clearance;
|
|
21805
|
-
if (
|
|
21824
|
+
if (segmentMaxX + margin < Math.min(blocker.segment.start.x, blocker.segment.end.x) || segmentMinX - margin > Math.max(blocker.segment.start.x, blocker.segment.end.x) || segmentMaxY + margin < Math.min(blocker.segment.start.y, blocker.segment.end.y) || segmentMinY - margin > Math.max(blocker.segment.start.y, blocker.segment.end.y))
|
|
21806
21825
|
continue;
|
|
21807
21826
|
if (distanceSegmentToSegment(
|
|
21808
21827
|
segment2.start,
|
|
@@ -21818,10 +21837,6 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21818
21837
|
if (distancePointToSegment(other.exitPoint, segment2.start, segment2.end) < traceWidth + clearance - EPSILON7)
|
|
21819
21838
|
return false;
|
|
21820
21839
|
}
|
|
21821
|
-
const segmentMinX = Math.min(segment2.start.x, segment2.end.x);
|
|
21822
|
-
const segmentMaxX = Math.max(segment2.start.x, segment2.end.x);
|
|
21823
|
-
const segmentMinY = Math.min(segment2.start.y, segment2.end.y);
|
|
21824
|
-
const segmentMaxY = Math.max(segment2.start.y, segment2.end.y);
|
|
21825
21840
|
for (let viaIndex = getFirstViaAtOrAfterX(
|
|
21826
21841
|
segmentMinX - maximumViaToTraceDistance
|
|
21827
21842
|
); viaIndex < viasByX.length; viaIndex++) {
|
|
@@ -21992,16 +22007,25 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21992
22007
|
);
|
|
21993
22008
|
const previous = new Int32Array(stateCount).fill(-1);
|
|
21994
22009
|
const heap = new MinHeap();
|
|
21995
|
-
const
|
|
22010
|
+
const remainingDistances = new Float64Array(nodeCount);
|
|
22011
|
+
const lanePenalties = new Float64Array(nodeCount);
|
|
22012
|
+
const targetTrack = getPerpendicularAxis(
|
|
22013
|
+
terminal.exitPoint,
|
|
22014
|
+
boundaryDirection
|
|
22015
|
+
);
|
|
22016
|
+
for (let nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
|
|
22017
|
+
const point6 = nodes[nodeIndex].point;
|
|
21996
22018
|
const deltaX = Math.abs(point6.x - terminal.exitPoint.x);
|
|
21997
22019
|
const deltaY = Math.abs(point6.y - terminal.exitPoint.y);
|
|
21998
|
-
|
|
21999
|
-
|
|
22020
|
+
remainingDistances[nodeIndex] = Math.max(deltaX, deltaY) + (Math.SQRT2 - 1) * Math.min(deltaX, deltaY);
|
|
22021
|
+
const nextTrack = getPerpendicularAxis(point6, boundaryDirection);
|
|
22022
|
+
lanePenalties[nodeIndex] = laneBias === 0 ? 0 : laneBias > 0 ? Math.max(0, targetTrack - nextTrack) * 0.2 : Math.max(0, nextTrack - targetTrack) * 0.2;
|
|
22023
|
+
}
|
|
22000
22024
|
for (const start of starts) {
|
|
22001
22025
|
const state = start.nodeIndex * 9 + 8;
|
|
22002
22026
|
if (start.length >= distances[state]) continue;
|
|
22003
22027
|
distances[state] = start.length;
|
|
22004
|
-
const remaining =
|
|
22028
|
+
const remaining = remainingDistances[start.nodeIndex];
|
|
22005
22029
|
heap.push({
|
|
22006
22030
|
node: start.nodeIndex,
|
|
22007
22031
|
direction: 8,
|
|
@@ -22018,6 +22042,13 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22018
22042
|
[0, -1],
|
|
22019
22043
|
[1, -1]
|
|
22020
22044
|
];
|
|
22045
|
+
const nextDirectionsByIncoming = Array.from(
|
|
22046
|
+
{ length: 9 },
|
|
22047
|
+
(_, incoming) => directions.flatMap((_2, directionIndex) => {
|
|
22048
|
+
const delta = Math.abs(incoming - directionIndex);
|
|
22049
|
+
return incoming === 8 || Math.min(delta, 8 - delta) <= 1 ? [directionIndex] : [];
|
|
22050
|
+
})
|
|
22051
|
+
);
|
|
22021
22052
|
const startsByNode = /* @__PURE__ */ new Map();
|
|
22022
22053
|
for (const start of starts) {
|
|
22023
22054
|
const values = startsByNode.get(start.nodeIndex) ?? [];
|
|
@@ -22035,7 +22066,7 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22035
22066
|
if (current.score >= bestGoalCost - EPSILON7) break;
|
|
22036
22067
|
const state = current.node * 9 + current.direction;
|
|
22037
22068
|
const currentDistance = distances[state];
|
|
22038
|
-
if (current.score > currentDistance +
|
|
22069
|
+
if (current.score > currentDistance + remainingDistances[current.node] + EPSILON7)
|
|
22039
22070
|
continue;
|
|
22040
22071
|
expandedStateCount++;
|
|
22041
22072
|
expandedStatesSinceYield++;
|
|
@@ -22085,13 +22116,7 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22085
22116
|
}
|
|
22086
22117
|
}
|
|
22087
22118
|
const node = nodes[current.node];
|
|
22088
|
-
for (
|
|
22089
|
-
if (current.direction !== 8) {
|
|
22090
|
-
const rawDirectionDelta = Math.abs(current.direction - directionIndex);
|
|
22091
|
-
if (Math.min(rawDirectionDelta, 8 - rawDirectionDelta) > 1) {
|
|
22092
|
-
continue;
|
|
22093
|
-
}
|
|
22094
|
-
}
|
|
22119
|
+
for (const directionIndex of nextDirectionsByIncoming[current.direction]) {
|
|
22095
22120
|
const [deltaColumn, deltaRow] = directions[directionIndex];
|
|
22096
22121
|
const column = node.column + deltaColumn;
|
|
22097
22122
|
const row = node.row + deltaRow;
|
|
@@ -22101,12 +22126,7 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22101
22126
|
const nextNode = row * columnCount + column;
|
|
22102
22127
|
const nextPoint = nodes[nextNode].point;
|
|
22103
22128
|
const addsTurn = current.direction !== 8 && current.direction !== directionIndex;
|
|
22104
|
-
const
|
|
22105
|
-
const targetTrack = getPerpendicularAxis(
|
|
22106
|
-
terminal.exitPoint,
|
|
22107
|
-
boundaryDirection
|
|
22108
|
-
);
|
|
22109
|
-
const lanePenalty = laneBias === 0 ? 0 : laneBias > 0 ? Math.max(0, targetTrack - nextTrack) * 0.2 : Math.max(0, nextTrack - targetTrack) * 0.2;
|
|
22129
|
+
const lanePenalty = lanePenalties[nextNode];
|
|
22110
22130
|
const nextDistance = currentDistance + (deltaColumn !== 0 && deltaRow !== 0 ? gridStep * Math.SQRT2 : gridStep) + (addsTurn ? gridStep * 0.2 : 0) + lanePenalty + (softViaCosts?.[nextNode] ?? 0);
|
|
22111
22131
|
const nextState = nextNode * 9 + directionIndex;
|
|
22112
22132
|
if (nextDistance >= distances[nextState] - EPSILON7) continue;
|
|
@@ -22128,7 +22148,7 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22128
22148
|
if (edgeClearance[edgeIndex] === 2) continue;
|
|
22129
22149
|
distances[nextState] = nextDistance;
|
|
22130
22150
|
previous[nextState] = state;
|
|
22131
|
-
const remaining =
|
|
22151
|
+
const remaining = remainingDistances[nextNode];
|
|
22132
22152
|
heap.push({
|
|
22133
22153
|
node: nextNode,
|
|
22134
22154
|
direction: directionIndex,
|
|
@@ -22236,6 +22256,7 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22236
22256
|
};
|
|
22237
22257
|
const alternatives = [];
|
|
22238
22258
|
const seenAlternativeKeys = /* @__PURE__ */ new Set();
|
|
22259
|
+
const failedSearches = /* @__PURE__ */ new Map();
|
|
22239
22260
|
let routeOrderAttemptCount = 0;
|
|
22240
22261
|
for (const routeOrder of adaptiveRouteOrders()) {
|
|
22241
22262
|
for (const laneBias of laneBiases) {
|
|
@@ -22248,13 +22269,33 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22248
22269
|
let failed = false;
|
|
22249
22270
|
for (let terminalIndex = 0; terminalIndex < routeOrder.length; terminalIndex++) {
|
|
22250
22271
|
const terminal = routeOrder[terminalIndex];
|
|
22272
|
+
const failedSearchKey = JSON.stringify([
|
|
22273
|
+
terminals.indexOf(terminal),
|
|
22274
|
+
laneBias,
|
|
22275
|
+
acceptedAttemptSegments.map(({ connectionName: connectionName2, segment: segment2 }) => [
|
|
22276
|
+
connectionName2,
|
|
22277
|
+
segment2.start.x,
|
|
22278
|
+
segment2.start.y,
|
|
22279
|
+
segment2.end.x,
|
|
22280
|
+
segment2.end.y,
|
|
22281
|
+
segment2.width,
|
|
22282
|
+
segment2.layer
|
|
22283
|
+
])
|
|
22284
|
+
]);
|
|
22285
|
+
const cachedFailure = failedSearches.get(failedSearchKey);
|
|
22251
22286
|
const connectionSteps = routeOneSteps({
|
|
22252
22287
|
terminal,
|
|
22253
22288
|
acceptedAttemptSegments,
|
|
22254
22289
|
laneBias
|
|
22255
22290
|
});
|
|
22256
|
-
let connectionResult = connectionSteps.next()
|
|
22257
|
-
|
|
22291
|
+
let connectionResult = cachedFailure === void 0 ? connectionSteps.next() : {
|
|
22292
|
+
done: true,
|
|
22293
|
+
value: {
|
|
22294
|
+
points: null,
|
|
22295
|
+
expandedStateCount: cachedFailure.expandedStateCount
|
|
22296
|
+
}
|
|
22297
|
+
};
|
|
22298
|
+
let searchBatch = cachedFailure?.searchBatch ?? 0;
|
|
22258
22299
|
let expandedStateCount = 0;
|
|
22259
22300
|
while (!connectionResult.done) {
|
|
22260
22301
|
expandedStateCount = connectionResult.value.expandedStateCount;
|
|
@@ -22296,6 +22337,10 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
22296
22337
|
} : {}
|
|
22297
22338
|
};
|
|
22298
22339
|
if (!points) {
|
|
22340
|
+
failedSearches.set(failedSearchKey, {
|
|
22341
|
+
expandedStateCount: finalExpandedStateCount,
|
|
22342
|
+
searchBatch
|
|
22343
|
+
});
|
|
22299
22344
|
if (adaptiveRouteOrder && maximumRouteOrderAttempts !== void 0 && terminalIndex > 0) {
|
|
22300
22345
|
const others = routeOrder.filter(
|
|
22301
22346
|
(candidate) => candidate !== terminal
|
|
@@ -23630,6 +23675,8 @@ function planIsClearOfPlans(params) {
|
|
|
23630
23675
|
clearance,
|
|
23631
23676
|
blockingBusCounts
|
|
23632
23677
|
} = params;
|
|
23678
|
+
const planSegments = getPlanSegments(plan);
|
|
23679
|
+
const planVias = getPlanVias2(plan);
|
|
23633
23680
|
for (const otherPlan of otherPlans) {
|
|
23634
23681
|
if (allowSameNetMerges && connectionsShareElectricalNet(
|
|
23635
23682
|
srj,
|
|
@@ -23647,9 +23694,7 @@ function planIsClearOfPlans(params) {
|
|
|
23647
23694
|
(blockingBusCounts.get(otherPlan.busId) ?? 0) + 1
|
|
23648
23695
|
);
|
|
23649
23696
|
};
|
|
23650
|
-
const planSegments = getPlanSegments(plan);
|
|
23651
23697
|
const otherSegments = getPlanSegments(otherPlan);
|
|
23652
|
-
const planVias = getPlanVias2(plan);
|
|
23653
23698
|
const otherVias = getPlanVias2(otherPlan);
|
|
23654
23699
|
for (const segment2 of planSegments) {
|
|
23655
23700
|
for (const otherSegment of otherSegments) {
|
|
@@ -24180,6 +24225,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24180
24225
|
adaptiveWindingRouteOrder = false,
|
|
24181
24226
|
alignWindingGridToPads = false,
|
|
24182
24227
|
fixedViaFallbackRouteOrderAttempts = 24,
|
|
24228
|
+
allowFixedViaReservedExitFallback = false,
|
|
24183
24229
|
cornerBandTargetTrackOffset
|
|
24184
24230
|
} = params;
|
|
24185
24231
|
if (!Number.isInteger(maxAlternatives) || maxAlternatives < 1) {
|
|
@@ -24448,7 +24494,23 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24448
24494
|
reserveTerminalExitPoints: !preferTargetDirectedLaneBias,
|
|
24449
24495
|
allowLayerInterleaving: true
|
|
24450
24496
|
}))
|
|
24451
|
-
).flat() : []
|
|
24497
|
+
).flat() : [],
|
|
24498
|
+
// A single-layer target permutation can also let an early lane
|
|
24499
|
+
// close a future terminal's exit gap. Keep the original attempts
|
|
24500
|
+
// first, then retry the same fixed sites with every exit reserved.
|
|
24501
|
+
...allowFixedViaReservedExitFallback && fixedViaPointsByConnectionIndex && !getCornerSide(bus) && windingTargetOrderCount === 1 && bus.connections.length > 2 ? [true, false].map((preferTargetDirectedLaneBias) => ({
|
|
24502
|
+
label: `fixed-vias-reserved-exits-${preferTargetDirectedLaneBias}`,
|
|
24503
|
+
useViaInPad: false,
|
|
24504
|
+
getViaHandedness: () => 0,
|
|
24505
|
+
getViaPoint: (connection) => coordinatedViaPoints.get(connection.connectionIndex),
|
|
24506
|
+
maximumRouteOrderAttempts: Math.min(
|
|
24507
|
+
maximumThroughAllRouteOrderAttempts,
|
|
24508
|
+
fixedViaFallbackRouteOrderAttempts
|
|
24509
|
+
),
|
|
24510
|
+
windingOrderIndex: 0,
|
|
24511
|
+
preferTargetDirectedLaneBias,
|
|
24512
|
+
reserveTerminalExitPoints: true
|
|
24513
|
+
})) : []
|
|
24452
24514
|
] : [];
|
|
24453
24515
|
const planeTerminationsAlreadyOccupyTheFanout = acceptedPlans.some(
|
|
24454
24516
|
(plan) => plan.termination.type === "plane"
|
|
@@ -31097,7 +31159,9 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31097
31159
|
this.config.allowBlindAndBuriedVias
|
|
31098
31160
|
);
|
|
31099
31161
|
const useConfiguredDensePlaneRouting = configuredDensePlaneRouting || useAdaptiveDensePlaneRouting;
|
|
31100
|
-
const
|
|
31162
|
+
const useBoundaryRecovery = params.boundaryRecovery !== void 0;
|
|
31163
|
+
const useJointPlaneRepair = useConfiguredDensePlaneRouting || useBoundaryRecovery;
|
|
31164
|
+
const useJointPlaneSelection = useBoundaryRecovery || useAdaptiveDensePlaneRouting && ((params.planeReservationRetryCount ?? 0) === 0 || Boolean(params.preferredBoundaryViaPoints));
|
|
31101
31165
|
const matchLengthsAfterPlanes = useConfiguredDensePlaneRouting && params.lengthMatchingStage !== "before-planes";
|
|
31102
31166
|
const useJointBoundaryViaReservation = shouldUseJointBoundaryViaReservation(
|
|
31103
31167
|
unsortedBoundaryBuses.map((bus) => bus.connections.length)
|
|
@@ -31252,7 +31316,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31252
31316
|
return first.busId.localeCompare(second.busId);
|
|
31253
31317
|
}
|
|
31254
31318
|
);
|
|
31255
|
-
const debugBoundaryOrder = process.env.FANOUT_DEBUG_BOUNDARY_ORDER?.split(",") ?? (process.env.FANOUT_DEBUG_FIRST_BOUNDARY_BUS ? [process.env.FANOUT_DEBUG_FIRST_BOUNDARY_BUS] : []);
|
|
31319
|
+
const debugBoundaryOrder = process.env.FANOUT_DEBUG_BOUNDARY_ORDER?.split(",") ?? (process.env.FANOUT_DEBUG_FIRST_BOUNDARY_BUS ? [process.env.FANOUT_DEBUG_FIRST_BOUNDARY_BUS] : params.boundaryRecovery ? [params.boundaryRecovery.busId] : []);
|
|
31256
31320
|
const boundaryBuses = debugBoundaryOrder.length > 0 ? initiallySortedBoundaryBuses.toSorted((first, second) => {
|
|
31257
31321
|
const firstIndex = debugBoundaryOrder.indexOf(first.busId);
|
|
31258
31322
|
const secondIndex = debugBoundaryOrder.indexOf(second.busId);
|
|
@@ -31289,6 +31353,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31289
31353
|
];
|
|
31290
31354
|
}
|
|
31291
31355
|
const unroutablePlaneBusIds = /* @__PURE__ */ new Set();
|
|
31356
|
+
let failedWideBoundaryBus;
|
|
31292
31357
|
debugDense(
|
|
31293
31358
|
"start",
|
|
31294
31359
|
boundaryBuses.map((bus) => `${bus.busId}:${bus.connections.length}`),
|
|
@@ -31348,6 +31413,16 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31348
31413
|
if (entersNeighboringSourceField)
|
|
31349
31414
|
preferBoundaryOutwardByBusId.set(bus.busId, false);
|
|
31350
31415
|
}
|
|
31416
|
+
if (params.boundaryRecovery) {
|
|
31417
|
+
preferredBoundaryPerpendicularSideByBusId.set(
|
|
31418
|
+
params.boundaryRecovery.busId,
|
|
31419
|
+
params.boundaryRecovery.perpendicularSide
|
|
31420
|
+
);
|
|
31421
|
+
preferBoundaryOutwardByBusId.set(
|
|
31422
|
+
params.boundaryRecovery.busId,
|
|
31423
|
+
params.boundaryRecovery.preferOutward
|
|
31424
|
+
);
|
|
31425
|
+
}
|
|
31351
31426
|
const debugFlippedBoundaryBus = process.env.FANOUT_DEBUG_FLIP_BOUNDARY_BUS;
|
|
31352
31427
|
if (debugFlippedBoundaryBus) {
|
|
31353
31428
|
preferredBoundaryPerpendicularSideByBusId.set(debugFlippedBoundaryBus, -1);
|
|
@@ -31796,6 +31871,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31796
31871
|
allowBoundarySideViaFallback: bus.connections.length === 1,
|
|
31797
31872
|
preferCornerBoundaryVia: useConfiguredDensePlaneRouting,
|
|
31798
31873
|
adaptiveWindingRouteOrder,
|
|
31874
|
+
allowFixedViaReservedExitFallback: useBoundaryRecovery,
|
|
31799
31875
|
// Retain pad-aligned channels even when plane sites are reserved
|
|
31800
31876
|
// adaptively; the boundary grid can fence off a turning wide bus.
|
|
31801
31877
|
alignWindingGridToPads: usePadAlignedDenseRouting && !configuredDensePlaneRouting,
|
|
@@ -32089,6 +32165,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32089
32165
|
}
|
|
32090
32166
|
}
|
|
32091
32167
|
if (!busPlans) {
|
|
32168
|
+
if (bus.connections.length >= 8) failedWideBoundaryBus ??= bus;
|
|
32092
32169
|
debugDense("route:failed", bus.busId);
|
|
32093
32170
|
return false;
|
|
32094
32171
|
}
|
|
@@ -32371,6 +32448,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32371
32448
|
let feasibleAlternatePlanePlans = [];
|
|
32372
32449
|
const matchViaPointsAroundPlans = (candidatePlans, promotedAlternatePlaneBusIds = /* @__PURE__ */ new Set()) => {
|
|
32373
32450
|
feasibleAlternatePlanePlans = [];
|
|
32451
|
+
matchedPlaneBusesInRoutingOrder = null;
|
|
32374
32452
|
const fixedBoundaryViaPoints = new Map(
|
|
32375
32453
|
candidatePlans.flatMap(
|
|
32376
32454
|
(plan) => plan.via ? [[plan.connectionIndex, plan.via.center]] : []
|
|
@@ -32420,9 +32498,9 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32420
32498
|
});
|
|
32421
32499
|
if (retainedViaPoints)
|
|
32422
32500
|
return new Map([...fixedBoundaryViaPoints, ...retainedViaPoints]);
|
|
32423
|
-
if (
|
|
32501
|
+
if (useJointPlaneRepair || process.env.FANOUT_DEBUG_INCREMENTAL_PLANE_MATCH === "1") {
|
|
32424
32502
|
let incrementalViaPoints = new Map(fixedBoundaryViaPoints);
|
|
32425
|
-
const matchedPlaneBuses = [...activeBoundaryReservationPlaneBuses];
|
|
32503
|
+
const matchedPlaneBuses = useBoundaryRecovery ? [] : [...activeBoundaryReservationPlaneBuses];
|
|
32426
32504
|
for (const planeBus of matchedPlaneBuses) {
|
|
32427
32505
|
for (const connection of planeBus.connections) {
|
|
32428
32506
|
const reservedPoint = fixedViaPointsByConnectionIndex.get(
|
|
@@ -32538,14 +32616,14 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32538
32616
|
"plane-match:preflight-failed",
|
|
32539
32617
|
independentlyUnmatchablePlaneBuses.map((bus) => bus.busId)
|
|
32540
32618
|
);
|
|
32541
|
-
if (!
|
|
32619
|
+
if (!useJointPlaneRepair && process.env.FANOUT_DEBUG_ROUTE_UNMATCHED_PLANES !== "1") {
|
|
32542
32620
|
return null;
|
|
32543
32621
|
}
|
|
32544
32622
|
let alternatePlaneSearchStates = 0;
|
|
32545
32623
|
const maximumAlternatePlaneSearchStates = Number(
|
|
32546
32624
|
process.env.FANOUT_DEBUG_ALTERNATE_SEARCH_STATES ?? // Keep the initial search short before reserving blocked
|
|
32547
32625
|
// plane sites. Later joint repairs retain the full budget.
|
|
32548
|
-
(useAdaptiveDensePlaneRouting && (params.planeReservationRetryCount ?? 0) === 0 ? 1e4 : useConfiguredDensePlaneRouting ? 3e6 : 1e3)
|
|
32626
|
+
(useAdaptiveDensePlaneRouting && (params.planeReservationRetryCount ?? 0) === 0 ? 1e4 : useConfiguredDensePlaneRouting ? 3e6 : useBoundaryRecovery ? 1e4 : 1e3)
|
|
32549
32627
|
);
|
|
32550
32628
|
const maximumAlternatePlaneRoutes = Number(
|
|
32551
32629
|
process.env.FANOUT_DEBUG_ALTERNATE_ROUTE_COUNT ?? (useConfiguredDensePlaneRouting ? 128 : 8)
|
|
@@ -32674,7 +32752,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32674
32752
|
return null;
|
|
32675
32753
|
};
|
|
32676
32754
|
let alternatePlanePlans;
|
|
32677
|
-
if (
|
|
32755
|
+
if (useJointPlaneRepair || process.env.FANOUT_DEBUG_EXACT_COVER_ALTERNATES === "1") {
|
|
32678
32756
|
const candidateSets = orderedAlternatePlaneBuses.map(
|
|
32679
32757
|
(planeBus) => ({
|
|
32680
32758
|
planeBus,
|
|
@@ -32688,7 +32766,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32688
32766
|
}))
|
|
32689
32767
|
})
|
|
32690
32768
|
);
|
|
32691
|
-
if (
|
|
32769
|
+
if (useJointPlaneSelection) {
|
|
32692
32770
|
const acceptedPlans = [
|
|
32693
32771
|
...candidatePlans,
|
|
32694
32772
|
...feasibleAlternatePlanePlans
|
|
@@ -32945,7 +33023,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
32945
33023
|
);
|
|
32946
33024
|
if (!alternatePlanePlans) return null;
|
|
32947
33025
|
feasibleAlternatePlanePlans = alternatePlanePlans;
|
|
32948
|
-
if (
|
|
33026
|
+
if (useJointPlaneSelection) {
|
|
32949
33027
|
matchedPlaneBusesInRoutingOrder = [];
|
|
32950
33028
|
return new Map([
|
|
32951
33029
|
...fixedBoundaryViaPoints,
|
|
@@ -33383,6 +33461,27 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
33383
33461
|
denseRoutingStrategy: "boundary-aligned"
|
|
33384
33462
|
});
|
|
33385
33463
|
if (boundaryAlignedState) return boundaryAlignedState;
|
|
33464
|
+
if (!useBoundaryRecovery && failedWideBoundaryBus) {
|
|
33465
|
+
const busId = failedWideBoundaryBus.busId;
|
|
33466
|
+
const outward = preferBoundaryOutwardByBusId.get(busId) ?? true;
|
|
33467
|
+
const side = preferredBoundaryPerpendicularSideByBusId.get(busId) ?? 1;
|
|
33468
|
+
for (const [preferOutward, perpendicularSide] of [
|
|
33469
|
+
[!outward, -side],
|
|
33470
|
+
[!outward, side],
|
|
33471
|
+
[outward, -side],
|
|
33472
|
+
[outward, side]
|
|
33473
|
+
]) {
|
|
33474
|
+
const recoveredState = yield* this.routeDenseThroughAllMixedTerminationSteps({
|
|
33475
|
+
...params,
|
|
33476
|
+
boundaryRecovery: {
|
|
33477
|
+
busId,
|
|
33478
|
+
preferOutward,
|
|
33479
|
+
perpendicularSide
|
|
33480
|
+
}
|
|
33481
|
+
});
|
|
33482
|
+
if (recoveredState) return recoveredState;
|
|
33483
|
+
}
|
|
33484
|
+
}
|
|
33386
33485
|
}
|
|
33387
33486
|
if (!usePadAlignedDenseRouting || process.env.FANOUT_DEBUG_DENSE_ONLY === "1")
|
|
33388
33487
|
return null;
|
|
@@ -47305,7 +47404,7 @@ function Group_getRoutingPhasePlans(group) {
|
|
|
47305
47404
|
var package_default = {
|
|
47306
47405
|
name: "@tscircuit/core",
|
|
47307
47406
|
type: "module",
|
|
47308
|
-
version: "0.0.
|
|
47407
|
+
version: "0.0.1854",
|
|
47309
47408
|
types: "dist/index.d.ts",
|
|
47310
47409
|
main: "dist/index.js",
|
|
47311
47410
|
module: "dist/index.js",
|
|
@@ -47340,12 +47439,12 @@ var package_default = {
|
|
|
47340
47439
|
"@tscircuit/alphabet": "0.0.25",
|
|
47341
47440
|
"@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
|
|
47342
47441
|
"@tscircuit/capacity-autorouter": "^0.0.885",
|
|
47343
|
-
"@tscircuit/checks": "^0.0.
|
|
47442
|
+
"@tscircuit/checks": "^0.0.184",
|
|
47344
47443
|
"@tscircuit/circuit-json-util": "^0.0.106",
|
|
47345
47444
|
"@tscircuit/common": "^0.0.20",
|
|
47346
47445
|
"@tscircuit/copper-pour-solver": "^0.0.52",
|
|
47347
47446
|
"@tscircuit/create-fdm-enclosure": "0.0.4",
|
|
47348
|
-
"@tscircuit/fanout-solver": "0.0.
|
|
47447
|
+
"@tscircuit/fanout-solver": "0.0.64",
|
|
47349
47448
|
"@tscircuit/footprinter": "^0.0.426",
|
|
47350
47449
|
"@tscircuit/image-utils": "^0.0.8",
|
|
47351
47450
|
"@tscircuit/implicit-copper-pour-solver": "github:tscircuit/implicit-copper-pour-solver#a5cbbda0cd65fd4707c5c1af25779837c25aba92",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.1855",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"@tscircuit/alphabet": "0.0.25",
|
|
37
37
|
"@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
|
|
38
38
|
"@tscircuit/capacity-autorouter": "^0.0.885",
|
|
39
|
-
"@tscircuit/checks": "^0.0.
|
|
39
|
+
"@tscircuit/checks": "^0.0.184",
|
|
40
40
|
"@tscircuit/circuit-json-util": "^0.0.106",
|
|
41
41
|
"@tscircuit/common": "^0.0.20",
|
|
42
42
|
"@tscircuit/copper-pour-solver": "^0.0.52",
|
|
43
43
|
"@tscircuit/create-fdm-enclosure": "0.0.4",
|
|
44
|
-
"@tscircuit/fanout-solver": "0.0.
|
|
44
|
+
"@tscircuit/fanout-solver": "0.0.64",
|
|
45
45
|
"@tscircuit/footprinter": "^0.0.426",
|
|
46
46
|
"@tscircuit/image-utils": "^0.0.8",
|
|
47
47
|
"@tscircuit/implicit-copper-pour-solver": "github:tscircuit/implicit-copper-pour-solver#a5cbbda0cd65fd4707c5c1af25779837c25aba92",
|