Skip to content

Commit 5d76d6a

Browse files
committed
Eliminate false DRC via-collision errors by carrying true routed via diameters through SRJ→circuit-json conversion
1 parent da416cb commit 5d76d6a

File tree

6 files changed

+107
-5
lines changed

6 files changed

+107
-5
lines changed

lib/testing/utils/convertToCircuitJson.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ function createPcbSmtPads(srj: SimpleRouteJson): AnyCircuitElement[] {
365365
*/
366366
function extractViasFromRoutes(
367367
routes: SimplifiedPcbTrace[] | HighDensityRoute[],
368-
minViaDiameter = 0.6,
368+
minViaDiameter = 0.3,
369369
): PcbVia[] {
370370
const vias: PcbVia[] = []
371371
const viaLocations = new Set<string>() // Track unique via locations
@@ -376,6 +376,7 @@ function extractViasFromRoutes(
376376
;(routes as SimplifiedPcbTrace[]).forEach((trace) => {
377377
trace.route.forEach((segment) => {
378378
if (segment.route_type === "via") {
379+
const viaDiameter = segment.via_diameter ?? minViaDiameter
379380
const locationKey = `${segment.x},${segment.y},${segment.from_layer},${segment.to_layer}`
380381
if (!viaLocations.has(locationKey)) {
381382
vias.push({
@@ -384,8 +385,8 @@ function extractViasFromRoutes(
384385
pcb_trace_id: trace.pcb_trace_id,
385386
x: segment.x,
386387
y: segment.y,
387-
outer_diameter: minViaDiameter,
388-
hole_diameter: minViaDiameter * 0.5,
388+
outer_diameter: viaDiameter,
389+
hole_diameter: viaDiameter * 0.5,
389390
layers: [segment.from_layer, segment.to_layer] as LayerName[],
390391
})
391392
viaLocations.add(locationKey)
@@ -397,7 +398,7 @@ function extractViasFromRoutes(
397398
// Extract vias from HighDensityRoutes by looking for layer changes
398399
;(routes as HighDensityRoute[]).forEach((route, routeIndex) => {
399400
const traceId = `trace_${routeIndex}`
400-
const viaDiameter = route.viaDiameter || minViaDiameter
401+
const viaDiameter = route.viaDiameter ?? minViaDiameter
401402
for (let i = 1; i < route.route.length; i++) {
402403
const prevPoint = route.route[i - 1]
403404
const currPoint = route.route[i]
@@ -445,7 +446,7 @@ export function convertToCircuitJson(
445446
srjWithPointPairs: SimpleRouteJson,
446447
routes: SimplifiedPcbTrace[] | HighDensityRoute[],
447448
minTraceWidth = 0.1,
448-
minViaDiameter = 0.6,
449+
minViaDiameter = srjWithPointPairs.minViaDiameter ?? 0.3,
449450
): AnyCircuitElement[] {
450451
// Start with empty circuit JSON
451452
const circuitJson: AnyCircuitElement[] = []

lib/types/srj-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export interface SimplifiedPcbTrace {
9797
y: number
9898
to_layer: string
9999
from_layer: string
100+
via_diameter?: number
100101
}
101102
| {
102103
route_type: "jumper"

lib/utils/convertHdRouteToSimplifiedRoute.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const convertHdRouteToSimplifiedRoute = (
5858
y: point.y,
5959
from_layer: fromLayer,
6060
to_layer: toLayer,
61+
via_diameter: hdRoute.viaDiameter,
6162
})
6263
}
6364

tests/features/fixed-topology-high-density-intra-node-solver.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import { getDrcErrors } from "lib/testing/getDrcErrors"
55
import { convertToCircuitJson } from "lib/testing/utils/convertToCircuitJson"
66
import { createSrjFromNodeWithPortPoints } from "lib/utils/createSrjFromNodeWithPortPoints"
77
import { HyperSingleIntraNodeSolver } from "lib/solvers/HyperHighDensitySolver/HyperSingleIntraNodeSolver"
8+
import { convertHdRouteToSimplifiedRoute } from "lib/utils/convertHdRouteToSimplifiedRoute"
89
import input03 from "../../fixtures/features/via-high-density/via-high-density03-input.json" with {
910
type: "json",
1011
}
1112
import { FixedTopologyHighDensityIntraNodeSolver } from "lib/solvers/FixedTopologyHighDensityIntraNodeSolver"
13+
import type { SimplifiedPcbTrace } from "lib/types"
1214

1315
test("FixedTopologyHighDensityIntraNodeSolver test", () => {
1416
const solver = new FixedTopologyHighDensityIntraNodeSolver({
@@ -47,6 +49,30 @@ test("FixedTopologyHighDensityIntraNodeSolver test", () => {
4749
),
4850
)
4951
expect(hasBottomLayerTrace).toBe(true)
52+
expect(
53+
circuitJson
54+
.filter((element) => element.type === "pcb_via")
55+
.every((via) => via.outer_diameter <= 0.3 + 1e-6),
56+
).toBe(true)
57+
58+
const simplifiedTraces: SimplifiedPcbTrace[] = solver.solvedRoutes.map(
59+
(route, index) => ({
60+
type: "pcb_trace",
61+
pcb_trace_id: `fixed_topology_${index}`,
62+
connection_name: route.connectionName,
63+
route: convertHdRouteToSimplifiedRoute(route, srj.layerCount),
64+
}),
65+
)
66+
const circuitJsonFromSimplified = convertToCircuitJson(
67+
srj,
68+
simplifiedTraces,
69+
srj.minTraceWidth,
70+
)
71+
expect(
72+
circuitJsonFromSimplified
73+
.filter((element) => element.type === "pcb_via")
74+
.every((via) => via.outer_diameter <= 0.3 + 1e-6),
75+
).toBe(true)
5076

5177
const pcbSvg = convertCircuitJsonToPcbSvg(circuitJson as AnyCircuitElement[])
5278
expect(pcbSvg).toMatchSvgSnapshot(import.meta.path)

tests/utils/convertHdRouteToSimplifiedRoute.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ describe("convertHdRouteToSimplifiedRoute", () => {
8585
"from_layer": "top",
8686
"route_type": "via",
8787
"to_layer": "inner1",
88+
"via_diameter": 0.5,
8889
"x": 2,
8990
"y": 2,
9091
},
@@ -113,6 +114,7 @@ describe("convertHdRouteToSimplifiedRoute", () => {
113114
"from_layer": "inner1",
114115
"route_type": "via",
115116
"to_layer": "inner2",
117+
"via_diameter": 0.5,
116118
"x": 4,
117119
"y": 4,
118120
},
@@ -187,6 +189,7 @@ describe("convertHdRouteToSimplifiedRoute", () => {
187189
"from_layer": "top",
188190
"route_type": "via",
189191
"to_layer": "inner1",
192+
"via_diameter": 0.4,
190193
"x": 2,
191194
"y": 2,
192195
},
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { expect, test } from "bun:test"
2+
import type { SimpleRouteJson, SimplifiedPcbTrace } from "lib/types"
3+
import { convertToCircuitJson } from "lib/testing/utils/convertToCircuitJson"
4+
5+
const createSrj = (minViaDiameter?: number): SimpleRouteJson => ({
6+
layerCount: 2,
7+
minTraceWidth: 0.1,
8+
...(minViaDiameter !== undefined ? { minViaDiameter } : {}),
9+
obstacles: [],
10+
connections: [
11+
{
12+
name: "conn_1",
13+
pointsToConnect: [
14+
{ x: 0, y: 0, layer: "top", pointId: "p1" },
15+
{ x: 1, y: 1, layer: "bottom", pointId: "p2" },
16+
],
17+
},
18+
],
19+
bounds: { minX: -2, maxX: 2, minY: -2, maxY: 2 },
20+
})
21+
22+
const createSimplifiedTraces = (viaDiameter?: number): SimplifiedPcbTrace[] => [
23+
{
24+
type: "pcb_trace",
25+
pcb_trace_id: "conn_1_0",
26+
connection_name: "conn_1",
27+
route: [
28+
{ route_type: "wire", x: 0, y: 0, width: 0.1, layer: "top" },
29+
{
30+
route_type: "via",
31+
x: 0.5,
32+
y: 0.5,
33+
from_layer: "top",
34+
to_layer: "bottom",
35+
...(viaDiameter !== undefined ? { via_diameter: viaDiameter } : {}),
36+
},
37+
{ route_type: "wire", x: 1, y: 1, width: 0.1, layer: "bottom" },
38+
],
39+
},
40+
]
41+
42+
test("uses actual via diameter from simplified route when available", () => {
43+
const circuitJson = convertToCircuitJson(
44+
createSrj(0.24),
45+
createSimplifiedTraces(0.33),
46+
)
47+
const vias = circuitJson.filter((e) => e.type === "pcb_via")
48+
expect(vias).toHaveLength(1)
49+
expect(vias[0].outer_diameter).toBe(0.33)
50+
})
51+
52+
test("falls back to srj.minViaDiameter when actual diameter is missing", () => {
53+
const circuitJson = convertToCircuitJson(
54+
createSrj(0.24),
55+
createSimplifiedTraces(),
56+
)
57+
const vias = circuitJson.filter((e) => e.type === "pcb_via")
58+
expect(vias).toHaveLength(1)
59+
expect(vias[0].outer_diameter).toBe(0.24)
60+
})
61+
62+
test("falls back to 0.3 when neither actual nor srj min via diameter is available", () => {
63+
const circuitJson = convertToCircuitJson(
64+
createSrj(),
65+
createSimplifiedTraces(),
66+
)
67+
const vias = circuitJson.filter((e) => e.type === "pcb_via")
68+
expect(vias).toHaveLength(1)
69+
expect(vias[0].outer_diameter).toBe(0.3)
70+
})

0 commit comments

Comments
 (0)