Multi-file IEEE 1685-2022 IP-XACT linking and
checking, built on ipxact-compiler.
ipxact-compiler reads one IP-XACT file into Python objects and can validate it against the
XSD. XactFlow works across files: it resolves a Design against a library of components, bus
definitions and abstraction definitions, and checks the result against the Semantic Consistency
Rules (SCRs) of the standard.
pip install xactflowRequires Python 3.9 or later. This README follows main: the plugin API it describes is newer
than the 0.3.0 release (see Plugins).
For development, requirements-dev.txt installs ipxact-compiler from a sibling checkout
(../ipxact-compiler); change the path if needed:
pip install -r requirements-dev.txt -e .xactflow link design.xml --lib DIR [--lib DIR ...] [--config designConfig.xml]
xactflow check file.xmllinkscans the--libfolders, resolves the design against them, prints the diagnostics, and exits with 1 if any is an error.checkruns the checks that need only one file, without a library.
Each installed plugin adds its own subcommand (see Plugins). Both kinds work on one
Library, scanned from the --lib folders:
- an exporter:
xactflow <exporter> file.xml --lib DIR [--config FILE] --output DIRaddsfile.xmlto the library as the target to export, links it first if it is a design, and passes the library to the exporter; - an importer:
xactflow <importer> source --lib DIRadds what it reads to the library, with--then <exporter>to pass that same library straight to an exporter, without an intermediate file:
xactflow sv module.sv --option metadata=module_ipxact.json --then component --output out/
xactflow archidesc soc.py --lib ip/ --lib bus_definitions/ --then topgen --output out/--option KEY=VALUE sets a plugin option; --then-option KEY=VALUE sets one for the --then
exporter. If that exporter supports none of the importer's documents, the command prints a
one-line error naming both plugins.
import ipxact
from xactflow import Library, link
library = Library.scan("path/to/ip/library")
design = ipxact.parse_file("path/to/top_design.xml")
linked = link(design, library) # optional: design_configuration=..., component=...
linked.instances # dict[str, LinkedInstance], by instance name
linked.interconnections # list[LinkedInterconnection], with the interfaces that resolved
linked.component # the component containing the design, or None
linked.diagnostics # list[Diagnostic]A design's hierInterface and externalPortReference elements refer to the bus interfaces and
ports of the component containing it. link() uses the component given with component=, or
else the one component of the library with a view instantiating the design. With none, or
several, these references are not checked, and a warning says so.
Each Diagnostic has a message, a severity (Severity.ERROR or Severity.WARNING), a
location (a VLNV, a file, or a path such as vendor:lib:top:1.0/conn0), and, when it is an
Annex B rule, its rule_id and rule_name. str(diagnostic) gives the line the CLI prints:
error: [SCR 2.4] interconnection 'conn0' connects ... (example.org:soc:top:1.0/conn0)
Library indexes documents by VLNV:
Library.scan(*folders)reads every IEEE 1685-2022 file under the folders. A missing folder raises an error; files of another IP-XACT version, or a folder with no 1685-2022 file, give a warning inlibrary.diagnostics.library.add_file(path)adds one file, with the same checks.library.add(document, path=None, replace=False, target=False)adds a document that only exists in memory, e.g. an importer's result.pathonly records where it came from.library.documents(kind=None)returns every document, or those of one type, e.g.library.documents(ipxact.Component).library.targets(kind=None)returns only the documents added withtarget=True: the ones an exporter writes, as opposed to those it only looks up.library.get(vlnv)returns the document with that VLNV, or None;get_component,get_design,get_bus_definition,get_abstraction_definitionandget_design_configurationalso return None for a document of another type.
A duplicate VLNV is reported as an SCR 1.1 error, unless replace=True.
IP-XACT values such as addressOffset, size or a parameter value are expressions, kept as
text by ipxact-compiler. xactflow.evaluate() computes them, following the expression
language of IEEE 1685-2022 Annex E (a subset of SystemVerilog):
from xactflow import evaluate, parameter_resolver
evaluate("2 + 3 * 4") # 14
evaluate("{3{1'b1}}") # 7
evaluate("WIDTH - 1", resolve_parameter=lambda name: "8") # 7
resolve = parameter_resolver(component.parameters) # by parameterId
evaluate(register.size, resolve_parameter=resolve) # an ipxact.Expression- A referenced parameter is cast to its
typeandsign: abytewith value200is-56. - A value outside its
minimum/maximumraisesExpressionError, naming the parameter, or thename=given toevaluate(). - Supported: integral and real values, all non-string operators (with reductions,
->,<->,inside), casts, concatenation, replication, streaming, bit and part selects,'0/'1, escaped identifiers,$clog2and the real math functions ($ln,$pow, ...). - Not supported, because
evaluate()returns one number: strings and$sformatf, array parameters, and the$ipxact_*functions, whose value depends on the design environment. - Arithmetic works on plain values, without SystemVerilog's context-dependent width rules:
4'hF + 4'h1is16. - Numbers use SystemVerilog syntax only: write
'h1F, not0x1F.
Annex B of the standard defines 281 SCRs in 15 tables. All are registered in xactflow.SCR,
one module per table, with their id, name and text as written in the standard (without its
"See also" references). 15 have a check today: SCR 1.2, 1.5, 1.9, 2.1 to 2.10, 2.17 and 13.5.
The others are placeholders that report nothing.
from xactflow import SCR
len(SCR.all_rules()) # 281
[r.id for r in SCR.all_rules() if r.implemented] # the 15 rules with a checkSCR.run_single_doc_checks(document) and SCR.run_post_config_checks(linked) can be called on
their own, e.g. by an exporter to check the IP-XACT it writes.
Plugins live in their own packages and are found through entry points:
- an
xactflow.Importer(groupxactflow.importers) reads a non-IP-XACT source and adds the IP-XACT documents it describes to aLibrary, withtarget=True. - an
xactflow.Exporter(groupxactflow.exporters) writes an output from the targets of aLibrary: RTL, documentation, IP-XACT XML... It looks up anything else it needs in the library, e.g. withlink(design, library). Each exporter says which targets it supports and raisesTypeErrorwhen the library has none.
class MyImporter(Importer):
name = "mine"
def import_(self, source_path, library, **options):
library.add(build_component(source_path), target=True)
class MyExporter(Exporter):
name = "mine"
def export(self, library, output_dir, **options):
designs = list(library.targets(ipxact.Design))
if not designs:
raise TypeError("'mine' needs an ipxact.Design target")
for design in designs:
write_rtl(link(design, library), output_dir)[project.entry-points."xactflow.importers"]
sv = "xactflow_sv:SVImporter"
[project.entry-points."xactflow.exporters"]
component = "xactflow_component:ComponentExporter"The entry point name is the subcommand.
A plugin that fails to load is skipped with a warning; the others keep working.
| Package | Kind | Subcommand | Does |
|---|---|---|---|
| XactFlow-sv | importer | sv |
SystemVerilog module + metadata → ipxact.Component |
| XactFlow-archidesc | importer | archidesc |
architecture description → ipxact.Design |
| XactFlow-component | exporter | component |
ipxact.Component → component XML |
| XactFlow-design | exporter | design |
ipxact.Design → design XML |
The plugins above were written for the previous API, where import_ returned an object and
export took one; they need a release for this one.
- 266 of the 281 SCRs have no check yet. Next: the single-file rules, and the
overlap/alignment rules, which can now use
evaluate(). - Monitor connections are not checked.
link()resolves them, but a broken reference is dropped without a message. - One level of hierarchy.
link()checks a design against its instances and the component containing it, but does not go into the designs of its instances.
LGPL-3.0. See LICENSE.