@tscircuit/checks 0.0.117 → 0.0.119
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/README.md +2 -1
- package/dist/index.d.ts +21 -6
- package/dist/index.js +395 -75
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ and output an array of arrays for any issues found.
|
|
|
19
19
|
| [`checkPcbComponentOverlap`](./lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts) | Returns `pcb_footprint_overlap_error` when footprint elements from different components overlap in disallowed ways. |
|
|
20
20
|
| [`checkPcbComponentsOutOfBoard`](./lib/check-pcb-components-out-of-board/checkPcbComponentsOutOfBoard.ts) | Returns `pcb_placement_error` when PCB components do not fit inside the board area. |
|
|
21
21
|
| [`checkPcbTracesOutOfBoard`](./lib/check-trace-out-of-board/checkTraceOutOfBoard.ts) | Returns `pcb_trace_error` when any trace segment or via extends beyond the board boundary. |
|
|
22
|
+
| [`checkViaTraceClearance`](./lib/check-via-trace-clearance.ts) | Returns `pcb_via_trace_clearance_error` when a via and unrelated trace segment violate minimum clearance. |
|
|
22
23
|
| [`checkPinMustBeConnected`](./lib/check-pin-must-be-connected.ts) | Returns `pcb_trace_error` when required source pins are not connected. |
|
|
23
24
|
| [`checkSameNetViaSpacing`](./lib/check-same-net-via-spacing.ts) | Returns `pcb_via_clearance_error` if vias on the same net are closer than the allowed margin. |
|
|
24
25
|
| [`checkSourceTracesHavePcbTraces`](./lib/check-source-traces-have-pcb-traces.ts) | Returns `pcb_trace_error` when source traces are missing corresponding `pcb_trace` routes. |
|
|
@@ -32,7 +33,7 @@ and output an array of arrays for any issues found.
|
|
|
32
33
|
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs all placement checks (`checkViasOffBoard`, `checkPcbComponentsOutOfBoard`, `checkPcbComponentOverlap`, and `checkConnectorAccessibleOrientation`). |
|
|
33
34
|
| [`runAllNetlistChecks`](./lib/run-all-checks.ts) | Runs netlist connectivity checks (currently `checkPinMustBeConnected`). |
|
|
34
35
|
| [`runAllPinSpecificationChecks`](./lib/run-all-checks.ts) | Runs pin specification checks (e.g. `checkAllPinsInComponentAreUnderspecified`, `checkNoPowerPinDefined`, and `checkNoGroundPinDefined`). |
|
|
35
|
-
| [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). |
|
|
36
|
+
| [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, `checkViaTraceClearance`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). |
|
|
36
37
|
| [`runAllChecks`](./lib/run-all-checks.ts) | Runs placement, netlist, pin specification, and routing checks and returns a combined list of issues. |
|
|
37
38
|
|
|
38
39
|
## Implementation Details
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as circuit_json from 'circuit-json';
|
|
2
|
-
import { AnyCircuitElement, PcbPortNotConnectedError, PcbTraceError, PcbPlacementError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, PcbConnectorNotInAccessibleOrientationWarning } from 'circuit-json';
|
|
2
|
+
import { AnyCircuitElement, PcbPortNotConnectedError, PcbTraceError, PcbPlacementError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbPadTraceClearanceError, PcbViaTraceClearanceError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, PcbConnectorNotInAccessibleOrientationWarning } from 'circuit-json';
|
|
3
3
|
import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
|
|
4
4
|
|
|
5
5
|
declare function checkEachPcbPortConnectedToPcbTraces(circuitJson: AnyCircuitElement[]): PcbPortNotConnectedError[];
|
|
@@ -61,6 +61,21 @@ declare function checkPcbTracesOutOfBoard(circuitJson: AnyCircuitElement[], conf
|
|
|
61
61
|
*/
|
|
62
62
|
declare function checkPcbComponentOverlap(circuitJson: AnyCircuitElement[]): PcbFootprintOverlapError[];
|
|
63
63
|
|
|
64
|
+
declare function checkPadPadClearance(circuitJson: AnyCircuitElement[], { connMap, minSpacing, }?: {
|
|
65
|
+
connMap?: ConnectivityMap;
|
|
66
|
+
minSpacing?: number;
|
|
67
|
+
}): PcbPadPadClearanceError[];
|
|
68
|
+
|
|
69
|
+
declare function checkPadTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minSpacing, }?: {
|
|
70
|
+
connMap?: ConnectivityMap;
|
|
71
|
+
minSpacing?: number;
|
|
72
|
+
}): PcbPadTraceClearanceError[];
|
|
73
|
+
|
|
74
|
+
declare function checkViaTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minSpacing, }?: {
|
|
75
|
+
connMap?: ConnectivityMap;
|
|
76
|
+
minSpacing?: number;
|
|
77
|
+
}): PcbViaTraceClearanceError[];
|
|
78
|
+
|
|
64
79
|
type SourcePinMustBeConnectedError = {
|
|
65
80
|
type: "source_pin_must_be_connected_error";
|
|
66
81
|
source_pin_must_be_connected_error_id: string;
|
|
@@ -96,7 +111,7 @@ declare function checkNoPowerPinDefined(circuitJson: AnyCircuitElement[]): Sourc
|
|
|
96
111
|
*/
|
|
97
112
|
declare function checkNoGroundPinDefined(circuitJson: AnyCircuitElement[]): SourceNoGroundPinDefinedWarning[];
|
|
98
113
|
|
|
99
|
-
declare function runAllPlacementChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbFootprintOverlapError | circuit_json.
|
|
114
|
+
declare function runAllPlacementChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbFootprintOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbPadTraceClearanceError | circuit_json.PcbConnectorNotInAccessibleOrientationWarning | circuit_json.PcbCourtyardOverlapError)[]>;
|
|
100
115
|
declare function runAllNetlistChecks(circuitJson: AnyCircuitElement[]): Promise<{
|
|
101
116
|
type: "source_pin_must_be_connected_error";
|
|
102
117
|
source_pin_must_be_connected_error_id: string;
|
|
@@ -107,8 +122,8 @@ declare function runAllNetlistChecks(circuitJson: AnyCircuitElement[]): Promise<
|
|
|
107
122
|
subcircuit_id?: string;
|
|
108
123
|
}[]>;
|
|
109
124
|
declare function runAllPinSpecificationChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning)[]>;
|
|
110
|
-
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError)[]>;
|
|
111
|
-
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbFootprintOverlapError | {
|
|
125
|
+
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbViaTraceClearanceError)[]>;
|
|
126
|
+
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbFootprintOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbPadTraceClearanceError | circuit_json.PcbViaTraceClearanceError | {
|
|
112
127
|
type: "source_pin_must_be_connected_error";
|
|
113
128
|
source_pin_must_be_connected_error_id: string;
|
|
114
129
|
error_type: "source_pin_must_be_connected_error";
|
|
@@ -116,8 +131,8 @@ declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circui
|
|
|
116
131
|
source_component_id: string;
|
|
117
132
|
source_port_id: string;
|
|
118
133
|
subcircuit_id?: string;
|
|
119
|
-
} | circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning | circuit_json.
|
|
134
|
+
} | circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning | circuit_json.PcbConnectorNotInAccessibleOrientationWarning | circuit_json.PcbCourtyardOverlapError)[]>;
|
|
120
135
|
|
|
121
136
|
declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElement[]): PcbConnectorNotInAccessibleOrientationWarning[];
|
|
122
137
|
|
|
123
|
-
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkViasOffBoard, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
|
|
138
|
+
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkViaTraceClearance, checkViasOffBoard, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
|
package/dist/index.js
CHANGED
|
@@ -369,6 +369,8 @@ var DEFAULT_TRACE_THICKNESS = 0.15;
|
|
|
369
369
|
var DEFAULT_VIA_BOARD_MARGIN = 0.3;
|
|
370
370
|
var DEFAULT_SAME_NET_VIA_MARGIN = 0.2;
|
|
371
371
|
var DEFAULT_DIFFERENT_NET_VIA_MARGIN = 0.3;
|
|
372
|
+
var DEFAULT_PAD_PAD_CLEARANCE = 0.1;
|
|
373
|
+
var DEFAULT_PAD_TRACE_CLEARANCE = 0.1;
|
|
372
374
|
var EPSILON = 5e-3;
|
|
373
375
|
|
|
374
376
|
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
@@ -1601,6 +1603,318 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1601
1603
|
return errors;
|
|
1602
1604
|
}
|
|
1603
1605
|
|
|
1606
|
+
// lib/check-pad-pad-clearance.ts
|
|
1607
|
+
import {
|
|
1608
|
+
getPrimaryId as getPrimaryId3,
|
|
1609
|
+
getReadableNameForElement as getReadableNameForElement6
|
|
1610
|
+
} from "@tscircuit/circuit-json-util";
|
|
1611
|
+
import {
|
|
1612
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson7
|
|
1613
|
+
} from "circuit-json-to-connectivity-map";
|
|
1614
|
+
|
|
1615
|
+
// lib/check-pad-clearance/common.ts
|
|
1616
|
+
import {
|
|
1617
|
+
cju as cju5,
|
|
1618
|
+
distanceBetweenCircleAndCircle,
|
|
1619
|
+
distanceBetweenCircleAndPolygon,
|
|
1620
|
+
distanceBetweenPolygonAndPolygon,
|
|
1621
|
+
getBoundsOfPcbElements as getBoundsOfPcbElements5
|
|
1622
|
+
} from "@tscircuit/circuit-json-util";
|
|
1623
|
+
import { midpoint } from "@tscircuit/math-utils";
|
|
1624
|
+
var formatMm = (value) => {
|
|
1625
|
+
const rounded = Math.round(value * 1e3) / 1e3;
|
|
1626
|
+
return `${Number(rounded.toFixed(3))}mm`;
|
|
1627
|
+
};
|
|
1628
|
+
var getPadBounds = (pad) => getBoundsOfPcbElements5([pad]);
|
|
1629
|
+
var getPadCenter = (pad) => {
|
|
1630
|
+
const bounds = getPadBounds(pad);
|
|
1631
|
+
return midpoint(
|
|
1632
|
+
{ x: bounds.minX, y: bounds.minY },
|
|
1633
|
+
{ x: bounds.maxX, y: bounds.maxY }
|
|
1634
|
+
);
|
|
1635
|
+
};
|
|
1636
|
+
var getPadRadius = (pad) => {
|
|
1637
|
+
const bounds = getPadBounds(pad);
|
|
1638
|
+
return Math.min(bounds.maxX - bounds.minX, bounds.maxY - bounds.minY) / 2;
|
|
1639
|
+
};
|
|
1640
|
+
var isCircularPad = (pad) => pad.shape === "circle";
|
|
1641
|
+
var getCircleShape = (pad) => {
|
|
1642
|
+
const center = getPadCenter(pad);
|
|
1643
|
+
return {
|
|
1644
|
+
kind: "circle",
|
|
1645
|
+
x: center.x,
|
|
1646
|
+
y: center.y,
|
|
1647
|
+
radius: getPadRadius(pad)
|
|
1648
|
+
};
|
|
1649
|
+
};
|
|
1650
|
+
var getPolygonShape = (pad) => {
|
|
1651
|
+
const bounds = getPadBounds(pad);
|
|
1652
|
+
return {
|
|
1653
|
+
kind: "polygon",
|
|
1654
|
+
points: [
|
|
1655
|
+
{ x: bounds.minX, y: bounds.minY },
|
|
1656
|
+
{ x: bounds.maxX, y: bounds.minY },
|
|
1657
|
+
{ x: bounds.maxX, y: bounds.maxY },
|
|
1658
|
+
{ x: bounds.minX, y: bounds.maxY }
|
|
1659
|
+
]
|
|
1660
|
+
};
|
|
1661
|
+
};
|
|
1662
|
+
var getPadToPadGap = (padA, padB) => {
|
|
1663
|
+
if (isCircularPad(padA) && isCircularPad(padB)) {
|
|
1664
|
+
return distanceBetweenCircleAndCircle(
|
|
1665
|
+
getCircleShape(padA),
|
|
1666
|
+
getCircleShape(padB)
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
if (isCircularPad(padA)) {
|
|
1670
|
+
return distanceBetweenCircleAndPolygon(
|
|
1671
|
+
getCircleShape(padA),
|
|
1672
|
+
getPolygonShape(padB)
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
if (isCircularPad(padB)) {
|
|
1676
|
+
return distanceBetweenCircleAndPolygon(
|
|
1677
|
+
getCircleShape(padB),
|
|
1678
|
+
getPolygonShape(padA)
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
return distanceBetweenPolygonAndPolygon(
|
|
1682
|
+
getPolygonShape(padA),
|
|
1683
|
+
getPolygonShape(padB)
|
|
1684
|
+
);
|
|
1685
|
+
};
|
|
1686
|
+
var getPads = (circuitJson) => [
|
|
1687
|
+
...cju5(circuitJson).pcb_smtpad.list(),
|
|
1688
|
+
...cju5(circuitJson).pcb_plated_hole.list()
|
|
1689
|
+
];
|
|
1690
|
+
var getTraceSegments = (circuitJson) => {
|
|
1691
|
+
const pcbTraces = cju5(circuitJson).pcb_trace.list();
|
|
1692
|
+
return pcbTraces.flatMap((pcbTrace) => {
|
|
1693
|
+
const segments = [];
|
|
1694
|
+
for (let i = 0; i < pcbTrace.route.length - 1; i++) {
|
|
1695
|
+
const p1 = pcbTrace.route[i];
|
|
1696
|
+
const p2 = pcbTrace.route[i + 1];
|
|
1697
|
+
if (p1.route_type !== "wire") continue;
|
|
1698
|
+
if (p2.route_type !== "wire") continue;
|
|
1699
|
+
if (p1.layer !== p2.layer) continue;
|
|
1700
|
+
segments.push({
|
|
1701
|
+
type: "pcb_trace_segment",
|
|
1702
|
+
pcb_trace_id: pcbTrace.pcb_trace_id,
|
|
1703
|
+
_pcbTrace: pcbTrace,
|
|
1704
|
+
thickness: "width" in p1 ? p1.width : "width" in p2 ? p2.width : DEFAULT_TRACE_THICKNESS,
|
|
1705
|
+
layer: p1.layer,
|
|
1706
|
+
x1: p1.x,
|
|
1707
|
+
y1: p1.y,
|
|
1708
|
+
x2: p2.x,
|
|
1709
|
+
y2: p2.y
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
return segments;
|
|
1713
|
+
});
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1716
|
+
// lib/check-pad-pad-clearance.ts
|
|
1717
|
+
function checkPadPadClearance(circuitJson, {
|
|
1718
|
+
connMap,
|
|
1719
|
+
minSpacing = DEFAULT_PAD_PAD_CLEARANCE
|
|
1720
|
+
} = {}) {
|
|
1721
|
+
const pads = getPads(circuitJson);
|
|
1722
|
+
if (pads.length < 2) return [];
|
|
1723
|
+
connMap ??= getFullConnectivityMapFromCircuitJson7(circuitJson);
|
|
1724
|
+
const spatialIndex = new SpatialObjectIndex({
|
|
1725
|
+
objects: pads,
|
|
1726
|
+
getBounds: getPadBounds,
|
|
1727
|
+
getId: (pad) => getPrimaryId3(pad)
|
|
1728
|
+
});
|
|
1729
|
+
const errors = /* @__PURE__ */ new Map();
|
|
1730
|
+
for (const padA of pads) {
|
|
1731
|
+
const padAId = getPrimaryId3(padA);
|
|
1732
|
+
const nearbyPads = spatialIndex.getObjectsInBounds(
|
|
1733
|
+
getPadBounds(padA),
|
|
1734
|
+
minSpacing
|
|
1735
|
+
);
|
|
1736
|
+
for (const padB of nearbyPads) {
|
|
1737
|
+
const padBId = getPrimaryId3(padB);
|
|
1738
|
+
if (padAId === padBId) continue;
|
|
1739
|
+
if (!getLayersOfPcbElement(padA).some(
|
|
1740
|
+
(layer) => getLayersOfPcbElement(padB).includes(layer)
|
|
1741
|
+
)) {
|
|
1742
|
+
continue;
|
|
1743
|
+
}
|
|
1744
|
+
if (connMap.areIdsConnected(padAId, padBId)) continue;
|
|
1745
|
+
const pairId = [padAId, padBId].sort().join("_");
|
|
1746
|
+
const gap = getPadToPadGap(padA, padB);
|
|
1747
|
+
if (gap + EPSILON >= minSpacing) continue;
|
|
1748
|
+
const centerA = getPadCenter(padA);
|
|
1749
|
+
const centerB = getPadCenter(padB);
|
|
1750
|
+
const nextError = {
|
|
1751
|
+
type: "pcb_pad_pad_clearance_error",
|
|
1752
|
+
pcb_pad_pad_clearance_error_id: `pad_pad_clearance_${pairId}`,
|
|
1753
|
+
error_type: "pcb_pad_pad_clearance_error",
|
|
1754
|
+
message: `Pads ${getReadableNameForElement6(circuitJson, padAId)} and ${getReadableNameForElement6(circuitJson, padBId)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minSpacing)})`,
|
|
1755
|
+
pcb_pad_ids: [padAId, padBId],
|
|
1756
|
+
minimum_clearance: minSpacing,
|
|
1757
|
+
actual_clearance: gap,
|
|
1758
|
+
center: {
|
|
1759
|
+
x: (centerA.x + centerB.x) / 2,
|
|
1760
|
+
y: (centerA.y + centerB.y) / 2
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
if (!errors.has(pairId)) {
|
|
1764
|
+
errors.set(pairId, nextError);
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
return Array.from(errors.values());
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
// lib/check-pad-trace-clearance.ts
|
|
1772
|
+
import {
|
|
1773
|
+
getPrimaryId as getPrimaryId4,
|
|
1774
|
+
getReadableNameForElement as getReadableNameForElement7
|
|
1775
|
+
} from "@tscircuit/circuit-json-util";
|
|
1776
|
+
import {
|
|
1777
|
+
segmentToBoundsMinDistance as segmentToBoundsMinDistance2,
|
|
1778
|
+
segmentToCircleMinDistance as segmentToCircleMinDistance2
|
|
1779
|
+
} from "@tscircuit/math-utils";
|
|
1780
|
+
import {
|
|
1781
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson8
|
|
1782
|
+
} from "circuit-json-to-connectivity-map";
|
|
1783
|
+
function checkPadTraceClearance(circuitJson, {
|
|
1784
|
+
connMap,
|
|
1785
|
+
minSpacing = DEFAULT_PAD_TRACE_CLEARANCE
|
|
1786
|
+
} = {}) {
|
|
1787
|
+
const pads = getPads(circuitJson);
|
|
1788
|
+
const segments = getTraceSegments(circuitJson);
|
|
1789
|
+
if (pads.length === 0 || segments.length === 0) return [];
|
|
1790
|
+
connMap ??= getFullConnectivityMapFromCircuitJson8(circuitJson);
|
|
1791
|
+
const spatialIndex = new SpatialObjectIndex({
|
|
1792
|
+
objects: pads,
|
|
1793
|
+
getBounds: getPadBounds,
|
|
1794
|
+
getId: (pad) => getPrimaryId4(pad)
|
|
1795
|
+
});
|
|
1796
|
+
const errors = /* @__PURE__ */ new Map();
|
|
1797
|
+
for (const segment of segments) {
|
|
1798
|
+
const nearbyPads = spatialIndex.getObjectsInBounds(
|
|
1799
|
+
getCollidableBounds(segment),
|
|
1800
|
+
minSpacing + segment.thickness / 2
|
|
1801
|
+
);
|
|
1802
|
+
for (const pad of nearbyPads) {
|
|
1803
|
+
const padId = getPrimaryId4(pad);
|
|
1804
|
+
if (!getLayersOfPcbElement(pad).includes(segment.layer)) continue;
|
|
1805
|
+
if (connMap.areIdsConnected(segment.pcb_trace_id, padId)) continue;
|
|
1806
|
+
const center = getPadCenter(pad);
|
|
1807
|
+
const gap = isCircularPad(pad) ? segmentToCircleMinDistance2(
|
|
1808
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1809
|
+
{ x: segment.x2, y: segment.y2 },
|
|
1810
|
+
{ x: center.x, y: center.y, radius: getPadRadius(pad) }
|
|
1811
|
+
) - segment.thickness / 2 : segmentToBoundsMinDistance2(
|
|
1812
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1813
|
+
{ x: segment.x2, y: segment.y2 },
|
|
1814
|
+
getPadBounds(pad)
|
|
1815
|
+
) - segment.thickness / 2;
|
|
1816
|
+
if (gap + EPSILON >= minSpacing) continue;
|
|
1817
|
+
const pairId = `${padId}_${segment.pcb_trace_id}`;
|
|
1818
|
+
const nextError = {
|
|
1819
|
+
type: "pcb_pad_trace_clearance_error",
|
|
1820
|
+
pcb_pad_trace_clearance_error_id: `pad_trace_clearance_${pairId}`,
|
|
1821
|
+
error_type: "pcb_pad_trace_clearance_error",
|
|
1822
|
+
message: `Pad ${getReadableNameForElement7(circuitJson, padId)} and trace ${getReadableNameForElement7(circuitJson, segment.pcb_trace_id)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minSpacing)})`,
|
|
1823
|
+
pcb_pad_id: padId,
|
|
1824
|
+
pcb_trace_id: segment.pcb_trace_id,
|
|
1825
|
+
minimum_clearance: minSpacing,
|
|
1826
|
+
actual_clearance: gap,
|
|
1827
|
+
center: {
|
|
1828
|
+
x: (center.x + (segment.x1 + segment.x2) / 2) / 2,
|
|
1829
|
+
y: (center.y + (segment.y1 + segment.y2) / 2) / 2
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
const current = errors.get(pairId);
|
|
1833
|
+
if (!current || gap < current.gap) {
|
|
1834
|
+
errors.set(pairId, { error: nextError, gap });
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
return Array.from(errors.values()).map(({ error }) => error);
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// lib/check-via-trace-clearance.ts
|
|
1842
|
+
import { getReadableNameForElement as getReadableNameForElement8 } from "@tscircuit/circuit-json-util";
|
|
1843
|
+
import { segmentToCircleMinDistance as segmentToCircleMinDistance3 } from "@tscircuit/math-utils";
|
|
1844
|
+
import {
|
|
1845
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson9
|
|
1846
|
+
} from "circuit-json-to-connectivity-map";
|
|
1847
|
+
var getClosestPointOnSegment = (point, segmentStart, segmentEnd) => {
|
|
1848
|
+
const dx = segmentEnd.x - segmentStart.x;
|
|
1849
|
+
const dy = segmentEnd.y - segmentStart.y;
|
|
1850
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
1851
|
+
if (lengthSquared === 0) return segmentStart;
|
|
1852
|
+
const t = Math.max(
|
|
1853
|
+
0,
|
|
1854
|
+
Math.min(
|
|
1855
|
+
1,
|
|
1856
|
+
((point.x - segmentStart.x) * dx + (point.y - segmentStart.y) * dy) / lengthSquared
|
|
1857
|
+
)
|
|
1858
|
+
);
|
|
1859
|
+
return {
|
|
1860
|
+
x: segmentStart.x + t * dx,
|
|
1861
|
+
y: segmentStart.y + t * dy
|
|
1862
|
+
};
|
|
1863
|
+
};
|
|
1864
|
+
function checkViaTraceClearance(circuitJson, {
|
|
1865
|
+
connMap,
|
|
1866
|
+
minSpacing = DEFAULT_PAD_TRACE_CLEARANCE
|
|
1867
|
+
} = {}) {
|
|
1868
|
+
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1869
|
+
const segments = getTraceSegments(circuitJson);
|
|
1870
|
+
if (vias.length === 0 || segments.length === 0) return [];
|
|
1871
|
+
connMap ??= getFullConnectivityMapFromCircuitJson9(circuitJson);
|
|
1872
|
+
const errors = /* @__PURE__ */ new Map();
|
|
1873
|
+
for (const via of vias) {
|
|
1874
|
+
const viaRadius = via.outer_diameter / 2;
|
|
1875
|
+
for (const segment of segments) {
|
|
1876
|
+
if (!getLayersOfPcbElement(via).includes(segment.layer)) continue;
|
|
1877
|
+
if (connMap.areIdsConnected(segment.pcb_trace_id, via.pcb_via_id))
|
|
1878
|
+
continue;
|
|
1879
|
+
const gap = segmentToCircleMinDistance3(
|
|
1880
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1881
|
+
{ x: segment.x2, y: segment.y2 },
|
|
1882
|
+
{
|
|
1883
|
+
x: via.x,
|
|
1884
|
+
y: via.y,
|
|
1885
|
+
radius: viaRadius
|
|
1886
|
+
}
|
|
1887
|
+
) - segment.thickness / 2;
|
|
1888
|
+
if (gap + EPSILON >= minSpacing) continue;
|
|
1889
|
+
const closestPoint = getClosestPointOnSegment(
|
|
1890
|
+
{ x: via.x, y: via.y },
|
|
1891
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1892
|
+
{ x: segment.x2, y: segment.y2 }
|
|
1893
|
+
);
|
|
1894
|
+
const pairId = `${via.pcb_via_id}_${segment.pcb_trace_id}`;
|
|
1895
|
+
const nextError = {
|
|
1896
|
+
type: "pcb_via_trace_clearance_error",
|
|
1897
|
+
pcb_via_trace_clearance_error_id: `via_trace_clearance_${pairId}`,
|
|
1898
|
+
error_type: "pcb_via_trace_clearance_error",
|
|
1899
|
+
message: `Via ${getReadableNameForElement8(circuitJson, via.pcb_via_id)} and trace ${getReadableNameForElement8(circuitJson, segment.pcb_trace_id)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minSpacing)})`,
|
|
1900
|
+
pcb_via_id: via.pcb_via_id,
|
|
1901
|
+
pcb_trace_id: segment.pcb_trace_id,
|
|
1902
|
+
minimum_clearance: minSpacing,
|
|
1903
|
+
actual_clearance: gap,
|
|
1904
|
+
center: {
|
|
1905
|
+
x: (via.x + closestPoint.x) / 2,
|
|
1906
|
+
y: (via.y + closestPoint.y) / 2
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
const current = errors.get(pairId);
|
|
1910
|
+
if (!current || gap < current.gap) {
|
|
1911
|
+
errors.set(pairId, { error: nextError, gap });
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
return Array.from(errors.values()).map(({ error }) => error);
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1604
1918
|
// lib/check-pin-must-be-connected.ts
|
|
1605
1919
|
function checkPinMustBeConnected(circuitJson) {
|
|
1606
1920
|
const errors = [];
|
|
@@ -1660,7 +1974,7 @@ function checkPinMustBeConnected(circuitJson) {
|
|
|
1660
1974
|
}
|
|
1661
1975
|
|
|
1662
1976
|
// lib/check-all-pins-in-component-are-underspecified.ts
|
|
1663
|
-
import { cju as
|
|
1977
|
+
import { cju as cju6 } from "@tscircuit/circuit-json-util";
|
|
1664
1978
|
var PIN_ATTRIBUTE_KEYS = [
|
|
1665
1979
|
"must_be_connected",
|
|
1666
1980
|
"provides_power",
|
|
@@ -1705,7 +2019,7 @@ function hasAnyPinAttribute(port) {
|
|
|
1705
2019
|
}
|
|
1706
2020
|
function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
1707
2021
|
const warnings = [];
|
|
1708
|
-
const db =
|
|
2022
|
+
const db = cju6(circuitJson);
|
|
1709
2023
|
const sourceComponents = db.source_component.list();
|
|
1710
2024
|
const sourcePorts = db.source_port.list();
|
|
1711
2025
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -1737,10 +2051,10 @@ function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
|
1737
2051
|
}
|
|
1738
2052
|
|
|
1739
2053
|
// lib/check-no-power-pin-defined.ts
|
|
1740
|
-
import { cju as
|
|
2054
|
+
import { cju as cju7 } from "@tscircuit/circuit-json-util";
|
|
1741
2055
|
function checkNoPowerPinDefined(circuitJson) {
|
|
1742
2056
|
const warnings = [];
|
|
1743
|
-
const db =
|
|
2057
|
+
const db = cju7(circuitJson);
|
|
1744
2058
|
const sourceComponents = db.source_component.list();
|
|
1745
2059
|
const sourcePorts = db.source_port.list();
|
|
1746
2060
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -1772,10 +2086,10 @@ function checkNoPowerPinDefined(circuitJson) {
|
|
|
1772
2086
|
}
|
|
1773
2087
|
|
|
1774
2088
|
// lib/check-no-ground-pin-defined.ts
|
|
1775
|
-
import { cju as
|
|
2089
|
+
import { cju as cju8 } from "@tscircuit/circuit-json-util";
|
|
1776
2090
|
function checkNoGroundPinDefined(circuitJson) {
|
|
1777
2091
|
const warnings = [];
|
|
1778
|
-
const db =
|
|
2092
|
+
const db = cju8(circuitJson);
|
|
1779
2093
|
const sourceComponents = db.source_component.list();
|
|
1780
2094
|
const sourcePorts = db.source_port.list();
|
|
1781
2095
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -1806,6 +2120,75 @@ function checkNoGroundPinDefined(circuitJson) {
|
|
|
1806
2120
|
return warnings;
|
|
1807
2121
|
}
|
|
1808
2122
|
|
|
2123
|
+
// lib/check-connector-accessible-orientation.ts
|
|
2124
|
+
import { getBoardBounds } from "@tscircuit/circuit-json-util";
|
|
2125
|
+
function getFacingDirection(component) {
|
|
2126
|
+
if (!component.center || !component.cable_insertion_center) return null;
|
|
2127
|
+
const dx = component.cable_insertion_center.x - component.center.x;
|
|
2128
|
+
const dy = component.cable_insertion_center.y - component.center.y;
|
|
2129
|
+
if (Math.abs(dx) < 1e-6 && Math.abs(dy) < 1e-6) return null;
|
|
2130
|
+
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
2131
|
+
return dx >= 0 ? "x+" : "x-";
|
|
2132
|
+
}
|
|
2133
|
+
return dy >= 0 ? "y+" : "y-";
|
|
2134
|
+
}
|
|
2135
|
+
function getRecommendedFacingDirection(component, bounds) {
|
|
2136
|
+
if (!component.center) return null;
|
|
2137
|
+
const distances = [
|
|
2138
|
+
{ direction: "x-", distance: component.center.x - bounds.minX },
|
|
2139
|
+
{ direction: "x+", distance: bounds.maxX - component.center.x },
|
|
2140
|
+
{ direction: "y-", distance: component.center.y - bounds.minY },
|
|
2141
|
+
{ direction: "y+", distance: bounds.maxY - component.center.y }
|
|
2142
|
+
];
|
|
2143
|
+
distances.sort((a, b) => a.distance - b.distance);
|
|
2144
|
+
return distances[0]?.direction ?? null;
|
|
2145
|
+
}
|
|
2146
|
+
function checkConnectorAccessibleOrientation(circuitJson) {
|
|
2147
|
+
const board = circuitJson.find(
|
|
2148
|
+
(el) => el.type === "pcb_board"
|
|
2149
|
+
);
|
|
2150
|
+
if (!board) return [];
|
|
2151
|
+
const bounds = (() => {
|
|
2152
|
+
try {
|
|
2153
|
+
return getBoardBounds(board);
|
|
2154
|
+
} catch {
|
|
2155
|
+
return null;
|
|
2156
|
+
}
|
|
2157
|
+
})();
|
|
2158
|
+
if (!bounds) return [];
|
|
2159
|
+
const warnings = [];
|
|
2160
|
+
const components = circuitJson.filter(
|
|
2161
|
+
(el) => el.type === "pcb_component"
|
|
2162
|
+
);
|
|
2163
|
+
for (const component of components) {
|
|
2164
|
+
if (!component.cable_insertion_center) continue;
|
|
2165
|
+
const facingDirection = getFacingDirection(component);
|
|
2166
|
+
const recommendedFacingDirection = getRecommendedFacingDirection(
|
|
2167
|
+
component,
|
|
2168
|
+
bounds
|
|
2169
|
+
);
|
|
2170
|
+
if (!facingDirection || !recommendedFacingDirection) continue;
|
|
2171
|
+
if (facingDirection === recommendedFacingDirection) continue;
|
|
2172
|
+
const componentName = getReadableNameForComponent(
|
|
2173
|
+
circuitJson,
|
|
2174
|
+
component.pcb_component_id
|
|
2175
|
+
);
|
|
2176
|
+
warnings.push({
|
|
2177
|
+
type: "pcb_connector_not_in_accessible_orientation_warning",
|
|
2178
|
+
warning_type: "pcb_connector_not_in_accessible_orientation_warning",
|
|
2179
|
+
pcb_connector_not_in_accessible_orientation_warning_id: `pcb_connector_not_in_accessible_orientation_warning_${component.pcb_component_id}`,
|
|
2180
|
+
message: `${componentName} is facing ${facingDirection} but should face ${recommendedFacingDirection} so the connector is accessible from the board edge`,
|
|
2181
|
+
pcb_component_id: component.pcb_component_id,
|
|
2182
|
+
source_component_id: component.source_component_id,
|
|
2183
|
+
pcb_board_id: board.pcb_board_id,
|
|
2184
|
+
facing_direction: facingDirection,
|
|
2185
|
+
recommended_facing_direction: recommendedFacingDirection,
|
|
2186
|
+
subcircuit_id: component.subcircuit_id
|
|
2187
|
+
});
|
|
2188
|
+
}
|
|
2189
|
+
return warnings;
|
|
2190
|
+
}
|
|
2191
|
+
|
|
1809
2192
|
// lib/check-courtyard-overlap/checkCourtyardOverlap.ts
|
|
1810
2193
|
import {
|
|
1811
2194
|
doSegmentsIntersect,
|
|
@@ -1912,75 +2295,6 @@ function checkCourtyardOverlap(circuitJson) {
|
|
|
1912
2295
|
return errors;
|
|
1913
2296
|
}
|
|
1914
2297
|
|
|
1915
|
-
// lib/check-connector-accessible-orientation.ts
|
|
1916
|
-
import { getBoardBounds } from "@tscircuit/circuit-json-util";
|
|
1917
|
-
function getFacingDirection(component) {
|
|
1918
|
-
if (!component.center || !component.cable_insertion_center) return null;
|
|
1919
|
-
const dx = component.cable_insertion_center.x - component.center.x;
|
|
1920
|
-
const dy = component.cable_insertion_center.y - component.center.y;
|
|
1921
|
-
if (Math.abs(dx) < 1e-6 && Math.abs(dy) < 1e-6) return null;
|
|
1922
|
-
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
1923
|
-
return dx >= 0 ? "x+" : "x-";
|
|
1924
|
-
}
|
|
1925
|
-
return dy >= 0 ? "y+" : "y-";
|
|
1926
|
-
}
|
|
1927
|
-
function getRecommendedFacingDirection(component, bounds) {
|
|
1928
|
-
if (!component.center) return null;
|
|
1929
|
-
const distances = [
|
|
1930
|
-
{ direction: "x-", distance: component.center.x - bounds.minX },
|
|
1931
|
-
{ direction: "x+", distance: bounds.maxX - component.center.x },
|
|
1932
|
-
{ direction: "y-", distance: component.center.y - bounds.minY },
|
|
1933
|
-
{ direction: "y+", distance: bounds.maxY - component.center.y }
|
|
1934
|
-
];
|
|
1935
|
-
distances.sort((a, b) => a.distance - b.distance);
|
|
1936
|
-
return distances[0]?.direction ?? null;
|
|
1937
|
-
}
|
|
1938
|
-
function checkConnectorAccessibleOrientation(circuitJson) {
|
|
1939
|
-
const board = circuitJson.find(
|
|
1940
|
-
(el) => el.type === "pcb_board"
|
|
1941
|
-
);
|
|
1942
|
-
if (!board) return [];
|
|
1943
|
-
const bounds = (() => {
|
|
1944
|
-
try {
|
|
1945
|
-
return getBoardBounds(board);
|
|
1946
|
-
} catch {
|
|
1947
|
-
return null;
|
|
1948
|
-
}
|
|
1949
|
-
})();
|
|
1950
|
-
if (!bounds) return [];
|
|
1951
|
-
const warnings = [];
|
|
1952
|
-
const components = circuitJson.filter(
|
|
1953
|
-
(el) => el.type === "pcb_component"
|
|
1954
|
-
);
|
|
1955
|
-
for (const component of components) {
|
|
1956
|
-
if (!component.cable_insertion_center) continue;
|
|
1957
|
-
const facingDirection = getFacingDirection(component);
|
|
1958
|
-
const recommendedFacingDirection = getRecommendedFacingDirection(
|
|
1959
|
-
component,
|
|
1960
|
-
bounds
|
|
1961
|
-
);
|
|
1962
|
-
if (!facingDirection || !recommendedFacingDirection) continue;
|
|
1963
|
-
if (facingDirection === recommendedFacingDirection) continue;
|
|
1964
|
-
const componentName = getReadableNameForComponent(
|
|
1965
|
-
circuitJson,
|
|
1966
|
-
component.pcb_component_id
|
|
1967
|
-
);
|
|
1968
|
-
warnings.push({
|
|
1969
|
-
type: "pcb_connector_not_in_accessible_orientation_warning",
|
|
1970
|
-
warning_type: "pcb_connector_not_in_accessible_orientation_warning",
|
|
1971
|
-
pcb_connector_not_in_accessible_orientation_warning_id: `pcb_connector_not_in_accessible_orientation_warning_${component.pcb_component_id}`,
|
|
1972
|
-
message: `${componentName} is facing ${facingDirection} but should face ${recommendedFacingDirection} so the connector is accessible from the board edge`,
|
|
1973
|
-
pcb_component_id: component.pcb_component_id,
|
|
1974
|
-
source_component_id: component.source_component_id,
|
|
1975
|
-
pcb_board_id: board.pcb_board_id,
|
|
1976
|
-
facing_direction: facingDirection,
|
|
1977
|
-
recommended_facing_direction: recommendedFacingDirection,
|
|
1978
|
-
subcircuit_id: component.subcircuit_id
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
return warnings;
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
2298
|
// lib/check-traces-are-contiguous/check-traces-are-contiguous.ts
|
|
1985
2299
|
import { getReadableNameForPcbPort as getReadableNameForPcbPort2 } from "@tscircuit/circuit-json-util";
|
|
1986
2300
|
|
|
@@ -1990,6 +2304,8 @@ async function runAllPlacementChecks(circuitJson) {
|
|
|
1990
2304
|
...checkViasOffBoard(circuitJson),
|
|
1991
2305
|
...checkPcbComponentsOutOfBoard(circuitJson),
|
|
1992
2306
|
...checkPcbComponentOverlap(circuitJson),
|
|
2307
|
+
...checkPadPadClearance(circuitJson),
|
|
2308
|
+
...checkPadTraceClearance(circuitJson),
|
|
1993
2309
|
...checkCourtyardOverlap(circuitJson),
|
|
1994
2310
|
...checkConnectorAccessibleOrientation(circuitJson)
|
|
1995
2311
|
];
|
|
@@ -2009,6 +2325,7 @@ async function runAllRoutingChecks(circuitJson) {
|
|
|
2009
2325
|
...checkEachPcbPortConnectedToPcbTraces(circuitJson),
|
|
2010
2326
|
...checkSourceTracesHavePcbTraces(circuitJson),
|
|
2011
2327
|
...checkEachPcbTraceNonOverlapping(circuitJson),
|
|
2328
|
+
...checkViaTraceClearance(circuitJson),
|
|
2012
2329
|
...checkSameNetViaSpacing(circuitJson),
|
|
2013
2330
|
...checkDifferentNetViaSpacing(circuitJson),
|
|
2014
2331
|
// ...checkTracesAreContiguous(circuitJson),
|
|
@@ -2032,6 +2349,8 @@ export {
|
|
|
2032
2349
|
checkEachPcbTraceNonOverlapping,
|
|
2033
2350
|
checkNoGroundPinDefined,
|
|
2034
2351
|
checkNoPowerPinDefined,
|
|
2352
|
+
checkPadPadClearance,
|
|
2353
|
+
checkPadTraceClearance,
|
|
2035
2354
|
checkPcbComponentOverlap,
|
|
2036
2355
|
checkPcbComponentsOutOfBoard,
|
|
2037
2356
|
checkPcbTracesOutOfBoard,
|
|
@@ -2039,6 +2358,7 @@ export {
|
|
|
2039
2358
|
checkSameNetViaSpacing,
|
|
2040
2359
|
checkSourceTracesHavePcbTraces,
|
|
2041
2360
|
checkSourceTracesMatchPcbTraceThickness,
|
|
2361
|
+
checkViaTraceClearance,
|
|
2042
2362
|
checkViasOffBoard,
|
|
2043
2363
|
runAllChecks,
|
|
2044
2364
|
runAllNetlistChecks,
|