Skip to content

Commit ccd9622

Browse files
committed
Preserve trace-layer improvements for the via-pad repair phase
1 parent 6346ce3 commit ccd9622

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

lib/solvers/GlobalDrcForceImproveSolver/GlobalDrcBranchPortfolioSolver.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,11 +492,15 @@ export class GlobalDrcBranchPortfolioSolver extends BaseSolver {
492492
this.params.connMap,
493493
this.autoroutingDrcEngine,
494494
)
495+
// Match the inner solver's staged scoring: via-pad issues are handled
496+
// by the following phase, while via-pair/trace collisions stay guarded.
495497
const inputViaIssueCount = getViaDrcIssueCount(
496498
this.safeTraceLayerInputSnapshot!,
499+
false,
497500
)
498501
const safeTraceLayerViaIssueCount = getViaDrcIssueCount(
499502
safeTraceLayerSnapshot,
503+
false,
500504
)
501505
this.safeTraceLayerPhaseAccepted =
502506
safeTraceLayerViaIssueCount <= inputViaIssueCount &&
@@ -506,6 +510,7 @@ export class GlobalDrcBranchPortfolioSolver extends BaseSolver {
506510
this.safeTraceLayerInputSnapshot!.count,
507511
this.safeTraceLayerInputSnapshot!.issueScore,
508512
inputViaIssueCount,
513+
this.safeTraceLayerInputSnapshot!,
509514
)
510515
const acceptedRoutes = this.safeTraceLayerPhaseAccepted
511516
? safeTraceLayerRoutes
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { expect, test } from "bun:test"
2+
import {
3+
GlobalDrcBranchPortfolioSolver,
4+
type DrcEvaluator,
5+
type HighDensityRoute,
6+
type SimpleRouteJson,
7+
} from "../lib"
8+
9+
test("keeps trace-layer improvements for via-pad repair without accepting via-trace regressions", () => {
10+
const srj: SimpleRouteJson = {
11+
layerCount: 3,
12+
minTraceWidth: 0.1,
13+
minViaDiameter: 0.3,
14+
bounds: { minX: -3, minY: -3, maxX: 3, maxY: 3 },
15+
obstacles: [],
16+
connections: [
17+
{
18+
name: "trace",
19+
pointsToConnect: [
20+
{ x: -2, y: 0, layer: "top" },
21+
{ x: 2, y: 0, layer: "top" },
22+
],
23+
},
24+
{
25+
name: "foreign",
26+
pointsToConnect: [
27+
{ x: 0, y: -2, layer: "top" },
28+
{ x: 0, y: 2, layer: "top" },
29+
],
30+
},
31+
],
32+
}
33+
const hdRoutes: HighDensityRoute[] = srj.connections.map((connection) => ({
34+
connectionName: connection.name,
35+
traceThickness: 0.1,
36+
viaDiameter: 0.3,
37+
vias: [],
38+
route: connection.pointsToConnect.map((point) => ({
39+
x: point.x,
40+
y: point.y,
41+
z: 0,
42+
})),
43+
}))
44+
const initialError = {
45+
type: "pcb_trace_error",
46+
pcb_trace_id: "trace_0",
47+
pcb_trace_error_id: "overlap_trace_0_foreign_0",
48+
center: { x: 0, y: 0 },
49+
}
50+
for (const errorType of [
51+
"pcb_pad_pad_clearance_error",
52+
"pcb_via_trace_clearance_error",
53+
]) {
54+
const residualError = {
55+
type: errorType,
56+
pcb_via_ids: ["trace_via_0"],
57+
center: { x: -2, y: 0 },
58+
}
59+
const drcEvaluator: DrcEvaluator = ({ routes, hdRoutes }) => {
60+
const candidateRoutes = hdRoutes ?? routes
61+
if (!candidateRoutes) throw new Error("Expected candidate routes")
62+
return candidateRoutes.some((route) =>
63+
route.route.some((point) => point.z !== 0),
64+
)
65+
? [residualError]
66+
: [initialError]
67+
}
68+
const solver = new GlobalDrcBranchPortfolioSolver({
69+
srj,
70+
hdRoutes,
71+
drcEvaluator,
72+
maxIterations: 2,
73+
broadMaxIterations: 1,
74+
broadPassMultiplier: 1,
75+
viaInPadMaxIterations: 1,
76+
enableLargeBoardBroadFallback: false,
77+
enablePostSolveClearanceRelaxation: false,
78+
enableSafeTraceLayerMoves: true,
79+
enableViaInPadLayerMoves: false,
80+
})
81+
solver.solve()
82+
83+
expect(solver.solved).toBe(true)
84+
const shouldAccept = errorType === "pcb_pad_pad_clearance_error"
85+
expect(solver.stats.drcBranchPortfolioSafeTraceLayerPhaseAccepted).toBe(
86+
shouldAccept,
87+
)
88+
expect(drcEvaluator({ traces: [], hdRoutes: solver.getOutput() })).toEqual([
89+
shouldAccept ? residualError : initialError,
90+
])
91+
}
92+
expect(
93+
hdRoutes.every((route) => route.route.every((point) => point.z === 0)),
94+
).toBe(true)
95+
})

0 commit comments

Comments
 (0)