Treat 3V3_/1V8_ nets as power and ignore SPI pins aliased as SDA/SCL.
Hub Audio pull-ups sit on 3V3_DIGITAL typed as signal, and ADAU/TAC5212 SPI pins list SDA in the name — both produced false I2C/reset warnings. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -154,6 +154,11 @@ def _infer_net_properties(name: str) -> tuple[NetType, float | None]:
|
|||||||
voltage = _parse_rail_voltage(name)
|
voltage = _parse_rail_voltage(name)
|
||||||
return NetType.POWER, voltage
|
return NetType.POWER, voltage
|
||||||
|
|
||||||
|
# KiCad-style rails: 3V3_DIGITAL, 1V8_SI4684, 5V_USB (not I2C1-SCL-3V3).
|
||||||
|
if re.match(r"^\d+V\d*", upper):
|
||||||
|
voltage = _parse_rail_voltage(name)
|
||||||
|
return NetType.POWER, voltage
|
||||||
|
|
||||||
# Everything else is a signal
|
# Everything else is a signal
|
||||||
return NetType.SIGNAL, None
|
return NetType.SIGNAL, None
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,23 @@ def _is_i2c_pin(
|
|||||||
pin_num: str,
|
pin_num: str,
|
||||||
net_name: str,
|
net_name: str,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
return bool(_I2C_RE.search(_pin_blob(cons, pin_num, net_name)))
|
net = net_name or ""
|
||||||
|
if re.match(r"(?i)SPI([_-]|$)", net) or re.search(
|
||||||
|
r"(?i)\bSPI[_-]?(CLK|SCK|MOSI|MISO|CS|SS)\b", net,
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
primary = ""
|
||||||
|
if cons:
|
||||||
|
pin = cons.pin_by_number(pin_num)
|
||||||
|
if pin and pin.name:
|
||||||
|
primary = pin.name.split("/")[0].strip()
|
||||||
|
if re.search(r"(?i)\b(MISO|MOSI|SCLK|SCK)\b", primary):
|
||||||
|
return False
|
||||||
|
if _I2C_RE.search(net):
|
||||||
|
return True
|
||||||
|
if _I2C_RE.search(primary):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _is_reset_pin(
|
def _is_reset_pin(
|
||||||
@@ -241,7 +257,9 @@ def _is_ground_net(graph: DesignGraph, name: str) -> bool:
|
|||||||
|
|
||||||
def _is_power_net(graph: DesignGraph, name: str) -> bool:
|
def _is_power_net(graph: DesignGraph, name: str) -> bool:
|
||||||
net = graph.nets.get(name)
|
net = graph.nets.get(name)
|
||||||
return bool(net and net.net_type == NetType.POWER)
|
if net and net.net_type == NetType.POWER:
|
||||||
|
return True
|
||||||
|
return bool(re.match(r"^\d+V\d*", (name or "").upper()))
|
||||||
|
|
||||||
|
|
||||||
def _capacitor_to_ground(graph: DesignGraph, power_net: str) -> bool:
|
def _capacitor_to_ground(graph: DesignGraph, power_net: str) -> bool:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from backend.pinscopex.graph import _infer_net_properties
|
||||||
from backend.pinscopex.models import (
|
from backend.pinscopex.models import (
|
||||||
Component,
|
Component,
|
||||||
ComponentConstraints,
|
ComponentConstraints,
|
||||||
@@ -19,6 +20,17 @@ from backend.pinscopex.passive_rail_check import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ki_cad_voltage_prefix_is_power():
|
||||||
|
ntype, volts = _infer_net_properties("3V3_DIGITAL")
|
||||||
|
assert ntype == NetType.POWER
|
||||||
|
assert volts == 3.3
|
||||||
|
ntype, volts = _infer_net_properties("1V8_SI4684")
|
||||||
|
assert ntype == NetType.POWER
|
||||||
|
assert volts == 1.8
|
||||||
|
ntype, _ = _infer_net_properties("I2C1-SCL-3V3")
|
||||||
|
assert ntype == NetType.SIGNAL
|
||||||
|
|
||||||
|
|
||||||
def _graph(components, nets):
|
def _graph(components, nets):
|
||||||
net_objs = {}
|
net_objs = {}
|
||||||
for name, (ntype, conns) in nets.items():
|
for name, (ntype, conns) in nets.items():
|
||||||
@@ -117,6 +129,44 @@ def test_i2c_pullup_present():
|
|||||||
assert check_i2c_pullups(g, cons) == []
|
assert check_i2c_pullups(g, cons) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_i2c_pullup_to_3v3_digital_typed_as_signal():
|
||||||
|
cons = {
|
||||||
|
"UTEST": ComponentConstraints(
|
||||||
|
mpn="UTEST",
|
||||||
|
pintable=[Pin(number=8, name="SDA")],
|
||||||
|
absolute_maximum_ratings=[], rules=[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
r = Component(
|
||||||
|
reference="R1", value="4.7k", footprint="",
|
||||||
|
component_type=ComponentType.RESISTOR, mpn="R1",
|
||||||
|
pins={"1": "I2C_SDA", "2": "3V3_DIGITAL"},
|
||||||
|
)
|
||||||
|
g = _graph(
|
||||||
|
{"U1": _ic("U1", {"8": "I2C_SDA"}), "R1": r},
|
||||||
|
{
|
||||||
|
"I2C_SDA": (NetType.SIGNAL, [("U1", "8"), ("R1", "1")]),
|
||||||
|
"3V3_DIGITAL": (NetType.SIGNAL, [("R1", "2")]),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert check_i2c_pullups(g, cons) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_spi_pin_alias_sda_is_not_i2c():
|
||||||
|
cons = {
|
||||||
|
"UTEST": ComponentConstraints(
|
||||||
|
mpn="UTEST",
|
||||||
|
pintable=[Pin(number=38, name="MISO/SDA")],
|
||||||
|
absolute_maximum_ratings=[], rules=[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
g = _graph(
|
||||||
|
{"U1": _ic("U1", {"38": "SPI_MISO"})},
|
||||||
|
{"SPI_MISO": (NetType.SIGNAL, [("U1", "38")])},
|
||||||
|
)
|
||||||
|
assert check_i2c_pullups(g, cons) == []
|
||||||
|
|
||||||
|
|
||||||
def test_reset_no_finding_when_gpio_drives():
|
def test_reset_no_finding_when_gpio_drives():
|
||||||
cons = {
|
cons = {
|
||||||
"UTEST": ComponentConstraints(
|
"UTEST": ComponentConstraints(
|
||||||
|
|||||||
Reference in New Issue
Block a user