From 36ad9796125a9580f8d77725ea146c8dbf7d6482 Mon Sep 17 00:00:00 2001 From: Michele Bigi Date: Tue, 22 Sep 2026 11:57:26 +0200 Subject: [PATCH] Add protocol-certification M0 catalog, loader, and empty report (2.64.0). Versioned JSON skeletons without invented ohms/mm/ps. RECOMMENDED is not FAIL-mandatory; typical-as-standard is rejected. Report Protocolli is empty until recognition (M1+). Native src overlays inherited periscopex on the package path. --- backend/__init__.py | 28 +- periscope/dependency/backend/__init__.py | 12 +- .../dependency/backend/periscopex/__init__.py | 12 +- .../dependency/backend/periscopex/models.py | 1 + periscope/src/backend/__init__.py | 12 +- periscope/src/backend/periscopex/__init__.py | 12 +- periscope/src/backend/periscopex/models.py | 2 + .../backend/periscopex/protocol_catalog.py | 781 ++++ .../periscopex/protocol_data/catalog.json | 3832 +++++++++++++++++ .../protocol_data/schema-1.0.0.json | 422 ++ .../src/backend/services/pcb_pipeline.py | 2 + periscope/src/backend/services/validation.py | 3 + periscope/src/frontend/content/changelog.md | 9 + periscope/src/frontend/package.json | 2 +- .../app/(app)/project/[id]/report/page.tsx | 2 + .../components/report/protocol-section.tsx | 32 + periscope/src/frontend/src/lib/types.ts | 9 + periscope/src/frontend/src/lib/version.ts | 2 +- tests/conftest.py | 7 +- tests/pcb/test_protocol_catalog_m0.py | 231 + 20 files changed, 5401 insertions(+), 12 deletions(-) create mode 100644 periscope/src/backend/periscopex/protocol_catalog.py create mode 100644 periscope/src/backend/periscopex/protocol_data/catalog.json create mode 100644 periscope/src/backend/periscopex/protocol_data/schema-1.0.0.json create mode 100644 periscope/src/frontend/src/components/report/protocol-section.tsx create mode 100644 tests/pcb/test_protocol_catalog_m0.py diff --git a/backend/__init__.py b/backend/__init__.py index 18c8f1d..2335a3a 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -10,9 +10,29 @@ from pathlib import Path from pkgutil import extend_path _REPO = Path(__file__).resolve().parents[1] -for _p in (_REPO / "periscope" / "src", _REPO / "periscope" / "dependency"): +_SRC = _REPO / "periscope" / "src" +_DEP = _REPO / "periscope" / "dependency" +# Last insert is searched first: native src overlays inherited dependency. +for _p in (_DEP, _SRC): _s = str(_p) - if _p.is_dir() and _s not in sys.path: - sys.path.insert(0, _s) + if not _p.is_dir(): + continue + if _s in sys.path: + sys.path.remove(_s) + sys.path.insert(0, _s) -__path__ = list(extend_path(__path__, __name__)) + +def _prefer_native_backend(paths: list[str]) -> list[str]: + src, other, dep = [], [], [] + for p in paths: + norm = p.replace("\\", "/") + if "/periscope/src/" in norm: + src.append(p) + elif "/periscope/dependency/" in norm: + dep.append(p) + else: + other.append(p) + return src + other + dep + + +__path__ = _prefer_native_backend(list(extend_path(__path__, __name__))) diff --git a/periscope/dependency/backend/__init__.py b/periscope/dependency/backend/__init__.py index 0b54cc6..4d1da87 100644 --- a/periscope/dependency/backend/__init__.py +++ b/periscope/dependency/backend/__init__.py @@ -1,4 +1,14 @@ """PinScope-inherited backend package (in-tree dependency).""" from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = list(extend_path(__path__, __name__)) +_src, _other, _dep = [], [], [] +for _p in __path__: + _n = str(_p).replace("\\", "/") + if "/periscope/src/" in _n: + _src.append(_p) + elif "/periscope/dependency/" in _n: + _dep.append(_p) + else: + _other.append(_p) +__path__[:] = _src + _other + _dep diff --git a/periscope/dependency/backend/periscopex/__init__.py b/periscope/dependency/backend/periscopex/__init__.py index b36383a..bc6b849 100644 --- a/periscope/dependency/backend/periscopex/__init__.py +++ b/periscope/dependency/backend/periscopex/__init__.py @@ -1,3 +1,13 @@ from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = list(extend_path(__path__, __name__)) +_src, _other, _dep = [], [], [] +for _p in __path__: + _n = str(_p).replace("\\", "/") + if "/periscope/src/" in _n: + _src.append(_p) + elif "/periscope/dependency/" in _n: + _dep.append(_p) + else: + _other.append(_p) +__path__[:] = _src + _other + _dep diff --git a/periscope/dependency/backend/periscopex/models.py b/periscope/dependency/backend/periscopex/models.py index 8abb147..9b8af01 100644 --- a/periscope/dependency/backend/periscopex/models.py +++ b/periscope/dependency/backend/periscopex/models.py @@ -380,6 +380,7 @@ class ValidationReport(BaseModel): coverage: dict[str, list[str]] = {} # designator -> areas checked and found OK review_errors: dict[str, str] = {} # designator -> error message for ICs whose review raised not_reviewed: list[dict] = [] # [{"designator","reason"}] — ICs skipped (e.g. no datasheet PDF) + protocol_certification: dict[str, Any] | None = None class FindingComment(BaseModel): diff --git a/periscope/src/backend/__init__.py b/periscope/src/backend/__init__.py index ee69a73..d07eafd 100644 --- a/periscope/src/backend/__init__.py +++ b/periscope/src/backend/__init__.py @@ -1,4 +1,14 @@ """Native Periscope backend modules.""" from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = list(extend_path(__path__, __name__)) +_src, _other, _dep = [], [], [] +for _p in __path__: + _n = str(_p).replace("\\", "/") + if "/periscope/src/" in _n: + _src.append(_p) + elif "/periscope/dependency/" in _n: + _dep.append(_p) + else: + _other.append(_p) +__path__[:] = _src + _other + _dep diff --git a/periscope/src/backend/periscopex/__init__.py b/periscope/src/backend/periscopex/__init__.py index c503d2f..c90032a 100644 --- a/periscope/src/backend/periscopex/__init__.py +++ b/periscope/src/backend/periscopex/__init__.py @@ -1,4 +1,14 @@ """Native Periscope core modules (finding engine, PCB, checks).""" from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = list(extend_path(__path__, __name__)) +_src, _other, _dep = [], [], [] +for _p in __path__: + _n = _p.replace("\\", "/") + if "/periscope/src/" in _n: + _src.append(_p) + elif "/periscope/dependency/" in _n: + _dep.append(_p) + else: + _other.append(_p) +__path__[:] = _src + _other + _dep diff --git a/periscope/src/backend/periscopex/models.py b/periscope/src/backend/periscopex/models.py index 47eb6d1..66f8897 100644 --- a/periscope/src/backend/periscopex/models.py +++ b/periscope/src/backend/periscopex/models.py @@ -385,6 +385,8 @@ class ValidationReport(BaseModel): coverage: dict[str, list[str]] = {} # designator -> areas checked and found OK review_errors: dict[str, str] = {} # designator -> error message for ICs whose review raised not_reviewed: list[dict] = [] # [{"designator","reason"}] — ICs skipped (e.g. no datasheet PDF) + # M0 protocol cert: empty instances / "nessun protocollo riconosciuto". No Z. + protocol_certification: dict[str, Any] | None = None class FindingComment(BaseModel): diff --git a/periscope/src/backend/periscopex/protocol_catalog.py b/periscope/src/backend/periscopex/protocol_catalog.py new file mode 100644 index 0000000..627c62c --- /dev/null +++ b/periscope/src/backend/periscopex/protocol_catalog.py @@ -0,0 +1,781 @@ +"""M0 protocol catalog: versioned JSON pack, loader, validator. + +No invented ohms/mm/ps. Constraints without an official cite stay +UNKNOWN / CONTROLLER_DEPENDENT / PHY_DEPENDENT / MISSING_SOURCE / +VENDOR_DEPENDENT / NOT_APPLICABLE. logical_protocol_id is never the +same string as physical_interface_id. pcb_relevant is YES|NO|CONDITIONAL. +RECOMMENDED is not FAIL-mandatory. Typical-as-standard is rejected. + +Recognition and L0–L3 certifiers are M1+ — this module only loads packs +and builds the empty report section. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any, Literal + +from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator + +SCHEMA_VERSION = "1.0.0" +PACK_MACROPHASE = "M0" + +CATALOG_DIR = Path(__file__).resolve().parent / "protocol_data" +CATALOG_PATH = CATALOG_DIR / "catalog.json" +SCHEMA_PATH = CATALOG_DIR / f"schema-{SCHEMA_VERSION}.json" + +EMPTY_PROTOCOL_MESSAGE = "nessun protocollo riconosciuto" + +BusType = Literal[ + "MEMORY", + "PROCESSOR_INTERCONNECT", + "PERIPHERAL", + "CHIP_TO_CHIP", + "STORAGE", + "GRAPHICS", + "SERIAL", + "PARALLEL", +] +PhysicalLayer = Literal[ + "INTERNAL", + "PARALLEL_SINGLE_ENDED", + "PARALLEL_DIFFERENTIAL", + "SERIAL_SINGLE_ENDED", + "SERIAL_DIFFERENTIAL", + "MIXED", +] +PcbRelevant = Literal["YES", "NO", "CONDITIONAL"] +ValueKind = Literal[ + "NUMERIC", + "UNKNOWN", + "CONTROLLER_DEPENDENT", + "PHY_DEPENDENT", + "VENDOR_DEPENDENT", + "NOT_APPLICABLE", + "MISSING_SOURCE", +] +MandatoryClass = Literal["MANDATORY", "RECOMMENDED", "OPTIONAL", "INFORMATIONAL"] +SourceType = Literal[ + "STANDARD", + "CONNECTOR", + "PHY", + "CONTROLLER", + "MEMORY", + "COMPONENT", + "CABLE", + "PCB", + "DERIVED", +] +SourceClass = Literal["NORMATIVE", "VENDOR", "IMPLEMENTATION", "DERIVED"] +ValueOrigin = Literal["SPEC", "TYPICAL", "EXAMPLE", "DERIVED"] +MeasurementMethod = Literal[ + "DATASHEET", + "TDR", + "FIELD_SOLVER", + "PCB_STACKUP", + "FABRICATOR", + "SIMULATION", + "CALCULATION", + "EXTRACTION", + "MEASUREMENT", +] +LimitKind = Literal["STANDARD", "DESIGN"] +ProtocolResult = Literal[ + "PASS", + "FAIL", + "WARNING", + "UNKNOWN", + "NOT_APPLICABLE", + "VENDOR_DEPENDENT", + "MISSING_SOURCE", +] + + +class ProtocolCatalogError(ValueError): + """Invalid protocol pack (typical-as-standard, missing source, …).""" + + +class ConstraintSource(BaseModel): + document: str | None = None + organization: str | None = None + revision: str | None = None + section: str | None = None + table: str | None = None + page: str | None = None + url: str | None = None + + +class ProtocolConstraint(BaseModel): + model_config = ConfigDict(extra="forbid") + + id: str + parameter: str + value_kind: ValueKind + mandatory: MandatoryClass + source_type: SourceType + source_class: SourceClass + value: float | None = None + unit: str | None = None + source: ConstraintSource | None = None + conditions: list[str] = Field(default_factory=list) + measurement_method: MeasurementMethod | None = None + limit_kind: LimitKind | None = None + value_origin: ValueOrigin = "SPEC" + typical: bool = False + + @field_validator("source_type") + @classmethod + def _source_type_required(cls, v: str) -> str: + if not v: + raise ProtocolCatalogError("constraint without source_type") + return v + + @model_validator(mode="after") + def _reject_typical_and_bare_numeric(self) -> ProtocolConstraint: + if self.typical or self.value_origin in {"TYPICAL", "EXAMPLE"}: + if self.source_type == "STANDARD" or self.source_class == "NORMATIVE": + raise ProtocolCatalogError( + f"{self.id}: typical/example cannot be STANDARD/NORMATIVE" + ) + if self.mandatory == "MANDATORY": + raise ProtocolCatalogError( + f"{self.id}: typical/example cannot be MANDATORY" + ) + if self.value_kind == "NUMERIC": + if self.value is None: + raise ProtocolCatalogError(f"{self.id}: NUMERIC needs a value") + if self.source is None or not ( + self.source.document or self.source.organization + ): + raise ProtocolCatalogError( + f"{self.id}: NUMERIC constraint needs an official cite" + ) + elif self.value is not None: + raise ProtocolCatalogError( + f"{self.id}: non-NUMERIC value_kind cannot carry a number" + ) + return self + + def is_fail_mandatory(self) -> bool: + """FAIL is allowed only for MANDATORY. RECOMMENDED never FAIL-mandatory.""" + return self.mandatory == "MANDATORY" + + +class LogicalProtocol(BaseModel): + model_config = ConfigDict(extra="forbid") + + id: str + name: str + bus_type: BusType + family: str = "" + notes: str = "" + + +class PhysicalInterface(BaseModel): + model_config = ConfigDict(extra="forbid") + + id: str + logical_protocol_id: str + bus_type: BusType + physical_layer: PhysicalLayer + pcb_relevant: PcbRelevant + connector: str = "none" + recognition_hints: list[str] = Field(default_factory=list) + required_checks: list[str] = Field(default_factory=list) + constraints: list[ProtocolConstraint] = Field(default_factory=list) + notes: str = "" + + @model_validator(mode="after") + def _logical_differs_from_physical(self) -> PhysicalInterface: + if self.id == self.logical_protocol_id: + raise ProtocolCatalogError( + f"{self.id}: logical_protocol_id must differ from physical_interface_id" + ) + return self + + +class ProtocolCatalog(BaseModel): + model_config = ConfigDict(extra="forbid") + + schema_version: str + logical_protocols: list[LogicalProtocol] + physical_interfaces: list[PhysicalInterface] + + @model_validator(mode="after") + def _index_integrity(self) -> ProtocolCatalog: + if self.schema_version != SCHEMA_VERSION: + raise ProtocolCatalogError( + f"schema_version {self.schema_version!r} != {SCHEMA_VERSION}" + ) + logical_ids = [p.id for p in self.logical_protocols] + if len(logical_ids) != len(set(logical_ids)): + raise ProtocolCatalogError("duplicate logical_protocol id") + physical_ids = [p.id for p in self.physical_interfaces] + if len(physical_ids) != len(set(physical_ids)): + raise ProtocolCatalogError("duplicate physical_interface id") + logical_set = set(logical_ids) + overlap = logical_set & set(physical_ids) + if overlap: + raise ProtocolCatalogError( + f"id used as both logical and physical: {sorted(overlap)}" + ) + for iface in self.physical_interfaces: + if iface.logical_protocol_id not in logical_set: + raise ProtocolCatalogError( + f"{iface.id}: unknown logical_protocol_id " + f"{iface.logical_protocol_id}" + ) + return self + + +class ProtocolCertificationSection(BaseModel): + """Report hook. M0: no instances, no Z numbers.""" + + schema_version: str = SCHEMA_VERSION + macrophase: str = PACK_MACROPHASE + recognized_instances: list[dict[str, Any]] = Field(default_factory=list) + message: str = EMPTY_PROTOCOL_MESSAGE + max_level_reached: str | None = None + + +def empty_protocol_section() -> ProtocolCertificationSection: + return ProtocolCertificationSection() + + +def fail_mandatory(constraint: ProtocolConstraint) -> bool: + return constraint.is_fail_mandatory() + + +def map_protocol_outcome( + result: ProtocolResult, + mandatory: MandatoryClass, +) -> tuple[str, str, str]: + """(finding_class, status, evidence_status) — RECOMMENDED never ERROR FAIL.""" + if result == "PASS": + return "RULE", "INFO", "SUFFICIENT" + if result == "NOT_APPLICABLE": + return "INFO", "INFO", "SUFFICIENT" + if result in {"UNKNOWN", "MISSING_SOURCE"}: + return "REVIEW", "WARNING", "INSUFFICIENT" + if result == "VENDOR_DEPENDENT": + return "REVIEW", "WARNING", "INSUFFICIENT" + if result == "FAIL": + if mandatory != "MANDATORY": + return "RISK", "WARNING", "SUFFICIENT" + return "RULE", "ERROR", "SUFFICIENT" + if result == "WARNING": + return "RISK", "WARNING", "SUFFICIENT" + return "REVIEW", "WARNING", "INSUFFICIENT" + + +def catalog_json_schema() -> dict[str, Any]: + return ProtocolCatalog.model_json_schema() + + +def load_catalog(path: Path | None = None) -> ProtocolCatalog: + target = path or CATALOG_PATH + raw = json.loads(target.read_text(encoding="utf-8")) + return parse_catalog(raw) + + +def parse_catalog(raw: Any) -> ProtocolCatalog: + if not isinstance(raw, dict): + raise ProtocolCatalogError("catalog must be a JSON object") + try: + return ProtocolCatalog.model_validate(raw) + except ProtocolCatalogError: + raise + except Exception as exc: + raise ProtocolCatalogError(str(exc)) from exc + + +def _c( + iface_id: str, + parameter: str, + value_kind: ValueKind, + *, + mandatory: MandatoryClass = "MANDATORY", + source_type: SourceType = "STANDARD", + source_class: SourceClass = "NORMATIVE", + conditions: list[str] | None = None, + measurement_method: MeasurementMethod | None = None, +) -> dict[str, Any]: + row: dict[str, Any] = { + "id": f"{iface_id}-{parameter}", + "parameter": parameter, + "value_kind": value_kind, + "mandatory": mandatory, + "source_type": source_type, + "source_class": source_class, + "value": None, + "unit": None, + "source": None, + "conditions": conditions or [], + "value_origin": "SPEC", + "typical": False, + } + if measurement_method: + row["measurement_method"] = measurement_method + return row + + +def _iface( + pid: str, + logical: str, + bus_type: BusType, + layer: PhysicalLayer, + pcb: PcbRelevant, + checks: list[str], + constraints: list[dict[str, Any]], + *, + connector: str = "none", + hints: list[str] | None = None, + notes: str = "", +) -> dict[str, Any]: + return { + "id": pid, + "logical_protocol_id": logical, + "bus_type": bus_type, + "physical_layer": layer, + "pcb_relevant": pcb, + "connector": connector, + "recognition_hints": hints or [], + "required_checks": checks, + "constraints": constraints, + "notes": notes, + } + + +USB2_CHECKS = [ + "differential_impedance", + "intra_pair_skew", + "topology", + "length", + "vias", + "return_path", +] +ETH_CHECKS = [ + "differential_impedance", + "pair_skew", + "length", + "magnetics", + "return_path", + "phy_requirements", +] +HDMI_CHECKS = [ + "differential_impedance", + "pair_skew", + "lane_relationships", + "insertion_loss", + "return_loss", + "vias", + "connector", +] +DDR_CHECKS = [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path", +] +QSPI_CHECKS = ["clock_length", "data_length", "stubs", "vias", "return_path"] +OCTAL_CHECKS = [ + "dq_group", + "dqs_relationship_if_present", + "clock_to_data_skew", + "topology", + "impedance_if_required", + "length", + "vias", + "stubs", +] +EMMC_CHECKS = ["cmd_dat_grouping", "clk_reference", "impedance", "skew", "length"] +UFS_CHECKS = [ + "differential_impedance", + "intra_pair_skew", + "insertion_loss", + "return_loss", + "via_transition", + "ac_coupling", +] +PCIE_CHECKS = [ + "differential_impedance", + "intra_pair_skew", + "lane_to_lane_skew", + "insertion_loss", + "return_loss", + "vias", + "connectors", + "return_path", +] +HYPERBUS_CHECKS = [ + "dq_to_rwds_skew", + "ck_to_dq_relationship", + "impedance", + "topology", + "length", + "vias", + "stubs", +] + + +def build_m0_catalog() -> dict[str, Any]: + """Skeleton catalog. No numeric USB/ETH/HDMI/DDR values.""" + logical: list[dict[str, Any]] = [] + physical: list[dict[str, Any]] = [] + + def L(pid: str, name: str, bus: BusType, family: str, notes: str = "") -> None: + logical.append({ + "id": pid, "name": name, "bus_type": bus, "family": family, "notes": notes, + }) + + L("usb2-ls-fs", "USB 2.0 Low/Full Speed", "SERIAL", "USB") + L("usb2-hs", "USB 2.0 High Speed", "SERIAL", "USB") + L("usb-c-usb2", "USB Type-C carrying USB 2.x only", "SERIAL", "USB") + L("usb-c-pd", "USB Power Delivery on CC", "SERIAL", "USB") + L("100base-tx", "100BASE-TX Fast Ethernet", "SERIAL", "ETHERNET") + L("hdmi-1.4", "HDMI 1.4 TMDS", "SERIAL", "HDMI") + L("hdmi-2.0", "HDMI 2.0 TMDS", "SERIAL", "HDMI") + L("ddr-family", "DDR family (abstract)", "MEMORY", "DDR") + for gen, title in ( + ("ddr1", "DDR1"), ("ddr2", "DDR2"), ("ddr3", "DDR3"), + ("ddr3l", "DDR3L"), ("ddr4", "DDR4"), ("ddr5", "DDR5"), + ): + L(gen, title, "MEMORY", "DDR") + L("lpddr-family", "LPDDR family (abstract)", "MEMORY", "LPDDR") + for gen, title in ( + ("lpddr2", "LPDDR2"), ("lpddr3", "LPDDR3"), ("lpddr4", "LPDDR4"), + ("lpddr4x", "LPDDR4X"), ("lpddr5", "LPDDR5"), ("lpddr5x", "LPDDR5X"), + ): + L(gen, title, "MEMORY", "LPDDR") + L("hbm-family", "HBM family (abstract)", "MEMORY", "HBM") + for gen, title in ( + ("hbm", "HBM"), ("hbm2", "HBM2"), ("hbm2e", "HBM2E"), + ("hbm3", "HBM3"), ("hbm3e", "HBM3E"), + ): + L(gen, title, "MEMORY", "HBM") + L("hyperbus", "HyperBus", "MEMORY", "HYPERBUS") + L("hyperram", "HyperRAM", "MEMORY", "HYPERBUS") + L("spi-nor", "SPI NOR", "MEMORY", "SPI") + L("qspi", "Quad SPI", "MEMORY", "SPI") + L("octal-spi", "Octal SPI", "MEMORY", "SPI") + L("opi", "OPI", "MEMORY", "SPI") + L("xspi", "xSPI", "MEMORY", "SPI") + L("emmc", "eMMC", "STORAGE", "STORAGE") + L("ufs", "UFS", "STORAGE", "STORAGE") + L("amba", "AMBA (umbrella)", "PROCESSOR_INTERCONNECT", "AMBA") + for pid, name in ( + ("axi4", "AXI4"), ("axi4-lite", "AXI4-Lite"), ("axi4-stream", "AXI4-Stream"), + ("ahb", "AHB"), ("ahb-lite", "AHB-Lite"), ("apb", "APB"), + ("ace", "ACE"), ("ace-lite", "ACE-Lite"), ("amba-chi", "AMBA CHI"), + ): + L(pid, name, "PROCESSOR_INTERCONNECT", "AMBA") + L("wishbone", "Wishbone", "PROCESSOR_INTERCONNECT", "OPEN_BUS") + L("avalon-mm", "Avalon-MM", "PROCESSOR_INTERCONNECT", "INTEL_FPGA") + L("avalon-st", "Avalon-ST", "PROCESSOR_INTERCONNECT", "INTEL_FPGA") + L("tilelink", "TileLink", "PROCESSOR_INTERCONNECT", "RISC-V") + L("pcie", "PCI Express (logical)", "CHIP_TO_CHIP", "PCIE") + L("cxl", "CXL (logical)", "CHIP_TO_CHIP", "CXL") + + missing_usb = [ + _c("usb2-hs-dpair", "differential_impedance", "MISSING_SOURCE", + measurement_method="PCB_STACKUP"), + _c("usb2-hs-dpair", "intra_pair_skew", "MISSING_SOURCE", + measurement_method="CALCULATION"), + _c("usb2-hs-dpair", "topology", "UNKNOWN"), + _c("usb2-hs-dpair", "length", "UNKNOWN"), + _c("usb2-hs-dpair", "vias", "UNKNOWN"), + _c("usb2-hs-dpair", "return_path", "UNKNOWN", mandatory="RECOMMENDED", + source_class="VENDOR"), + ] + physical.append(_iface( + "usb2-ls-fs-dpair", "usb2-ls-fs", "SERIAL", "SERIAL_DIFFERENTIAL", "YES", + USB2_CHECKS, + [ + _c("usb2-ls-fs-dpair", "differential_impedance", "MISSING_SOURCE", + measurement_method="PCB_STACKUP"), + _c("usb2-ls-fs-dpair", "intra_pair_skew", "MISSING_SOURCE"), + _c("usb2-ls-fs-dpair", "topology", "UNKNOWN"), + ], + hints=["USB_D+", "USB_D-", "USB_DP", "USB_DM", "D+", "D-"], + notes="LS/FS pair. No invented Z.", + )) + physical.append(_iface( + "usb2-hs-dpair", "usb2-hs", "SERIAL", "SERIAL_DIFFERENTIAL", "YES", + USB2_CHECKS, missing_usb, + hints=["USB_D+", "USB_D-", "USB_HS"], + notes="HS pair. Official USB-IF cite required before NUMERIC Z.", + )) + physical.append(_iface( + "usb-c-usb2-receptacle", "usb-c-usb2", "SERIAL", "MIXED", "YES", + USB2_CHECKS + ["cc_rd_rp", "vbus_gnd", "superspeed_absence"], + [ + _c("usb-c-usb2-receptacle", "differential_impedance", "MISSING_SOURCE"), + _c("usb-c-usb2-receptacle", "cc_termination", "MISSING_SOURCE", + source_type="CONNECTOR", source_class="NORMATIVE"), + _c("usb-c-usb2-receptacle", "superspeed_pairs", "NOT_APPLICABLE", + mandatory="INFORMATIONAL", + conditions=["usb2_only"]), + ], + connector="Type-C", + hints=["CC1", "CC2", "USB_C", "TYPE_C", "A5", "B5"], + notes="Type-C carrying USB2. Electrical USB2 + CC. No invented Rd ohms.", + )) + physical.append(_iface( + "usb-c-pd-cc", "usb-c-pd", "SERIAL", "SERIAL_SINGLE_ENDED", "CONDITIONAL", + ["cc_pd_contract"], + [_c("usb-c-pd-cc", "pd_contract", "MISSING_SOURCE", + source_type="STANDARD", conditions=["pd_present"])], + connector="Type-C", + hints=["CC1", "CC2", "USB_PD"], + )) + physical.append(_iface( + "100base-tx-mdi", "100base-tx", "SERIAL", "SERIAL_DIFFERENTIAL", "YES", + ETH_CHECKS, + [ + _c("100base-tx-mdi", "differential_impedance", "MISSING_SOURCE", + source_type="STANDARD"), + _c("100base-tx-mdi", "pair_skew", "MISSING_SOURCE"), + _c("100base-tx-mdi", "magnetics", "PHY_DEPENDENT", + source_type="PHY", source_class="VENDOR"), + _c("100base-tx-mdi", "bob_smith", "UNKNOWN", mandatory="RECOMMENDED", + source_type="PHY", source_class="VENDOR"), + ], + connector="RJ45", + hints=["TD+", "TD-", "RD+", "RD-", "MDI", "RJ45", "100BASE"], + notes="IEEE numbers stay MISSING_SOURCE until the spec is on file.", + )) + for hid, lid, conn, note in ( + ("hdmi-1.4-tmds-type-a", "hdmi-1.4", "HDMI-A", "Type A land"), + ("hdmi-1.4-tmds-type-c-mini", "hdmi-1.4", "HDMI-C-mini", + "Mini Type C land; electrical HDMI 1.4, not a second standard"), + ("hdmi-2.0-tmds-type-a", "hdmi-2.0", "HDMI-A", "Type A land"), + ("hdmi-2.0-tmds-type-c-mini", "hdmi-2.0", "HDMI-C-mini", + "Mini Type C land; electrical HDMI 2.0"), + ): + physical.append(_iface( + hid, lid, "SERIAL", "SERIAL_DIFFERENTIAL", "YES", HDMI_CHECKS, + [ + _c(hid, "differential_impedance", "MISSING_SOURCE"), + _c(hid, "pair_skew", "MISSING_SOURCE"), + _c(hid, "insertion_loss", "MISSING_SOURCE", mandatory="RECOMMENDED"), + ], + connector=conn, hints=["HDMI", "TMDS", "TX0", "TX1", "TX2", "CLK"], + notes=note, + )) + + def _mem_constraints(pid: str, kind: ValueKind, source_type: SourceType) -> list[dict[str, Any]]: + cls: SourceClass = "VENDOR" if source_type != "STANDARD" else "NORMATIVE" + params = [ + "impedance", "max_length", "dq_to_dqs_skew", "byte_to_byte_skew", + "topology", "termination", + ] + return [ + _c(pid, p, kind, source_type=source_type, source_class=cls) + for p in params + ] + + physical.append(_iface( + "ddr-family-sdram-pcb", "ddr-family", "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + DDR_CHECKS, _mem_constraints("ddr-family-sdram-pcb", "CONTROLLER_DEPENDENT", "CONTROLLER"), + hints=["DQ", "DQS", "CK", "A0", "RAS", "CAS", "WE"], + notes="No universal mm/ps for DDR.", + )) + for gen in ("ddr1", "ddr2", "ddr3", "ddr3l", "ddr4", "ddr5"): + kind: ValueKind = ( + "PHY_DEPENDENT" if gen in {"ddr4", "ddr5"} else "CONTROLLER_DEPENDENT" + ) + src: SourceType = "PHY" if kind == "PHY_DEPENDENT" else "CONTROLLER" + physical.append(_iface( + f"{gen}-sdram-pcb", gen, "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + DDR_CHECKS, _mem_constraints(f"{gen}-sdram-pcb", kind, src), + hints=["DQ", "DQS", "CK", gen.upper()], + notes="Controller/PHY dependent. Zero universal skew/length.", + )) + physical.append(_iface( + "lpddr-family-pcb", "lpddr-family", "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + DDR_CHECKS, _mem_constraints("lpddr-family-pcb", "CONTROLLER_DEPENDENT", "CONTROLLER"), + hints=["DQ", "DQS", "CK", "CA", "LPDDR"], + )) + for gen, kind in ( + ("lpddr2", "CONTROLLER_DEPENDENT"), + ("lpddr3", "CONTROLLER_DEPENDENT"), + ("lpddr4", "PHY_DEPENDENT"), + ("lpddr4x", "PHY_DEPENDENT"), + ("lpddr5", "PHY_DEPENDENT"), + ("lpddr5x", "PHY_DEPENDENT"), + ): + src = "PHY" if kind == "PHY_DEPENDENT" else "CONTROLLER" + physical.append(_iface( + f"{gen}-pcb", gen, "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + DDR_CHECKS, _mem_constraints(f"{gen}-pcb", kind, src), # type: ignore[arg-type] + hints=["DQ", "DQS", "CK", "CA", "WCK", gen.upper()], + )) + for gen in ("hbm", "hbm2", "hbm2e", "hbm3", "hbm3e"): + physical.append(_iface( + f"{gen}-package", gen, "MEMORY", "INTERNAL", "NO", + ["package", "silicon"], + [ + _c(f"{gen}-package", "pcb_individual_dq_routing", "NOT_APPLICABLE", + mandatory="INFORMATIONAL", source_type="PCB", source_class="IMPLEMENTATION"), + ], + notes="HBM is package/interposer. Do not apply DDR DQ PCB rules.", + )) + physical.append(_iface( + "hbm-family-package", "hbm-family", "MEMORY", "INTERNAL", "NO", + ["package", "silicon"], + [_c("hbm-family-package", "pcb_individual_dq_routing", "NOT_APPLICABLE", + mandatory="INFORMATIONAL", source_type="PCB", source_class="IMPLEMENTATION")], + )) + physical.append(_iface( + "hyperbus-pcb", "hyperbus", "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + HYPERBUS_CHECKS, + [ + _c("hyperbus-pcb", "dq_to_rwds_skew", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + _c("hyperbus-pcb", "impedance", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + ], + hints=["RWDS", "DQ0", "CK", "HYPERBUS"], + )) + physical.append(_iface( + "hyperram-pcb", "hyperram", "MEMORY", "PARALLEL_SINGLE_ENDED", "YES", + HYPERBUS_CHECKS, + [_c("hyperram-pcb", "impedance", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR")], + hints=["HYPERRAM", "RWDS"], + )) + physical.append(_iface( + "spi-nor-pcb", "spi-nor", "MEMORY", "SERIAL_SINGLE_ENDED", "YES", + ["topology", "length"], + [ + _c("spi-nor-pcb", "topology", "UNKNOWN", mandatory="RECOMMENDED", + source_type="COMPONENT", source_class="VENDOR"), + _c("spi-nor-pcb", "impedance", "NOT_APPLICABLE", mandatory="INFORMATIONAL", + source_type="COMPONENT", source_class="VENDOR"), + _c("spi-nor-pcb", "length", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + ], + hints=["SCLK", "CS", "MOSI", "MISO", "SPI"], + )) + physical.append(_iface( + "qspi-pcb", "qspi", "MEMORY", "SERIAL_SINGLE_ENDED", "YES", QSPI_CHECKS, + [ + _c("qspi-pcb", "clock_length", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + _c("qspi-pcb", "impedance", "UNKNOWN", + source_type="COMPONENT", source_class="VENDOR"), + ], + hints=["QSPI", "IO0", "IO1", "IO2", "IO3", "SCLK"], + )) + for pid, logical_id in ( + ("octal-spi-pcb", "octal-spi"), ("opi-pcb", "opi"), ("xspi-pcb", "xspi"), + ): + physical.append(_iface( + pid, logical_id, "MEMORY", "SERIAL_SINGLE_ENDED", "YES", OCTAL_CHECKS, + [ + _c(pid, "clock_to_data_skew", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + _c(pid, "impedance", "UNKNOWN", + source_type="COMPONENT", source_class="VENDOR"), + ], + hints=["DQ0", "DQS", "OSPI", "XSPI", "OCTAL"], + )) + physical.append(_iface( + "emmc-pcb", "emmc", "STORAGE", "PARALLEL_SINGLE_ENDED", "YES", EMMC_CHECKS, + [ + _c("emmc-pcb", "impedance", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + _c("emmc-pcb", "skew", "UNKNOWN", conditions=["mode=HS200|HS400"]), + ], + hints=["eMMC", "DAT0", "CMD", "MMC_CLK"], + )) + physical.append(_iface( + "ufs-mphy-pcb", "ufs", "STORAGE", "SERIAL_DIFFERENTIAL", "YES", UFS_CHECKS, + [ + _c("ufs-mphy-pcb", "differential_impedance", "MISSING_SOURCE"), + _c("ufs-mphy-pcb", "intra_pair_skew", "MISSING_SOURCE"), + ], + hints=["UFS", "MPHY", "TX+", "RX+"], + )) + + amba = [ + "axi4", "axi4-lite", "axi4-stream", "ahb", "ahb-lite", "apb", + "ace", "ace-lite", "amba-chi", "amba", + ] + for pid in amba: + physical.append(_iface( + f"{pid}-internal", pid, "PROCESSOR_INTERCONNECT", "INTERNAL", "NO", + [], + [_c(f"{pid}-internal", "pcb_routing", "NOT_APPLICABLE", + mandatory="INFORMATIONAL", source_type="PCB", + source_class="IMPLEMENTATION")], + notes="On-chip interconnect. Recognisable; not PCB routing.", + )) + physical.append(_iface( + "axi4-chip-to-chip-phy", "axi4", "CHIP_TO_CHIP", "MIXED", "CONDITIONAL", + ["impedance", "timing", "topology", "voltage"], + [ + _c("axi4-chip-to-chip-phy", "impedance", "PHY_DEPENDENT", + source_type="PHY", source_class="VENDOR"), + _c("axi4-chip-to-chip-phy", "timing", "VENDOR_DEPENDENT", + source_type="COMPONENT", source_class="VENDOR"), + ], + notes="AXI4 name is logical. PCB rules come from the external PHY, not AXI4.", + )) + for pid in ("wishbone", "avalon-mm", "avalon-st", "tilelink"): + physical.append(_iface( + f"{pid}-internal", pid, "PROCESSOR_INTERCONNECT", "INTERNAL", "NO", + [], + [_c(f"{pid}-internal", "pcb_routing", "NOT_APPLICABLE", + mandatory="INFORMATIONAL", source_type="PCB", + source_class="IMPLEMENTATION")], + )) + + physical.append(_iface( + "pcie-phy-pcb", "pcie", "CHIP_TO_CHIP", "SERIAL_DIFFERENTIAL", "YES", + PCIE_CHECKS, + [ + _c("pcie-phy-pcb", "differential_impedance", "MISSING_SOURCE"), + _c("pcie-phy-pcb", "intra_pair_skew", "MISSING_SOURCE"), + _c("pcie-phy-pcb", "insertion_loss", "MISSING_SOURCE"), + ], + hints=["PCIE", "PETX", "PERX", "REFCLK"], + notes="Logical vs physical split. Empty numbers until PCI-SIG cite.", + )) + physical.append(_iface( + "cxl-phy-pcb", "cxl", "CHIP_TO_CHIP", "SERIAL_DIFFERENTIAL", "YES", + PCIE_CHECKS, + [ + _c("cxl-phy-pcb", "differential_impedance", "MISSING_SOURCE"), + _c("cxl-phy-pcb", "intra_pair_skew", "MISSING_SOURCE"), + ], + hints=["CXL"], + notes="Physical electrical pack empty until official cite.", + )) + + return { + "schema_version": SCHEMA_VERSION, + "logical_protocols": logical, + "physical_interfaces": physical, + } + + +def write_catalog_files(directory: Path | None = None) -> tuple[Path, Path]: + directory = directory or CATALOG_DIR + directory.mkdir(parents=True, exist_ok=True) + catalog_path = directory / "catalog.json" + schema_path = directory / f"schema-{SCHEMA_VERSION}.json" + data = build_m0_catalog() + parse_catalog(data) + catalog_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8") + schema_path.write_text( + json.dumps(catalog_json_schema(), indent=2) + "\n", encoding="utf-8", + ) + return catalog_path, schema_path diff --git a/periscope/src/backend/periscopex/protocol_data/catalog.json b/periscope/src/backend/periscopex/protocol_data/catalog.json new file mode 100644 index 0000000..5dacb4b --- /dev/null +++ b/periscope/src/backend/periscopex/protocol_data/catalog.json @@ -0,0 +1,3832 @@ +{ + "schema_version": "1.0.0", + "logical_protocols": [ + { + "id": "usb2-ls-fs", + "name": "USB 2.0 Low/Full Speed", + "bus_type": "SERIAL", + "family": "USB", + "notes": "" + }, + { + "id": "usb2-hs", + "name": "USB 2.0 High Speed", + "bus_type": "SERIAL", + "family": "USB", + "notes": "" + }, + { + "id": "usb-c-usb2", + "name": "USB Type-C carrying USB 2.x only", + "bus_type": "SERIAL", + "family": "USB", + "notes": "" + }, + { + "id": "usb-c-pd", + "name": "USB Power Delivery on CC", + "bus_type": "SERIAL", + "family": "USB", + "notes": "" + }, + { + "id": "100base-tx", + "name": "100BASE-TX Fast Ethernet", + "bus_type": "SERIAL", + "family": "ETHERNET", + "notes": "" + }, + { + "id": "hdmi-1.4", + "name": "HDMI 1.4 TMDS", + "bus_type": "SERIAL", + "family": "HDMI", + "notes": "" + }, + { + "id": "hdmi-2.0", + "name": "HDMI 2.0 TMDS", + "bus_type": "SERIAL", + "family": "HDMI", + "notes": "" + }, + { + "id": "ddr-family", + "name": "DDR family (abstract)", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr1", + "name": "DDR1", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr2", + "name": "DDR2", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr3", + "name": "DDR3", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr3l", + "name": "DDR3L", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr4", + "name": "DDR4", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "ddr5", + "name": "DDR5", + "bus_type": "MEMORY", + "family": "DDR", + "notes": "" + }, + { + "id": "lpddr-family", + "name": "LPDDR family (abstract)", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr2", + "name": "LPDDR2", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr3", + "name": "LPDDR3", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr4", + "name": "LPDDR4", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr4x", + "name": "LPDDR4X", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr5", + "name": "LPDDR5", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "lpddr5x", + "name": "LPDDR5X", + "bus_type": "MEMORY", + "family": "LPDDR", + "notes": "" + }, + { + "id": "hbm-family", + "name": "HBM family (abstract)", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hbm", + "name": "HBM", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hbm2", + "name": "HBM2", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hbm2e", + "name": "HBM2E", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hbm3", + "name": "HBM3", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hbm3e", + "name": "HBM3E", + "bus_type": "MEMORY", + "family": "HBM", + "notes": "" + }, + { + "id": "hyperbus", + "name": "HyperBus", + "bus_type": "MEMORY", + "family": "HYPERBUS", + "notes": "" + }, + { + "id": "hyperram", + "name": "HyperRAM", + "bus_type": "MEMORY", + "family": "HYPERBUS", + "notes": "" + }, + { + "id": "spi-nor", + "name": "SPI NOR", + "bus_type": "MEMORY", + "family": "SPI", + "notes": "" + }, + { + "id": "qspi", + "name": "Quad SPI", + "bus_type": "MEMORY", + "family": "SPI", + "notes": "" + }, + { + "id": "octal-spi", + "name": "Octal SPI", + "bus_type": "MEMORY", + "family": "SPI", + "notes": "" + }, + { + "id": "opi", + "name": "OPI", + "bus_type": "MEMORY", + "family": "SPI", + "notes": "" + }, + { + "id": "xspi", + "name": "xSPI", + "bus_type": "MEMORY", + "family": "SPI", + "notes": "" + }, + { + "id": "emmc", + "name": "eMMC", + "bus_type": "STORAGE", + "family": "STORAGE", + "notes": "" + }, + { + "id": "ufs", + "name": "UFS", + "bus_type": "STORAGE", + "family": "STORAGE", + "notes": "" + }, + { + "id": "amba", + "name": "AMBA (umbrella)", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "axi4", + "name": "AXI4", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "axi4-lite", + "name": "AXI4-Lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "axi4-stream", + "name": "AXI4-Stream", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "ahb", + "name": "AHB", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "ahb-lite", + "name": "AHB-Lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "apb", + "name": "APB", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "ace", + "name": "ACE", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "ace-lite", + "name": "ACE-Lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "amba-chi", + "name": "AMBA CHI", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "AMBA", + "notes": "" + }, + { + "id": "wishbone", + "name": "Wishbone", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "OPEN_BUS", + "notes": "" + }, + { + "id": "avalon-mm", + "name": "Avalon-MM", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "INTEL_FPGA", + "notes": "" + }, + { + "id": "avalon-st", + "name": "Avalon-ST", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "INTEL_FPGA", + "notes": "" + }, + { + "id": "tilelink", + "name": "TileLink", + "bus_type": "PROCESSOR_INTERCONNECT", + "family": "RISC-V", + "notes": "" + }, + { + "id": "pcie", + "name": "PCI Express (logical)", + "bus_type": "CHIP_TO_CHIP", + "family": "PCIE", + "notes": "" + }, + { + "id": "cxl", + "name": "CXL (logical)", + "bus_type": "CHIP_TO_CHIP", + "family": "CXL", + "notes": "" + } + ], + "physical_interfaces": [ + { + "id": "usb2-ls-fs-dpair", + "logical_protocol_id": "usb2-ls-fs", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "USB_D+", + "USB_D-", + "USB_DP", + "USB_DM", + "D+", + "D-" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "topology", + "length", + "vias", + "return_path" + ], + "constraints": [ + { + "id": "usb2-ls-fs-dpair-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false, + "measurement_method": "PCB_STACKUP" + }, + { + "id": "usb2-ls-fs-dpair-intra_pair_skew", + "parameter": "intra_pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb2-ls-fs-dpair-topology", + "parameter": "topology", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "LS/FS pair. No invented Z." + }, + { + "id": "usb2-hs-dpair", + "logical_protocol_id": "usb2-hs", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "USB_D+", + "USB_D-", + "USB_HS" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "topology", + "length", + "vias", + "return_path" + ], + "constraints": [ + { + "id": "usb2-hs-dpair-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false, + "measurement_method": "PCB_STACKUP" + }, + { + "id": "usb2-hs-dpair-intra_pair_skew", + "parameter": "intra_pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false, + "measurement_method": "CALCULATION" + }, + { + "id": "usb2-hs-dpair-topology", + "parameter": "topology", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb2-hs-dpair-length", + "parameter": "length", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb2-hs-dpair-vias", + "parameter": "vias", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb2-hs-dpair-return_path", + "parameter": "return_path", + "value_kind": "UNKNOWN", + "mandatory": "RECOMMENDED", + "source_type": "STANDARD", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HS pair. Official USB-IF cite required before NUMERIC Z." + }, + { + "id": "usb-c-usb2-receptacle", + "logical_protocol_id": "usb-c-usb2", + "bus_type": "SERIAL", + "physical_layer": "MIXED", + "pcb_relevant": "YES", + "connector": "Type-C", + "recognition_hints": [ + "CC1", + "CC2", + "USB_C", + "TYPE_C", + "A5", + "B5" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "topology", + "length", + "vias", + "return_path", + "cc_rd_rp", + "vbus_gnd", + "superspeed_absence" + ], + "constraints": [ + { + "id": "usb-c-usb2-receptacle-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb-c-usb2-receptacle-cc_termination", + "parameter": "cc_termination", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "CONNECTOR", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "usb-c-usb2-receptacle-superspeed_pairs", + "parameter": "superspeed_pairs", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [ + "usb2_only" + ], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Type-C carrying USB2. Electrical USB2 + CC. No invented Rd ohms." + }, + { + "id": "usb-c-pd-cc", + "logical_protocol_id": "usb-c-pd", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "CONDITIONAL", + "connector": "Type-C", + "recognition_hints": [ + "CC1", + "CC2", + "USB_PD" + ], + "required_checks": [ + "cc_pd_contract" + ], + "constraints": [ + { + "id": "usb-c-pd-cc-pd_contract", + "parameter": "pd_contract", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [ + "pd_present" + ], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "100base-tx-mdi", + "logical_protocol_id": "100base-tx", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "RJ45", + "recognition_hints": [ + "TD+", + "TD-", + "RD+", + "RD-", + "MDI", + "RJ45", + "100BASE" + ], + "required_checks": [ + "differential_impedance", + "pair_skew", + "length", + "magnetics", + "return_path", + "phy_requirements" + ], + "constraints": [ + { + "id": "100base-tx-mdi-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "100base-tx-mdi-pair_skew", + "parameter": "pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "100base-tx-mdi-magnetics", + "parameter": "magnetics", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "100base-tx-mdi-bob_smith", + "parameter": "bob_smith", + "value_kind": "UNKNOWN", + "mandatory": "RECOMMENDED", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "IEEE numbers stay MISSING_SOURCE until the spec is on file." + }, + { + "id": "hdmi-1.4-tmds-type-a", + "logical_protocol_id": "hdmi-1.4", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "HDMI-A", + "recognition_hints": [ + "HDMI", + "TMDS", + "TX0", + "TX1", + "TX2", + "CLK" + ], + "required_checks": [ + "differential_impedance", + "pair_skew", + "lane_relationships", + "insertion_loss", + "return_loss", + "vias", + "connector" + ], + "constraints": [ + { + "id": "hdmi-1.4-tmds-type-a-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-1.4-tmds-type-a-pair_skew", + "parameter": "pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-1.4-tmds-type-a-insertion_loss", + "parameter": "insertion_loss", + "value_kind": "MISSING_SOURCE", + "mandatory": "RECOMMENDED", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Type A land" + }, + { + "id": "hdmi-1.4-tmds-type-c-mini", + "logical_protocol_id": "hdmi-1.4", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "HDMI-C-mini", + "recognition_hints": [ + "HDMI", + "TMDS", + "TX0", + "TX1", + "TX2", + "CLK" + ], + "required_checks": [ + "differential_impedance", + "pair_skew", + "lane_relationships", + "insertion_loss", + "return_loss", + "vias", + "connector" + ], + "constraints": [ + { + "id": "hdmi-1.4-tmds-type-c-mini-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-1.4-tmds-type-c-mini-pair_skew", + "parameter": "pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-1.4-tmds-type-c-mini-insertion_loss", + "parameter": "insertion_loss", + "value_kind": "MISSING_SOURCE", + "mandatory": "RECOMMENDED", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Mini Type C land; electrical HDMI 1.4, not a second standard" + }, + { + "id": "hdmi-2.0-tmds-type-a", + "logical_protocol_id": "hdmi-2.0", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "HDMI-A", + "recognition_hints": [ + "HDMI", + "TMDS", + "TX0", + "TX1", + "TX2", + "CLK" + ], + "required_checks": [ + "differential_impedance", + "pair_skew", + "lane_relationships", + "insertion_loss", + "return_loss", + "vias", + "connector" + ], + "constraints": [ + { + "id": "hdmi-2.0-tmds-type-a-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-2.0-tmds-type-a-pair_skew", + "parameter": "pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-2.0-tmds-type-a-insertion_loss", + "parameter": "insertion_loss", + "value_kind": "MISSING_SOURCE", + "mandatory": "RECOMMENDED", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Type A land" + }, + { + "id": "hdmi-2.0-tmds-type-c-mini", + "logical_protocol_id": "hdmi-2.0", + "bus_type": "SERIAL", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "HDMI-C-mini", + "recognition_hints": [ + "HDMI", + "TMDS", + "TX0", + "TX1", + "TX2", + "CLK" + ], + "required_checks": [ + "differential_impedance", + "pair_skew", + "lane_relationships", + "insertion_loss", + "return_loss", + "vias", + "connector" + ], + "constraints": [ + { + "id": "hdmi-2.0-tmds-type-c-mini-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-2.0-tmds-type-c-mini-pair_skew", + "parameter": "pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hdmi-2.0-tmds-type-c-mini-insertion_loss", + "parameter": "insertion_loss", + "value_kind": "MISSING_SOURCE", + "mandatory": "RECOMMENDED", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Mini Type C land; electrical HDMI 2.0" + }, + { + "id": "ddr-family-sdram-pcb", + "logical_protocol_id": "ddr-family", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "A0", + "RAS", + "CAS", + "WE" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr-family-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr-family-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr-family-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr-family-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr-family-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr-family-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "No universal mm/ps for DDR." + }, + { + "id": "ddr1-sdram-pcb", + "logical_protocol_id": "ddr1", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR1" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr1-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr1-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr1-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr1-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr1-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr1-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "ddr2-sdram-pcb", + "logical_protocol_id": "ddr2", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR2" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr2-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr2-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr2-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr2-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr2-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr2-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "ddr3-sdram-pcb", + "logical_protocol_id": "ddr3", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR3" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr3-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "ddr3l-sdram-pcb", + "logical_protocol_id": "ddr3l", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR3L" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr3l-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3l-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3l-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3l-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3l-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr3l-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "ddr4-sdram-pcb", + "logical_protocol_id": "ddr4", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR4" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr4-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr4-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr4-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr4-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr4-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr4-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "ddr5-sdram-pcb", + "logical_protocol_id": "ddr5", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "DDR5" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "ddr5-sdram-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr5-sdram-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr5-sdram-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr5-sdram-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr5-sdram-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ddr5-sdram-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Controller/PHY dependent. Zero universal skew/length." + }, + { + "id": "lpddr-family-pcb", + "logical_protocol_id": "lpddr-family", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "LPDDR" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr-family-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr-family-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr-family-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr-family-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr-family-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr-family-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr2-pcb", + "logical_protocol_id": "lpddr2", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR2" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr2-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr2-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr2-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr2-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr2-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr2-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr3-pcb", + "logical_protocol_id": "lpddr3", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR3" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr3-pcb-impedance", + "parameter": "impedance", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr3-pcb-max_length", + "parameter": "max_length", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr3-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr3-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr3-pcb-topology", + "parameter": "topology", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr3-pcb-termination", + "parameter": "termination", + "value_kind": "CONTROLLER_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "CONTROLLER", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr4-pcb", + "logical_protocol_id": "lpddr4", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR4" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr4-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr4x-pcb", + "logical_protocol_id": "lpddr4x", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR4X" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr4x-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4x-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4x-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4x-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4x-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr4x-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr5-pcb", + "logical_protocol_id": "lpddr5", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR5" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr5-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "lpddr5x-pcb", + "logical_protocol_id": "lpddr5x", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ", + "DQS", + "CK", + "CA", + "WCK", + "LPDDR5X" + ], + "required_checks": [ + "byte_lane_mapping", + "dq_to_dqs_skew", + "byte_lane_skew", + "ck_to_command_skew", + "topology", + "impedance", + "termination", + "via_count", + "stub_length", + "return_path" + ], + "constraints": [ + { + "id": "lpddr5x-pcb-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5x-pcb-max_length", + "parameter": "max_length", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5x-pcb-dq_to_dqs_skew", + "parameter": "dq_to_dqs_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5x-pcb-byte_to_byte_skew", + "parameter": "byte_to_byte_skew", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5x-pcb-topology", + "parameter": "topology", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "lpddr5x-pcb-termination", + "parameter": "termination", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "hbm-package", + "logical_protocol_id": "hbm", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HBM is package/interposer. Do not apply DDR DQ PCB rules." + }, + { + "id": "hbm2-package", + "logical_protocol_id": "hbm2", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm2-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HBM is package/interposer. Do not apply DDR DQ PCB rules." + }, + { + "id": "hbm2e-package", + "logical_protocol_id": "hbm2e", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm2e-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HBM is package/interposer. Do not apply DDR DQ PCB rules." + }, + { + "id": "hbm3-package", + "logical_protocol_id": "hbm3", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm3-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HBM is package/interposer. Do not apply DDR DQ PCB rules." + }, + { + "id": "hbm3e-package", + "logical_protocol_id": "hbm3e", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm3e-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "HBM is package/interposer. Do not apply DDR DQ PCB rules." + }, + { + "id": "hbm-family-package", + "logical_protocol_id": "hbm-family", + "bus_type": "MEMORY", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "package", + "silicon" + ], + "constraints": [ + { + "id": "hbm-family-package-pcb_individual_dq_routing", + "parameter": "pcb_individual_dq_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "hyperbus-pcb", + "logical_protocol_id": "hyperbus", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "RWDS", + "DQ0", + "CK", + "HYPERBUS" + ], + "required_checks": [ + "dq_to_rwds_skew", + "ck_to_dq_relationship", + "impedance", + "topology", + "length", + "vias", + "stubs" + ], + "constraints": [ + { + "id": "hyperbus-pcb-dq_to_rwds_skew", + "parameter": "dq_to_rwds_skew", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "hyperbus-pcb-impedance", + "parameter": "impedance", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "hyperram-pcb", + "logical_protocol_id": "hyperram", + "bus_type": "MEMORY", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "HYPERRAM", + "RWDS" + ], + "required_checks": [ + "dq_to_rwds_skew", + "ck_to_dq_relationship", + "impedance", + "topology", + "length", + "vias", + "stubs" + ], + "constraints": [ + { + "id": "hyperram-pcb-impedance", + "parameter": "impedance", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "spi-nor-pcb", + "logical_protocol_id": "spi-nor", + "bus_type": "MEMORY", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "SCLK", + "CS", + "MOSI", + "MISO", + "SPI" + ], + "required_checks": [ + "topology", + "length" + ], + "constraints": [ + { + "id": "spi-nor-pcb-topology", + "parameter": "topology", + "value_kind": "UNKNOWN", + "mandatory": "RECOMMENDED", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "spi-nor-pcb-impedance", + "parameter": "impedance", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "spi-nor-pcb-length", + "parameter": "length", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "qspi-pcb", + "logical_protocol_id": "qspi", + "bus_type": "MEMORY", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "QSPI", + "IO0", + "IO1", + "IO2", + "IO3", + "SCLK" + ], + "required_checks": [ + "clock_length", + "data_length", + "stubs", + "vias", + "return_path" + ], + "constraints": [ + { + "id": "qspi-pcb-clock_length", + "parameter": "clock_length", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "qspi-pcb-impedance", + "parameter": "impedance", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "octal-spi-pcb", + "logical_protocol_id": "octal-spi", + "bus_type": "MEMORY", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ0", + "DQS", + "OSPI", + "XSPI", + "OCTAL" + ], + "required_checks": [ + "dq_group", + "dqs_relationship_if_present", + "clock_to_data_skew", + "topology", + "impedance_if_required", + "length", + "vias", + "stubs" + ], + "constraints": [ + { + "id": "octal-spi-pcb-clock_to_data_skew", + "parameter": "clock_to_data_skew", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "octal-spi-pcb-impedance", + "parameter": "impedance", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "opi-pcb", + "logical_protocol_id": "opi", + "bus_type": "MEMORY", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ0", + "DQS", + "OSPI", + "XSPI", + "OCTAL" + ], + "required_checks": [ + "dq_group", + "dqs_relationship_if_present", + "clock_to_data_skew", + "topology", + "impedance_if_required", + "length", + "vias", + "stubs" + ], + "constraints": [ + { + "id": "opi-pcb-clock_to_data_skew", + "parameter": "clock_to_data_skew", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "opi-pcb-impedance", + "parameter": "impedance", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "xspi-pcb", + "logical_protocol_id": "xspi", + "bus_type": "MEMORY", + "physical_layer": "SERIAL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "DQ0", + "DQS", + "OSPI", + "XSPI", + "OCTAL" + ], + "required_checks": [ + "dq_group", + "dqs_relationship_if_present", + "clock_to_data_skew", + "topology", + "impedance_if_required", + "length", + "vias", + "stubs" + ], + "constraints": [ + { + "id": "xspi-pcb-clock_to_data_skew", + "parameter": "clock_to_data_skew", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "xspi-pcb-impedance", + "parameter": "impedance", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "emmc-pcb", + "logical_protocol_id": "emmc", + "bus_type": "STORAGE", + "physical_layer": "PARALLEL_SINGLE_ENDED", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "eMMC", + "DAT0", + "CMD", + "MMC_CLK" + ], + "required_checks": [ + "cmd_dat_grouping", + "clk_reference", + "impedance", + "skew", + "length" + ], + "constraints": [ + { + "id": "emmc-pcb-impedance", + "parameter": "impedance", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "emmc-pcb-skew", + "parameter": "skew", + "value_kind": "UNKNOWN", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [ + "mode=HS200|HS400" + ], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "ufs-mphy-pcb", + "logical_protocol_id": "ufs", + "bus_type": "STORAGE", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "UFS", + "MPHY", + "TX+", + "RX+" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "insertion_loss", + "return_loss", + "via_transition", + "ac_coupling" + ], + "constraints": [ + { + "id": "ufs-mphy-pcb-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "ufs-mphy-pcb-intra_pair_skew", + "parameter": "intra_pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "axi4-internal", + "logical_protocol_id": "axi4", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "axi4-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "axi4-lite-internal", + "logical_protocol_id": "axi4-lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "axi4-lite-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "axi4-stream-internal", + "logical_protocol_id": "axi4-stream", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "axi4-stream-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "ahb-internal", + "logical_protocol_id": "ahb", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "ahb-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "ahb-lite-internal", + "logical_protocol_id": "ahb-lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "ahb-lite-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "apb-internal", + "logical_protocol_id": "apb", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "apb-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "ace-internal", + "logical_protocol_id": "ace", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "ace-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "ace-lite-internal", + "logical_protocol_id": "ace-lite", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "ace-lite-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "amba-chi-internal", + "logical_protocol_id": "amba-chi", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "amba-chi-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "amba-internal", + "logical_protocol_id": "amba", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "amba-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "On-chip interconnect. Recognisable; not PCB routing." + }, + { + "id": "axi4-chip-to-chip-phy", + "logical_protocol_id": "axi4", + "bus_type": "CHIP_TO_CHIP", + "physical_layer": "MIXED", + "pcb_relevant": "CONDITIONAL", + "connector": "none", + "recognition_hints": [], + "required_checks": [ + "impedance", + "timing", + "topology", + "voltage" + ], + "constraints": [ + { + "id": "axi4-chip-to-chip-phy-impedance", + "parameter": "impedance", + "value_kind": "PHY_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "PHY", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "axi4-chip-to-chip-phy-timing", + "parameter": "timing", + "value_kind": "VENDOR_DEPENDENT", + "mandatory": "MANDATORY", + "source_type": "COMPONENT", + "source_class": "VENDOR", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "AXI4 name is logical. PCB rules come from the external PHY, not AXI4." + }, + { + "id": "wishbone-internal", + "logical_protocol_id": "wishbone", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "wishbone-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "avalon-mm-internal", + "logical_protocol_id": "avalon-mm", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "avalon-mm-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "avalon-st-internal", + "logical_protocol_id": "avalon-st", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "avalon-st-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "tilelink-internal", + "logical_protocol_id": "tilelink", + "bus_type": "PROCESSOR_INTERCONNECT", + "physical_layer": "INTERNAL", + "pcb_relevant": "NO", + "connector": "none", + "recognition_hints": [], + "required_checks": [], + "constraints": [ + { + "id": "tilelink-internal-pcb_routing", + "parameter": "pcb_routing", + "value_kind": "NOT_APPLICABLE", + "mandatory": "INFORMATIONAL", + "source_type": "PCB", + "source_class": "IMPLEMENTATION", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "" + }, + { + "id": "pcie-phy-pcb", + "logical_protocol_id": "pcie", + "bus_type": "CHIP_TO_CHIP", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "PCIE", + "PETX", + "PERX", + "REFCLK" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "lane_to_lane_skew", + "insertion_loss", + "return_loss", + "vias", + "connectors", + "return_path" + ], + "constraints": [ + { + "id": "pcie-phy-pcb-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "pcie-phy-pcb-intra_pair_skew", + "parameter": "intra_pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "pcie-phy-pcb-insertion_loss", + "parameter": "insertion_loss", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Logical vs physical split. Empty numbers until PCI-SIG cite." + }, + { + "id": "cxl-phy-pcb", + "logical_protocol_id": "cxl", + "bus_type": "CHIP_TO_CHIP", + "physical_layer": "SERIAL_DIFFERENTIAL", + "pcb_relevant": "YES", + "connector": "none", + "recognition_hints": [ + "CXL" + ], + "required_checks": [ + "differential_impedance", + "intra_pair_skew", + "lane_to_lane_skew", + "insertion_loss", + "return_loss", + "vias", + "connectors", + "return_path" + ], + "constraints": [ + { + "id": "cxl-phy-pcb-differential_impedance", + "parameter": "differential_impedance", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + }, + { + "id": "cxl-phy-pcb-intra_pair_skew", + "parameter": "intra_pair_skew", + "value_kind": "MISSING_SOURCE", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "value": null, + "unit": null, + "source": null, + "conditions": [], + "value_origin": "SPEC", + "typical": false + } + ], + "notes": "Physical electrical pack empty until official cite." + } + ] +} diff --git a/periscope/src/backend/periscopex/protocol_data/schema-1.0.0.json b/periscope/src/backend/periscopex/protocol_data/schema-1.0.0.json new file mode 100644 index 0000000..7df3333 --- /dev/null +++ b/periscope/src/backend/periscopex/protocol_data/schema-1.0.0.json @@ -0,0 +1,422 @@ +{ + "$defs": { + "ConstraintSource": { + "properties": { + "document": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Document" + }, + "organization": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Organization" + }, + "revision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Revision" + }, + "section": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Section" + }, + "table": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Table" + }, + "page": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Page" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + } + }, + "title": "ConstraintSource", + "type": "object" + }, + "LogicalProtocol": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "bus_type": { + "enum": [ + "MEMORY", + "PROCESSOR_INTERCONNECT", + "PERIPHERAL", + "CHIP_TO_CHIP", + "STORAGE", + "GRAPHICS", + "SERIAL", + "PARALLEL" + ], + "title": "Bus Type", + "type": "string" + }, + "family": { + "default": "", + "title": "Family", + "type": "string" + }, + "notes": { + "default": "", + "title": "Notes", + "type": "string" + } + }, + "required": [ + "id", + "name", + "bus_type" + ], + "title": "LogicalProtocol", + "type": "object" + }, + "PhysicalInterface": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "logical_protocol_id": { + "title": "Logical Protocol Id", + "type": "string" + }, + "bus_type": { + "enum": [ + "MEMORY", + "PROCESSOR_INTERCONNECT", + "PERIPHERAL", + "CHIP_TO_CHIP", + "STORAGE", + "GRAPHICS", + "SERIAL", + "PARALLEL" + ], + "title": "Bus Type", + "type": "string" + }, + "physical_layer": { + "enum": [ + "INTERNAL", + "PARALLEL_SINGLE_ENDED", + "PARALLEL_DIFFERENTIAL", + "SERIAL_SINGLE_ENDED", + "SERIAL_DIFFERENTIAL", + "MIXED" + ], + "title": "Physical Layer", + "type": "string" + }, + "pcb_relevant": { + "enum": [ + "YES", + "NO", + "CONDITIONAL" + ], + "title": "Pcb Relevant", + "type": "string" + }, + "connector": { + "default": "none", + "title": "Connector", + "type": "string" + }, + "recognition_hints": { + "items": { + "type": "string" + }, + "title": "Recognition Hints", + "type": "array" + }, + "required_checks": { + "items": { + "type": "string" + }, + "title": "Required Checks", + "type": "array" + }, + "constraints": { + "items": { + "$ref": "#/$defs/ProtocolConstraint" + }, + "title": "Constraints", + "type": "array" + }, + "notes": { + "default": "", + "title": "Notes", + "type": "string" + } + }, + "required": [ + "id", + "logical_protocol_id", + "bus_type", + "physical_layer", + "pcb_relevant" + ], + "title": "PhysicalInterface", + "type": "object" + }, + "ProtocolConstraint": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "parameter": { + "title": "Parameter", + "type": "string" + }, + "value_kind": { + "enum": [ + "NUMERIC", + "UNKNOWN", + "CONTROLLER_DEPENDENT", + "PHY_DEPENDENT", + "VENDOR_DEPENDENT", + "NOT_APPLICABLE", + "MISSING_SOURCE" + ], + "title": "Value Kind", + "type": "string" + }, + "mandatory": { + "enum": [ + "MANDATORY", + "RECOMMENDED", + "OPTIONAL", + "INFORMATIONAL" + ], + "title": "Mandatory", + "type": "string" + }, + "source_type": { + "enum": [ + "STANDARD", + "CONNECTOR", + "PHY", + "CONTROLLER", + "MEMORY", + "COMPONENT", + "CABLE", + "PCB", + "DERIVED" + ], + "title": "Source Type", + "type": "string" + }, + "source_class": { + "enum": [ + "NORMATIVE", + "VENDOR", + "IMPLEMENTATION", + "DERIVED" + ], + "title": "Source Class", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Value" + }, + "unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Unit" + }, + "source": { + "anyOf": [ + { + "$ref": "#/$defs/ConstraintSource" + }, + { + "type": "null" + } + ], + "default": null + }, + "conditions": { + "items": { + "type": "string" + }, + "title": "Conditions", + "type": "array" + }, + "measurement_method": { + "anyOf": [ + { + "enum": [ + "DATASHEET", + "TDR", + "FIELD_SOLVER", + "PCB_STACKUP", + "FABRICATOR", + "SIMULATION", + "CALCULATION", + "EXTRACTION", + "MEASUREMENT" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Measurement Method" + }, + "limit_kind": { + "anyOf": [ + { + "enum": [ + "STANDARD", + "DESIGN" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit Kind" + }, + "value_origin": { + "default": "SPEC", + "enum": [ + "SPEC", + "TYPICAL", + "EXAMPLE", + "DERIVED" + ], + "title": "Value Origin", + "type": "string" + }, + "typical": { + "default": false, + "title": "Typical", + "type": "boolean" + } + }, + "required": [ + "id", + "parameter", + "value_kind", + "mandatory", + "source_type", + "source_class" + ], + "title": "ProtocolConstraint", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "schema_version": { + "title": "Schema Version", + "type": "string" + }, + "logical_protocols": { + "items": { + "$ref": "#/$defs/LogicalProtocol" + }, + "title": "Logical Protocols", + "type": "array" + }, + "physical_interfaces": { + "items": { + "$ref": "#/$defs/PhysicalInterface" + }, + "title": "Physical Interfaces", + "type": "array" + } + }, + "required": [ + "schema_version", + "logical_protocols", + "physical_interfaces" + ], + "title": "ProtocolCatalog", + "type": "object" +} diff --git a/periscope/src/backend/services/pcb_pipeline.py b/periscope/src/backend/services/pcb_pipeline.py index 844191a..aa5b23f 100644 --- a/periscope/src/backend/services/pcb_pipeline.py +++ b/periscope/src/backend/services/pcb_pipeline.py @@ -28,6 +28,7 @@ from backend.periscopex.layout_rules import needs_layout_rules_refresh from backend.periscopex.models import ( ComponentConstraints, ComponentType, DesignGraph, LayoutGraph, ValidationReport, ) +from backend.periscopex.protocol_catalog import empty_protocol_section from backend.periscopex.af_ai_hf import append_investigated, hypotheses_from_rows from backend.periscopex.af_trace_check import check_af_traces from backend.periscopex.pcb_checks import assign_pcb_finding_ids, run_pcb_checks @@ -393,6 +394,7 @@ async def run_pcb_pipeline( summary=summary, coverage=coverage, not_reviewed=skipped + si_skip, + protocol_certification=empty_protocol_section().model_dump(), ) report_path = ws.local_path("pcb_report.json") report_path.write_text(report.model_dump_json(indent=2) + "\n") diff --git a/periscope/src/backend/services/validation.py b/periscope/src/backend/services/validation.py index a053c45..a3bc2db 100644 --- a/periscope/src/backend/services/validation.py +++ b/periscope/src/backend/services/validation.py @@ -28,6 +28,7 @@ from backend.periscopex.interface_class_check import check_interface_classes from backend.periscopex.led_current_check import check_led_current from backend.periscopex.lifecycle import check_lifecycle, load_lifecycle_dir from backend.periscopex.models import ComponentType, DesignGraph, Finding, ValidationReport +from backend.periscopex.protocol_catalog import empty_protocol_section from backend.periscopex.nc_pin_check import check_nc_pins from backend.periscopex.parsers import ic_mpn_skip_reason from backend.periscopex.passive_rail_check import ( @@ -228,6 +229,7 @@ async def validate_design_async( coverage=_sanitize_coverage(all_coverage), review_errors=dict(review_errors), not_reviewed=not_reviewed, + protocol_certification=empty_protocol_section().model_dump(), ) except Exception: report = ValidationReport( @@ -238,6 +240,7 @@ async def validate_design_async( coverage={}, review_errors=dict(review_errors), not_reviewed=not_reviewed, + protocol_certification=empty_protocol_section().model_dump(), ) report_dict = json.loads(report.model_dump_json(indent=2)) if preserved_comments is not None: diff --git a/periscope/src/frontend/content/changelog.md b/periscope/src/frontend/content/changelog.md index d0906b0..a3c9c27 100644 --- a/periscope/src/frontend/content/changelog.md +++ b/periscope/src/frontend/content/changelog.md @@ -2,6 +2,15 @@ What's new in Periscope. +## 2.64.0 — 2026-09-22 — Protocol certification M0 (catalog, no numbers) + +Versioned JSON protocol pack + Python loader/validator. Catalog skeletons for USB2 / USB-C-USB2 / 100BASE-TX / HDMI (connector distinct) / DDR / LPDDR / HBM / HyperBus / QSPI-octal / eMMC / UFS / AMBA / Wishbone / Avalon / TileLink / PCIe-CXL. Constraints without an official cite are UNKNOWN / CONTROLLER_DEPENDENT / PHY_DEPENDENT / MISSING_SOURCE — **no invented 90/100/50 Ω**. `logical_protocol_id` ≠ `physical_interface_id`. `pcb_relevant` is YES|NO|CONDITIONAL. RECOMMENDED is not FAIL-mandatory. Typical-as-standard is rejected by the parser. Report section **Protocolli** is empty (`nessun protocollo riconosciuto`). Recognition and L0–L3 certifiers are not in this release. + +- [New] `protocol_catalog.py`, `protocol_data/catalog.json`, schema 1.0.0. +- [New] `protocol_certification` on `ValidationReport`; UI section Protocolli. +- [New] pytest `tests/pcb/test_protocol_catalog_m0.py`. +- [Fixed] Native `periscope/src` wins over inherited `periscopex` on the package path. + ## 2.63.5 — 2026-09-22 — AF trace analysis (trigger, cascade, visible skips) PCB exam adds **AF trace analysis** after unchanged `run_pcb_checks` (SI/HF stay). Trigger is λ/10 or tr/(6 tpd) from FACT only. Differential pairs are one unit. Z0/Zdiff only vs a **datasheet** window. Missing tr/f/εr/stackup/Z target/via span is a visible INSUFFICIENT finding («Pista ad alta frequenza non controllata per mancanza di …»), not invented 50/90 Ω. Trigger false → no AF finding. Numerical cascade is lossless RLGC sections (ImpedenceFinder Z0); not OpenEMS/FEM. Python. PE-AF-001 AI path unchanged. diff --git a/periscope/src/frontend/package.json b/periscope/src/frontend/package.json index 5ce20f5..cd16444 100644 --- a/periscope/src/frontend/package.json +++ b/periscope/src/frontend/package.json @@ -1,6 +1,6 @@ { "name": "periscope-web", - "version": "2.63.4", + "version": "2.64.0", "private": true, "scripts": { "sync-version": "node scripts/sync-version.mjs", diff --git a/periscope/src/frontend/src/app/(app)/project/[id]/report/page.tsx b/periscope/src/frontend/src/app/(app)/project/[id]/report/page.tsx index f831d7e..3d5f093 100644 --- a/periscope/src/frontend/src/app/(app)/project/[id]/report/page.tsx +++ b/periscope/src/frontend/src/app/(app)/project/[id]/report/page.tsx @@ -18,6 +18,7 @@ import { useReviewedFindings } from "@/hooks/use-reviewed-findings"; import { ReportSummary } from "@/components/report/report-summary"; import { FindingsList } from "@/components/report/findings-list"; import { FindingFocusView } from "@/components/report/finding-focus-view"; +import { ProtocolSection } from "@/components/report/protocol-section"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { Toast, useToast } from "@/components/ui/toast"; @@ -303,6 +304,7 @@ function ReportContent({ projectId }: { projectId: string }) { creditsSpent={creditsSpent} totalCostUsd={totalCostUsd} /> + {failedReviews > 0 && (

