fix(wire_connectivity): pwr-flags must not bridge unrelated power rails (#177)
Every power:PWR_FLAG symbol carries Value="PWR_FLAG" — the ERC marker inherits its rail's name from the wire/label it sits on. Commit7f3a379added #FLG symbols to the same handling loop as #PWR power ports inside _parse_virtual_connections, so every pwr-flag was getting appended to label_to_points["PWR_FLAG"]. The BFS in _find_connected_wires uses label_to_points for virtual jumps; reaching any pwr-flag pin caused it to teleport to every other pwr-flag pin, walking across each one's stub wire into a different power rail. The result: get_net_connections(rail) returned the union of pins on every rail that had a pwr-flag, for any rail. Fix: pwr-flag pin positions still register as anchors in point_to_label (preserving the original intent of7f3a379so find_orphaned_wires keeps accepting them), but they no longer enter label_to_points. The pwr-flag remains electrically connected to its rail via the wire-graph BFS through the wire it sits on; the label-jump mechanism is unnecessary for that path and actively harmful when the "label" is the same for unrelated rails. Tests: three unit tests on _parse_virtual_connections cover the bug (over-merge gone), regression check (power ports still work in both maps), and edge case (pwr-flag and port at same point — port name wins). All three fail on main, pass on this branch. Full suite: 667 passed, 11 skipped, 0 regressions (modulo the pre-existing tests/test_get_pin_angle.py collection error which is unrelated to wire_connectivity). End-to-end verification on a single-sheet schematic with 7 distinct power rails each carrying a pwr-flag: every queried net now matches the official kicad-cli netlist output (modulo a separate library-symbol bug on PCM_Diode_Schottky_AKL:MBRS130 with duplicate pin definitions, out of scope here). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -236,7 +236,9 @@ def _parse_virtual_connections(
|
||||
if not hasattr(symbol, "property") or not hasattr(symbol.property, "Reference"):
|
||||
continue
|
||||
ref = symbol.property.Reference.value
|
||||
if not (ref.startswith("#PWR") or ref.startswith("#FLG")):
|
||||
is_pwr_port = ref.startswith("#PWR")
|
||||
is_pwr_flag = ref.startswith("#FLG")
|
||||
if not (is_pwr_port or is_pwr_flag):
|
||||
continue
|
||||
if ref.startswith("_TEMPLATE"):
|
||||
continue
|
||||
@@ -248,8 +250,28 @@ def _parse_virtual_connections(
|
||||
continue
|
||||
pin_data = all_pins["1"]
|
||||
pt = _to_iu(float(pin_data[0]), float(pin_data[1]))
|
||||
point_to_label[pt] = name
|
||||
label_to_points.setdefault(name, []).append(pt)
|
||||
|
||||
if is_pwr_port:
|
||||
# Power-port symbol: Value is the net name (+BATT, GND, ...).
|
||||
# Register in both maps so BFS-via-label-jump can bridge to
|
||||
# other instances of the same named power net.
|
||||
point_to_label[pt] = name
|
||||
label_to_points.setdefault(name, []).append(pt)
|
||||
else:
|
||||
# Power-flag symbol (#FLG*): Value is always "PWR_FLAG" — an
|
||||
# ERC marker, not a net name. The pin position is registered
|
||||
# in point_to_label so find_orphaned_wires accepts wire ends
|
||||
# terminating on a PWR_FLAG as valid anchors. It is NOT added
|
||||
# to label_to_points: doing so would let BFS-via-label-jump
|
||||
# virtually bridge every distinct power rail that has a
|
||||
# pwr-flag into one mega-net (since every #FLG shares
|
||||
# Value="PWR_FLAG"). The pwr-flag remains electrically
|
||||
# connected to its rail via the wire-graph BFS through the
|
||||
# wire it sits on; the label-bridge mechanism is unneeded
|
||||
# and actively harmful here.
|
||||
# setdefault avoids clobbering an upstream power-port label
|
||||
# in the unlikely case that one sits at the same point.
|
||||
point_to_label.setdefault(pt, name)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error parsing power symbol: {e}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user