@tscircuit/schematic-trace-solver 0.0.164 → 0.0.166
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.d.ts +5 -1
- package/dist/index.js +370 -24
- package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +225 -24
- package/lib/solvers/SameNetJunctionAlignmentSolver/SameNetJunctionAlignmentSolver.ts +11 -5
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +1 -1
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +310 -0
- package/package.json +1 -1
- package/tests/assets/example51.json +6 -0
- package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
- package/tests/examples/__snapshots__/example51.snap.svg +42 -78
- package/tests/examples/example51.test.ts +24 -0
- package/tests/fixtures/convertSolverOutputToCircuitJson.ts +22 -3
- package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bluetooth-controller-ground-decoupling-groups.snap.svg +1 -15
- package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +2 -16
- package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +10 -10
- package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +18 -18
- package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +1 -15
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +33 -47
- package/tests/repros/repro-board-648-esp12f-section.test.ts +3 -0
- package/tests/repros/repro-isolated-rs485-isow7841.test.ts +33 -1
- package/tests/repros/repro-nrf52810-clock-routing.test.ts +26 -1
- package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-same-net-cycles.test.ts +154 -0
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getTraceRecoveryConnectivityMaps,
|
|
13
13
|
type TraceRecoveryPin,
|
|
14
14
|
} from "lib/solvers/NetLabelTraceRecovery/getTraceRecoveryConnectivityMaps"
|
|
15
|
+
import { getTraceConnectedPinComponents } from "lib/solvers/SchematicTraceLinesSolver/getTraceConnectedPinComponents"
|
|
15
16
|
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
16
17
|
import { SchematicTraceSingleLineSolver2 } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2"
|
|
17
18
|
import type {
|
|
@@ -37,10 +38,14 @@ interface CandidatePair {
|
|
|
37
38
|
perpendicularOffset: number
|
|
38
39
|
routeDistance: number
|
|
39
40
|
key: string
|
|
41
|
+
recoveryMode: "fallback_labels" | "routed_components"
|
|
42
|
+
netConnectionPinIds?: PinId[]
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
const AVAILABLE_NET_ORIENTATION_PREFIX = "available-net-orientation-"
|
|
43
46
|
const RECOVERED_TRACE_PREFIX = "net-label-to-trace-"
|
|
47
|
+
const MAX_NAMED_NET_RECOVERY_PERPENDICULAR_OFFSET = 0.05
|
|
48
|
+
const MAX_ROUTED_COMPONENT_RECOVERY_PERPENDICULAR_OFFSET = 0.25
|
|
44
49
|
|
|
45
50
|
const getCanonicalPairKey = (firstPinId: PinId, secondPinId: PinId) =>
|
|
46
51
|
[firstPinId, secondPinId].sort().join("--")
|
|
@@ -70,14 +75,28 @@ export const pathIntersectsRenderedLabel = (
|
|
|
70
75
|
return false
|
|
71
76
|
}
|
|
72
77
|
|
|
73
|
-
const getPerpendicularOffset = (
|
|
78
|
+
const getPerpendicularOffset = (firstPoint: Point, secondPoint: Point) => {
|
|
79
|
+
const xDistance = Math.abs(firstPoint.x - secondPoint.x)
|
|
80
|
+
const yDistance = Math.abs(firstPoint.y - secondPoint.y)
|
|
81
|
+
if (xDistance >= yDistance) return yDistance
|
|
82
|
+
return xDistance
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const arePinsCoFacingAlongSeparationAxis = (
|
|
74
86
|
firstPin: TraceRecoveryPin,
|
|
75
87
|
secondPin: TraceRecoveryPin,
|
|
76
88
|
) => {
|
|
89
|
+
if (firstPin._facingDirection !== secondPin._facingDirection) return false
|
|
77
90
|
const xDistance = Math.abs(firstPin.x - secondPin.x)
|
|
78
91
|
const yDistance = Math.abs(firstPin.y - secondPin.y)
|
|
79
|
-
if (xDistance >= yDistance)
|
|
80
|
-
|
|
92
|
+
if (xDistance >= yDistance) {
|
|
93
|
+
return (
|
|
94
|
+
firstPin._facingDirection === "x+" || firstPin._facingDirection === "x-"
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
return (
|
|
98
|
+
firstPin._facingDirection === "y+" || firstPin._facingDirection === "y-"
|
|
99
|
+
)
|
|
81
100
|
}
|
|
82
101
|
|
|
83
102
|
export class NetLabelToTraceSolver extends BaseSolver {
|
|
@@ -113,20 +132,20 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
113
132
|
return [this.input]
|
|
114
133
|
}
|
|
115
134
|
|
|
116
|
-
private
|
|
135
|
+
private isPortOnlyFallbackLabel(
|
|
117
136
|
label: NetLabelPlacement,
|
|
118
|
-
|
|
137
|
+
groundGlobalConnNetIds: Set<GlobalConnNetId>,
|
|
119
138
|
) {
|
|
120
|
-
|
|
139
|
+
return !(
|
|
121
140
|
label.pinIds.length !== 1 ||
|
|
122
141
|
label.mspConnectionPairIds.length !== 0 ||
|
|
123
142
|
!label.netId ||
|
|
124
|
-
label.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return false
|
|
128
|
-
}
|
|
143
|
+
groundGlobalConnNetIds.has(label.globalConnNetId)
|
|
144
|
+
)
|
|
145
|
+
}
|
|
129
146
|
|
|
147
|
+
private isDirectConnectionLabel(label: NetLabelPlacement) {
|
|
148
|
+
if (!label.netId || label.pinIds.length !== 1) return false
|
|
130
149
|
const pinId = label.pinIds[0]!
|
|
131
150
|
return this.inputProblem.directConnections.some(
|
|
132
151
|
(connection) =>
|
|
@@ -134,20 +153,35 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
134
153
|
)
|
|
135
154
|
}
|
|
136
155
|
|
|
156
|
+
private getMultiPinNetConnection(label: NetLabelPlacement) {
|
|
157
|
+
if (!label.netId || label.pinIds.length !== 1) return undefined
|
|
158
|
+
const pinId = label.pinIds[0]!
|
|
159
|
+
return this.inputProblem.netConnections.find(
|
|
160
|
+
(connection) =>
|
|
161
|
+
connection.isGround === false &&
|
|
162
|
+
connection.pinIds.length > 2 &&
|
|
163
|
+
connection.netId === label.netId &&
|
|
164
|
+
connection.pinIds.includes(pinId),
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
137
168
|
private buildCandidatePairs() {
|
|
138
169
|
const { netConnMap } = getConnectivityMapsFromInputProblem(
|
|
139
170
|
this.inputProblem,
|
|
140
171
|
)
|
|
141
|
-
const
|
|
142
|
-
|
|
172
|
+
const groundGlobalConnNetIds = new Set<GlobalConnNetId>()
|
|
173
|
+
for (const connection of this.inputProblem.netConnections) {
|
|
174
|
+
if (!connection.isGround) continue
|
|
175
|
+
const globalConnNetId = netConnMap.getNetConnectedToId(connection.netId)
|
|
176
|
+
if (globalConnNetId) groundGlobalConnNetIds.add(globalConnNetId)
|
|
177
|
+
}
|
|
143
178
|
const labelsByGlobalNet = new Map<GlobalConnNetId, NetLabelPlacement[]>()
|
|
144
179
|
|
|
145
180
|
for (const label of this.input.netLabelPlacements) {
|
|
146
181
|
if (
|
|
147
|
-
!this.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
182
|
+
!this.isPortOnlyFallbackLabel(label, groundGlobalConnNetIds) ||
|
|
183
|
+
(!this.isDirectConnectionLabel(label) &&
|
|
184
|
+
!this.getMultiPinNetConnection(label))
|
|
151
185
|
) {
|
|
152
186
|
continue
|
|
153
187
|
}
|
|
@@ -169,6 +203,25 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
169
203
|
const firstPin = this.pinMap.get(firstLabel.pinIds[0]!)
|
|
170
204
|
const secondPin = this.pinMap.get(secondLabel.pinIds[0]!)
|
|
171
205
|
if (!firstPin || !secondPin) continue
|
|
206
|
+
const perpendicularOffset = getPerpendicularOffset(
|
|
207
|
+
firstPin,
|
|
208
|
+
secondPin,
|
|
209
|
+
)
|
|
210
|
+
const bothLabelsBelongToDirectConnections =
|
|
211
|
+
this.isDirectConnectionLabel(firstLabel) &&
|
|
212
|
+
this.isDirectConnectionLabel(secondLabel)
|
|
213
|
+
const firstMultiPinNetConnection =
|
|
214
|
+
this.getMultiPinNetConnection(firstLabel)
|
|
215
|
+
const secondMultiPinNetConnection =
|
|
216
|
+
this.getMultiPinNetConnection(secondLabel)
|
|
217
|
+
if (
|
|
218
|
+
!bothLabelsBelongToDirectConnections &&
|
|
219
|
+
(!firstMultiPinNetConnection ||
|
|
220
|
+
firstMultiPinNetConnection !== secondMultiPinNetConnection ||
|
|
221
|
+
perpendicularOffset > MAX_NAMED_NET_RECOVERY_PERPENDICULAR_OFFSET)
|
|
222
|
+
) {
|
|
223
|
+
continue
|
|
224
|
+
}
|
|
172
225
|
if (
|
|
173
226
|
arePinsInDifferentSchematicSections(
|
|
174
227
|
this.inputProblem,
|
|
@@ -194,16 +247,19 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
194
247
|
firstLabel,
|
|
195
248
|
secondLabel,
|
|
196
249
|
pins: [firstPin, secondPin],
|
|
197
|
-
perpendicularOffset
|
|
250
|
+
perpendicularOffset,
|
|
198
251
|
routeDistance:
|
|
199
252
|
Math.abs(firstPin.x - secondPin.x) +
|
|
200
253
|
Math.abs(firstPin.y - secondPin.y),
|
|
201
254
|
key: getCanonicalPairKey(firstPin.pinId, secondPin.pinId),
|
|
255
|
+
recoveryMode: "fallback_labels",
|
|
202
256
|
})
|
|
203
257
|
}
|
|
204
258
|
}
|
|
205
259
|
}
|
|
206
260
|
|
|
261
|
+
candidates.push(...this.buildRoutedComponentCandidates())
|
|
262
|
+
|
|
207
263
|
candidates.sort(
|
|
208
264
|
(first, second) =>
|
|
209
265
|
first.perpendicularOffset - second.perpendicularOffset ||
|
|
@@ -213,6 +269,129 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
213
269
|
return candidates
|
|
214
270
|
}
|
|
215
271
|
|
|
272
|
+
private buildRoutedComponentCandidates() {
|
|
273
|
+
const { netConnMap } = getConnectivityMapsFromInputProblem(
|
|
274
|
+
this.inputProblem,
|
|
275
|
+
)
|
|
276
|
+
const candidates: CandidatePair[] = []
|
|
277
|
+
|
|
278
|
+
for (const connection of this.inputProblem.netConnections) {
|
|
279
|
+
if (connection.pinIds.length <= 2 || connection.isGround !== false)
|
|
280
|
+
continue
|
|
281
|
+
const globalConnNetId = netConnMap.getNetConnectedToId(connection.netId)
|
|
282
|
+
if (!globalConnNetId) continue
|
|
283
|
+
|
|
284
|
+
const traceConnectedPinComponents = getTraceConnectedPinComponents({
|
|
285
|
+
pinIds: connection.pinIds,
|
|
286
|
+
traces: this.outputTraces.filter(
|
|
287
|
+
(trace) => trace.globalConnNetId === globalConnNetId,
|
|
288
|
+
),
|
|
289
|
+
}).filter((component) => component.traces.length > 0)
|
|
290
|
+
|
|
291
|
+
for (
|
|
292
|
+
let firstIndex = 0;
|
|
293
|
+
firstIndex < traceConnectedPinComponents.length;
|
|
294
|
+
firstIndex++
|
|
295
|
+
) {
|
|
296
|
+
for (
|
|
297
|
+
let secondIndex = firstIndex + 1;
|
|
298
|
+
secondIndex < traceConnectedPinComponents.length;
|
|
299
|
+
secondIndex++
|
|
300
|
+
) {
|
|
301
|
+
const firstComponent = traceConnectedPinComponents[firstIndex]!
|
|
302
|
+
const secondComponent = traceConnectedPinComponents[secondIndex]!
|
|
303
|
+
const firstLabel = this.input.netLabelPlacements.find(
|
|
304
|
+
(label) =>
|
|
305
|
+
label.globalConnNetId === globalConnNetId &&
|
|
306
|
+
label.mspConnectionPairIds.length > 0 &&
|
|
307
|
+
label.pinIds.some((pinId) =>
|
|
308
|
+
firstComponent.pinIds.includes(pinId),
|
|
309
|
+
),
|
|
310
|
+
)
|
|
311
|
+
const secondLabel = this.input.netLabelPlacements.find(
|
|
312
|
+
(label) =>
|
|
313
|
+
label.globalConnNetId === globalConnNetId &&
|
|
314
|
+
label.mspConnectionPairIds.length > 0 &&
|
|
315
|
+
label.pinIds.some((pinId) =>
|
|
316
|
+
secondComponent.pinIds.includes(pinId),
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
if (!firstLabel || !secondLabel || firstLabel === secondLabel)
|
|
320
|
+
continue
|
|
321
|
+
if (
|
|
322
|
+
getPerpendicularOffset(
|
|
323
|
+
firstLabel.anchorPoint,
|
|
324
|
+
secondLabel.anchorPoint,
|
|
325
|
+
) > MAX_ROUTED_COMPONENT_RECOVERY_PERPENDICULAR_OFFSET
|
|
326
|
+
) {
|
|
327
|
+
continue
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
let bestCandidate: CandidatePair | undefined
|
|
331
|
+
for (const firstPinId of firstComponent.pinIds) {
|
|
332
|
+
for (const secondPinId of secondComponent.pinIds) {
|
|
333
|
+
const firstPin = this.pinMap.get(firstPinId)
|
|
334
|
+
const secondPin = this.pinMap.get(secondPinId)
|
|
335
|
+
if (!firstPin || !secondPin) continue
|
|
336
|
+
const perpendicularOffset = getPerpendicularOffset(
|
|
337
|
+
firstPin,
|
|
338
|
+
secondPin,
|
|
339
|
+
)
|
|
340
|
+
if (
|
|
341
|
+
perpendicularOffset >
|
|
342
|
+
MAX_ROUTED_COMPONENT_RECOVERY_PERPENDICULAR_OFFSET ||
|
|
343
|
+
arePinsCoFacingAlongSeparationAxis(firstPin, secondPin) ||
|
|
344
|
+
arePinsInDifferentSchematicSections(
|
|
345
|
+
this.inputProblem,
|
|
346
|
+
firstPin,
|
|
347
|
+
secondPin,
|
|
348
|
+
) ||
|
|
349
|
+
doesPairCrossRestrictedCenterLines({
|
|
350
|
+
inputProblem: this.inputProblem,
|
|
351
|
+
chipMap: this.chipMap,
|
|
352
|
+
pinIdMap: this.pinMap,
|
|
353
|
+
p1: firstPin,
|
|
354
|
+
p2: secondPin,
|
|
355
|
+
})
|
|
356
|
+
) {
|
|
357
|
+
continue
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const routeDistance =
|
|
361
|
+
Math.abs(firstPin.x - secondPin.x) +
|
|
362
|
+
Math.abs(firstPin.y - secondPin.y)
|
|
363
|
+
const candidate: CandidatePair = {
|
|
364
|
+
firstLabel,
|
|
365
|
+
secondLabel,
|
|
366
|
+
pins: [firstPin, secondPin],
|
|
367
|
+
perpendicularOffset,
|
|
368
|
+
routeDistance,
|
|
369
|
+
key: getCanonicalPairKey(firstPin.pinId, secondPin.pinId),
|
|
370
|
+
recoveryMode: "routed_components",
|
|
371
|
+
netConnectionPinIds: connection.pinIds,
|
|
372
|
+
}
|
|
373
|
+
if (
|
|
374
|
+
!bestCandidate ||
|
|
375
|
+
candidate.routeDistance < bestCandidate.routeDistance ||
|
|
376
|
+
(candidate.routeDistance === bestCandidate.routeDistance &&
|
|
377
|
+
(candidate.perpendicularOffset <
|
|
378
|
+
bestCandidate.perpendicularOffset ||
|
|
379
|
+
(candidate.perpendicularOffset ===
|
|
380
|
+
bestCandidate.perpendicularOffset &&
|
|
381
|
+
candidate.key.localeCompare(bestCandidate.key) < 0)))
|
|
382
|
+
) {
|
|
383
|
+
bestCandidate = candidate
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (bestCandidate) candidates.push(bestCandidate)
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return candidates
|
|
393
|
+
}
|
|
394
|
+
|
|
216
395
|
private isSupersededConnectorTrace(
|
|
217
396
|
trace: SolvedTracePath,
|
|
218
397
|
candidate: CandidatePair,
|
|
@@ -247,8 +426,15 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
247
426
|
const retainedTraces = this.outputTraces.filter(
|
|
248
427
|
(trace) => !this.isSupersededConnectorTrace(trace, candidate),
|
|
249
428
|
)
|
|
429
|
+
let collisionTraces = retainedTraces
|
|
430
|
+
if (candidate.recoveryMode === "routed_components") {
|
|
431
|
+
collisionTraces = retainedTraces.filter(
|
|
432
|
+
(trace) =>
|
|
433
|
+
trace.globalConnNetId !== candidate.firstLabel.globalConnNetId,
|
|
434
|
+
)
|
|
435
|
+
}
|
|
250
436
|
if (
|
|
251
|
-
doesTraceOverlapWithExistingTraces(tracePath,
|
|
437
|
+
doesTraceOverlapWithExistingTraces(tracePath, collisionTraces) ||
|
|
252
438
|
this.routeIntersectsRemainingLabels(tracePath, candidate)
|
|
253
439
|
) {
|
|
254
440
|
return
|
|
@@ -267,13 +453,27 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
267
453
|
}
|
|
268
454
|
|
|
269
455
|
this.outputTraces = [...retainedTraces, recoveredTrace]
|
|
270
|
-
|
|
271
|
-
(
|
|
272
|
-
label
|
|
273
|
-
|
|
456
|
+
if (candidate.recoveryMode === "fallback_labels") {
|
|
457
|
+
this.outputNetLabelPlacements = this.outputNetLabelPlacements.filter(
|
|
458
|
+
(label) =>
|
|
459
|
+
label !== candidate.firstLabel && label !== candidate.secondLabel,
|
|
460
|
+
)
|
|
461
|
+
}
|
|
274
462
|
this.stats.recoveredTraceCount++
|
|
275
463
|
}
|
|
276
464
|
|
|
465
|
+
private areCandidatePinsAlreadyConnected(candidate: CandidatePair) {
|
|
466
|
+
if (!candidate.netConnectionPinIds) return false
|
|
467
|
+
return getTraceConnectedPinComponents({
|
|
468
|
+
pinIds: candidate.netConnectionPinIds,
|
|
469
|
+
traces: this.outputTraces,
|
|
470
|
+
}).some(
|
|
471
|
+
(component) =>
|
|
472
|
+
component.pinIds.includes(candidate.pins[0].pinId) &&
|
|
473
|
+
component.pinIds.includes(candidate.pins[1].pinId),
|
|
474
|
+
)
|
|
475
|
+
}
|
|
476
|
+
|
|
277
477
|
override _step() {
|
|
278
478
|
if (this.activeSubSolver) {
|
|
279
479
|
this.activeSubSolver.step()
|
|
@@ -292,7 +492,8 @@ export class NetLabelToTraceSolver extends BaseSolver {
|
|
|
292
492
|
while (
|
|
293
493
|
candidate &&
|
|
294
494
|
(!this.outputNetLabelPlacements.includes(candidate.firstLabel) ||
|
|
295
|
-
!this.outputNetLabelPlacements.includes(candidate.secondLabel)
|
|
495
|
+
!this.outputNetLabelPlacements.includes(candidate.secondLabel) ||
|
|
496
|
+
this.areCandidatePinsAlreadyConnected(candidate))
|
|
296
497
|
) {
|
|
297
498
|
candidate = this.queuedCandidates.shift()
|
|
298
499
|
}
|
|
@@ -6,6 +6,7 @@ import { visualizeInputProblem } from "lib/solvers/SchematicTracePipelineSolver/
|
|
|
6
6
|
import type { InputProblem } from "lib/types/InputProblem"
|
|
7
7
|
import { getColorFromString } from "lib/utils/getColorFromString"
|
|
8
8
|
import { alignSameNetJunctions } from "./alignSameNetJunctions"
|
|
9
|
+
import { collapseSameNetCycles } from "./collapseSameNetCycles"
|
|
9
10
|
import { placeGroundRailLabelsAtOuterEnd } from "./placeGroundRailLabelsAtOuterEnd"
|
|
10
11
|
|
|
11
12
|
interface SameNetJunctionAlignmentSolverInput {
|
|
@@ -28,14 +29,19 @@ export class SameNetJunctionAlignmentSolver extends BaseSolver {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
override _step() {
|
|
31
|
-
const
|
|
32
|
-
|
|
32
|
+
const alignment = alignSameNetJunctions(this.input)
|
|
33
|
+
const cycleCollapse = collapseSameNetCycles({
|
|
34
|
+
traces: alignment.traces,
|
|
35
|
+
netLabelPlacements: alignment.netLabelPlacements,
|
|
36
|
+
})
|
|
37
|
+
this.outputTraces = cycleCollapse.traces
|
|
33
38
|
this.outputNetLabelPlacements = placeGroundRailLabelsAtOuterEnd({
|
|
34
39
|
inputProblem: this.input.inputProblem,
|
|
35
|
-
traces:
|
|
36
|
-
netLabelPlacements:
|
|
40
|
+
traces: cycleCollapse.traces,
|
|
41
|
+
netLabelPlacements: cycleCollapse.netLabelPlacements,
|
|
37
42
|
})
|
|
38
|
-
this.stats.alignedJunctionCount =
|
|
43
|
+
this.stats.alignedJunctionCount = alignment.alignedJunctionCount
|
|
44
|
+
this.stats.collapsedCycleCount = cycleCollapse.collapsedCycleCount
|
|
39
45
|
this.solved = true
|
|
40
46
|
}
|
|
41
47
|
|