@tscircuit/core 0.0.1850 → 0.0.1852
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 +376 -30
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -21192,6 +21192,24 @@ function getComponentDogboneViaSiteCandidates(preparedBuses, rules) {
|
|
|
21192
21192
|
)
|
|
21193
21193
|
);
|
|
21194
21194
|
}
|
|
21195
|
+
function* getSingleDogboneViaSiteRepairs(bus, rules, fixedViaPointsByConnectionIndex) {
|
|
21196
|
+
const sites = getComponentDogboneViaSiteCandidates([bus], rules);
|
|
21197
|
+
let remainingAttempts = 24;
|
|
21198
|
+
for (const connection of bus.connections.toReversed()) {
|
|
21199
|
+
const original = fixedViaPointsByConnectionIndex.get(
|
|
21200
|
+
connection.connectionIndex
|
|
21201
|
+
);
|
|
21202
|
+
if (!original) continue;
|
|
21203
|
+
for (const candidate of sites) {
|
|
21204
|
+
if (candidate.connectionIndex !== connection.connectionIndex || distance9(candidate.point, original) <= EPSILON6)
|
|
21205
|
+
continue;
|
|
21206
|
+
if (remainingAttempts-- <= 0) return;
|
|
21207
|
+
const replacement = new Map(fixedViaPointsByConnectionIndex);
|
|
21208
|
+
replacement.set(connection.connectionIndex, candidate.point);
|
|
21209
|
+
yield replacement;
|
|
21210
|
+
}
|
|
21211
|
+
}
|
|
21212
|
+
}
|
|
21195
21213
|
|
|
21196
21214
|
// node_modules/@tscircuit/fanout-solver/lib/route-via-minimal-winding.ts
|
|
21197
21215
|
var EPSILON7 = 1e-7;
|
|
@@ -21606,7 +21624,8 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21606
21624
|
allowSourceLayerRouting = false,
|
|
21607
21625
|
adaptiveRouteOrder = false,
|
|
21608
21626
|
alignGridToPads = false,
|
|
21609
|
-
includeReverseTargetRotation = false
|
|
21627
|
+
includeReverseTargetRotation = false,
|
|
21628
|
+
reserveTerminalExitPoints = false
|
|
21610
21629
|
} = params;
|
|
21611
21630
|
if (maximumRouteOrderAttempts !== void 0 && (!Number.isInteger(maximumRouteOrderAttempts) || maximumRouteOrderAttempts < 1)) {
|
|
21612
21631
|
throw new Error(
|
|
@@ -21794,6 +21813,11 @@ function* routeViaMinimalWindingAlternativesSteps(params, maximumAlternatives =
|
|
|
21794
21813
|
return false;
|
|
21795
21814
|
}
|
|
21796
21815
|
}
|
|
21816
|
+
for (const other of reserveTerminalExitPoints ? terminals : []) {
|
|
21817
|
+
if (sharesNet(connectionName, other.connection.connection.name)) continue;
|
|
21818
|
+
if (distancePointToSegment(other.exitPoint, segment2.start, segment2.end) < traceWidth + clearance - EPSILON7)
|
|
21819
|
+
return false;
|
|
21820
|
+
}
|
|
21797
21821
|
const segmentMinX = Math.min(segment2.start.x, segment2.end.x);
|
|
21798
21822
|
const segmentMaxX = Math.max(segment2.start.x, segment2.end.x);
|
|
21799
21823
|
const segmentMinY = Math.min(segment2.start.y, segment2.end.y);
|
|
@@ -22442,6 +22466,35 @@ function getWindingTargetOrders(params) {
|
|
|
22442
22466
|
candidateOrders.push(adjacentExtension);
|
|
22443
22467
|
}
|
|
22444
22468
|
candidateOrders.push(legacyOrderedConnections);
|
|
22469
|
+
const ordinaryOrderCount = new Set(
|
|
22470
|
+
candidateOrders.map(
|
|
22471
|
+
(order) => order.map((candidate) => candidate.connectionIndex).join(",")
|
|
22472
|
+
)
|
|
22473
|
+
).size;
|
|
22474
|
+
if (!getCornerSide(bus) && bus.connections.length <= 8 && orderedLayers.length > 1) {
|
|
22475
|
+
const layerSequences = orderedLayers.map(
|
|
22476
|
+
(layer) => connectionsByLayer.get(layer).toSorted(compareWithinLayer)
|
|
22477
|
+
);
|
|
22478
|
+
const offsets = layerSequences.map(() => 0);
|
|
22479
|
+
const current = [];
|
|
22480
|
+
const append = () => {
|
|
22481
|
+
if (candidateOrders.length >= 128) return;
|
|
22482
|
+
if (current.length === bus.connections.length) {
|
|
22483
|
+
candidateOrders.push([...current]);
|
|
22484
|
+
return;
|
|
22485
|
+
}
|
|
22486
|
+
for (let layer = 0; layer < layerSequences.length; layer++) {
|
|
22487
|
+
const next = layerSequences[layer][offsets[layer]];
|
|
22488
|
+
if (!next) continue;
|
|
22489
|
+
offsets[layer]++;
|
|
22490
|
+
current.push(next);
|
|
22491
|
+
append();
|
|
22492
|
+
current.pop();
|
|
22493
|
+
offsets[layer]--;
|
|
22494
|
+
}
|
|
22495
|
+
};
|
|
22496
|
+
append();
|
|
22497
|
+
}
|
|
22445
22498
|
const seenOrders = /* @__PURE__ */ new Set();
|
|
22446
22499
|
const orders = candidateOrders.filter((order) => {
|
|
22447
22500
|
const key = order.map((candidate) => candidate.connectionIndex).join(",");
|
|
@@ -22449,7 +22502,7 @@ function getWindingTargetOrders(params) {
|
|
|
22449
22502
|
seenOrders.add(key);
|
|
22450
22503
|
return true;
|
|
22451
22504
|
});
|
|
22452
|
-
return { orders, legacyOrder: legacyOrderedConnections };
|
|
22505
|
+
return { orders, legacyOrder: legacyOrderedConnections, ordinaryOrderCount };
|
|
22453
22506
|
}
|
|
22454
22507
|
function getWindingTargetRank(params) {
|
|
22455
22508
|
const { connection, windingOrderIndex = 0 } = params;
|
|
@@ -22496,7 +22549,7 @@ function getDistributedBoundaryTargetTracks(params) {
|
|
|
22496
22549
|
)
|
|
22497
22550
|
).toSorted((a, b) => a - b);
|
|
22498
22551
|
const pitch = traceWidth + clearance;
|
|
22499
|
-
if (tracks.every(
|
|
22552
|
+
if (!params.allowLayerInterleaving && tracks.every(
|
|
22500
22553
|
(track, index) => index === 0 || track - tracks[index - 1] >= pitch - 1e-9
|
|
22501
22554
|
))
|
|
22502
22555
|
return void 0;
|
|
@@ -24215,17 +24268,22 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24215
24268
|
})
|
|
24216
24269
|
);
|
|
24217
24270
|
const maximumThroughAllRouteOrderAttempts = 24;
|
|
24218
|
-
const
|
|
24219
|
-
|
|
24220
|
-
|
|
24221
|
-
|
|
24222
|
-
|
|
24223
|
-
|
|
24271
|
+
const usesDistributedWindingTargets = Boolean(
|
|
24272
|
+
cornerSide || getDistributedBoundaryTargetTracks({
|
|
24273
|
+
bus,
|
|
24274
|
+
boundaryDirection,
|
|
24275
|
+
traceWidth,
|
|
24276
|
+
clearance
|
|
24277
|
+
})
|
|
24278
|
+
);
|
|
24279
|
+
const windingTargetOrders = getWindingTargetOrders({
|
|
24224
24280
|
bus,
|
|
24225
24281
|
boundaryDirection,
|
|
24226
24282
|
layerNames,
|
|
24227
24283
|
targetLayer
|
|
24228
|
-
})
|
|
24284
|
+
});
|
|
24285
|
+
const windingTargetOrderCount = windingTargetOrders.orders.length;
|
|
24286
|
+
const ordinaryWindingTargetOrderCount = usesDistributedWindingTargets ? windingTargetOrders.ordinaryOrderCount : 1;
|
|
24229
24287
|
const uniformDogboneTerminalPatterns = viaHandednesses.map((viaHandedness) => ({
|
|
24230
24288
|
label: `uniform-${viaHandedness}`,
|
|
24231
24289
|
useViaInPad: false,
|
|
@@ -24353,7 +24411,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24353
24411
|
}) : null);
|
|
24354
24412
|
const fixedViaTerminalPatterns = coordinatedViaPoints ? [
|
|
24355
24413
|
...Array.from(
|
|
24356
|
-
{ length:
|
|
24414
|
+
{ length: ordinaryWindingTargetOrderCount },
|
|
24357
24415
|
(_, windingOrderIndex) => ({
|
|
24358
24416
|
label: `component-matched-vias-winding-${windingOrderIndex}`,
|
|
24359
24417
|
useViaInPad: false,
|
|
@@ -24374,7 +24432,23 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24374
24432
|
maximumRouteOrderAttempts: fixedViaFallbackRouteOrderAttempts,
|
|
24375
24433
|
windingOrderIndex: 0,
|
|
24376
24434
|
preferTargetDirectedLaneBias: true
|
|
24377
|
-
}
|
|
24435
|
+
},
|
|
24436
|
+
// Keep ordinary fixed-site attempts first. Forward retries reserve
|
|
24437
|
+
// future exits so an earlier lane cannot close their final gap.
|
|
24438
|
+
...!getCornerSide(bus) && windingTargetOrderCount > 1 ? Array.from(
|
|
24439
|
+
{ length: windingTargetOrderCount },
|
|
24440
|
+
(_, windingOrderIndex) => [true, false].map((preferTargetDirectedLaneBias) => ({
|
|
24441
|
+
label: `expanded-winding-${windingOrderIndex}-${preferTargetDirectedLaneBias}`,
|
|
24442
|
+
useViaInPad: false,
|
|
24443
|
+
getViaHandedness: () => 0,
|
|
24444
|
+
getViaPoint: (connection) => coordinatedViaPoints.get(connection.connectionIndex),
|
|
24445
|
+
maximumRouteOrderAttempts: 1,
|
|
24446
|
+
windingOrderIndex,
|
|
24447
|
+
preferTargetDirectedLaneBias,
|
|
24448
|
+
reserveTerminalExitPoints: !preferTargetDirectedLaneBias,
|
|
24449
|
+
allowLayerInterleaving: true
|
|
24450
|
+
}))
|
|
24451
|
+
).flat() : []
|
|
24378
24452
|
] : [];
|
|
24379
24453
|
const planeTerminationsAlreadyOccupyTheFanout = acceptedPlans.some(
|
|
24380
24454
|
(plan) => plan.termination.type === "plane"
|
|
@@ -24415,6 +24489,21 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24415
24489
|
}
|
|
24416
24490
|
}
|
|
24417
24491
|
}
|
|
24492
|
+
if (alignWindingGridToPads && cornerSide) {
|
|
24493
|
+
const layerLocalExitOffset = getCornerLaneOffsets(
|
|
24494
|
+
bus,
|
|
24495
|
+
acceptedPlans.filter((plan) => plan.targetLayer === targetLayer)
|
|
24496
|
+
).exit;
|
|
24497
|
+
if (layerLocalExitOffset !== cornerLaneOffsets.exit) {
|
|
24498
|
+
terminalPatterns.push(
|
|
24499
|
+
...terminalPatterns.map((pattern) => ({
|
|
24500
|
+
...pattern,
|
|
24501
|
+
label: `${pattern.label}-layer-local-corner`,
|
|
24502
|
+
cornerExitLaneOffset: layerLocalExitOffset
|
|
24503
|
+
}))
|
|
24504
|
+
);
|
|
24505
|
+
}
|
|
24506
|
+
}
|
|
24418
24507
|
const seenTerminalSignatures = /* @__PURE__ */ new Set();
|
|
24419
24508
|
for (const terminalPattern of terminalPatterns) {
|
|
24420
24509
|
const terminals = bus.connections.map((preparedConnection) => {
|
|
@@ -24422,7 +24511,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24422
24511
|
const boundaryTrack = cornerSide ? getCornerTargetTrack({
|
|
24423
24512
|
bus,
|
|
24424
24513
|
connection: preparedConnection,
|
|
24425
|
-
cornerExitLaneOffset: cornerLaneOffsets.exit,
|
|
24514
|
+
cornerExitLaneOffset: terminalPattern.cornerExitLaneOffset ?? cornerLaneOffsets.exit,
|
|
24426
24515
|
traceWidth,
|
|
24427
24516
|
viaDiameter,
|
|
24428
24517
|
clearance,
|
|
@@ -24431,6 +24520,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24431
24520
|
windingOrderIndex: terminalPattern.windingOrderIndex,
|
|
24432
24521
|
cornerBandTargetTrackOffset
|
|
24433
24522
|
}) : getBoundaryTargetTrack({
|
|
24523
|
+
allowLayerInterleaving: terminalPattern.allowLayerInterleaving,
|
|
24434
24524
|
bus,
|
|
24435
24525
|
connection: preparedConnection,
|
|
24436
24526
|
boundaryDirection,
|
|
@@ -24500,7 +24590,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24500
24590
|
(terminal) => `${terminal.connection.connectionIndex}:${terminal.viaPoint.x}:${terminal.viaPoint.y}:${terminal.exitPoint.x}:${terminal.exitPoint.y}`
|
|
24501
24591
|
).join(
|
|
24502
24592
|
"|"
|
|
24503
|
-
)}:${terminalPattern.maximumRouteOrderAttempts ?? "all"}:${gridStepDivisor}:${alignGridToPads}:${Boolean(terminalPattern.localDogboneRepair)}`;
|
|
24593
|
+
)}:${terminalPattern.maximumRouteOrderAttempts ?? "all"}:${gridStepDivisor}:${alignGridToPads}:${Boolean(terminalPattern.localDogboneRepair)}:${Boolean(terminalPattern.preferTargetDirectedLaneBias)}:${Boolean(terminalPattern.reserveTerminalExitPoints)}`;
|
|
24504
24594
|
if (seenTerminalSignatures.has(terminalSignature)) continue;
|
|
24505
24595
|
seenTerminalSignatures.add(terminalSignature);
|
|
24506
24596
|
const windingSteps = routeViaMinimalWindingAlternativesSteps(
|
|
@@ -24523,6 +24613,7 @@ function* routeBusAlternativesSteps(params, maxAlternatives = 1, includeVisualiz
|
|
|
24523
24613
|
includeReverseTargetRotation: terminalPattern.localDogboneRepair,
|
|
24524
24614
|
reservedVias,
|
|
24525
24615
|
softReservedVias,
|
|
24616
|
+
reserveTerminalExitPoints: terminalPattern.reserveTerminalExitPoints,
|
|
24526
24617
|
gridStepDivisor,
|
|
24527
24618
|
preferTargetDirectedLaneBias: terminalPattern.preferTargetDirectedLaneBias
|
|
24528
24619
|
},
|
|
@@ -25286,7 +25377,23 @@ function replacementCopperIsSelfClear(params) {
|
|
|
25286
25377
|
if (pointsMatch2(via.center, replacement.start) || pointsMatch2(via.center, replacement.end)) {
|
|
25287
25378
|
continue;
|
|
25288
25379
|
}
|
|
25289
|
-
|
|
25380
|
+
const viaClearance = via.diameter / 2 + replacement.width / 2 + clearance;
|
|
25381
|
+
const connectsThroughShortStub = (direction) => {
|
|
25382
|
+
let point6 = direction === -1 ? replacement.start : replacement.end;
|
|
25383
|
+
let pathDistance = 0;
|
|
25384
|
+
for (let index = replacementIndex + direction; index >= 0 && index < segments.length; index += direction) {
|
|
25385
|
+
const segment2 = segments[index];
|
|
25386
|
+
if (segment2.layer !== replacement.layer) return false;
|
|
25387
|
+
const connectedEnd = direction === -1 ? segment2.end : segment2.start;
|
|
25388
|
+
if (!pointsMatch2(point6, connectedEnd)) return false;
|
|
25389
|
+
pathDistance += distance9(segment2.start, segment2.end);
|
|
25390
|
+
if (pathDistance > viaClearance + EPSILON8) return false;
|
|
25391
|
+
point6 = direction === -1 ? segment2.start : segment2.end;
|
|
25392
|
+
if (pointsMatch2(point6, via.center)) return true;
|
|
25393
|
+
}
|
|
25394
|
+
return false;
|
|
25395
|
+
};
|
|
25396
|
+
if (distancePointToSegment(via.center, replacement.start, replacement.end) < viaClearance - EPSILON8 && !connectsThroughShortStub(-1) && !connectsThroughShortStub(1)) {
|
|
25290
25397
|
return false;
|
|
25291
25398
|
}
|
|
25292
25399
|
}
|
|
@@ -30289,7 +30396,92 @@ function createInitialLayerAssignment(params) {
|
|
|
30289
30396
|
assignment[bus.busId] = sourceLayer;
|
|
30290
30397
|
} else if (viaLayers.length > 0) {
|
|
30291
30398
|
if (preferOrderedCoordinatedWindingLayers && busUsesCoordinatedWinding(bus)) {
|
|
30292
|
-
|
|
30399
|
+
const cornerSide = getCornerBandSide(bus.exitEdge, bus.preferredExit);
|
|
30400
|
+
const getBoundaryCongestion = (layer) => {
|
|
30401
|
+
if (!bus.exitEdge || bus.connections.length < 8) return 0;
|
|
30402
|
+
const horizontalEdge = bus.exitEdge === "left" || bus.exitEdge === "right";
|
|
30403
|
+
const axis = horizontalEdge ? "y" : "x";
|
|
30404
|
+
const minimum = horizontalEdge ? bus.sharedBoundary.minY : bus.sharedBoundary.minX;
|
|
30405
|
+
const maximum = horizontalEdge ? bus.sharedBoundary.maxY : bus.sharedBoundary.maxX;
|
|
30406
|
+
if (!cornerSide) {
|
|
30407
|
+
const tracks = bus.connections.map((connection) => {
|
|
30408
|
+
const target = connection.exitTargetPoint ?? connection.targetPoint;
|
|
30409
|
+
return Math.max(minimum, Math.min(maximum, target[axis]));
|
|
30410
|
+
});
|
|
30411
|
+
const bandMinimum = Math.min(...tracks);
|
|
30412
|
+
const bandMaximum = Math.max(...tracks);
|
|
30413
|
+
const forwardAxis = horizontalEdge ? "x" : "y";
|
|
30414
|
+
const sign = bus.exitEdge === "right" || bus.exitEdge === "top" ? 1 : -1;
|
|
30415
|
+
const sourceNearEnd = Math.min(
|
|
30416
|
+
...bus.connections.map(
|
|
30417
|
+
(connection) => sign * connection.sourcePoint[forwardAxis]
|
|
30418
|
+
)
|
|
30419
|
+
);
|
|
30420
|
+
const sourceMinimum = Math.min(
|
|
30421
|
+
...bus.connections.map(
|
|
30422
|
+
(connection) => connection.sourcePoint[axis]
|
|
30423
|
+
)
|
|
30424
|
+
);
|
|
30425
|
+
const sourceMaximum = Math.max(
|
|
30426
|
+
...bus.connections.map(
|
|
30427
|
+
(connection) => connection.sourcePoint[axis]
|
|
30428
|
+
)
|
|
30429
|
+
);
|
|
30430
|
+
return buses.reduce((count, other) => {
|
|
30431
|
+
const otherCorner = getCornerBandSide(
|
|
30432
|
+
other.exitEdge,
|
|
30433
|
+
other.preferredExit
|
|
30434
|
+
);
|
|
30435
|
+
if (other === bus || other.termination.type !== "boundary" || other.componentId !== bus.componentId || other.exitEdge !== bus.exitEdge || !otherCorner || getCommonExplicitExitTargetLayer(other) !== layer)
|
|
30436
|
+
return count;
|
|
30437
|
+
const center = minimum + (maximum - minimum) * (otherCorner === "minimum" ? 0.25 : 0.75);
|
|
30438
|
+
const halfWidth = (Math.max(
|
|
30439
|
+
other.connections.length,
|
|
30440
|
+
other.cornerBandConnectionCount ?? 0
|
|
30441
|
+
) - 1) * Math.max(
|
|
30442
|
+
params.traceWidth + params.clearance,
|
|
30443
|
+
params.viaDiameter + params.clearance
|
|
30444
|
+
) / 2;
|
|
30445
|
+
const margin = params.traceWidth + params.clearance;
|
|
30446
|
+
const overlapsBoundaryBand = bandMaximum + margin >= center - halfWidth && bandMinimum - margin <= center + halfWidth;
|
|
30447
|
+
const crossesSourceField = Math.max(
|
|
30448
|
+
...other.connections.map(
|
|
30449
|
+
(connection) => sign * connection.sourcePoint[forwardAxis]
|
|
30450
|
+
)
|
|
30451
|
+
) < sourceNearEnd - 1e-9 && Math.min(
|
|
30452
|
+
...other.connections.map(
|
|
30453
|
+
(connection) => connection.sourcePoint[axis]
|
|
30454
|
+
)
|
|
30455
|
+
) <= sourceMaximum + margin && Math.max(
|
|
30456
|
+
...other.connections.map(
|
|
30457
|
+
(connection) => connection.sourcePoint[axis]
|
|
30458
|
+
)
|
|
30459
|
+
) >= sourceMinimum - margin;
|
|
30460
|
+
return count + (overlapsBoundaryBand || crossesSourceField ? other.connections.length : 0);
|
|
30461
|
+
}, 0);
|
|
30462
|
+
}
|
|
30463
|
+
const bandCenter = minimum + (maximum - minimum) * (cornerSide === "minimum" ? 0.25 : 0.75);
|
|
30464
|
+
const pitch = Math.max(
|
|
30465
|
+
params.traceWidth + params.clearance,
|
|
30466
|
+
params.viaDiameter + params.clearance
|
|
30467
|
+
);
|
|
30468
|
+
const bandHalfWidth = (Math.max(
|
|
30469
|
+
bus.connections.length,
|
|
30470
|
+
bus.cornerBandConnectionCount ?? 0
|
|
30471
|
+
) - 1) * pitch / 2;
|
|
30472
|
+
return buses.reduce((count, other) => {
|
|
30473
|
+
if (other === bus || other.termination.type !== "boundary" || other.componentId !== bus.componentId || other.exitEdge !== bus.exitEdge || getCornerBandSide(other.exitEdge, other.preferredExit) || getCommonExplicitExitTargetLayer(other) !== layer)
|
|
30474
|
+
return count;
|
|
30475
|
+
return count + other.connections.filter((connection) => {
|
|
30476
|
+
const target = connection.exitTargetPoint ?? connection.targetPoint;
|
|
30477
|
+
const track = Math.max(minimum, Math.min(maximum, target[axis]));
|
|
30478
|
+
return Math.abs(track - bandCenter) <= bandHalfWidth + params.traceWidth + params.clearance;
|
|
30479
|
+
}).length;
|
|
30480
|
+
}, 0);
|
|
30481
|
+
};
|
|
30482
|
+
assignment[bus.busId] = viaLayers.toSorted(
|
|
30483
|
+
(first, second) => getBoundaryCongestion(first) - getBoundaryCongestion(second)
|
|
30484
|
+
)[0];
|
|
30293
30485
|
continue;
|
|
30294
30486
|
}
|
|
30295
30487
|
const componentDirections = directionsByComponent.get(bus.componentId);
|
|
@@ -30585,6 +30777,9 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
30585
30777
|
buses: this.preparedBuses,
|
|
30586
30778
|
escapeLayers: this.config.escapeLayers,
|
|
30587
30779
|
escapeLayersByBusId: this.escapeLayersByBusId,
|
|
30780
|
+
traceWidth: this.config.traceWidth,
|
|
30781
|
+
viaDiameter: this.config.viaDiameter,
|
|
30782
|
+
clearance: this.config.clearance,
|
|
30588
30783
|
preferOrderedCoordinatedWindingLayers: this.config.densePlaneReservationBusIds.length > 0 || this.config.denseUnrestrictedPlaneRoutingBusIds.length > 0 || shouldUseAdaptiveDensePlaneRouting(
|
|
30589
30784
|
this.preparedBuses,
|
|
30590
30785
|
this.config.allowBlindAndBuriedVias
|
|
@@ -30926,6 +31121,40 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
30926
31121
|
const wideBoundaryBuses = unsortedBoundaryBuses.filter(
|
|
30927
31122
|
(bus) => bus.connections.length >= 8
|
|
30928
31123
|
);
|
|
31124
|
+
const adjacentCenteredFieldByTurningBus = /* @__PURE__ */ new Map();
|
|
31125
|
+
if (usePadAlignedDenseRouting && !configuredDensePlaneRouting) {
|
|
31126
|
+
for (const bus of wideBoundaryBuses) {
|
|
31127
|
+
if (!getCornerBandSide(bus.exitEdge, bus.preferredExit) || new Set(bus.routableEscapeLayers ?? bus.allowedLayers ?? []).size !== 1)
|
|
31128
|
+
continue;
|
|
31129
|
+
const axis = bus.direction === "up" || bus.direction === "down" ? "y" : "x";
|
|
31130
|
+
const track = axis === "x" ? "y" : "x";
|
|
31131
|
+
const sign = bus.direction === "up" || bus.direction === "right" ? 1 : -1;
|
|
31132
|
+
const forwardEnd = Math.max(
|
|
31133
|
+
...bus.connections.map((c) => sign * c.sourcePoint[axis])
|
|
31134
|
+
);
|
|
31135
|
+
const minTrack = Math.min(
|
|
31136
|
+
...bus.connections.map((c) => c.sourcePoint[track])
|
|
31137
|
+
);
|
|
31138
|
+
const maxTrack = Math.max(
|
|
31139
|
+
...bus.connections.map((c) => c.sourcePoint[track])
|
|
31140
|
+
);
|
|
31141
|
+
const pitch = axis === "x" ? bus.pitchX : bus.pitchY;
|
|
31142
|
+
const field = wideBoundaryBuses.find((candidate) => {
|
|
31143
|
+
if (candidate === bus || candidate.componentId !== bus.componentId || candidate.exitEdge !== bus.exitEdge || getCornerBandSide(candidate.exitEdge, candidate.preferredExit))
|
|
31144
|
+
return false;
|
|
31145
|
+
const nearEnd = Math.min(
|
|
31146
|
+
...candidate.connections.map((c) => sign * c.sourcePoint[axis])
|
|
31147
|
+
);
|
|
31148
|
+
const gap = nearEnd - forwardEnd;
|
|
31149
|
+
return gap >= -1e-9 && gap <= pitch + 1e-9 && Math.min(
|
|
31150
|
+
...candidate.connections.map((c) => c.sourcePoint[track])
|
|
31151
|
+
) <= maxTrack + 1e-9 && Math.max(
|
|
31152
|
+
...candidate.connections.map((c) => c.sourcePoint[track])
|
|
31153
|
+
) >= minTrack - 1e-9;
|
|
31154
|
+
});
|
|
31155
|
+
if (field) adjacentCenteredFieldByTurningBus.set(bus, field);
|
|
31156
|
+
}
|
|
31157
|
+
}
|
|
30929
31158
|
const hasThreeWideBoundaryBuses = useConfiguredDensePlaneRouting && wideBoundaryBuses.length === 3;
|
|
30930
31159
|
const getBoundaryTargetSpan = (bus) => {
|
|
30931
31160
|
const coordinates = bus.connections.map((connection) => {
|
|
@@ -31378,8 +31607,29 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31378
31607
|
bus
|
|
31379
31608
|
])
|
|
31380
31609
|
];
|
|
31610
|
+
for (const [bus] of adjacentCenteredFieldByTurningBus) {
|
|
31611
|
+
const axis = bus.direction === "up" || bus.direction === "down" ? "y" : "x";
|
|
31612
|
+
const sign = bus.direction === "up" || bus.direction === "right" ? 1 : -1;
|
|
31613
|
+
const backwardEnd = Math.min(
|
|
31614
|
+
...bus.connections.map(
|
|
31615
|
+
(connection) => sign * connection.sourcePoint[axis]
|
|
31616
|
+
)
|
|
31617
|
+
);
|
|
31618
|
+
const index = denseBoundaryBusesInRoutingOrder.indexOf(bus);
|
|
31619
|
+
const earlierCornerIndex = denseBoundaryBusesInRoutingOrder.findIndex(
|
|
31620
|
+
(candidate) => candidate !== bus && candidate.connections.length >= 8 && candidate.componentId === bus.componentId && candidate.direction === bus.direction && Math.max(
|
|
31621
|
+
...candidate.connections.map(
|
|
31622
|
+
(connection) => sign * connection.sourcePoint[axis]
|
|
31623
|
+
)
|
|
31624
|
+
) <= backwardEnd + 1e-9 && candidate.exitEdge === bus.exitEdge && getCornerBandSide(candidate.exitEdge, candidate.preferredExit) === getCornerBandSide(bus.exitEdge, bus.preferredExit)
|
|
31625
|
+
);
|
|
31626
|
+
if (earlierCornerIndex >= 0 && earlierCornerIndex < index) {
|
|
31627
|
+
denseBoundaryBusesInRoutingOrder.splice(index, 1);
|
|
31628
|
+
denseBoundaryBusesInRoutingOrder.splice(earlierCornerIndex, 0, bus);
|
|
31629
|
+
}
|
|
31630
|
+
}
|
|
31381
31631
|
const areAdjacentInvertedNarrowBuses = (first, second) => {
|
|
31382
|
-
if (!usePadAlignedDenseRouting ||
|
|
31632
|
+
if (!usePadAlignedDenseRouting || first.componentId !== second.componentId || first.exitEdge !== second.exitEdge || first.direction !== second.direction || getCornerBandSide(first.exitEdge, first.preferredExit) !== getCornerBandSide(second.exitEdge, second.preferredExit) || params.busLayerAssignments[first.busId] !== params.busLayerAssignments[second.busId] || getContainingWideSourceField(first) !== getContainingWideSourceField(second) || !getContainingWideSourceField(first))
|
|
31383
31633
|
return false;
|
|
31384
31634
|
const firstCenter = {
|
|
31385
31635
|
x: first.connections.reduce(
|
|
@@ -31414,7 +31664,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31414
31664
|
return (firstCenter[axis] - secondCenter[axis]) * (targetTrack(first) - targetTrack(second)) < -1e-9;
|
|
31415
31665
|
};
|
|
31416
31666
|
const centeredPairPromotionGroups = /* @__PURE__ */ new Set();
|
|
31417
|
-
for (const singleton of
|
|
31667
|
+
for (const singleton of leadingWideSingletonBuses) {
|
|
31418
31668
|
if (getCornerBandSide(singleton.exitEdge, singleton.preferredExit))
|
|
31419
31669
|
continue;
|
|
31420
31670
|
for (const pair of boundaryBuses) {
|
|
@@ -31446,6 +31696,21 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31446
31696
|
}
|
|
31447
31697
|
}
|
|
31448
31698
|
}
|
|
31699
|
+
for (const field of adjacentCenteredFieldByTurningBus.values()) {
|
|
31700
|
+
for (const pair of boundaryBuses) {
|
|
31701
|
+
if (pair.connections.length !== 2 || getContainingWideSourceField(pair) !== field)
|
|
31702
|
+
continue;
|
|
31703
|
+
for (const singleton of singletonBoundaryBuses) {
|
|
31704
|
+
if (!areAdjacentInvertedNarrowBuses(singleton, pair)) continue;
|
|
31705
|
+
const pairIndex = denseBoundaryBusesInRoutingOrder.indexOf(pair);
|
|
31706
|
+
const singletonIndex = denseBoundaryBusesInRoutingOrder.indexOf(singleton);
|
|
31707
|
+
if (singletonIndex > pairIndex) {
|
|
31708
|
+
denseBoundaryBusesInRoutingOrder.splice(singletonIndex, 1);
|
|
31709
|
+
denseBoundaryBusesInRoutingOrder.splice(pairIndex, 0, singleton);
|
|
31710
|
+
}
|
|
31711
|
+
}
|
|
31712
|
+
}
|
|
31713
|
+
}
|
|
31449
31714
|
let fixedViaPointsByConnectionIndex = seedViaPoints;
|
|
31450
31715
|
let matchedPlans = [];
|
|
31451
31716
|
let matchedRoutingSucceeded = true;
|
|
@@ -31558,7 +31823,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31558
31823
|
(candidate) => candidate.connections.length < 8 && getContainingWideSourceField(candidate) === bus && matchedPlans.some((plan) => plan.busId === candidate.busId)
|
|
31559
31824
|
);
|
|
31560
31825
|
const preferSingleLayerWinding = useConfiguredDensePlaneRouting && singleLayerBus !== bus && !embeddedNarrowBusAlreadyRouted;
|
|
31561
|
-
let
|
|
31826
|
+
let usedRepairedViaSites = false;
|
|
31562
31827
|
let busPlans = (yield* routeAlternatives(
|
|
31563
31828
|
preferSingleLayerWinding ? { ...routeParams, bus: singleLayerBus } : routeParams,
|
|
31564
31829
|
1
|
|
@@ -31658,14 +31923,95 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31658
31923
|
}
|
|
31659
31924
|
}
|
|
31660
31925
|
}
|
|
31661
|
-
if (!busPlans && bus.connections.length >= 8 &&
|
|
31662
|
-
(
|
|
31926
|
+
if (!busPlans && useAdaptiveDensePlaneRouting && bus.connections.length >= 8 && getCornerBandSide(bus.exitEdge, bus.preferredExit) && new Set(bus.routableEscapeLayers ?? bus.allowedLayers ?? []).size === 1 && !matchedPlans.some(
|
|
31927
|
+
(plan) => wideBoundaryBuses.some(
|
|
31928
|
+
(candidate) => candidate.busId === plan.busId
|
|
31929
|
+
)
|
|
31663
31930
|
)) {
|
|
31931
|
+
const reservedVias = getReservedVias(bus);
|
|
31932
|
+
const siteRepairs = getSingleDogboneViaSiteRepairs(
|
|
31933
|
+
bus,
|
|
31934
|
+
{
|
|
31935
|
+
viaDiameter: this.config.viaDiameter,
|
|
31936
|
+
viaHoleDiameter: this.config.viaHoleDiameter,
|
|
31937
|
+
traceWidth: this.config.traceWidth,
|
|
31938
|
+
clearance: this.config.clearance,
|
|
31939
|
+
additionalObstacles: this.routingSrj.obstacles,
|
|
31940
|
+
blockingSegments: [
|
|
31941
|
+
...matchedPlans.flatMap(
|
|
31942
|
+
(plan) => plan.segments.map((segment2) => ({
|
|
31943
|
+
connectionIndex: plan.connectionIndex,
|
|
31944
|
+
segment: segment2
|
|
31945
|
+
}))
|
|
31946
|
+
),
|
|
31947
|
+
...reservedVias.flatMap(
|
|
31948
|
+
(reserved) => reserved.sourceEscapeSegment ? [
|
|
31949
|
+
{
|
|
31950
|
+
connectionIndex: -1,
|
|
31951
|
+
segment: reserved.sourceEscapeSegment
|
|
31952
|
+
}
|
|
31953
|
+
] : []
|
|
31954
|
+
)
|
|
31955
|
+
],
|
|
31956
|
+
blockingVias: [
|
|
31957
|
+
...matchedPlans.flatMap(
|
|
31958
|
+
(plan) => plan.via ? [{ connectionIndex: plan.connectionIndex, ...plan.via }] : []
|
|
31959
|
+
),
|
|
31960
|
+
...reservedVias.map((reserved) => ({
|
|
31961
|
+
connectionIndex: -1,
|
|
31962
|
+
...reserved.via
|
|
31963
|
+
}))
|
|
31964
|
+
]
|
|
31965
|
+
},
|
|
31966
|
+
fixedViaPointsByConnectionIndex
|
|
31967
|
+
);
|
|
31968
|
+
for (const replacementPoints of siteRepairs) {
|
|
31969
|
+
const replacementPlans = (yield* routeAlternatives(
|
|
31970
|
+
{
|
|
31971
|
+
...routeParams,
|
|
31972
|
+
fixedViaPointsByConnectionIndex: replacementPoints,
|
|
31973
|
+
reservedVias,
|
|
31974
|
+
fixedViaFallbackRouteOrderAttempts: 1
|
|
31975
|
+
},
|
|
31976
|
+
1
|
|
31977
|
+
))[0];
|
|
31978
|
+
if (!replacementPlans) continue;
|
|
31979
|
+
busPlans = replacementPlans;
|
|
31980
|
+
fixedViaPointsByConnectionIndex = replacementPoints;
|
|
31981
|
+
usedRepairedViaSites = true;
|
|
31982
|
+
break;
|
|
31983
|
+
}
|
|
31984
|
+
}
|
|
31985
|
+
if (!busPlans && useAdaptiveDensePlaneRouting && bus.connections.length >= 8 && getCornerBandSide(bus.exitEdge, bus.preferredExit)) {
|
|
31986
|
+
busPlans = (yield* routeAlternatives(
|
|
31987
|
+
{
|
|
31988
|
+
...routeParams,
|
|
31989
|
+
fixedViaPointsByConnectionIndex: void 0,
|
|
31990
|
+
reservedVias: getReservedVias(bus)
|
|
31991
|
+
},
|
|
31992
|
+
1
|
|
31993
|
+
))[0];
|
|
31994
|
+
if (busPlans) {
|
|
31995
|
+
usedRepairedViaSites = true;
|
|
31996
|
+
fixedViaPointsByConnectionIndex = new Map([
|
|
31997
|
+
...fixedViaPointsByConnectionIndex,
|
|
31998
|
+
...busPlans.filter((plan) => plan.via).map(
|
|
31999
|
+
(plan) => [plan.connectionIndex, plan.via.center]
|
|
32000
|
+
)
|
|
32001
|
+
]);
|
|
32002
|
+
}
|
|
32003
|
+
debugDense("local-sites", bus.busId, busPlans?.length ?? "failed");
|
|
32004
|
+
}
|
|
32005
|
+
if (!busPlans && bus.connections.length >= 8 && (adjacentCenteredFieldByTurningBus.has(bus) || boundaryBuses.some(
|
|
32006
|
+
(candidate) => candidate.connections.length >= 8 && matchedPlans.some((plan) => plan.busId === candidate.busId)
|
|
32007
|
+
))) {
|
|
31664
32008
|
const committedNames = new Set(
|
|
31665
32009
|
matchedPlans.map((plan) => plan.connectionName)
|
|
31666
32010
|
);
|
|
31667
|
-
const
|
|
31668
|
-
this.preparedBuses.filter(
|
|
32011
|
+
const provisionalReservationNames = new Set(
|
|
32012
|
+
this.preparedBuses.filter(
|
|
32013
|
+
(candidate) => candidate.termination.type === "plane" || candidate === adjacentCenteredFieldByTurningBus.get(bus)
|
|
32014
|
+
).flatMap(
|
|
31669
32015
|
(candidate) => candidate.connections.map(
|
|
31670
32016
|
(connection) => connection.connection.name
|
|
31671
32017
|
)
|
|
@@ -31676,10 +32022,10 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31676
32022
|
...routeParams,
|
|
31677
32023
|
fixedViaPointsByConnectionIndex: void 0,
|
|
31678
32024
|
reservedVias: routeParams.reservedVias.filter(
|
|
31679
|
-
(reserved) => !
|
|
32025
|
+
(reserved) => !provisionalReservationNames.has(reserved.connectionName)
|
|
31680
32026
|
),
|
|
31681
32027
|
softReservedVias: routeParams.reservedVias.filter(
|
|
31682
|
-
(reserved) =>
|
|
32028
|
+
(reserved) => provisionalReservationNames.has(reserved.connectionName)
|
|
31683
32029
|
)
|
|
31684
32030
|
},
|
|
31685
32031
|
1
|
|
@@ -31719,7 +32065,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31719
32065
|
if (rematchedPoints) {
|
|
31720
32066
|
busPlans = freePlans;
|
|
31721
32067
|
fixedViaPointsByConnectionIndex = rematchedPoints;
|
|
31722
|
-
|
|
32068
|
+
usedRepairedViaSites = true;
|
|
31723
32069
|
}
|
|
31724
32070
|
}
|
|
31725
32071
|
}
|
|
@@ -31732,7 +32078,7 @@ var FanoutSolver = class extends BaseSolver {
|
|
|
31732
32078
|
rawSkew,
|
|
31733
32079
|
maximumSkew: bus.maxLengthSkew
|
|
31734
32080
|
});
|
|
31735
|
-
if (needsRouteDiversity && !matchLengthsAfterPlanes && !
|
|
32081
|
+
if (needsRouteDiversity && !matchLengthsAfterPlanes && !usedRepairedViaSites) {
|
|
31736
32082
|
busPlans = (yield* routeAlternatives(routeParams, 3)).toSorted(
|
|
31737
32083
|
(first, second) => {
|
|
31738
32084
|
const firstLengths = first.map((plan) => plan.length);
|
|
@@ -46959,7 +47305,7 @@ function Group_getRoutingPhasePlans(group) {
|
|
|
46959
47305
|
var package_default = {
|
|
46960
47306
|
name: "@tscircuit/core",
|
|
46961
47307
|
type: "module",
|
|
46962
|
-
version: "0.0.
|
|
47308
|
+
version: "0.0.1851",
|
|
46963
47309
|
types: "dist/index.d.ts",
|
|
46964
47310
|
main: "dist/index.js",
|
|
46965
47311
|
module: "dist/index.js",
|
|
@@ -46999,7 +47345,7 @@ var package_default = {
|
|
|
46999
47345
|
"@tscircuit/common": "^0.0.20",
|
|
47000
47346
|
"@tscircuit/copper-pour-solver": "^0.0.52",
|
|
47001
47347
|
"@tscircuit/create-fdm-enclosure": "0.0.4",
|
|
47002
|
-
"@tscircuit/fanout-solver": "0.0.
|
|
47348
|
+
"@tscircuit/fanout-solver": "0.0.62",
|
|
47003
47349
|
"@tscircuit/footprinter": "^0.0.426",
|
|
47004
47350
|
"@tscircuit/image-utils": "^0.0.8",
|
|
47005
47351
|
"@tscircuit/implicit-copper-pour-solver": "github:tscircuit/implicit-copper-pour-solver#a5cbbda0cd65fd4707c5c1af25779837c25aba92",
|
|
@@ -47014,7 +47360,7 @@ var package_default = {
|
|
|
47014
47360
|
"@tscircuit/ngspice-spice-engine": "^0.0.20",
|
|
47015
47361
|
"@tscircuit/props": "^0.0.646",
|
|
47016
47362
|
"@tscircuit/schematic-match-adapt": "^0.0.18",
|
|
47017
|
-
"@tscircuit/schematic-trace-solver": "^0.0.
|
|
47363
|
+
"@tscircuit/schematic-trace-solver": "^0.0.186",
|
|
47018
47364
|
"@tscircuit/solver-utils": "^0.0.16",
|
|
47019
47365
|
"@tscircuit/soup-util": "^0.0.41",
|
|
47020
47366
|
"@tscircuit/winding-breakout-point-solver": "github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803",
|
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.1852",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
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.62",
|
|
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",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@tscircuit/ngspice-spice-engine": "^0.0.20",
|
|
57
57
|
"@tscircuit/props": "^0.0.646",
|
|
58
58
|
"@tscircuit/schematic-match-adapt": "^0.0.18",
|
|
59
|
-
"@tscircuit/schematic-trace-solver": "^0.0.
|
|
59
|
+
"@tscircuit/schematic-trace-solver": "^0.0.186",
|
|
60
60
|
"@tscircuit/solver-utils": "^0.0.16",
|
|
61
61
|
"@tscircuit/soup-util": "^0.0.41",
|
|
62
62
|
"@tscircuit/winding-breakout-point-solver": "github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803",
|