XSA Pipeline Module
The XSA module converts Vivado .xsa archives into Linux device tree
sources. See XSA to Device Tree for the user guide and XSA Pipeline — Developer Guide
for the architecture documentation.
XSA-to-DeviceTree pipeline: parse Vivado archives and generate Linux DTS overlays.
Topology
Data model and parser for extracting IP topology from a Vivado XSA archive.
- class adidt.xsa.parse.topology.Jesd204Instance(name: str, base_addr: int, num_lanes: int, irq: int | None, link_clk: str, direction: str)
Bases:
objectOne JESD204 TX or RX IP core instance found in the HWH netlist.
- class adidt.xsa.parse.topology.ClkgenInstance(name: str, base_addr: int, output_clks: list[str] = <factory>)
Bases:
objectOne AXI clock-generator IP core instance found in the HWH netlist.
- class adidt.xsa.parse.topology.ConverterInstance(name: str, ip_type: str, base_addr: int, spi_bus: int | None, spi_cs: int | None)
Bases:
objectOne ADC/DAC/transceiver IP core instance found in the HWH netlist.
- class adidt.xsa.parse.topology.SignalConnection(signal: str, producers: list[str] = <factory>, consumers: list[str] = <factory>, bidirectional: list[str] = <factory>)
Bases:
objectConnectivity information for one HWH signal net.
- class adidt.xsa.parse.topology.XsaTopology(jesd204_rx: list[Jesd204Instance] = <factory>, jesd204_tx: list[Jesd204Instance] = <factory>, clkgens: list[ClkgenInstance] = <factory>, converters: list[ConverterInstance] = <factory>, signal_connections: list[SignalConnection] = <factory>, fpga_part: str = '')
Bases:
objectFull topology extracted from a single Vivado XSA archive.
- jesd204_rx: list[Jesd204Instance]
- jesd204_tx: list[Jesd204Instance]
- clkgens: list[ClkgenInstance]
- converters: list[ConverterInstance]
- signal_connections: list[SignalConnection]
- has_converter_types(*ip_types: str) bool
Return True if every requested ip_types is present among the topology’s converters.
- class adidt.xsa.parse.topology.XsaParser
Bases:
objectParses a Vivado .xsa file and returns an XsaTopology.
- parse_hwh_map(hwh_content: str) dict
Parse a HWH XML string into an IP-instance map and write debug diagram files.
- parse(xsa_path: Path) XsaTopology
Extract the hardware topology from an XSA archive and return an XsaTopology.
Pipeline
Orchestrate the full XSA-to-DeviceTree pipeline from archive to merged DTS.
- class adidt.xsa.pipeline.XsaPipeline
Bases:
objectOrchestrates the five-stage XSA-to-DeviceTree pipeline.
- run(xsa_path: Path, cfg: PipelineConfig | dict[str, Any], output_dir: Path, sdtgen_timeout: int = 120, profile: str | None = None, reference_dts: Path | None = None, strict_parity: bool = False, emit_report: bool = True, emit_clock_graphs: bool = True, emit_wiring_graph: bool = True, lint: bool = False, strict_lint: bool = False, output_format: str = 'default') dict[str, Path]
Run the full pipeline.
- Parameters:
xsa_path – Path to the Vivado
.xsaarchive.cfg – User-supplied configuration dictionary passed to
NodeBuilder.output_dir – Directory where all output files are written. Created automatically if it does not exist.
sdtgen_timeout – Maximum seconds to wait for
sdtgento finish generating the base DTS. Defaults to120.profile – Name of a built-in profile to load (e.g.
"adrv9009_zcu102"). WhenNonethe pipeline attempts to auto-detect a matching profile from the XSA topology.reference_dts – Optional path to a reference DTS used for parity checking. When provided,
"map"and"coverage"keys are added to the result.strict_parity – When
Trueand reference_dts is provided, raiseParityErrorif the merged DTS is missing required roles, links, or properties.emit_report – When
True(default) the HTML topology report is generated and"report"is included in the result dict. PassFalseto skip report generation.emit_clock_graphs – When
True(default) DOT and D2 clock-tree diagrams are generated and their paths included in the result dict. PassFalseto skip clock-graph generation.emit_wiring_graph – When
True(default) a control-plane wiring graph (SPI / JESD / GPIO / IRQ / I2C edges) is generated as DOT + D2 alongside the clock-tree diagrams. PassFalseto skip.lint – When
True, run the structural DTS linter on the merged DTS and write a diagnostics JSON file. Defaults toFalse.strict_lint – When
True, raiseDtsLintErrorif the linter finds any errors. Implieslint=True.output_format –
"default"produces the standard overlay + merged outputs."petalinux"additionally generates asystem-user.dtsianddevice-tree.bbappendsuitable for dropping into a PetaLinux project.
- Returns:
Dict always containing
"base_dir","overlay", and"merged"."report"is present when emit_report isTrue."clock_dot"and"clock_d2"(plus optionally"clock_dot_svg"/"clock_d2_svg") are present when emit_clock_graphs isTrue."wiring_dot"and"wiring_d2"(plus optionally"wiring_dot_svg"/"wiring_d2_svg") are present when emit_wiring_graph isTrue."map"and"coverage"are present when reference_dts is provided."diagnostics"is present when lint or strict_lint isTrue.- Raises:
ParityError – When strict_parity is
Trueand the merged DTS fails the parity check against reference_dts.DtsLintError – When strict_lint is
Trueand the linter finds errors in the generated DTS.
- run_petalinux_only(xsa_path: Path, cfg: PipelineConfig | dict[str, Any], output_dir: Path, profile: str | None = None) dict[str, Path]
Generate
system-user.dtsi+device-tree.bbappendwithout sdtgen.Use when PetaLinux’s own DTG (invoked by
petalinux-config --get-hw-description) provides the base device tree — pyadi-dt’s sdtgen call is then redundant and forces a Vitis dependency that callers in PetaLinux-only environments don’t have.Produces the same
system-user.dtsianddevice-tree.bbappendasrun()withoutput_format="petalinux", but skips sdtgen, the merged DTS, the HTML report, and the clock graphs.The overlay’s bus reference (
&ambavs&amba_pl) is determined the same way: a stub base DTS declaresamba; thePetalinuxFormatterrewrites toamba_plfor ZynqMP platforms based ontopology.inferred_platform().- Returns:
Dict with
"system_user_dtsi"and"bbappend"keys.
Node Builder
Build ADI device-driver DTS overlay nodes from an XSA topology and config.
- class adidt.xsa.build.node_builder.NodeBuilder
Bases:
objectBuilds ADI DTS node strings from XsaTopology + pyadi-jif JSON config.
- build(topology: XsaTopology, cfg: PipelineConfig | dict[str, Any]) dict[str, list[str]]
Render ADI DTS nodes.
- Parameters:
topology – Parsed XSA topology.
cfg – Pipeline configuration as a
PipelineConfigor raw dict. Dicts are used as-is for backward compatibility.PipelineConfiginstances are converted to dict viaPipelineConfig.to_dict().
- Returns:
Dict with keys “jesd204_rx”, “jesd204_tx”, “converters”.
DTS Merger
Merge a generated base DTS with ADI overlay nodes into a single DTS file.
HTML Visualizer
Generate an interactive HTML report visualising XSA topology and DTS output.
- class adidt.xsa.viz.visualizer.HtmlVisualizer
Bases:
objectGenerates a self-contained interactive HTML report.
- generate(topology: XsaTopology, cfg: dict[str, Any], merged_dts: str, output_dir: Path, name: str) str
Render and write a self-contained HTML report; returns the HTML string.
Wiring Graph
Generate control-plane wiring graphs for an XSA design or System composition.
Renders a single combined diagram showing SPI buses, JESD204 links, GPIO
control lines, interrupts, and I2C buses, with edges color-keyed by kind.
Two output formats: Graphviz DOT and D2 (with optional SVG when dot /
d2 are on PATH).
Two input adapters:
WiringGraph.from_topology()— XSA pipeline path; consumes anXsaTopologyplus the merged DTS string for GPIO / I2C extraction.WiringGraph.from_system()— declarative path; consumes aSystem.
- class adidt.xsa.viz.wiring_graph.WiringNode(label: str, node_name: str, kind: str)
Bases:
objectOne node in the wiring graph.
labelis the unique identifier (DTS label).node_nameis the DTS node name with optional@addrsuffix; falls back to label when no node name is known.kindis the visual category used to colour the node — one of the categories returned byadidt.xsa.viz._common.categorise()plus the wiring-specificspi_master,gpio_controller,i2c_master, andinterrupt_controllersynthetic categories.
- class adidt.xsa.viz.wiring_graph.WiringEdge(src: str, dst: str, kind: Literal['spi', 'jesd', 'gpio', 'irq', 'i2c'], label: str = '')
Bases:
objectOne directed edge in the wiring graph.
- class adidt.xsa.viz.wiring_graph.WiringGraph(nodes: list[WiringNode] = <factory>, edges: list[WiringEdge] = <factory>)
Bases:
objectCollected nodes + edges, source-agnostic.
- nodes: list[WiringNode]
- edges: list[WiringEdge]
- add_edge(edge: WiringEdge) None
- classmethod from_topology(topology: XsaTopology, cfg: dict[str, Any] | None = None, merged_dts: str | None = None) WiringGraph
Build a
WiringGraphfrom an XSA topology.cfgis currently unused but accepted for symmetry with the pipeline call sites that already plumb config dicts.merged_dtsenables GPIO and I2C edge extraction; without it those edge kinds are skipped.
- classmethod from_system(system: Any) WiringGraph
Build a
WiringGraphfrom aadidt.system.System.
- class adidt.xsa.viz.wiring_graph.WiringGraphGenerator
Bases:
objectWrite DOT + D2 wiring diagrams (and optional SVGs) for a graph.
- generate(graph: WiringGraph, output_dir: Path, name: str, *, kinds: set[Literal['spi', 'jesd', 'gpio', 'irq', 'i2c']] | None = None) dict[str, Path]
Render graph to
{name}_wiring.dot/.d2under output_dir.Returns a dict of artifact paths with keys
wiring_dot,wiring_d2, pluswiring_dot_svg/wiring_d2_svgwhen the respective renderer is available on PATH.kindsfilters edges to the given kinds;Nonekeeps all.
SDT Generator Runner
Wrapper for invoking the sdtgen tool to generate a base SDT/DTS from an XSA.
- class adidt.xsa.parse.sdtgen.SdtgenRunner(binary: str = 'sdtgen')
Bases:
objectInvokes sdtgen as a subprocess to generate a base SDT/DTS from an XSA file.
- run(xsa_path: Path, output_dir: Path, timeout: int = 120) Path
Run sdtgen and return the path to the generated base DTS file.
- Raises:
SdtgenNotFoundError – If sdtgen is not on PATH.
SdtgenError – If sdtgen fails, times out, or produces no output.
Exceptions
Custom exception types for the XSA-to-DeviceTree pipeline.
- exception adidt.xsa.exceptions.SdtgenNotFoundError(message: str = 'sdtgen not found on PATH')
Bases:
ExceptionRaised when sdtgen/lopper binary is not found on PATH.
- exception adidt.xsa.exceptions.SdtgenError(message: str, stderr: str = '')
Bases:
ExceptionRaised when sdtgen exits with a non-zero status or produces no output.
- exception adidt.xsa.exceptions.XsaParseError
Bases:
ExceptionRaised when the XSA file cannot be parsed.
- exception adidt.xsa.exceptions.ConfigError(missing_field: str)
Bases:
ExceptionRaised when the pyadi-jif JSON config is missing required fields.
- exception adidt.xsa.exceptions.ProfileError
Bases:
ExceptionRaised when a board profile cannot be loaded or is invalid.
Board Configurations
Public board configuration dataclasses for the XSA-to-DeviceTree pipeline.
These types formalize the raw dict[str, Any] configuration that the pipeline
has historically accepted. Each board family has a dedicated dataclass with
typed fields and defaults matching the existing .get(key, default) patterns
in adidt.xsa.build.node_builder.
Backward compatibility
Every config type provides a from_dict class method so that JSON profiles,
MCP server requests, and existing test dicts continue to work unchanged:
cfg = FMCDAQ2BoardConfig.from_dict(raw_dict)
Validation
__post_init__ on each type runs the same checks that profiles.py
_validate_typed_keys previously performed (non-negative ints, non-empty
strings). Construct the object to validate; catch ValueError on failure.
- class adidt.xsa.config.board_configs.JesdLinkParams(F: int = 1, K: int = 32, M: int = 2, L: int = 4, Np: int = 16, S: int = 1)
Bases:
objectJESD204 framing parameters for one direction (RX or TX).
- classmethod from_dict(d: dict[str, Any]) JesdLinkParams
Construct from a dict, coercing values to int.
- class adidt.xsa.config.board_configs.JesdConfig(rx: JesdLinkParams = <factory>, tx: JesdLinkParams = <factory>)
Bases:
objectJESD204 configuration for RX and TX directions.
- rx: JesdLinkParams
- tx: JesdLinkParams
- classmethod from_dict(d: dict[str, Any]) JesdConfig
Construct from a
{"rx": {...}, "tx": {...}}dict.
- class adidt.xsa.config.board_configs.ClockConfig(rx_device_clk_label: str = 'clkgen', rx_device_clk_index: int = 0, tx_device_clk_label: str = 'clkgen', tx_device_clk_index: int = 0, rx_b_device_clk_index: int | None = None, tx_b_device_clk_index: int | None = None, hmc7044_rx_channel: int | None = None, hmc7044_tx_channel: int | None = None)
Bases:
objectClock routing configuration shared across board families.
- classmethod from_dict(d: dict[str, Any]) ClockConfig
Construct from a clock config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.FMCDAQ2BoardConfig(spi_bus: str = 'spi0', clock_cs: int = 0, adc_cs: int = 2, dac_cs: int = 1, clock_vcxo_hz: int = 125000000, clock_spi_max_frequency: int = 10000000, adc_spi_max_frequency: int = 1000000, dac_spi_max_frequency: int = 1000000, adc_dma_label: str = 'axi_ad9680_dma', dac_dma_label: str = 'axi_ad9144_dma', adc_core_label: str = 'axi_ad9680_core', dac_core_label: str = 'axi_ad9144_core', adc_xcvr_label: str = 'axi_ad9680_adxcvr', dac_xcvr_label: str = 'axi_ad9144_adxcvr', adc_jesd_label: str = 'axi_ad9680_jesd204_rx', dac_jesd_label: str = 'axi_ad9144_jesd204_tx', adc_jesd_link_id: int = 0, dac_jesd_link_id: int = 0, gpio_controller: str = 'gpio0', adc_device_clk_idx: int = 13, adc_sysref_clk_idx: int = 5, adc_xcvr_ref_clk_idx: int = 4, adc_sampling_frequency_hz: int = 1000000000, dac_device_clk_idx: int = 1, dac_xcvr_ref_clk_idx: int = 9, clk_sync_gpio: Any = None, clk_status0_gpio: Any = None, clk_status1_gpio: Any = None, dac_txen_gpio: Any = None, dac_reset_gpio: Any = None, dac_irq_gpio: Any = None, adc_powerdown_gpio: Any = None, adc_fastdetect_a_gpio: Any = None, adc_fastdetect_b_gpio: Any = None)
Bases:
objectBoard-level configuration for FMCDAQ2 designs (AD9523-1 + AD9680 + AD9144).
Example:
cfg = FMCDAQ2BoardConfig.from_dict({ "spi_bus": "spi0", "clock_cs": 0, "adc_cs": 2, "dac_cs": 1, })
- classmethod from_dict(d: dict[str, Any]) FMCDAQ2BoardConfig
Construct from a board config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.FMCDAQ3BoardConfig(spi_bus: str = 'spi0', clock_cs: int = 0, adc_cs: int = 2, dac_cs: int = 1, clock_vcxo_hz: int = 100000000, clock_spi_max_frequency: int = 10000000, adc_spi_max_frequency: int = 10000000, dac_spi_max_frequency: int = 10000000, adc_dma_label: str = 'axi_ad9680_dma', dac_dma_label: str = 'axi_ad9152_dma', adc_core_label: str = 'axi_ad9680_tpl_core_adc_tpl_core', dac_core_label: str = 'axi_ad9152_tpl_core_dac_tpl_core', adc_xcvr_label: str = 'axi_ad9680_xcvr', dac_xcvr_label: str = 'axi_ad9152_xcvr', adc_jesd_label: str = 'axi_ad9680_jesd_rx_axi', dac_jesd_label: str = 'axi_ad9152_jesd_tx_axi', adc_jesd_link_id: int = 0, dac_jesd_link_id: int = 0, gpio_controller: str = 'gpio', adc_device_clk_idx: int = 13, adc_xcvr_ref_clk_idx: int = 9, adc_sampling_frequency_hz: int = 1233333333, dac_device_clk_idx: int = 2, dac_xcvr_ref_clk_idx: int = 4, clk_status0_gpio: Any = None, clk_status1_gpio: Any = None, dac_txen_gpio: Any = None, dac_irq_gpio: Any = None, adc_powerdown_gpio: Any = None, adc_fastdetect_a_gpio: Any = None, adc_fastdetect_b_gpio: Any = None, ad9152_jesd_link_mode: int = 4)
Bases:
objectBoard-level configuration for FMCDAQ3 designs (AD9528 + AD9680 + AD9152).
- classmethod from_dict(d: dict[str, Any]) FMCDAQ3BoardConfig
Construct from a board config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.AD9172BoardConfig(spi_bus: str = 'spi0', clock_cs: int = 0, dac_cs: int = 1, clock_spi_max_frequency: int = 10000000, dac_spi_max_frequency: int = 1000000, dac_core_label: str = 'axi_ad9172_core', dac_xcvr_label: str = 'axi_ad9172_adxcvr', dac_jesd_label: str = 'axi_ad9172_jesd_tx_axi', dac_jesd_link_id: int = 0, hmc7044_ref_clk_hz: int = 122880000, hmc7044_vcxo_hz: int = 122880000, hmc7044_out_freq_hz: int = 2949120000, ad9172_dac_rate_khz: int = 11796480, ad9172_jesd_link_mode: int = 4, ad9172_dac_interpolation: int = 8, ad9172_channel_interpolation: int = 4, ad9172_clock_output_divider: int = 4)
Bases:
objectBoard-level configuration for AD9172 DAC designs (HMC7044 + AD9172).
- classmethod from_dict(d: dict[str, Any]) AD9172BoardConfig
Construct from a board config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.AD9084BoardConfig(converter_spi: str = 'axi_spi_2', converter_cs: int = 0, clock_spi: str = 'axi_spi', hmc7044_cs: int = 1, converter_spi_max_hz: int = 1000000, hmc7044_spi_max_hz: int = 1000000, adf4382_cs: int | None = None, pll1_clkin_frequencies: list[int] = <factory>, vcxo_hz: int = 125000000, pll2_output_hz: int = 2500000000, fpga_refclk_channel: int = 10, pll1_loop_bandwidth_hz: int = 200, pll1_ref_prio_ctrl: str = '0xE1', pll1_ref_autorevert: bool = True, pll1_charge_pump_ua: int = 720, pfd1_max_freq_hz: int = 1000000, sysref_timer_divider: int = 1024, pulse_generator_mode: int = 0, clkin0_buffer_mode: str = '0x07', clkin1_buffer_mode: str = '0x07', oscin_buffer_mode: str = '0x15', gpi_controls: list[int] = <factory>, gpo_controls: list[int] = <factory>, jesd204_max_sysref_hz: int = 2000000, hmc7044_channels: list[dict[str, ~typing.Any]] | None=None, hmc7044_channel_blocks: list[Any] | None = None, dev_clk_source: str | None = None, dev_clk_ref: str | None = None, dev_clk_scales: str | None = None, dev_clk_channel: int = 9, firmware_name: str | None = None, reset_gpio: int | None = None, subclass: int = 0, side_b_separate_tpl: bool = True, rx_sys_clk_select: int = 3, tx_sys_clk_select: int = 3, rx_out_clk_select: int = 4, tx_out_clk_select: int = 4, rx_a_link_id: int = 0, rx_b_link_id: int = 1, tx_a_link_id: int = 2, tx_b_link_id: int = 3, jrx0_physical_lane_mapping: str | None = None, jtx0_logical_lane_mapping: str | None = None, jrx1_physical_lane_mapping: str | None = None, jtx1_logical_lane_mapping: str | None = None, hsci_label: str | None = None, hsci_speed_mhz: int = 800, hsci_auto_linkup: bool = False)
Bases:
objectBoard-level configuration for AD9084 dual-link designs.
Captures SPI bus assignments, clock chip settings, XCVR PLL selection, JESD204 link IDs, and lane mappings specific to AD9084 boards (e.g., AD9084-FMC-EBZ on VCU118).
Example:
cfg = AD9084BoardConfig.from_dict({ "converter_spi": "axi_spi_2", "converter_cs": 0, "clock_spi": "axi_spi", "hmc7044_cs": 1, })
- classmethod from_dict(d: dict[str, Any]) AD9084BoardConfig
Construct from a board config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.AD9081BoardConfig(clock_spi: str = 'spi1', clock_cs: int = 0, adc_spi: str = 'spi0', adc_cs: int = 0, reset_gpio: int | None = None, sysref_req_gpio: int | None = None, rx1_enable_gpio: int | None = None, rx2_enable_gpio: int | None = None, tx1_enable_gpio: int | None = None, tx2_enable_gpio: int | None = None, hmc7044_channel_blocks: list[Any] | None = None)
Bases:
objectBoard-level configuration for AD9081/AD9082/AD9083 MxFE designs.
- classmethod from_dict(d: dict[str, Any]) AD9081BoardConfig
Construct from a board config dict, ignoring unknown keys.
- class adidt.xsa.config.board_configs.ADRV9009BoardConfig(spi_bus: str = 'spi0', clk_cs: int = 0, trx_cs: int = 1, misc_clk_hz: int = 0, trx_reset_gpio: int | None = None, trx_sysref_req_gpio: int | None = None, trx_spi_max_frequency: int = 1000000, ad9528_vcxo_freq: int = 122880000, rx_link_id: int = 0, rx_os_link_id: int = 1, tx_link_id: int = 2, tx_octets_per_frame: int | None = None, rx_os_octets_per_frame: int | None = None, trx_profile_props: list[Any] | None = None, ad9528_channel_blocks: list[Any] | None = None)
Bases:
objectBoard-level configuration for ADRV9009/9025/9026 transceiver designs.
- classmethod from_dict(d: dict[str, Any]) ADRV9009BoardConfig
Construct from a board config dict, ignoring unknown keys.
Pipeline Configuration
Top-level pipeline configuration wrapping JESD, clock, and board configs.
PipelineConfig is the typed entry point for all pipeline configuration.
It can be constructed from a raw dict (backward compatible) or directly
with typed sub-configs:
# From a raw dict (JSON profile, MCP server, existing tests)
cfg = PipelineConfig.from_dict(raw_dict)
# Directly with typed configs
cfg = PipelineConfig(
jesd=JesdConfig(rx=JesdLinkParams(F=4, K=32)),
clock=ClockConfig(rx_device_clk_label="hmc7044"),
fmcdaq2_board=FMCDAQ2BoardConfig(spi_bus="spi0"),
)
- class adidt.xsa.config.pipeline_config.PipelineConfig(jesd: JesdConfig = <factory>, clock: ClockConfig = <factory>, fmcdaq2_board: FMCDAQ2BoardConfig | None = None, fmcdaq3_board: FMCDAQ3BoardConfig | None = None, ad9172_board: AD9172BoardConfig | None = None, ad9084_board: AD9084BoardConfig | None = None, ad9081_board: AD9081BoardConfig | None = None, adrv9009_board: ADRV9009BoardConfig | None = None, fpga_adc: dict[str, ~typing.Any]=<factory>, fpga_dac: dict[str, ~typing.Any]=<factory>, _extra: dict[str, ~typing.Any]=<factory>)
Bases:
objectTop-level configuration for the XSA-to-DeviceTree pipeline.
Wraps
JesdConfig,ClockConfig, and an optional board-family config. At most one board config should be set.The raw dict form (
cfg["jesd"]["rx"]["F"]) is still accepted everywhere viafrom_dict(), which auto-detects the board family from key presence.- jesd: JesdConfig
- clock: ClockConfig
- fmcdaq2_board: FMCDAQ2BoardConfig | None = None
- fmcdaq3_board: FMCDAQ3BoardConfig | None = None
- ad9172_board: AD9172BoardConfig | None = None
- ad9084_board: AD9084BoardConfig | None = None
- ad9081_board: AD9081BoardConfig | None = None
- adrv9009_board: ADRV9009BoardConfig | None = None
- classmethod from_dict(d: dict[str, Any]) PipelineConfig
Construct from a raw config dict, auto-detecting board family.
This is the backward-compatibility bridge for JSON profiles, MCP server requests, and existing test dicts.
Builders
Per-board builder modules for the XSA-to-DeviceTree pipeline.
Each builder implements the BoardBuilder protocol and is responsible
for a single board family (e.g., FMCDAQ2, AD9084). The NodeBuilder
iterates registered builders, calling matches() to determine which
builder handles the current topology, then build_nodes() to generate
the DTS node strings.
Adding a new board family:
Create
builders/new_board.pyimplementingBoardBuilder.Add it to
DEFAULT_BUILDERSbelow.No changes to
node_builder.pyorpipeline.pyare needed.
- class adidt.xsa.build.builders.BoardBuilder(*args, **kwargs)
Bases:
ProtocolProtocol for board-family specific DTS node builders.
Each builder is responsible for:
Detecting whether a given topology + config matches this board family.
Generating all DTS node strings for the matched design.
Reporting which JESD/clkgen/converter instances it handles (so the generic rendering loop in NodeBuilder can skip them).
- matches(topology: XsaTopology, cfg: dict[str, Any]) bool
Return True if topology and cfg represent this board family.
- build_nodes(node_builder: Any, topology: XsaTopology, cfg: dict[str, Any], ps_clk_label: str, ps_clk_index: int | None, gpio_label: str) list[str]
Generate DTS node strings for this board family.
- Parameters:
node_builder – The owning
NodeBuilderinstance, providing access to_render(),_wrap_spi_bus(), and other shared infrastructure.topology – Parsed XSA topology.
cfg – Raw pipeline config dict.
ps_clk_label – Platform PS clock label (e.g.,
"zynqmp_clk").ps_clk_index – Platform PS clock index (e.g.,
71).gpio_label – Platform GPIO controller label.
- Returns:
List of DTS node strings to append to
result["converters"].
- class adidt.xsa.build.builders.ADRV937xBuilder
Bases:
objectBoard builder for ADRV937x (AD9371) transceiver designs.
- matches(topology: XsaTopology, cfg: dict[str, Any]) bool
- build_nodes(node_builder: Any, topology: XsaTopology, cfg: dict[str, Any], ps_clk_label: str, ps_clk_index: int | None, gpio_label: str) list[str]
- build_model(topology: XsaTopology, cfg: dict[str, Any], ps_clk_label: str, ps_clk_index: int | None, gpio_label: str) BoardModel | None
Construct a BoardModel for an ADRV937x (AD9371) design.
Returns None if no ADRV937x instances are found in the topology.
DTS Linter
Structural DTS linter for generated device tree source files.
Operates on merged DTS text using regex-based parsing — no external tools
(dtc, dt-schema) required. Produces a list of LintDiagnostic
items with severity, rule ID, node location, and actionable message.
Usage:
from adidt.xsa.validate.dts_lint import DtsLinter
diagnostics = DtsLinter().lint(dts_text)
errors = [d for d in diagnostics if d.severity == "error"]
- class adidt.xsa.validate.dts_lint.LintDiagnostic(severity: str, rule: str, node: str, message: str, binding_confidence: str | None = None)
Bases:
objectOne issue found by the DTS linter.
- class adidt.xsa.validate.dts_lint.DtsLinter
Bases:
objectStructural linter for generated DTS files.
Example:
linter = DtsLinter() diagnostics = linter.lint(dts_text) for d in diagnostics: print(d)
- lint(dts_text: str, topology: Any = None, bindings: Any = None) list[LintDiagnostic]
Run all lint rules on dts_text and return diagnostics.
- Parameters:
dts_text – Merged DTS content as a string.
topology – Optional
XsaTopologyfor topology-aware rules.bindings – Optional
BindingRegistryfor binding cross-reference rules (Phase 8).
- Returns:
List of
LintDiagnosticitems, sorted by severity.
- lint_file(dts_path: Path, topology: Any = None, bindings: Any = None) list[LintDiagnostic]
Convenience wrapper that reads a file and lints its content.