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:
@@ -5,6 +5,7 @@ No SI/DRC. Schema validation stays complete without this file.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.models import (
|
||||
@@ -29,6 +30,24 @@ from backend.periscopex.parsers_kicad import (
|
||||
)
|
||||
|
||||
|
||||
def _copper_thickness_token(raw: object) -> float | None:
|
||||
"""Parse KiCad stackup thickness; units mm/um/mil. Never default 1 oz."""
|
||||
if isinstance(raw, (int, float)) and not isinstance(raw, bool):
|
||||
v = float(raw)
|
||||
return v if v > 0 else None
|
||||
s = str(raw or "").strip().lower().replace(" ", "")
|
||||
m = re.match(r"^([0-9]*\.?[0-9]+)(mm|um|µm|mil)?", s)
|
||||
if not m:
|
||||
return None
|
||||
n = float(m.group(1))
|
||||
unit = m.group(2) or "mm"
|
||||
if unit in {"um", "µm"}:
|
||||
n = n / 1000.0
|
||||
elif unit == "mil":
|
||||
n = n * 0.0254
|
||||
return n if n > 0 else None
|
||||
|
||||
|
||||
def _xy(node: object, name: str) -> tuple[float, float]:
|
||||
k = _kid(node, name)
|
||||
if not k or len(k) < 3:
|
||||
@@ -128,7 +147,11 @@ def _parse_stackup(tree: object) -> LayoutStackup | None:
|
||||
name = str(layer[1]) if len(layer) > 1 and not isinstance(layer[1], list) else ""
|
||||
kind = _layer_type(layer)
|
||||
thick = _kid(layer, "thickness")
|
||||
height = _fnum(thick[1]) if thick and len(thick) > 1 else None
|
||||
height = None
|
||||
if thick and len(thick) > 1:
|
||||
height = _copper_thickness_token(thick[1])
|
||||
if height is None and len(thick) > 2:
|
||||
height = _copper_thickness_token(f"{thick[1]}{thick[2]}")
|
||||
if kind == "copper" or name.endswith(".Cu"):
|
||||
if name:
|
||||
copper.append(name)
|
||||
@@ -147,9 +170,9 @@ def _parse_stackup(tree: object) -> LayoutStackup | None:
|
||||
er=er,
|
||||
height_mm=height,
|
||||
))
|
||||
if len(copper) < 2 or len(dielectrics) != len(copper) - 1:
|
||||
return None
|
||||
t = thicknesses[0] if thicknesses else None
|
||||
if not copper and t is None:
|
||||
return None
|
||||
return LayoutStackup(
|
||||
copper_layers=copper,
|
||||
dielectrics=dielectrics,
|
||||
@@ -291,6 +314,15 @@ def parse_kicad_pcb(path: str | Path) -> LayoutGraph:
|
||||
net=_net_name(node, nets),
|
||||
))
|
||||
continue
|
||||
if tag == "arc":
|
||||
segments.append(LayoutSegment(
|
||||
start=_xy(node, "start"),
|
||||
end=_xy(node, "end"),
|
||||
width=_fnum(_val(node, "width") or 0),
|
||||
layer=_val(node, "layer"),
|
||||
net=_net_name(node, nets),
|
||||
))
|
||||
continue
|
||||
if tag == "via":
|
||||
drill_el = _kid(node, "drill")
|
||||
drill = _fnum(drill_el[1]) if drill_el and len(drill_el) > 1 else None
|
||||
|
||||
Reference in New Issue
Block a user