A XactFlow importer plugin that reads a SystemVerilog
module plus a JSON metadata file (and, optionally, a SystemRDL register map) and produces an
ipxact.Component object, built on
ipxact-compiler's
IEEE 1685-2022 object model.
ipxact-compiler parses IP-XACT and hands back Python objects; XactFlow's Importer interface
is for the other direction, reading some non-IP-XACT source and producing that object model.
This package is one such importer: it does not write XML itself, turning the resulting
Component into a file is a separate exporter's job (see
xactflow-component).
The SystemVerilog parsing and metadata-driven design was informed by
ipxact-sv2ipxact, an earlier, experimental
standalone tool that solves a closely related problem by writing IP-XACT XML directly. This
package is a from-scratch implementation built against ipxact-compiler's object model rather
than a fork of it, and its scope, dependencies, and error handling are its own.
pip install xactflow-svFor local development, requirements-dev.txt overrides ipxact-compiler and xactflow to
local installations. It can be modified to adapt the paths or to keep either version on PyPI.
pip install -r requirements-dev.txt -e .Requires Python >= 3.9. Runtime dependencies beyond ipxact-compiler/xactflow:
pyslang for SystemVerilog parsing, and
systemrdl-compiler/
peakrdl-ipxact for register map conversion.
An importer's job stops at producing an ipxact.Component object; it does not write anything
out on its own, so getting an actual IP-XACT XML file also needs an exporter, like
xactflow-component. Once both are installed,
the importer registers itself under the xactflow.importers entry point group as sv, so
it can run as one XactFlow CLI command, --then chaining straight into the exporter
in the same process (requires xactflow>=0.1.1):
xactflow sv my_module.sv --option metadata=my_module_ipxact.json --then component --output out/
# writes out/<name>.xmlOr as a library, e.g. to inspect or modify the Component before exporting it:
from pathlib import Path
from xactflow_sv import SVImporter
from xactflow_component import ComponentExporter
component = SVImporter().import_(Path("my_module.sv"), metadata="my_module_ipxact.json")
component.vlnv # VLNV
component.model.ports # list[Port]
component.bus_interfaces # list[BusInterface]
component.memory_maps # list[MemoryMap]
ComponentExporter().export(component, Path("out")) # writes out/<name>.xmlOnly the SystemVerilog module header (parameters and ports) is inspected, with no elaboration, no package loading, no symbol resolution: types, values, and dimension expressions are taken verbatim from the source text, matching how IP-XACT's own expression model treats them.
A small JSON file supplies what can't be inferred from the SV source alone:
{
"vendor": "Vendor",
"library": "Library",
"version": "1.0",
"busInterfaces": {
"apb": {
"bus": "Vendor:Library:apb4:1.0",
"mode": "target",
"ports": {"PSEL": "psel", "PADDR": "bus_req_i.paddr"}
}
},
"registerFile": "register_map.rdl"
}vendor/libraryare required,versiondefaults to"1.0". The component'snamealways comes from the parsed module name, not from this file.busInterfacesmaps a bus interface name to its bus VLNV, mode (initiator/target, ormaster/slave), and either aportsmapping of logical bus signal names onto physical SV port names, or aninterfacePortnaming a genuine SVinterface-typed port that already groups its own signals. Aportsvalue can be a plain port name or a dottedport.fieldreference into a struct-typed port (e.g.bus_req_i.paddr). The abstraction definition is derived by convention as<bus-def-name>_rtlat the same vendor/library/version asbus. Everyinterface-typed port in the module must be described this way; there is no fallback guess for its bus VLNV or mode.registerFileis a path, relative to the metadata file, to a SystemRDL file describing the component's register map. It is compiled withsystemrdl-compiler, converted withpeakrdl-ipxact, and merged in as the component'smemory_maps.
--option define=SYM1,SYM2 (or defines=[...] when calling import_ directly) predefines
preprocessor symbols before parsing.
- Three independent stages, each targeting
ipxact-compilerdataclasses directly rather than XML:sv_parser.pyparses the module header into plain dicts,component_builder.pyturns those intoipxact.Port/ipxact.Parameter/the component'sModel,bus_interfaces.pybuildsipxact.BusInterfacefrom the metadata'sbusInterfaces, andregister_map.pybuildsipxact.MemoryMapfrom a SystemRDL file. register_map.pyreadspeakrdl-ipxact's own XML output, not throughipxact-compiler's parser.peakrdl-ipxactonly supports IEEE 1685-2014, whileipxact-compileronly supports IEEE 1685-2022. A namespace swap alone would silently lose that data (a field's access policy, or a register's array dimensions, would just come back empty rather than erroring), so a dedicated reader is used instead. This is a keep-it-simple choice for now, maybe not permanent, see Ideas for later.- Fails loudly instead of silently dropping data. Constructs this package does not yet
support (see below) raise
NotImplementedError/ValueErrorrather than producing aComponentthat quietly leaves something out.
- Explicit ANSI ports (
.name(expr)syntax) and non-ANSI port lists (module m(a, b); input a; ...) are not supported. Only implicit ANSI-style ports are. A direction-less first port defaults toinout, per the SystemVerilog LRM. - Indexed part-select dimensions are not supported, e.g.
[base+:width]/[base-:width]. Only a plain[left:right]range is. - Register/register file arrays are not supported.
- A
registerFiledefining anaddrmapthat is never used under the chosen top-leveladdrmapis rejected, rather than silently ignored as SystemRDL itself would. A reusable sub-blockaddrmapinstantiated under a real top is unaffected. - A register/field/register file/address block with
ispresent = falseis not supported. IEEE 1685-2022 has no equivalent ofisPresent, so there is no way to represent one as conditionally absent rather than silently promoting it to always-present. - A SystemRDL construct
peakrdl-ipxactcannot export at all raises an error, e.g. amemnode nested inside another node's hierarchy, rather than silently producing an incomplete memory map. fileSetsare not generated. The component never records which.svfile the module actually came from.
- Have
register_map.pybuild onipxact-compiler's own parser instead of its own ElementTree reader. Not a quick swap:peakrdl-ipxactonly emits IEEE 1685-2014 XML, andipxact-compiler's parser expects 2022's structure for field access and array dimensions (see Design notes). Feeding it 2014 XML after only a namespace fix-up parses without error but silently comes back missing that data, confirmed by testing it directly. Doing this properly needs a 2014-to-2022 XML restructuring step first (in this package, not inipxact-compiler, which is a 1685-2022 parser by design), or forpeakrdl-ipxactto gain 2022 output support upstream.
LGPL-3.0. See LICENSE.