Tighten PCB findings: actions, stitch gating, real copper.

Fill action on every finding and show it in the report. Stitch/return only
on large HS/power nets. Parse stackup thickness, arcs, and vias from the
board. IC courtyard pad copper is not PE-PLC-004 RULE. Recommended RC/cap
stay REVIEW.
This commit is contained in:
2026-09-20 08:58:54 +02:00
parent 1e379f6042
commit f63c1c3411
9 changed files with 326 additions and 59 deletions
+25 -4
View File
@@ -289,9 +289,15 @@ def _keepout_finding(ref, comp, cons, rule, graph: DesignGraph, layout: LayoutGr
own = _net_for_pin(graph, ref, pin_no) if pin_no else None
if not own:
return []
pad_nets = [
p.net for p in fp.pads
if p.net
]
foreign: list[str] = []
for s in layout.segments:
if not s.net or s.net == own:
if not s.net or kicad_nets_match(s.net, own):
continue
if any(kicad_nets_match(s.net, pn) for pn in pad_nets):
continue
if _in_poly(s.start[0], s.start[1], fp.courtyard) or _in_poly(
s.end[0], s.end[1], fp.courtyard
@@ -300,17 +306,32 @@ def _keepout_finding(ref, comp, cons, rule, graph: DesignGraph, layout: LayoutGr
if not foreign:
return []
net = sorted(set(foreign))[0]
is_crystal = comp.component_type == ComponentType.CRYSTAL
rec = (
"Keep unrelated nets out of the keepout if the datasheet shows a "
"keep-out zone; traces to this part's own pads are normal copper."
)
return [Finding(
designator=ref,
mpn=comp.mpn or cons.mpn,
aspect="placement",
finding=f"Track on {net} enters courtyard of {ref} (keepout on {own}).",
facts=f"Segment on '{net}' has an endpoint inside {ref} courtyard.",
requirement="layout_rules kind=keepout (recommended courtyard isolation).",
inference=(
"Crystal keepout may apply."
if is_crystal
else "Not a pad net of this footprint — review, not a mandatory DRC."
),
why="layout_rules kind=keepout.",
status="WARNING",
recommendation="Keep other nets out of the courtyard.",
status="WARNING" if is_crystal else "INFO",
recommendation=rec,
action=rec,
source="placement_check",
rule_id="PE-PLC-004",
finding_class="REVIEW",
provenance="RECOMMENDED",
net=net,
pins=[pin_no],
pins=[pin_no] if pin_no else [],
source_page=rule.get("source_page"),
)]