Fill protocol packs from recovered USB CTS, Type-C FTS, DVI 1.0, and IEEE 802.3-2012 Section Two (2.74.0).
NUMERIC rows cite document title, revision, section/table, and page. USB Zdiff, Type-C Rp/Rd, 10BASE-T, and 1000BASE-T stay UNKNOWN. PDFs are not in git.
This commit is contained in:
@@ -297,6 +297,25 @@ def parse_catalog(raw: Any) -> ProtocolCatalog:
|
||||
raise ProtocolCatalogError(str(exc)) from exc
|
||||
|
||||
|
||||
def _cite(
|
||||
*,
|
||||
document: str,
|
||||
organization: str,
|
||||
revision: str,
|
||||
section: str | None = None,
|
||||
table: str | None = None,
|
||||
page: str | None = None,
|
||||
) -> dict[str, str | None]:
|
||||
return {
|
||||
"document": document,
|
||||
"organization": organization,
|
||||
"revision": revision,
|
||||
"section": section,
|
||||
"table": table,
|
||||
"page": page,
|
||||
}
|
||||
|
||||
|
||||
def _c(
|
||||
iface_id: str,
|
||||
parameter: str,
|
||||
@@ -310,6 +329,9 @@ def _c(
|
||||
conditions: list[str] | None = None,
|
||||
measurement_method: MeasurementMethod | None = None,
|
||||
needed_document: str | None = None,
|
||||
value: float | None = None,
|
||||
unit: str | None = None,
|
||||
source: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
row: dict[str, Any] = {
|
||||
"id": f"{iface_id}-{parameter}",
|
||||
@@ -318,12 +340,12 @@ def _c(
|
||||
"mandatory": mandatory,
|
||||
"source_type": source_type,
|
||||
"source_class": source_class,
|
||||
"value": None,
|
||||
"unit": None,
|
||||
"source": None,
|
||||
"value": value,
|
||||
"unit": unit,
|
||||
"source": source,
|
||||
"conditions": conditions or [],
|
||||
"value_origin": "SPEC",
|
||||
"typical": False,
|
||||
"value_origin": value_origin,
|
||||
"typical": typical,
|
||||
}
|
||||
if measurement_method:
|
||||
row["measurement_method"] = measurement_method
|
||||
@@ -337,6 +359,47 @@ def _c(
|
||||
return row
|
||||
|
||||
|
||||
def _num(
|
||||
iface_id: str,
|
||||
parameter: str,
|
||||
value: float,
|
||||
unit: str,
|
||||
*,
|
||||
document: str,
|
||||
organization: str,
|
||||
revision: str,
|
||||
section: str | None = None,
|
||||
table: str | None = None,
|
||||
page: str | None = None,
|
||||
mandatory: MandatoryClass = "MANDATORY",
|
||||
source_type: SourceType = "STANDARD",
|
||||
source_class: SourceClass = "NORMATIVE",
|
||||
conditions: list[str] | None = None,
|
||||
measurement_method: MeasurementMethod | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""NUMERIC row. Every field carries title, revision, section/table, page."""
|
||||
return _c(
|
||||
iface_id,
|
||||
parameter,
|
||||
"NUMERIC",
|
||||
mandatory=mandatory,
|
||||
source_type=source_type,
|
||||
source_class=source_class,
|
||||
conditions=conditions,
|
||||
measurement_method=measurement_method,
|
||||
value=value,
|
||||
unit=unit,
|
||||
source=_cite(
|
||||
document=document,
|
||||
organization=organization,
|
||||
revision=revision,
|
||||
section=section,
|
||||
table=table,
|
||||
page=page,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _skel_constraints(
|
||||
iface_id: str,
|
||||
parameters: list[str],
|
||||
@@ -472,20 +535,77 @@ HDMI_CHECKS = [
|
||||
"cec",
|
||||
"hpd",
|
||||
]
|
||||
DVI_CHECKS = [
|
||||
"termination",
|
||||
"differential_impedance",
|
||||
"impedance_tolerance",
|
||||
"rise_time",
|
||||
"fall_time",
|
||||
"intra_pair_skew",
|
||||
"inter_lane_skew",
|
||||
"electrical_levels",
|
||||
"voltage",
|
||||
"connector_requirements",
|
||||
"data_rate",
|
||||
"vias",
|
||||
"stubs",
|
||||
"return_path",
|
||||
"topology",
|
||||
]
|
||||
# Recovered PDFs (USB Electrical CTS v1.08, Type-C Functional Test Rev 0.91, DVI 1.0).
|
||||
# IEEE 802.3 is not on file — do not fill Ethernet numbers from these documents.
|
||||
DOC_USB_CTS_108 = "USB 2.0 Electrical Compliance Test Specification"
|
||||
REV_USB_CTS_108 = "Version 1.08, April 2026"
|
||||
ORG_USBIF = "USB-IF"
|
||||
DOC_USBC_FTS = (
|
||||
"Universal Serial Bus Type-C Functional Test Specification Chapters 4 and 5"
|
||||
)
|
||||
REV_USBC_FTS = "Revision 0.91, March 3, 2024"
|
||||
DOC_DVI_10 = "Digital Visual Interface (DVI)"
|
||||
REV_DVI_10 = "Revision 1.0, 02 April 1999"
|
||||
ORG_DDWG = "DDWG"
|
||||
DOC_USB_BASE = (
|
||||
"USB-IF Base Specification (revision to fix when PDF is provided)"
|
||||
"USB-IF USB 2.0 Specification (not on file; Electrical CTS v1.08 does not state this field)"
|
||||
)
|
||||
DOC_USB_ELEC = (
|
||||
"USB-IF Electrical Compliance Specification (revision to fix when PDF is provided)"
|
||||
"USB 2.0 Electrical Compliance Test Specification Version 1.08 April 2026 "
|
||||
"(recovered; this PCB limit is not stated in the CTS)"
|
||||
)
|
||||
DOC_USB_CABLE = (
|
||||
"USB-IF Cable and Connector Specification (revision to fix when PDF is provided)"
|
||||
"USB Type-C Cable and Connector Specification (not on file; "
|
||||
"Functional Test Spec Rev 0.91 references Table 4-15 / 4.4.2 without stating ohms or volts)"
|
||||
)
|
||||
DOC_USB_CTS = (
|
||||
"USB-IF Compliance Test Specification (revision to fix when PDF is provided)"
|
||||
DOC_USB_CTS = DOC_USB_CTS_108 + " " + REV_USB_CTS_108
|
||||
DOC_USB_ECN = "USB ENGINEERING CHANGE NOTICE USB 2.0 DC Resistance (cited by Electrical CTS v1.08 §3.9)"
|
||||
DOC_USB_LSFS = (
|
||||
"USB 2.0 Specification LS/FS electrical (not on file; Electrical CTS v1.08 "
|
||||
"§2 lists LS/FS test names without numeric criteria)"
|
||||
)
|
||||
DOC_USB_ECN = "USB-IF ECN applicable to the revision used"
|
||||
DOC_IEEE_8023 = "IEEE 802.3 (clause for this variant; not on file)"
|
||||
DOC_IEEE_2012 = "IEEE Std 802.3-2012 IEEE Standard for Ethernet"
|
||||
REV_IEEE_2012 = "2012"
|
||||
ORG_IEEE = "IEEE"
|
||||
DOC_IEEE_S1_C14 = (
|
||||
"IEEE Std 802.3-2012 Section One Clause 14 (10BASE-T; not in Section Two)"
|
||||
)
|
||||
DOC_IEEE_S3_C40 = (
|
||||
"IEEE Std 802.3-2012 Section Three Clause 40 (1000BASE-T; not in Section Two)"
|
||||
)
|
||||
DOC_IEEE_S3_C36 = (
|
||||
"IEEE Std 802.3-2012 Section Three (1000BASE-X; not in Section Two)"
|
||||
)
|
||||
DOC_IEEE_TP_PMD = (
|
||||
"ANSI X3.263:1995 TP-PMD (incorporated by IEEE 802.3-2012 Clause 25; not on file. "
|
||||
"Section Two states 100 Ω as cabling/link-segment and as a ±1% test termination, "
|
||||
"not as a PCB trace differential impedance)"
|
||||
)
|
||||
DOC_IEEE_OTHER = {
|
||||
"2.5gbase-t": "IEEE 802.3bz / later 802.3 2.5GBASE-T clause (not in 2012 Section Two)",
|
||||
"5gbase-t": "IEEE 802.3bz / later 802.3 5GBASE-T clause (not in 2012 Section Two)",
|
||||
"10gbase-t": "IEEE Std 802.3-2012 Section Four Clause 55 (10GBASE-T; not in Section Two)",
|
||||
"sgmii": "SGMII is not an IEEE 802.3 MDI clause in 2012 Section Two",
|
||||
"10gbase-r": "IEEE 802.3 10GBASE-R clauses (not in 2012 Section Two)",
|
||||
}
|
||||
DOC_HDMI_ADOPTER = (
|
||||
"HDMI Adopter specification (not on file; 1.4 vs 2.x vs FRL must not be mixed)"
|
||||
)
|
||||
@@ -573,7 +693,7 @@ HYPERBUS_CHECKS = [
|
||||
|
||||
|
||||
def build_m0_catalog() -> dict[str, Any]:
|
||||
"""Skeleton catalog. No numeric USB/ETH/HDMI/DDR values."""
|
||||
"""Catalog. NUMERIC only with recovered-PDF cites. No invented ohms."""
|
||||
logical: list[dict[str, Any]] = []
|
||||
physical: list[dict[str, Any]] = []
|
||||
|
||||
@@ -612,6 +732,8 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
L("hdmi-2.0", "HDMI 2.0 TMDS", "SERIAL", "HDMI")
|
||||
L("hdmi-frl", "HDMI FRL mode", "SERIAL", "HDMI",
|
||||
"FRL is distinct from TMDS. Do not copy TMDS numbers onto FRL.")
|
||||
L("dvi", "DVI 1.0 TMDS", "SERIAL", "DVI",
|
||||
"DVI is not HDMI. Numbers from DDWG DVI Revision 1.0 only.")
|
||||
L("ddr-family", "DDR family (abstract)", "MEMORY", "DDR")
|
||||
for gen, title in (
|
||||
("ddr1", "DDR1"), ("ddr2", "DDR2"), ("ddr3", "DDR3"),
|
||||
@@ -667,22 +789,22 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
L("can", "CAN / CAN FD", "PERIPHERAL", "CAN")
|
||||
L("rgmii", "RGMII MAC-PHY", "PERIPHERAL", "ETHERNET")
|
||||
|
||||
def _usb2_cons(pid: str) -> list[dict[str, Any]]:
|
||||
def _usb2_cons(pid: str, *, hs: bool = False) -> list[dict[str, Any]]:
|
||||
docs = {
|
||||
"differential_impedance": DOC_USB_ELEC,
|
||||
"impedance_tolerance": DOC_USB_ELEC,
|
||||
"electrical_levels": DOC_USB_ELEC,
|
||||
"rise_time": DOC_USB_ELEC,
|
||||
"fall_time": DOC_USB_ELEC,
|
||||
"intra_pair_skew": DOC_USB_ELEC,
|
||||
"termination": DOC_USB_ELEC,
|
||||
"dc_resistance": DOC_USB_ELEC,
|
||||
"differential_impedance": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"impedance_tolerance": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"electrical_levels": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"rise_time": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"fall_time": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"intra_pair_skew": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"termination": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"dc_resistance": DOC_USB_ELEC if hs else DOC_USB_LSFS,
|
||||
"connector_requirements": DOC_USB_CABLE,
|
||||
"vbus_requirements": DOC_USB_BASE,
|
||||
"pull_up": DOC_USB_BASE,
|
||||
"pull_up": DOC_USB_BASE if not hs else DOC_USB_ELEC,
|
||||
"pull_down": DOC_USB_BASE,
|
||||
"signaling": DOC_USB_BASE,
|
||||
"data_rate": DOC_USB_BASE,
|
||||
"signaling": DOC_USB_BASE if not hs else DOC_USB_CTS_108,
|
||||
"data_rate": DOC_USB_LSFS if not hs else DOC_USB_CTS_108,
|
||||
"test_method": DOC_USB_CTS,
|
||||
"compliance_test": DOC_USB_CTS,
|
||||
}
|
||||
@@ -690,10 +812,62 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
out = []
|
||||
for p in USB2_CHECKS:
|
||||
mand: MandatoryClass = "RECOMMENDED" if p in rec else "MANDATORY"
|
||||
if hs and p == "data_rate":
|
||||
out.append(_num(
|
||||
pid, p, 480.0, "Mb/s",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.2 EL_2", page="3",
|
||||
conditions=["HS transmitter", "tolerance ±0.05%"],
|
||||
))
|
||||
continue
|
||||
if hs and p in {"rise_time", "fall_time"}:
|
||||
out.append(_num(
|
||||
pid, p, 300.0, "ps",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.2 EL_6", page="3",
|
||||
conditions=[
|
||||
"HS driver 10% to 90% differential",
|
||||
"minimum greater than 300 ps",
|
||||
],
|
||||
))
|
||||
continue
|
||||
if hs and p == "pull_up":
|
||||
out.append(_num(
|
||||
pid, p, 1500.0, "ohm",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.5 EL_31", page="4",
|
||||
conditions=["device speed detection 1.5K pull-up"],
|
||||
))
|
||||
continue
|
||||
if hs and p == "dc_resistance":
|
||||
out.append(_num(
|
||||
pid, p, 17.0, "ohm",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.9.1", page="7",
|
||||
conditions=[
|
||||
"HS device-only upstream",
|
||||
"D+ and D- individually",
|
||||
"maximum series DC resistance",
|
||||
],
|
||||
))
|
||||
continue
|
||||
out.append(_c(
|
||||
pid, p, "UNKNOWN",
|
||||
mandatory=mand,
|
||||
needed_document=docs.get(p, DOC_USB_BASE),
|
||||
needed_document=docs.get(p, DOC_USB_LSFS if not hs else DOC_USB_BASE),
|
||||
))
|
||||
if hs:
|
||||
out.append(_num(
|
||||
pid, "dc_resistance_captive_cable_device", 23.0, "ohm",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.9.1", page="7",
|
||||
conditions=["HS captive-cable device", "D+ and D- individually", "maximum"],
|
||||
))
|
||||
out.append(_num(
|
||||
pid, "dc_resistance_host_hub_downstream", 13.0, "ohm",
|
||||
document=DOC_USB_CTS_108, organization=ORG_USBIF,
|
||||
revision=REV_USB_CTS_108, section="3.9.2", page="7",
|
||||
conditions=["HS host/hub or dual-role device downstream", "D+ and D- individually", "maximum"],
|
||||
))
|
||||
return out
|
||||
|
||||
@@ -704,21 +878,122 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
doc = DOC_USB_CABLE if p in cable else DOC_USB_ELEC
|
||||
if p == "usb2_channel_requirements":
|
||||
doc = DOC_USB_ELEC
|
||||
if p in {"vbus_requirements", "voltage"}:
|
||||
doc = DOC_USB_CABLE
|
||||
out.append(_c(pid, p, "UNKNOWN", needed_document=doc))
|
||||
out.append(_num(
|
||||
pid, "gnd_ir_drop_cable", 250.0, "mV",
|
||||
document=DOC_USBC_FTS, organization=ORG_USBIF,
|
||||
revision=REV_USBC_FTS, section="4.4.1#1", page="10",
|
||||
mandatory="OPTIONAL", source_type="CABLE",
|
||||
conditions=["cable IR drop for ground; not a receptacle PCB ohm"],
|
||||
))
|
||||
out.append(_num(
|
||||
pid, "vbus_ir_drop_cable", 500.0, "mV",
|
||||
document=DOC_USBC_FTS, organization=ORG_USBIF,
|
||||
revision=REV_USBC_FTS, section="4.4.1#1", page="10",
|
||||
mandatory="OPTIONAL", source_type="CABLE",
|
||||
conditions=["cable IR drop for VBUS; not a receptacle PCB ohm"],
|
||||
))
|
||||
return out
|
||||
|
||||
def _eth_cons(pid: str, *, phy: bool = False) -> list[dict[str, Any]]:
|
||||
def _eth_cons(pid: str, lid: str) -> list[dict[str, Any]]:
|
||||
if lid == "10base-t":
|
||||
missing = DOC_IEEE_S1_C14
|
||||
elif lid == "1000base-t":
|
||||
missing = DOC_IEEE_S3_C40
|
||||
elif lid == "1000base-x":
|
||||
missing = DOC_IEEE_S3_C36
|
||||
elif lid == "100base-tx":
|
||||
missing = DOC_IEEE_TP_PMD
|
||||
elif lid == "100base-fx":
|
||||
missing = (
|
||||
"ISO/IEC 9314-3:1990 fiber-PMD (incorporated by IEEE 802.3-2012 Clause 26; "
|
||||
"optical MDI, not copper PCB ohms)"
|
||||
)
|
||||
else:
|
||||
missing = DOC_IEEE_OTHER.get(lid, DOC_IEEE_8023)
|
||||
out = []
|
||||
for p in ETH_CHECKS:
|
||||
if p in {"phy_requirements", "magnetics_requirements"} or phy:
|
||||
if p in {"phy_requirements", "magnetics_requirements"}:
|
||||
out.append(_c(
|
||||
pid, p, "PHY_DEPENDENT",
|
||||
source_type="PHY", source_class="VENDOR",
|
||||
needed_document="PHY vendor datasheet (not IEEE-universal)",
|
||||
))
|
||||
continue
|
||||
out.append(_c(pid, p, "UNKNOWN", needed_document=DOC_IEEE_8023))
|
||||
if p in {"phy_requirements", "magnetics_requirements"}:
|
||||
out.append(_c(
|
||||
pid, p, "PHY_DEPENDENT",
|
||||
source_type="PHY", source_class="VENDOR",
|
||||
needed_document="PHY vendor datasheet (not IEEE-universal)",
|
||||
))
|
||||
continue
|
||||
if lid == "100base-tx" and p == "data_rate":
|
||||
out.append(_num(
|
||||
pid, p, 100.0, "Mb/s",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="21.1", page="39",
|
||||
conditions=["100BASE-T family including 100BASE-TX"],
|
||||
))
|
||||
continue
|
||||
if lid == "100base-tx" and p == "maximum_channel_length":
|
||||
out.append(_num(
|
||||
pid, p, 100.0, "m",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="25.4.9.2", page="232",
|
||||
source_type="CABLE",
|
||||
conditions=["Category 5 link segment of up to 100 m"],
|
||||
))
|
||||
continue
|
||||
if lid == "100base-tx" and p == "cable_channel":
|
||||
out.append(_num(
|
||||
pid, p, 100.0, "ohm",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="25.4.9.2.2", page="232",
|
||||
source_type="CABLE",
|
||||
conditions=[
|
||||
"nominal differential characteristic impedance of the link segment",
|
||||
"1 MHz to 100 MHz including cords and connecting hardware",
|
||||
"not a PCB trace differential impedance",
|
||||
],
|
||||
))
|
||||
continue
|
||||
if lid == "100base-fx" and p == "data_rate":
|
||||
out.append(_num(
|
||||
pid, p, 100.0, "Mb/s",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="26.1", page="245",
|
||||
conditions=["100BASE-FX"],
|
||||
))
|
||||
continue
|
||||
if lid == "100base-fx" and p == "differential_impedance":
|
||||
out.append(_c(
|
||||
pid, p, "NOT_APPLICABLE",
|
||||
mandatory="INFORMATIONAL", source_type="STANDARD",
|
||||
conditions=["optical fiber MDI"],
|
||||
))
|
||||
continue
|
||||
nd = missing
|
||||
if lid == "100base-tx" and p in {
|
||||
"differential_impedance", "impedance_tolerance", "termination",
|
||||
}:
|
||||
nd = DOC_IEEE_TP_PMD
|
||||
out.append(_c(pid, p, "UNKNOWN", needed_document=nd))
|
||||
if lid == "100base-tx":
|
||||
out.append(_num(
|
||||
pid, "isolation_after_test", 2.0e6, "ohm",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="25.4.6", page="231",
|
||||
conditions=[
|
||||
"PMD MDI that is not a PI",
|
||||
"resistance after isolation test, measured at 500 V dc",
|
||||
"minimum 2 MΩ",
|
||||
],
|
||||
))
|
||||
out.append(_num(
|
||||
pid, "isolation_rms", 1500.0, "V",
|
||||
document=DOC_IEEE_2012, organization=ORG_IEEE,
|
||||
revision=REV_IEEE_2012, section="25.4.6 a", page="231",
|
||||
mandatory="OPTIONAL",
|
||||
conditions=[
|
||||
"one of three allowed isolation tests",
|
||||
"1500 V rms at 50 Hz to 60 Hz for 60 s",
|
||||
],
|
||||
))
|
||||
return out
|
||||
|
||||
def _hdmi_cons(pid: str) -> list[dict[str, Any]]:
|
||||
@@ -727,17 +1002,102 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
for p in HDMI_CHECKS
|
||||
]
|
||||
|
||||
for lid, pid, hints, note in (
|
||||
("usb2-ls", "usb2-ls-dpair", ["USB_D+", "USB_LS"], "USB 2.0 Low Speed. No invented Z."),
|
||||
("usb2-fs", "usb2-fs-dpair", ["USB_D+", "USB_FS"], "USB 2.0 Full Speed. No invented Z."),
|
||||
def _dvi_cons(pid: str) -> list[dict[str, Any]]:
|
||||
out = []
|
||||
for p in DVI_CHECKS:
|
||||
if p == "termination":
|
||||
out.append(_num(
|
||||
pid, p, 50.0, "ohm",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.2", table="Table 4-2", page="35",
|
||||
conditions=["TMDS termination resistance", "±10%"],
|
||||
))
|
||||
continue
|
||||
if p == "differential_impedance":
|
||||
out.append(_num(
|
||||
pid, p, 100.0, "ohm",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.4", table="Table 4-7", page="38",
|
||||
conditions=["receiver at termination", "±10%"],
|
||||
))
|
||||
continue
|
||||
if p == "impedance_tolerance":
|
||||
out.append(_num(
|
||||
pid, p, 10.0, "percent",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.4", table="Table 4-7", page="38",
|
||||
conditions=["at termination ±10%"],
|
||||
))
|
||||
continue
|
||||
if p in {"rise_time", "fall_time"}:
|
||||
out.append(_num(
|
||||
pid, p, 75.0, "ps",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.3", table="Table 4-4", page="36",
|
||||
conditions=["20%–80%", "minimum 75 ps", "maximum 0.4 Tbit"],
|
||||
))
|
||||
continue
|
||||
if p == "intra_pair_skew":
|
||||
out.append(_num(
|
||||
pid, p, 0.15, "Tbit",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.3", table="Table 4-4", page="36",
|
||||
conditions=["transmitter connector maximum"],
|
||||
))
|
||||
continue
|
||||
if p == "inter_lane_skew":
|
||||
out.append(_num(
|
||||
pid, p, 0.20, "Tpixel",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.3", table="Table 4-4", page="36",
|
||||
conditions=["transmitter connector maximum"],
|
||||
))
|
||||
continue
|
||||
if p == "electrical_levels":
|
||||
out.append(_num(
|
||||
pid, p, 400.0, "mV",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.3", table="Table 4-3", page="35",
|
||||
conditions=["single-ended Vswing minimum 400 mV", "maximum 600 mV"],
|
||||
))
|
||||
continue
|
||||
if p == "voltage":
|
||||
out.append(_num(
|
||||
pid, p, 3.3, "V",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.2", table="Table 4-2", page="35",
|
||||
conditions=["AVcc termination supply", "±5%"],
|
||||
))
|
||||
continue
|
||||
out.append(_c(
|
||||
pid, p, "UNKNOWN",
|
||||
needed_document=(
|
||||
"Digital Visual Interface (DVI) Revision 1.0 (recovered; this field is not a "
|
||||
"single PCB number in the cited tables)"
|
||||
),
|
||||
))
|
||||
out.append(_num(
|
||||
pid, "through_connection_impedance", 100.0, "ohm",
|
||||
document=DOC_DVI_10, organization=ORG_DDWG,
|
||||
revision=REV_DVI_10, section="4.4", table="Table 4-7", page="38",
|
||||
source_type="CONNECTOR",
|
||||
conditions=["through a mated connector", "±20%"],
|
||||
))
|
||||
return out
|
||||
|
||||
for lid, pid, hints, note, hs in (
|
||||
("usb2-ls", "usb2-ls-dpair", ["USB_D+", "USB_LS"],
|
||||
"USB 2.0 Low Speed. Electrical CTS v1.08 lists LS tests without numeric criteria.", False),
|
||||
("usb2-fs", "usb2-fs-dpair", ["USB_D+", "USB_FS"],
|
||||
"USB 2.0 Full Speed. Electrical CTS v1.08 lists FS tests without numeric criteria.", False),
|
||||
("usb2-ls-fs", "usb2-ls-fs-dpair", ["USB_D+", "USB_D-", "USB_DP", "USB_DM", "D+", "D-"],
|
||||
"LS/FS umbrella pair. No invented Z."),
|
||||
"LS/FS umbrella pair. No LS/FS ohms in Electrical CTS v1.08.", False),
|
||||
("usb2-hs", "usb2-hs-dpair", ["USB_D+", "USB_D-", "USB_HS"],
|
||||
"USB 2.0 High Speed. USB-IF cite required before NUMERIC Z."),
|
||||
"USB 2.0 High Speed. Zdiff is not stated in Electrical CTS v1.08 (do not invent differential ohms).", True),
|
||||
):
|
||||
physical.append(_iface(
|
||||
pid, lid, "SERIAL", "SERIAL_DIFFERENTIAL", "YES",
|
||||
USB2_CHECKS, _usb2_cons(pid),
|
||||
USB2_CHECKS, _usb2_cons(pid, hs=hs),
|
||||
hints=hints, notes=note,
|
||||
))
|
||||
physical.append(_iface(
|
||||
@@ -750,7 +1110,7 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
"No invented Rd/Rp ohms."
|
||||
),
|
||||
))
|
||||
usb2_over_c = _usb2_cons("usb-c-usb2-receptacle")
|
||||
usb2_over_c = _usb2_cons("usb-c-usb2-receptacle", hs=True)
|
||||
seen_p = {c["parameter"] for c in usb2_over_c}
|
||||
for c in _usbc_cons("usb-c-usb2-receptacle"):
|
||||
if c["parameter"] not in seen_p:
|
||||
@@ -841,11 +1201,14 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
conn = "none" if lid in {"sgmii", "1000base-x", "100base-fx", "10gbase-r"} else "RJ45"
|
||||
physical.append(_iface(
|
||||
pid, lid, "SERIAL", "SERIAL_DIFFERENTIAL", "YES",
|
||||
ETH_CHECKS, _eth_cons(pid),
|
||||
ETH_CHECKS, _eth_cons(pid, lid),
|
||||
connector=conn, hints=hints,
|
||||
notes=(
|
||||
f"Incomplete skeleton: IEEE 802.3 not on file. "
|
||||
f"IEEE vs PHY vs PCB vs magnetics are distinct. Not auto from RJ45."
|
||||
"IEEE 802.3-2012 Section Two (Clauses 21–33) on file. "
|
||||
"10BASE-T is Clause 14 (Section One, not here). "
|
||||
"1000BASE-T is Clause 40 (Section Three, not here). "
|
||||
"100 Ω in Clause 25 is cabling/link-segment, not PCB Z. "
|
||||
"Not auto from RJ45. IEEE vs PHY vs PCB vs magnetics are distinct."
|
||||
),
|
||||
incomplete=True,
|
||||
))
|
||||
@@ -875,6 +1238,16 @@ def build_m0_catalog() -> dict[str, Any]:
|
||||
notes="HDMI FRL is distinct from TMDS. Do not apply TMDS rules. UNKNOWN until Adopter spec.",
|
||||
incomplete=True,
|
||||
))
|
||||
physical.append(_iface(
|
||||
"dvi-1.0-tmds", "dvi", "SERIAL", "SERIAL_DIFFERENTIAL", "YES",
|
||||
DVI_CHECKS, _dvi_cons("dvi-1.0-tmds"),
|
||||
connector="DVI",
|
||||
hints=["DVI", "TMDS", "TX0", "TX1", "TX2"],
|
||||
notes=(
|
||||
"DVI 1.0 TMDS. Not HDMI. Table 4-2 termination 50 Ω ±10%; "
|
||||
"Table 4-7 receiver at termination 100 Ω ±10%. Table 4-8 cable skew is informative."
|
||||
),
|
||||
))
|
||||
|
||||
def _mem_constraints(pid: str, kind: ValueKind, source_type: SourceType) -> list[dict[str, Any]]:
|
||||
cls: SourceClass = "VENDOR" if source_type != "STANDARD" else "NORMATIVE"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -67,9 +67,10 @@ _ETH_PHY_RE = re.compile(
|
||||
)
|
||||
_ETH_MAG_RE = re.compile(r"MAGNETIC|PULSE\s*JACK|ETHERNET\s*XFR|LAN_XFR", re.I)
|
||||
_HDMI_MINI_RE = re.compile(r"MINI\s*HDMI|HDMI[\s_\-]*C\b|HDMI[\s_\-]*MINI", re.I)
|
||||
_HDMI_RE = re.compile(r"\bHDMI\b|TMDS", re.I)
|
||||
_HDMI_RE = re.compile(r"\bHDMI\b", re.I)
|
||||
_HDMI_FRL_RE = re.compile(r"\bFRL\b|HDMI\s*2\.1", re.I)
|
||||
_HDMI_TMDS_NET = re.compile(r"TMDS|HDMI[_]?TX|HDMI[_]?CLK|HDMI[_]?D\d", re.I)
|
||||
_HDMI_TMDS_NET = re.compile(r"HDMI[_]?TX|HDMI[_]?CLK|HDMI[_]?D\d|TMDS", re.I)
|
||||
_DVI_RE = re.compile(r"\bDVI\b|DVI[\s_\-]*[DAI]", re.I)
|
||||
_DDR_GEN = [
|
||||
("ddr5", re.compile(r"\bDDR5\b", re.I)),
|
||||
("ddr4", re.compile(r"\bDDR4\b|MT41|K4A|IS43TR", re.I)),
|
||||
@@ -283,6 +284,7 @@ def recognize_physical_buses(
|
||||
out.extend(_recognize_declared(graph, ifaces, logical))
|
||||
out.extend(_recognize_usb(graph, ifaces))
|
||||
out.extend(_recognize_ethernet(graph, ifaces))
|
||||
out.extend(_recognize_dvi(graph, ifaces))
|
||||
out.extend(_recognize_hdmi(graph, ifaces))
|
||||
out.extend(_recognize_hbm(graph, ifaces))
|
||||
out.extend(_recognize_ddr(graph, ifaces))
|
||||
@@ -615,6 +617,40 @@ def _recognize_ethernet(graph: DesignGraph, ifaces: dict) -> list[PhysicalBusIns
|
||||
)]
|
||||
|
||||
|
||||
def _recognize_dvi(graph: DesignGraph, ifaces: dict) -> list[PhysicalBusInstance]:
|
||||
conns = [
|
||||
c for c in graph.components.values()
|
||||
if c.component_type == ComponentType.CONNECTOR and (
|
||||
_DVI_RE.search(_blob(c, graph)) or _DVI_RE.search(c.footprint or "")
|
||||
)
|
||||
]
|
||||
if not conns:
|
||||
return []
|
||||
pid = "dvi-1.0-tmds"
|
||||
iface = ifaces.get(pid)
|
||||
if iface is None:
|
||||
return []
|
||||
host = conns[0].reference
|
||||
tmds = [
|
||||
n for n in graph.nets
|
||||
if _HDMI_TMDS_NET.search(n) or _HDMI_TMDS_NET.search(_leaf(n)) or _DVI_RE.search(n)
|
||||
]
|
||||
return [PhysicalBusInstance(
|
||||
instance_id=f"{pid}:{host}",
|
||||
logical_protocol_id="dvi",
|
||||
physical_interface_id=pid,
|
||||
pcb_relevant=iface.pcb_relevant,
|
||||
confidence=_EVIDENCE_SCORE["part"],
|
||||
evidence_kind="part",
|
||||
recognition_status="REVIEW" if not tmds else "RECOGNIZED",
|
||||
nets=tmds,
|
||||
host_ref=host,
|
||||
notes="DVI 1.0 TMDS. Not HDMI. Connector is not HDMI Type A.",
|
||||
connector="DVI",
|
||||
physical_implementation="DVI 1.0 TMDS",
|
||||
)]
|
||||
|
||||
|
||||
def _recognize_hdmi(graph: DesignGraph, ifaces: dict) -> list[PhysicalBusInstance]:
|
||||
conns = [
|
||||
c for c in graph.components.values()
|
||||
@@ -625,6 +661,12 @@ def _recognize_hdmi(graph: DesignGraph, ifaces: dict) -> list[PhysicalBusInstanc
|
||||
]
|
||||
tmds = [n for n in graph.nets if _HDMI_TMDS_NET.search(n) or _HDMI_TMDS_NET.search(_leaf(n))]
|
||||
blob = " ".join(_blob(c, graph) for c in graph.components.values())
|
||||
dvi_present = any(
|
||||
_DVI_RE.search(_blob(c, graph)) or _DVI_RE.search(c.footprint or "")
|
||||
for c in graph.components.values()
|
||||
)
|
||||
if dvi_present and not re.search(r"\bHDMI\b", blob, re.I):
|
||||
return []
|
||||
frl = bool(_HDMI_FRL_RE.search(blob) or any(_HDMI_FRL_RE.search(n) for n in graph.nets))
|
||||
mini = any(
|
||||
_HDMI_MINI_RE.search(_blob(c, graph)) or _HDMI_MINI_RE.search(c.footprint or "")
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
What's new in Periscope.
|
||||
|
||||
## 2.74.0 — 2026-09-22 — Protocol packs from recovered PDFs (USB CTS, Type-C FTS, DVI 1.0, IEEE 802.3-2012 §2)
|
||||
|
||||
NUMERIC constraints now carry title, revision, section/table, and page from the recovered PDFs. USB 2.0 HS fills data rate / rise-fall / 1.5 kΩ pull-up / DCR from Electrical CTS v1.08; Zdiff stays UNKNOWN (CTS does not state 90 Ω). Type-C Rp/Rd/VBUS volts stay UNKNOWN (Functional Test Spec points at Cable and Connector tables). DVI 1.0 is a separate protocol from HDMI. IEEE 802.3-2012 Section Two fills 100BASE-TX cabling 100 Ω / 100 m / isolation and 100 Mb/s; 10BASE-T Clause 14 and 1000BASE-T Clause 40 are not in Section Two.
|
||||
|
||||
- [Changed] `protocol_catalog.py` + `catalog.json`; DVI recognition.
|
||||
- [New] pytest `tests/pcb/test_protocol_pdf_pack.py`.
|
||||
|
||||
## 2.73.0 — 2026-09-22 — Protocol certification M6/M7 (USB-C / Ethernet / HDMI packs)
|
||||
|
||||
USB 2.0 (LS/FS/HS) is the protocol; USB Type-C is a connector/interface system; USB 2.0 over Type-C is the physical implementation. Type-C does not imply USB3 or USB4. Mini HDMI is a connector, not a protocol. Ethernet variants (10/100/1000/2.5G/5G/10G, SGMII, 1000BASE-X, 100BASE-FX, 10GBASE-R) are incomplete skeletons. All listed numeric fields stay **UNKNOWN** with `needed_document` (USB-IF / IEEE 802.3 / HDMI Adopter). No invented ohms, no typical-as-standard, no OpenEMS.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "periscope-web",
|
||||
"version": "2.73.0",
|
||||
"version": "2.74.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"sync-version": "node scripts/sync-version.mjs",
|
||||
|
||||
@@ -26,6 +26,7 @@ REQUIRED_LOGICAL = {
|
||||
"usb2-ls-fs", "usb2-ls", "usb2-fs", "usb2-hs", "usb-c", "usb-c-usb2",
|
||||
"usb3-x", "usb4", "100base-tx", "10base-t", "1000base-t",
|
||||
"hdmi-1.4", "hdmi-2.0", "hdmi-frl",
|
||||
"dvi",
|
||||
"ddr-family", "ddr4", "lpddr-family", "lpddr4",
|
||||
"hbm-family", "hbm3", "hyperbus", "qspi", "octal-spi", "emmc", "ufs",
|
||||
"axi4", "axi4-lite", "ahb", "apb", "wishbone", "avalon-mm", "avalon-st",
|
||||
@@ -98,12 +99,28 @@ def test_hdmi_mini_is_same_logical_different_connector():
|
||||
assert mini.connector == "HDMI-C-mini"
|
||||
|
||||
|
||||
def test_catalog_has_no_invented_ohm_numbers():
|
||||
def test_catalog_numeric_requires_official_cite_no_invented_usb_90ohm():
|
||||
cat = load_catalog()
|
||||
usb_z = []
|
||||
for iface in cat.physical_interfaces:
|
||||
for c in iface.constraints:
|
||||
assert c.value is None
|
||||
assert c.value_kind != "NUMERIC"
|
||||
if c.value_kind == "NUMERIC":
|
||||
assert c.value is not None
|
||||
assert c.source is not None
|
||||
assert c.source.document and c.source.organization
|
||||
assert c.source.revision
|
||||
assert c.source.page
|
||||
assert c.source.section or c.source.table
|
||||
if (
|
||||
iface.logical_protocol_id.startswith("usb")
|
||||
and c.parameter == "differential_impedance"
|
||||
):
|
||||
usb_z.append(c)
|
||||
assert c.value_kind != "NUMERIC"
|
||||
assert c.value is None
|
||||
assert usb_z
|
||||
blob = json.dumps([c.model_dump() for c in usb_z])
|
||||
assert "90" not in blob
|
||||
|
||||
|
||||
def test_recommended_is_not_fail_mandatory():
|
||||
|
||||
@@ -90,9 +90,11 @@ def test_m10_no_invented_ohms_and_no_usbif_fill():
|
||||
loaded = load_catalog()
|
||||
for iface in loaded.physical_interfaces:
|
||||
for c in iface.constraints:
|
||||
assert c.value is None
|
||||
assert c.value_kind != "NUMERIC" or (c.source is not None)
|
||||
if c.value_kind != "NUMERIC":
|
||||
if c.value_kind == "NUMERIC":
|
||||
assert c.source is not None
|
||||
assert c.source.document
|
||||
else:
|
||||
assert c.value is None
|
||||
assert c.unit is None
|
||||
blob = json.dumps([
|
||||
c.model_dump() for p in loaded.physical_interfaces for c in p.constraints
|
||||
|
||||
@@ -84,15 +84,21 @@ def test_usb2_and_usb_c_unknown_with_usbif_needed_document_no_90ohm():
|
||||
or p.id.startswith("usb-")
|
||||
]
|
||||
assert usb_ifaces
|
||||
blob = json.dumps([c.model_dump() for p in usb_ifaces for c in p.constraints])
|
||||
assert "90" not in blob
|
||||
z_blob = json.dumps([
|
||||
c.model_dump() for p in usb_ifaces for c in p.constraints
|
||||
if c.parameter == "differential_impedance"
|
||||
])
|
||||
assert "90" not in z_blob
|
||||
for p in usb_ifaces:
|
||||
for c in p.constraints:
|
||||
assert c.value is None
|
||||
assert c.value_kind != "NUMERIC"
|
||||
if c.parameter == "differential_impedance":
|
||||
assert c.value is None
|
||||
assert c.value_kind != "NUMERIC"
|
||||
if c.value_kind in {"UNKNOWN", "MISSING_SOURCE"}:
|
||||
assert c.needed_document
|
||||
assert "USB-IF" in c.needed_document or "specification" in c.needed_document.lower()
|
||||
assert "USB-IF" in c.needed_document or "specification" in c.needed_document.lower() or "Specification" in c.needed_document
|
||||
if p.logical_protocol_id == "usb-c" and c.parameter in {"rp", "rd"}:
|
||||
assert c.value_kind == "UNKNOWN"
|
||||
over = next(p for p in cat.physical_interfaces if p.id == "usb-c-usb2-receptacle")
|
||||
assert over.logical_protocol_id == "usb2-hs"
|
||||
assert over.connector == "Type-C"
|
||||
@@ -202,8 +208,8 @@ def test_mini_hdmi_is_connector_not_protocol_id():
|
||||
def test_ethernet_hdmi_skeletons_unknown_needed_document():
|
||||
cat = load_catalog()
|
||||
for lid in (
|
||||
"10base-t", "100base-tx", "1000base-t", "2.5gbase-t", "5gbase-t",
|
||||
"10gbase-t", "sgmii", "1000base-x", "100base-fx", "10gbase-r",
|
||||
"10base-t", "1000base-t", "2.5gbase-t", "5gbase-t",
|
||||
"10gbase-t", "sgmii", "1000base-x", "10gbase-r",
|
||||
"hdmi-1.4", "hdmi-2.0", "hdmi-frl",
|
||||
):
|
||||
ifaces = [p for p in cat.physical_interfaces if p.logical_protocol_id == lid]
|
||||
@@ -218,7 +224,7 @@ def test_ethernet_hdmi_skeletons_unknown_needed_document():
|
||||
if lid.startswith("hdmi"):
|
||||
assert "HDMI" in c.needed_document
|
||||
else:
|
||||
assert "IEEE" in c.needed_document or "PHY" in (c.needed_document or "")
|
||||
assert "IEEE" in c.needed_document or "PHY" in (c.needed_document or "") or "SGMII" in (c.needed_document or "")
|
||||
tmds = next(p for p in cat.physical_interfaces if p.id == "hdmi-1.4-tmds-type-a")
|
||||
frl = next(p for p in cat.physical_interfaces if p.id == "hdmi-frl-pcb")
|
||||
assert tmds.logical_protocol_id != frl.logical_protocol_id
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
"""Recovered-PDF pack: USB Electrical CTS, Type-C FTS, DVI 1.0, IEEE 802.3-2012 §2."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from backend.periscopex.models import (
|
||||
Component,
|
||||
ComponentType,
|
||||
DesignGraph,
|
||||
Net,
|
||||
NetType,
|
||||
PinConnection,
|
||||
)
|
||||
from backend.periscopex.protocol_catalog import load_catalog
|
||||
from backend.periscopex.protocol_recognize import recognize_physical_buses
|
||||
|
||||
|
||||
def _cite_ok(c) -> None:
|
||||
assert c.value_kind == "NUMERIC"
|
||||
assert c.value is not None
|
||||
src = c.source
|
||||
assert src is not None
|
||||
assert src.document
|
||||
assert src.organization
|
||||
assert src.revision
|
||||
assert src.page
|
||||
assert src.section or src.table
|
||||
|
||||
|
||||
def test_usb_cts_hs_numeric_cited_no_zdiff_90():
|
||||
cat = load_catalog()
|
||||
hs = next(p for p in cat.physical_interfaces if p.id == "usb2-hs-dpair")
|
||||
by = {c.parameter: c for c in hs.constraints}
|
||||
_cite_ok(by["data_rate"])
|
||||
assert by["data_rate"].value == 480.0
|
||||
assert by["data_rate"].unit == "Mb/s"
|
||||
assert by["data_rate"].source.document == "USB 2.0 Electrical Compliance Test Specification"
|
||||
assert "1.08" in by["data_rate"].source.revision
|
||||
assert "EL_2" in (by["data_rate"].source.section or "")
|
||||
assert by["rise_time"].value == 300.0
|
||||
assert by["fall_time"].value == 300.0
|
||||
assert by["pull_up"].value == 1500.0
|
||||
assert by["dc_resistance"].value == 17.0
|
||||
assert by["dc_resistance_captive_cable_device"].value == 23.0
|
||||
assert by["dc_resistance_host_hub_downstream"].value == 13.0
|
||||
for key in (
|
||||
"data_rate", "rise_time", "fall_time", "pull_up", "dc_resistance",
|
||||
"dc_resistance_captive_cable_device", "dc_resistance_host_hub_downstream",
|
||||
):
|
||||
_cite_ok(by[key])
|
||||
assert by[key].source.organization == "USB-IF"
|
||||
z = by["differential_impedance"]
|
||||
assert z.value_kind == "UNKNOWN"
|
||||
assert z.value is None
|
||||
ls = next(p for p in cat.physical_interfaces if p.id == "usb2-ls-dpair")
|
||||
ls_rate = next(c for c in ls.constraints if c.parameter == "data_rate")
|
||||
assert ls_rate.value_kind == "UNKNOWN"
|
||||
blob = json.dumps(z.model_dump())
|
||||
assert "90" not in blob
|
||||
|
||||
|
||||
def test_type_c_rp_rd_unknown_fts_does_not_state_ohms():
|
||||
cat = load_catalog()
|
||||
rec = next(p for p in cat.physical_interfaces if p.id == "usb-c-receptacle")
|
||||
by = {c.parameter: c for c in rec.constraints}
|
||||
for p in ("rp", "rd", "ra", "cc"):
|
||||
assert by[p].value_kind == "UNKNOWN"
|
||||
assert "Cable and Connector" in (by[p].needed_document or "")
|
||||
assert by["voltage"].value_kind == "UNKNOWN"
|
||||
_cite_ok(by["gnd_ir_drop_cable"])
|
||||
assert by["gnd_ir_drop_cable"].value == 250.0
|
||||
assert by["gnd_ir_drop_cable"].source_type == "CABLE"
|
||||
assert by["gnd_ir_drop_cable"].mandatory == "OPTIONAL"
|
||||
_cite_ok(by["vbus_ir_drop_cable"])
|
||||
assert by["vbus_ir_drop_cable"].value == 500.0
|
||||
assert "Functional Test" in by["vbus_ir_drop_cable"].source.document
|
||||
|
||||
|
||||
def test_dvi_not_hdmi_numeric_from_dvi_10():
|
||||
cat = load_catalog()
|
||||
logical = {p.id for p in cat.logical_protocols}
|
||||
assert "dvi" in logical
|
||||
assert "mini-hdmi" not in logical
|
||||
dvi = next(p for p in cat.physical_interfaces if p.id == "dvi-1.0-tmds")
|
||||
assert dvi.logical_protocol_id == "dvi"
|
||||
assert dvi.connector == "DVI"
|
||||
by = {c.parameter: c for c in dvi.constraints}
|
||||
_cite_ok(by["termination"])
|
||||
assert by["termination"].value == 50.0
|
||||
assert by["termination"].source.table == "Table 4-2"
|
||||
_cite_ok(by["differential_impedance"])
|
||||
assert by["differential_impedance"].value == 100.0
|
||||
assert by["differential_impedance"].source.table == "Table 4-7"
|
||||
assert by["differential_impedance"].source.organization == "DDWG"
|
||||
hdmi = next(p for p in cat.physical_interfaces if p.id == "hdmi-1.4-tmds-type-a")
|
||||
hz = next(c for c in hdmi.constraints if c.parameter == "differential_impedance")
|
||||
assert hz.value_kind == "UNKNOWN"
|
||||
g = DesignGraph(
|
||||
components={
|
||||
"J3": Component(
|
||||
reference="J3", value="DVI-D receptacle",
|
||||
footprint="DVI_D",
|
||||
component_type=ComponentType.CONNECTOR,
|
||||
pins={"1": "TX0+"},
|
||||
),
|
||||
},
|
||||
nets={"TX0+": Net(
|
||||
name="TX0+", net_type=NetType.SIGNAL,
|
||||
pins=[PinConnection(component_ref="J3", pin_number="1")],
|
||||
)},
|
||||
)
|
||||
insts = recognize_physical_buses(g)
|
||||
logs = {i.logical_protocol_id for i in insts}
|
||||
assert "dvi" in logs
|
||||
assert "hdmi-1.4" not in logs
|
||||
assert "hdmi-2.0" not in logs
|
||||
|
||||
|
||||
def test_ieee8023_section2_100base_tx_not_10base_or_1000():
|
||||
cat = load_catalog()
|
||||
tx = next(p for p in cat.physical_interfaces if p.id == "100base-tx-mdi")
|
||||
by = {c.parameter: c for c in tx.constraints}
|
||||
_cite_ok(by["data_rate"])
|
||||
assert by["data_rate"].value == 100.0
|
||||
assert by["data_rate"].source.document.startswith("IEEE Std 802.3-2012")
|
||||
assert by["data_rate"].source.revision == "2012"
|
||||
assert by["data_rate"].source.section == "21.1"
|
||||
_cite_ok(by["cable_channel"])
|
||||
assert by["cable_channel"].value == 100.0
|
||||
assert by["cable_channel"].source_type == "CABLE"
|
||||
assert by["cable_channel"].source.section == "25.4.9.2.2"
|
||||
z = by["differential_impedance"]
|
||||
assert z.value_kind == "UNKNOWN"
|
||||
assert "TP-PMD" in (z.needed_document or "")
|
||||
ten = next(p for p in cat.physical_interfaces if p.id == "10base-t-mdi")
|
||||
tdr = next(c for c in ten.constraints if c.parameter == "data_rate")
|
||||
assert tdr.value_kind == "UNKNOWN"
|
||||
assert "Clause 14" in (tdr.needed_document or "")
|
||||
gbe = next(p for p in cat.physical_interfaces if p.id == "1000base-t-mdi")
|
||||
gdr = next(c for c in gbe.constraints if c.parameter == "data_rate")
|
||||
assert gdr.value_kind == "UNKNOWN"
|
||||
assert "Clause 40" in (gdr.needed_document or "")
|
||||
fx = next(p for p in cat.physical_interfaces if p.id == "100base-fx-pcb")
|
||||
fxr = next(c for c in fx.constraints if c.parameter == "data_rate")
|
||||
_cite_ok(fxr)
|
||||
assert fxr.value == 100.0
|
||||
assert fxr.source.section == "26.1"
|
||||
Reference in New Issue
Block a user