Design rule checking (DRC)#
Design Rule Check (DRC) engine for PyEDB.
This module provides a high-performance, multi-threaded design-rule checker that runs inside an open PyEDB session and validates industry-standard rules including geometry, spacing, manufacturing, high-speed, and test constraints.
The DRC engine features:
Multi-threaded rule checking using ThreadPoolExecutor
R-tree spatial indexing for fast geometry queries
Impedance checks via analytical formulas (Wheeler, Cohn, Hammerstad-Jensen)
Copper balance verification by layer or zone polygons
Back-drill stub and depth verification
IPC-D-356A netlist export with DRC annotations
Examples#
Basic DRC workflow:
>>> import pyedb
>>> from pyedb.workflows.drc.drc import Drc, Rules
>>> edb = pyedb.Edb(edbpath="my_board.aedb")
>>> rules = Rules.parse_file("rules.json")
>>> drc = Drc(edb)
>>> violations = drc.check(rules)
>>> print(f"Found {len(violations)} violations")
Build rules programmatically:
>>> rules = (
... Rules()
... .add_min_line_width("trace_width", "3.5mil")
... .add_min_clearance("clk2data", "4mil", "CLK*", "DATA*")
... .add_copper_balance("top_balance", max_percent=10, layers=["TOP"])
... )
>>> drc = Drc(edb)
>>> violations = drc.check(rules)
Export results for fabrication review:
>>> drc.to_ipc356a("fab_review.ipc")
The pyedb.workflows.drc sub-package exposes a lightweight, high-accuracy
design-rule checker (DRC) that runs inside an open PyEDB session.
It validates more than 50 industry-standard rules (geometry, spacing,
manufacturing, high-speed, test) and exports an IPC-D-356A netlist annotated
with violations for CAM hand-off.
Features#
Impedance checks via improved analytical formulas (Wheeler, Cohn, Hammerstad–Jensen).
Copper-balance by layer or by arbitrary zone polygons.
Back-drill stub/depth verification.
R-tree spatial index for fast geometry queries.
Thread-safe, multi-threaded rule execution (automatic core detection).
Fluent, type-safe API to build rule decks programmatically.
JSON/YAML round-trip serialization (via Pydantic).
Quick start#
import pyedb
from pyedb.workflows.drc.drc import Drc, Rules
edb = pyedb.Edb("my_board.aedb")
rules = (
Rules()
.add_min_line_width("pwr", "15 mil")
.add_min_clearance("clk2data", "4 mil", "CLK*", "DATA*")
.add_min_annular_ring("via5", "5 mil")
.add_diff_pair_length_match("usb", tolerance="0.1 mm", pairs=[("USB_P", "USB_N")])
.add_copper_balance("top_bal", max_percent=10, layers=["TOP"])
)
drc = Drc(edb)
violations = drc.check(rules)
drc.to_ipc356a("fab_review.ipc")
API reference#
Rules container#
Centralized container for all design rule categories. |
|
Create Rules instance from dictionary. |
|
Convert Rules to dictionary. |
|
Append a minimum line width rule. |
|
Append a minimum clearance rule between nets. |
|
Append a minimum annular ring rule for drilled holes. |
|
Append a differential pair length matching rule. |
|
Append a maximum back-drill stub length rule. |
|
Append a copper density balance rule. |
Rule models#
Minimum trace width constraint rule. |
|
Minimum spacing constraint between nets. |
|
Minimum annular ring constraint for drilled holes. |
|
Differential pair net definition. |
|
Length matching constraint for differential pairs. |
|
Maximum back-drill stub length constraint. |
|
Copper density balance constraint. |
DRC engine#
High-performance DRC engine for PyEDB. |
|
Run all rules and return a list of violations. |
|
Write a complete IPC-D-356A netlist with DRC annotations. |
Implementation notes#
Thread safety#
All heavy geometry checks are embarrassingly parallel. The engine snapshots EDB data into plain Python objects before entering the worker pool, so the R-tree index is never accessed concurrently.
Extending the engine#
Add a new rule in three steps:
Create a Pydantic model inheriting from
Pydantic.BaseModel.Append the model to the
Rulescontainer and expose a fluent helper.Implement
_rule_<field_name>insideDrc; accept the rule instance and append violations toself.violations.
Examples#
Load a rule deck from JSON#
import json
from pyedb.workflows.drc.drc import Rules
with open("my_rules.json") as f:
rules = Rules.from_dict(json.load(f))
Export violations to CSV#
import csv
drc = Drc(edb)
drc.check(rules)
with open("violations.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=drc.violations[0].keys())
writer.writeheader()
writer.writerows(drc.violations)