diff --git a/periscope/src/frontend/src/components/report/protocol-section.tsx b/periscope/src/frontend/src/components/report/protocol-section.tsx new file mode 100644 index 0000000..4c636a4 --- /dev/null +++ b/periscope/src/frontend/src/components/report/protocol-section.tsx @@ -0,0 +1,32 @@ +"use client"; + +import type { ProtocolCertificationSection } from "@/lib/types"; + +export function ProtocolSection({ + section, +}: { + section?: ProtocolCertificationSection | null; +}) { + const message = section?.message || "nessun protocollo riconosciuto"; + const instances = section?.recognized_instances ?? []; + return ( +

+

Protocolli

+

+ Logical protocol vs physical interface. M0 loads the catalog only — + no recognition, no invented impedance. +

+ {instances.length === 0 ? ( +

{message}

+ ) : ( +
    + {instances.map((row, i) => ( +
  • + {String(row.physical_interface_id ?? row.logical_protocol_id ?? i)} +
  • + ))} +
+ )} +
+ ); +} diff --git a/periscope/src/frontend/src/lib/types.ts b/periscope/src/frontend/src/lib/types.ts index e869505..7a2b92d 100644 --- a/periscope/src/frontend/src/lib/types.ts +++ b/periscope/src/frontend/src/lib/types.ts @@ -75,6 +75,15 @@ export interface ValidationReport { comments?: Record; review_states?: Record; release?: ReportRelease; + protocol_certification?: ProtocolCertificationSection | null; +} + +export interface ProtocolCertificationSection { + schema_version: string; + macrophase: string; + recognized_instances: Record[]; + message: string; + max_level_reached: string | null; } export type NetType = "power" | "ground" | "signal" | "unknown"; diff --git a/periscope/src/frontend/src/lib/version.ts b/periscope/src/frontend/src/lib/version.ts index 1aff00c..18c87ea 100644 --- a/periscope/src/frontend/src/lib/version.ts +++ b/periscope/src/frontend/src/lib/version.ts @@ -1,3 +1,3 @@ /** Stamped from content/changelog.md by scripts/sync-version.mjs. */ -export const APP_VERSION = "2.63.4"; +export const APP_VERSION = "2.64.0"; export const APP_VERSION_DATE = "2026-09-22"; diff --git a/tests/conftest.py b/tests/conftest.py index 0816048..04006a3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,8 +16,11 @@ for p in ( REPO_ROOT, ): s = str(p) - if p.is_dir() and s not in sys.path: - sys.path.insert(0, s) + if not p.is_dir(): + continue + if s in sys.path: + sys.path.remove(s) + sys.path.insert(0, s) from backend.vendor_path import ensure_impedancefinder diff --git a/tests/pcb/test_protocol_catalog_m0.py b/tests/pcb/test_protocol_catalog_m0.py new file mode 100644 index 0000000..ef047c6 --- /dev/null +++ b/tests/pcb/test_protocol_catalog_m0.py @@ -0,0 +1,231 @@ +"""M0 protocol pack: parse, reject typical-as-standard, no invented ohms.""" + +from __future__ import annotations + +import copy +import json + +import pytest + +from backend.periscopex.models import ValidationReport +from backend.periscopex.protocol_catalog import ( + CATALOG_PATH, + SCHEMA_PATH, + SCHEMA_VERSION, + ProtocolCatalogError, + build_m0_catalog, + empty_protocol_section, + fail_mandatory, + load_catalog, + map_protocol_outcome, + parse_catalog, +) + + +REQUIRED_LOGICAL = { + "usb2-ls-fs", "usb2-hs", "usb-c-usb2", "100base-tx", + "hdmi-1.4", "hdmi-2.0", + "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", + "tilelink", "pcie", "cxl", +} + + +def test_committed_catalog_parses_and_matches_builder(): + loaded = load_catalog() + rebuilt = parse_catalog(build_m0_catalog()) + assert loaded.schema_version == SCHEMA_VERSION + assert loaded.model_dump() == rebuilt.model_dump() + assert CATALOG_PATH.is_file() + assert SCHEMA_PATH.is_file() + schema = json.loads(SCHEMA_PATH.read_text(encoding="utf-8")) + assert "properties" in schema + assert schema["properties"]["schema_version"] + + +def test_logical_and_physical_ids_are_disjoint(): + cat = load_catalog() + logical = {p.id for p in cat.logical_protocols} + physical = {p.id for p in cat.physical_interfaces} + assert not (logical & physical) + assert REQUIRED_LOGICAL <= logical + for iface in cat.physical_interfaces: + assert iface.id != iface.logical_protocol_id + assert iface.pcb_relevant in {"YES", "NO", "CONDITIONAL"} + + +def test_amba_internal_is_not_pcb_routing(): + cat = load_catalog() + axi = next(p for p in cat.physical_interfaces if p.id == "axi4-internal") + assert axi.pcb_relevant == "NO" + assert axi.physical_layer == "INTERNAL" + assert axi.logical_protocol_id == "axi4" + assert axi.constraints[0].value_kind == "NOT_APPLICABLE" + + +def test_ddr_has_no_universal_mm_or_ps(): + cat = load_catalog() + ddr4 = next(p for p in cat.physical_interfaces if p.id == "ddr4-sdram-pcb") + assert ddr4.pcb_relevant == "YES" + for c in ddr4.constraints: + assert c.value_kind in { + "CONTROLLER_DEPENDENT", "PHY_DEPENDENT", "UNKNOWN", + "VENDOR_DEPENDENT", "MISSING_SOURCE", "NOT_APPLICABLE", + } + assert c.value is None + assert c.unit is None + + +def test_hbm_dq_not_pcb_relevant(): + cat = load_catalog() + hbm = next(p for p in cat.physical_interfaces if p.id == "hbm3-package") + assert hbm.pcb_relevant == "NO" + + +def test_hdmi_mini_is_same_logical_different_connector(): + cat = load_catalog() + a = next(p for p in cat.physical_interfaces if p.id == "hdmi-1.4-tmds-type-a") + mini = next( + p for p in cat.physical_interfaces if p.id == "hdmi-1.4-tmds-type-c-mini" + ) + assert a.logical_protocol_id == mini.logical_protocol_id == "hdmi-1.4" + assert a.connector == "HDMI-A" + assert mini.connector == "HDMI-C-mini" + + +def test_catalog_has_no_invented_ohm_numbers(): + cat = load_catalog() + for iface in cat.physical_interfaces: + for c in iface.constraints: + assert c.value is None + assert c.value_kind != "NUMERIC" + + +def test_recommended_is_not_fail_mandatory(): + cat = load_catalog() + recs = [ + c + for iface in cat.physical_interfaces + for c in iface.constraints + if c.mandatory == "RECOMMENDED" + ] + assert recs, "catalog should include at least one RECOMMENDED skeleton" + for c in recs: + assert fail_mandatory(c) is False + cls, status, _ = map_protocol_outcome("FAIL", c.mandatory) + assert status != "ERROR" + assert cls != "RULE" + + +def test_mandatory_fail_can_be_error(): + cls, status, _ = map_protocol_outcome("FAIL", "MANDATORY") + assert cls == "RULE" + assert status == "ERROR" + + +def test_reject_typical_as_standard(): + raw = build_m0_catalog() + iface = raw["physical_interfaces"][0] + typical = copy.deepcopy(iface["constraints"][0]) + typical["id"] = "bad-typical" + typical["typical"] = True + typical["value_origin"] = "TYPICAL" + typical["source_type"] = "STANDARD" + typical["source_class"] = "NORMATIVE" + typical["mandatory"] = "MANDATORY" + typical["value_kind"] = "UNKNOWN" + typical["value"] = None + iface = copy.deepcopy(iface) + iface["id"] = "usb2-hs-typical-bad" + iface["constraints"] = [typical] + raw["physical_interfaces"].append(iface) + with pytest.raises(ProtocolCatalogError, match="typical"): + parse_catalog(raw) + + +def test_reject_constraint_without_source_type(): + raw = build_m0_catalog() + iface = copy.deepcopy(raw["physical_interfaces"][0]) + iface["id"] = "usb2-hs-no-source" + bad = copy.deepcopy(iface["constraints"][0]) + bad["id"] = "no-source" + del bad["source_type"] + iface["constraints"] = [bad] + raw["physical_interfaces"].append(iface) + with pytest.raises(ProtocolCatalogError): + parse_catalog(raw) + + +def test_reject_numeric_without_cite(): + raw = build_m0_catalog() + iface = copy.deepcopy(raw["physical_interfaces"][0]) + iface["id"] = "usb2-hs-fake-z" + iface["constraints"] = [{ + "id": "fake-zdiff", + "parameter": "differential_impedance", + "value_kind": "NUMERIC", + "value": 90.0, + "unit": "ohm", + "mandatory": "MANDATORY", + "source_type": "STANDARD", + "source_class": "NORMATIVE", + "source": None, + "typical": False, + "value_origin": "SPEC", + "conditions": [], + }] + raw["physical_interfaces"].append(iface) + with pytest.raises(ProtocolCatalogError, match="cite"): + parse_catalog(raw) + + +def test_reject_boolean_pcb_relevant(): + raw = build_m0_catalog() + iface = copy.deepcopy(raw["physical_interfaces"][0]) + iface["id"] = "usb2-hs-bool-pcb" + iface["pcb_relevant"] = True + raw["physical_interfaces"].append(iface) + with pytest.raises(ProtocolCatalogError): + parse_catalog(raw) + + +def test_reject_same_logical_and_physical_id(): + raw = build_m0_catalog() + iface = copy.deepcopy(raw["physical_interfaces"][0]) + iface["id"] = iface["logical_protocol_id"] + raw["physical_interfaces"].append(iface) + with pytest.raises(ProtocolCatalogError, match="differ"): + parse_catalog(raw) + + +def test_empty_report_section_has_no_z(): + section = empty_protocol_section() + dumped = section.model_dump() + assert section.message == "nessun protocollo riconosciuto" + assert section.recognized_instances == [] + assert dumped.get("max_level_reached") is None + blob = json.dumps(dumped) + assert "90" not in blob + assert "ohm" not in blob.lower() + assert "Zdiff" not in blob + assert "z0" not in blob.lower() + report = ValidationReport( + project="t", + timestamp="2026-09-22T00:00:00Z", + findings=[], + summary={"ERROR": 0, "WARNING": 0, "INFO": 0}, + protocol_certification=dumped, + ) + assert report.protocol_certification["message"] == "nessun protocollo riconosciuto" + + +def test_pcie_cxl_physical_packs_are_empty_numbers(): + cat = load_catalog() + for pid in ("pcie-phy-pcb", "cxl-phy-pcb"): + iface = next(p for p in cat.physical_interfaces if p.id == pid) + assert iface.logical_protocol_id in {"pcie", "cxl"} + assert iface.required_checks + for c in iface.constraints: + assert c.value_kind in {"MISSING_SOURCE", "UNKNOWN"} + assert c.value is None