ipxact-compiler 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ipxact_compiler-0.2.0/PKG-INFO +188 -0
- ipxact_compiler-0.2.0/README.md +161 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/pyproject.toml +1 -1
- ipxact_compiler-0.2.0/src/ipxact/__init__.py +17 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/abstractiondefinition_parser.py +49 -16
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/busdefinition_parser.py +10 -8
- ipxact_compiler-0.2.0/src/ipxact/parser/common_parser.py +739 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/component_parser.py +490 -227
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/design_parser.py +26 -21
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/designconfig_parser.py +10 -6
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/main_parser.py +14 -6
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/__init__.py +77 -12
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/abstractiondefinition.py +37 -4
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/busdefinition.py +3 -2
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/businterface.py +58 -39
- ipxact_compiler-0.2.0/src/ipxact/schema/common.py +416 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/component.py +4 -7
- ipxact_compiler-0.2.0/src/ipxact/schema/component_sections.py +262 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/design.py +14 -2
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/designconfig.py +8 -2
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/memorymap.py +101 -14
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/model.py +30 -11
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/ports.py +119 -19
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/vlnv.py +7 -3
- ipxact_compiler-0.2.0/src/ipxact/validation.py +57 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/LICENSE +202 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/README.md +12 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/abstractionDefinition.xsd +302 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/abstractor.xsd +165 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/autoConfigure.xsd +109 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/busDefinition.xsd +114 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/busInterface.xsd +591 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/catalog.xsd +79 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/commonStructures.xsd +1134 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/component.xsd +450 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/constraints.xsd +261 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/design.xsd +73 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/designConfig.xsd +187 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/file.xsd +467 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/fileType.xsd +88 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/generator.xsd +286 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/identifier.xsd +102 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/index.xsd +72 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/memoryMap.xsd +1862 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/model.xsd +372 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/port.xsd +1161 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/signalDrivers.xsd +221 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/simpleTypes.xsd +286 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/subInstances.xsd +376 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/typeDefinitions.xsd +198 -0
- ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/xml.xsd +24 -0
- ipxact_compiler-0.2.0/src/ipxact_compiler.egg-info/PKG-INFO +188 -0
- ipxact_compiler-0.2.0/src/ipxact_compiler.egg-info/SOURCES.txt +59 -0
- ipxact_compiler-0.2.0/tests/test_validation.py +66 -0
- ipxact_compiler-0.1.2/PKG-INFO +0 -133
- ipxact_compiler-0.1.2/README.md +0 -106
- ipxact_compiler-0.1.2/src/ipxact/__init__.py +0 -7
- ipxact_compiler-0.1.2/src/ipxact/parser/common_parser.py +0 -443
- ipxact_compiler-0.1.2/src/ipxact/schema/common.py +0 -176
- ipxact_compiler-0.1.2/src/ipxact/schema/component_sections.py +0 -146
- ipxact_compiler-0.1.2/src/ipxact_compiler.egg-info/PKG-INFO +0 -133
- ipxact_compiler-0.1.2/src/ipxact_compiler.egg-info/SOURCES.txt +0 -31
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/LICENSE +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/setup.cfg +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/__init__.py +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/py.typed +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/dependency_links.txt +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/requires.txt +0 -0
- {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ipxact-compiler
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Parses IEEE 1685-2022 IP-XACT XML into a Python object model.
|
|
5
|
+
Author: Maxime Travaillard
|
|
6
|
+
License-Expression: LGPL-3.0-only
|
|
7
|
+
Project-URL: Repository, https://github.com/IP-XACT/ipxact-compiler
|
|
8
|
+
Project-URL: Issues, https://github.com/IP-XACT/ipxact-compiler/issues
|
|
9
|
+
Keywords: IP-XACT,IEEE 1685,XML,Compiler
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: lxml
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# ipxact-compiler
|
|
29
|
+
|
|
30
|
+
A Python library that parses [IEEE 1685-2022](https://standards.ieee.org/ieee/1685/10307/) IP-XACT
|
|
31
|
+
XML documents into a Python object model.
|
|
32
|
+
|
|
33
|
+
It is a standalone, general-purpose parsing library, not tied to any specific downstream tool or
|
|
34
|
+
flow. `ipxact-compiler` reads IP-XACT and hands you back Python objects; it does not resolve
|
|
35
|
+
cross-file references, link a design, validate semantic consistency, or generate any output.
|
|
36
|
+
That is the job of tools built on top of it.
|
|
37
|
+
|
|
38
|
+
## What it supports
|
|
39
|
+
|
|
40
|
+
Five IP-XACT top-level document types are supported for now:
|
|
41
|
+
|
|
42
|
+
- `component`
|
|
43
|
+
- `design`
|
|
44
|
+
- `designConfiguration`
|
|
45
|
+
- `busDefinition`
|
|
46
|
+
- `abstractionDefinition`
|
|
47
|
+
|
|
48
|
+
The object model covers the IEEE 1685-2022 XSD schema for these document types: every element and
|
|
49
|
+
attribute the schema allows in them has a place in the object model and is read by the parser. This
|
|
50
|
+
is checked against the official Accellera XSD files, with XML documents generated from the schema
|
|
51
|
+
itself.
|
|
52
|
+
|
|
53
|
+
### How values are represented
|
|
54
|
+
|
|
55
|
+
- **Expressions are `Expression` objects.** Fields typed as an IP-XACT expression (parameter values,
|
|
56
|
+
addresses, sizes, vector and array bounds, and similar) hold an `Expression` with the raw `value`
|
|
57
|
+
text and its optional `minimum`/`maximum` bounds. Expressions are not evaluated: `"DATA_W-1"` stays
|
|
58
|
+
`"DATA_W-1"`. [XactFlow](https://github.com/IP-XACT/XactFlow) provides an evaluator
|
|
59
|
+
(`xactflow.evaluate`).
|
|
60
|
+
- **`xml:id` attributes** are kept as `xml_id` fields. Plain text elements that can carry an `xml:id`
|
|
61
|
+
(`viewRef`, `group`, `dependency`, ...) are `TextValue` objects (`value` and `xml_id`).
|
|
62
|
+
- **Attributes from other namespaces**, where the schema allows them, are kept in `other_attributes`
|
|
63
|
+
dictionaries, keyed by `{namespace}name`.
|
|
64
|
+
- **`vendorExtensions` is opaque.** Each extension is kept as a raw XML string, not modeled
|
|
65
|
+
per-vendor.
|
|
66
|
+
- **References are kept as references.** VLNV references (`busType`, `componentRef`, ...) and the
|
|
67
|
+
`*DefinitionRef` elements that point into a `typeDefinitions` document are stored as they are
|
|
68
|
+
written; resolving them is left to the caller.
|
|
69
|
+
|
|
70
|
+
### What is not kept
|
|
71
|
+
|
|
72
|
+
- XML comments and processing instructions.
|
|
73
|
+
- `xsi:` attributes, such as `xsi:schemaLocation` on the root element. On elements that have
|
|
74
|
+
`other_attributes`, they are kept there like any other foreign attribute.
|
|
75
|
+
- The relative order of sibling elements that the schema lets you mix but that end up in separate
|
|
76
|
+
lists: `interconnection` and `monitorInterconnection`, and the different kinds of instantiations.
|
|
77
|
+
Order within each list is kept.
|
|
78
|
+
- Whether an optional element or attribute with a schema default was written out or omitted: both give
|
|
79
|
+
the default value.
|
|
80
|
+
- The `invert` attribute of a `portMap` is not typed in the XSD; it is read as a boolean.
|
|
81
|
+
|
|
82
|
+
Other IP-XACT document types (`typeDefinitions`, `catalog`, `abstractor`, `generatorChain`) are not
|
|
83
|
+
parsed.
|
|
84
|
+
|
|
85
|
+
## Installation
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install ipxact-compiler
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or, for local development:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/IP-XACT/ipxact-compiler.git
|
|
95
|
+
cd ipxact-compiler
|
|
96
|
+
pip install -e ".[dev]"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Requires Python >= 3.9. The only runtime dependency is [`lxml`](https://lxml.de/).
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import ipxact
|
|
105
|
+
|
|
106
|
+
component = ipxact.parse_file("path/to/some_component.xml")
|
|
107
|
+
|
|
108
|
+
component.vlnv # VLNV
|
|
109
|
+
component.bus_interfaces # list[BusInterface]
|
|
110
|
+
component.memory_maps # list[MemoryMap]
|
|
111
|
+
component.model # Model | None
|
|
112
|
+
|
|
113
|
+
register = component.memory_maps[0].items[0].registers[0]
|
|
114
|
+
register.size # Expression(value="32", minimum=None, maximum=None, ...)
|
|
115
|
+
register.size.value # "32"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`ipxact.parse_file(path)` reads a file, figures out its document type from the root element, and
|
|
119
|
+
returns the matching dataclass (`Component`, `Design`, `DesignConfiguration`, `BusDefinition`, or
|
|
120
|
+
`AbstractionDefinition`).
|
|
121
|
+
|
|
122
|
+
Every schema class (`Component`, `VLNV`, `BusInterface`, `Register`, `Field`, `Expression`, and so
|
|
123
|
+
on) is re-exported at the top level, so `ipxact.<ClassName>` works without reaching into submodules.
|
|
124
|
+
|
|
125
|
+
### Validation
|
|
126
|
+
|
|
127
|
+
Parsing does not validate by default. The IEEE 1685-2022 XSD files are shipped with the package, so
|
|
128
|
+
validation works offline:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
issues = ipxact.validate("path/to/some_component.xml") # [] when valid
|
|
132
|
+
for issue in issues:
|
|
133
|
+
print(issue.line, issue.message)
|
|
134
|
+
|
|
135
|
+
component = ipxact.parse_file("path/to/some_component.xml", validate=True)
|
|
136
|
+
# raises ipxact.ValidationError (with .issues) if the file is not valid
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`ipxact.validate()` also accepts an lxml tree or element, so tools that write IP-XACT can validate
|
|
140
|
+
their output before saving it. `ipxact.xsd_path()` gives the folder holding the XSD files
|
|
141
|
+
(`index.xsd` is the entry point) for tools that need the files themselves.
|
|
142
|
+
|
|
143
|
+
XSD validation checks the structure, types and values of a document, and the uniqueness and reference
|
|
144
|
+
rules the schema defines (for example, two parameters with the same `parameterId`). It does not check
|
|
145
|
+
the Semantic Consistency Rules of the standard.
|
|
146
|
+
|
|
147
|
+
## Design principles
|
|
148
|
+
|
|
149
|
+
- **Single-file parsing only.** `ipxact-compiler` never opens a second file on its own. Resolving
|
|
150
|
+
VLNV references across a library of files (for example, finding the `Component` that a `Design`'s
|
|
151
|
+
instance refers to) is left to the caller.
|
|
152
|
+
- **Input files are assumed to be valid.** Unless you ask for validation, the parser assumes the
|
|
153
|
+
IP-XACT documents you give it are well-formed and conform to the standard. This is why it favors
|
|
154
|
+
defaulting over raising on missing or malformed data. Use `validate=True` or `ipxact.validate()`
|
|
155
|
+
when the input may not be valid.
|
|
156
|
+
- **The XSD files are shipped, not downloaded.** We decided to ship a copy of the official
|
|
157
|
+
Accellera files instead of downloading them when needed:
|
|
158
|
+
- Validation works offline, including in CI.
|
|
159
|
+
- Validation results only change when we decide to update. The published 1685-2022 files can be
|
|
160
|
+
updated at the same URL (two of the current files were last changed in September 2024, the others in July 2023); with a copy,
|
|
161
|
+
taking such an update is a deliberate change, tested like any other.
|
|
162
|
+
- The website only serves the files over plain HTTP.
|
|
163
|
+
|
|
164
|
+
The online URL (for example in `xsi:schemaLocation`) is only a hint of where to find the schema.
|
|
165
|
+
The schema itself is identified by its namespace, so a local copy is the same schema. To update the
|
|
166
|
+
copy, replace the files (see `src/ipxact/xsd/1685-2022/README.md`).
|
|
167
|
+
|
|
168
|
+
## Known limitations / ideas for later
|
|
169
|
+
|
|
170
|
+
These are open items, not commitments.
|
|
171
|
+
|
|
172
|
+
- **No deliberate error-handling philosophy yet.** Right now, malformed input either silently
|
|
173
|
+
produces a default value or raises whatever low-level Python exception happens to occur (a
|
|
174
|
+
`ValueError`, an `AttributeError`, etc.) rather than a clear, intentional error type. Deciding on
|
|
175
|
+
and implementing a consistent policy (raise vs. warn vs. silently default, and what exception
|
|
176
|
+
types/messages to use) is still open.
|
|
177
|
+
- **No Semantic Consistency Rule (SCR) checking.** This rules are out of scope for this library.
|
|
178
|
+
They are handled by [XactFlow](https://github.com/IP-XACT/XactFlow), including the rules that
|
|
179
|
+
can be checked on a single document.
|
|
180
|
+
- **No dedicated documentation yet.** This README covers the basics, but a proper documentation site
|
|
181
|
+
(full API reference, more usage examples) is planned for the future.
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
LGPL-3.0. See [`LICENSE`](LICENSE).
|
|
186
|
+
|
|
187
|
+
The IEEE 1685-2022 XSD files in `src/ipxact/xsd/1685-2022/` are Accellera's, unmodified, under the
|
|
188
|
+
Apache License 2.0 (see the `LICENSE` file in that folder).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# ipxact-compiler
|
|
2
|
+
|
|
3
|
+
A Python library that parses [IEEE 1685-2022](https://standards.ieee.org/ieee/1685/10307/) IP-XACT
|
|
4
|
+
XML documents into a Python object model.
|
|
5
|
+
|
|
6
|
+
It is a standalone, general-purpose parsing library, not tied to any specific downstream tool or
|
|
7
|
+
flow. `ipxact-compiler` reads IP-XACT and hands you back Python objects; it does not resolve
|
|
8
|
+
cross-file references, link a design, validate semantic consistency, or generate any output.
|
|
9
|
+
That is the job of tools built on top of it.
|
|
10
|
+
|
|
11
|
+
## What it supports
|
|
12
|
+
|
|
13
|
+
Five IP-XACT top-level document types are supported for now:
|
|
14
|
+
|
|
15
|
+
- `component`
|
|
16
|
+
- `design`
|
|
17
|
+
- `designConfiguration`
|
|
18
|
+
- `busDefinition`
|
|
19
|
+
- `abstractionDefinition`
|
|
20
|
+
|
|
21
|
+
The object model covers the IEEE 1685-2022 XSD schema for these document types: every element and
|
|
22
|
+
attribute the schema allows in them has a place in the object model and is read by the parser. This
|
|
23
|
+
is checked against the official Accellera XSD files, with XML documents generated from the schema
|
|
24
|
+
itself.
|
|
25
|
+
|
|
26
|
+
### How values are represented
|
|
27
|
+
|
|
28
|
+
- **Expressions are `Expression` objects.** Fields typed as an IP-XACT expression (parameter values,
|
|
29
|
+
addresses, sizes, vector and array bounds, and similar) hold an `Expression` with the raw `value`
|
|
30
|
+
text and its optional `minimum`/`maximum` bounds. Expressions are not evaluated: `"DATA_W-1"` stays
|
|
31
|
+
`"DATA_W-1"`. [XactFlow](https://github.com/IP-XACT/XactFlow) provides an evaluator
|
|
32
|
+
(`xactflow.evaluate`).
|
|
33
|
+
- **`xml:id` attributes** are kept as `xml_id` fields. Plain text elements that can carry an `xml:id`
|
|
34
|
+
(`viewRef`, `group`, `dependency`, ...) are `TextValue` objects (`value` and `xml_id`).
|
|
35
|
+
- **Attributes from other namespaces**, where the schema allows them, are kept in `other_attributes`
|
|
36
|
+
dictionaries, keyed by `{namespace}name`.
|
|
37
|
+
- **`vendorExtensions` is opaque.** Each extension is kept as a raw XML string, not modeled
|
|
38
|
+
per-vendor.
|
|
39
|
+
- **References are kept as references.** VLNV references (`busType`, `componentRef`, ...) and the
|
|
40
|
+
`*DefinitionRef` elements that point into a `typeDefinitions` document are stored as they are
|
|
41
|
+
written; resolving them is left to the caller.
|
|
42
|
+
|
|
43
|
+
### What is not kept
|
|
44
|
+
|
|
45
|
+
- XML comments and processing instructions.
|
|
46
|
+
- `xsi:` attributes, such as `xsi:schemaLocation` on the root element. On elements that have
|
|
47
|
+
`other_attributes`, they are kept there like any other foreign attribute.
|
|
48
|
+
- The relative order of sibling elements that the schema lets you mix but that end up in separate
|
|
49
|
+
lists: `interconnection` and `monitorInterconnection`, and the different kinds of instantiations.
|
|
50
|
+
Order within each list is kept.
|
|
51
|
+
- Whether an optional element or attribute with a schema default was written out or omitted: both give
|
|
52
|
+
the default value.
|
|
53
|
+
- The `invert` attribute of a `portMap` is not typed in the XSD; it is read as a boolean.
|
|
54
|
+
|
|
55
|
+
Other IP-XACT document types (`typeDefinitions`, `catalog`, `abstractor`, `generatorChain`) are not
|
|
56
|
+
parsed.
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install ipxact-compiler
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or, for local development:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/IP-XACT/ipxact-compiler.git
|
|
68
|
+
cd ipxact-compiler
|
|
69
|
+
pip install -e ".[dev]"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Requires Python >= 3.9. The only runtime dependency is [`lxml`](https://lxml.de/).
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import ipxact
|
|
78
|
+
|
|
79
|
+
component = ipxact.parse_file("path/to/some_component.xml")
|
|
80
|
+
|
|
81
|
+
component.vlnv # VLNV
|
|
82
|
+
component.bus_interfaces # list[BusInterface]
|
|
83
|
+
component.memory_maps # list[MemoryMap]
|
|
84
|
+
component.model # Model | None
|
|
85
|
+
|
|
86
|
+
register = component.memory_maps[0].items[0].registers[0]
|
|
87
|
+
register.size # Expression(value="32", minimum=None, maximum=None, ...)
|
|
88
|
+
register.size.value # "32"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`ipxact.parse_file(path)` reads a file, figures out its document type from the root element, and
|
|
92
|
+
returns the matching dataclass (`Component`, `Design`, `DesignConfiguration`, `BusDefinition`, or
|
|
93
|
+
`AbstractionDefinition`).
|
|
94
|
+
|
|
95
|
+
Every schema class (`Component`, `VLNV`, `BusInterface`, `Register`, `Field`, `Expression`, and so
|
|
96
|
+
on) is re-exported at the top level, so `ipxact.<ClassName>` works without reaching into submodules.
|
|
97
|
+
|
|
98
|
+
### Validation
|
|
99
|
+
|
|
100
|
+
Parsing does not validate by default. The IEEE 1685-2022 XSD files are shipped with the package, so
|
|
101
|
+
validation works offline:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
issues = ipxact.validate("path/to/some_component.xml") # [] when valid
|
|
105
|
+
for issue in issues:
|
|
106
|
+
print(issue.line, issue.message)
|
|
107
|
+
|
|
108
|
+
component = ipxact.parse_file("path/to/some_component.xml", validate=True)
|
|
109
|
+
# raises ipxact.ValidationError (with .issues) if the file is not valid
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`ipxact.validate()` also accepts an lxml tree or element, so tools that write IP-XACT can validate
|
|
113
|
+
their output before saving it. `ipxact.xsd_path()` gives the folder holding the XSD files
|
|
114
|
+
(`index.xsd` is the entry point) for tools that need the files themselves.
|
|
115
|
+
|
|
116
|
+
XSD validation checks the structure, types and values of a document, and the uniqueness and reference
|
|
117
|
+
rules the schema defines (for example, two parameters with the same `parameterId`). It does not check
|
|
118
|
+
the Semantic Consistency Rules of the standard.
|
|
119
|
+
|
|
120
|
+
## Design principles
|
|
121
|
+
|
|
122
|
+
- **Single-file parsing only.** `ipxact-compiler` never opens a second file on its own. Resolving
|
|
123
|
+
VLNV references across a library of files (for example, finding the `Component` that a `Design`'s
|
|
124
|
+
instance refers to) is left to the caller.
|
|
125
|
+
- **Input files are assumed to be valid.** Unless you ask for validation, the parser assumes the
|
|
126
|
+
IP-XACT documents you give it are well-formed and conform to the standard. This is why it favors
|
|
127
|
+
defaulting over raising on missing or malformed data. Use `validate=True` or `ipxact.validate()`
|
|
128
|
+
when the input may not be valid.
|
|
129
|
+
- **The XSD files are shipped, not downloaded.** We decided to ship a copy of the official
|
|
130
|
+
Accellera files instead of downloading them when needed:
|
|
131
|
+
- Validation works offline, including in CI.
|
|
132
|
+
- Validation results only change when we decide to update. The published 1685-2022 files can be
|
|
133
|
+
updated at the same URL (two of the current files were last changed in September 2024, the others in July 2023); with a copy,
|
|
134
|
+
taking such an update is a deliberate change, tested like any other.
|
|
135
|
+
- The website only serves the files over plain HTTP.
|
|
136
|
+
|
|
137
|
+
The online URL (for example in `xsi:schemaLocation`) is only a hint of where to find the schema.
|
|
138
|
+
The schema itself is identified by its namespace, so a local copy is the same schema. To update the
|
|
139
|
+
copy, replace the files (see `src/ipxact/xsd/1685-2022/README.md`).
|
|
140
|
+
|
|
141
|
+
## Known limitations / ideas for later
|
|
142
|
+
|
|
143
|
+
These are open items, not commitments.
|
|
144
|
+
|
|
145
|
+
- **No deliberate error-handling philosophy yet.** Right now, malformed input either silently
|
|
146
|
+
produces a default value or raises whatever low-level Python exception happens to occur (a
|
|
147
|
+
`ValueError`, an `AttributeError`, etc.) rather than a clear, intentional error type. Deciding on
|
|
148
|
+
and implementing a consistent policy (raise vs. warn vs. silently default, and what exception
|
|
149
|
+
types/messages to use) is still open.
|
|
150
|
+
- **No Semantic Consistency Rule (SCR) checking.** This rules are out of scope for this library.
|
|
151
|
+
They are handled by [XactFlow](https://github.com/IP-XACT/XactFlow), including the rules that
|
|
152
|
+
can be checked on a single document.
|
|
153
|
+
- **No dedicated documentation yet.** This README covers the basics, but a proper documentation site
|
|
154
|
+
(full API reference, more usage examples) is planned for the future.
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
LGPL-3.0. See [`LICENSE`](LICENSE).
|
|
159
|
+
|
|
160
|
+
The IEEE 1685-2022 XSD files in `src/ipxact/xsd/1685-2022/` are Accellera's, unmodified, under the
|
|
161
|
+
Apache License 2.0 (see the `LICENSE` file in that folder).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
__version__ = "0.2.0"
|
|
2
|
+
|
|
3
|
+
from .parser import parse_element, parse_file
|
|
4
|
+
from .schema import * # noqa: F401,F403
|
|
5
|
+
from .schema import __all__ as _schema_all
|
|
6
|
+
from .validation import ValidationError, ValidationIssue, validate, xsd_path
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
*_schema_all,
|
|
10
|
+
"parse_element",
|
|
11
|
+
"parse_file",
|
|
12
|
+
"validate",
|
|
13
|
+
"xsd_path",
|
|
14
|
+
"ValidationError",
|
|
15
|
+
"ValidationIssue",
|
|
16
|
+
"__version__",
|
|
17
|
+
]
|
{ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/abstractiondefinition_parser.py
RENAMED
|
@@ -5,6 +5,8 @@ from lxml import etree
|
|
|
5
5
|
from ..schema.abstractiondefinition import (
|
|
6
6
|
AbstractionDefinition,
|
|
7
7
|
AbstractionPort,
|
|
8
|
+
Packet,
|
|
9
|
+
PacketField,
|
|
8
10
|
PortConstraints,
|
|
9
11
|
Presence,
|
|
10
12
|
RequiresDriver,
|
|
@@ -22,11 +24,14 @@ from .common_parser import (
|
|
|
22
24
|
child,
|
|
23
25
|
children,
|
|
24
26
|
elem_text,
|
|
27
|
+
expr,
|
|
25
28
|
parse_assertions,
|
|
26
29
|
parse_children,
|
|
27
30
|
parse_choices,
|
|
28
31
|
parse_drive_constraint,
|
|
32
|
+
parse_optional_expression,
|
|
29
33
|
parse_load_constraint,
|
|
34
|
+
parse_name_group,
|
|
30
35
|
parse_parameters,
|
|
31
36
|
parse_protocol,
|
|
32
37
|
parse_qualifier,
|
|
@@ -34,7 +39,9 @@ from .common_parser import (
|
|
|
34
39
|
parse_vendor_extensions,
|
|
35
40
|
parse_vlnv,
|
|
36
41
|
parse_vlnv_ref,
|
|
42
|
+
required_expr,
|
|
37
43
|
text,
|
|
44
|
+
xml_id,
|
|
38
45
|
)
|
|
39
46
|
|
|
40
47
|
|
|
@@ -49,9 +56,8 @@ def parse_abstractiondefinition(root: etree._Element) -> AbstractionDefinition:
|
|
|
49
56
|
choices=parse_choices(root),
|
|
50
57
|
parameters=parse_parameters(root),
|
|
51
58
|
assertions=parse_assertions(root),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
description=text(root, "description"),
|
|
59
|
+
**parse_name_group(root),
|
|
60
|
+
xml_id=xml_id(root),
|
|
55
61
|
vendor_extensions=parse_vendor_extensions(root),
|
|
56
62
|
)
|
|
57
63
|
|
|
@@ -65,7 +71,7 @@ def _parse_port_constraints(elem: etree._Element) -> PortConstraints:
|
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
def _parse_requires_driver(elem: etree._Element) -> RequiresDriver:
|
|
68
|
-
return RequiresDriver(value=as_bool(elem
|
|
74
|
+
return RequiresDriver(value=as_bool(elem_text(elem), False), driver_type=elem.get("driverType", "any"))
|
|
69
75
|
|
|
70
76
|
|
|
71
77
|
def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
|
|
@@ -76,10 +82,10 @@ def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
|
|
|
76
82
|
mirrored_mode_constraints_elem = child(elem, "mirroredModeConstraints")
|
|
77
83
|
return WireModeConstraints(
|
|
78
84
|
presence=Presence(presence) if presence else Presence.OPTIONAL,
|
|
79
|
-
width=
|
|
85
|
+
width=parse_optional_expression(width_elem),
|
|
80
86
|
width_all_bits_required=attr_bool(width_elem, "allBits", False) if width_elem is not None else False,
|
|
81
|
-
#
|
|
82
|
-
direction=elem_text(direction_elem) or "out",
|
|
87
|
+
# default to out and missing means no restiction, so None.
|
|
88
|
+
direction=(elem_text(direction_elem) or "out") if direction_elem is not None else None,
|
|
83
89
|
mode_constraints=(
|
|
84
90
|
_parse_port_constraints(mode_constraints_elem) if mode_constraints_elem is not None else None
|
|
85
91
|
),
|
|
@@ -92,7 +98,9 @@ def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
|
|
|
92
98
|
|
|
93
99
|
|
|
94
100
|
def _parse_wire_system_constraints(elem: etree._Element) -> WireSystemConstraints:
|
|
95
|
-
return WireSystemConstraints(
|
|
101
|
+
return WireSystemConstraints(
|
|
102
|
+
group=text(elem, "group") or "", constraints=_parse_wire_mode_constraints(elem), xml_id=xml_id(elem)
|
|
103
|
+
)
|
|
96
104
|
|
|
97
105
|
|
|
98
106
|
def _parse_wire_abstraction_port(elem: etree._Element) -> WireAbstractionPort:
|
|
@@ -104,7 +112,7 @@ def _parse_wire_abstraction_port(elem: etree._Element) -> WireAbstractionPort:
|
|
|
104
112
|
on_system=[_parse_wire_system_constraints(e) for e in children(elem, "onSystem")],
|
|
105
113
|
on_initiator=_parse_wire_mode_constraints(on_initiator_elem) if on_initiator_elem is not None else None,
|
|
106
114
|
on_target=_parse_wire_mode_constraints(on_target_elem) if on_target_elem is not None else None,
|
|
107
|
-
default_value=
|
|
115
|
+
default_value=expr(elem, "defaultValue"),
|
|
108
116
|
requires_driver=_parse_requires_driver(requires_driver_elem) if requires_driver_elem is not None else None,
|
|
109
117
|
)
|
|
110
118
|
|
|
@@ -115,17 +123,18 @@ def _parse_transactional_mode_constraints(elem: etree._Element) -> Transactional
|
|
|
115
123
|
kind_elem = child(elem, "kind")
|
|
116
124
|
return TransactionalModeConstraints(
|
|
117
125
|
presence=Presence(presence) if presence else Presence.OPTIONAL,
|
|
118
|
-
#
|
|
119
|
-
initiative=elem_text(initiative_elem) or "requires",
|
|
126
|
+
# Same rule as <direction>: missing means "not restricted", default is "requires".
|
|
127
|
+
initiative=(elem_text(initiative_elem) or "requires") if initiative_elem is not None else None,
|
|
120
128
|
kind=elem_text(kind_elem),
|
|
121
|
-
|
|
129
|
+
kind_custom=kind_elem.get("custom") if kind_elem is not None else None,
|
|
130
|
+
bus_width=expr(elem, "busWidth"),
|
|
122
131
|
protocol=parse_protocol(elem),
|
|
123
132
|
)
|
|
124
133
|
|
|
125
134
|
|
|
126
135
|
def _parse_transactional_system_constraints(elem: etree._Element) -> TransactionalSystemConstraints:
|
|
127
136
|
return TransactionalSystemConstraints(
|
|
128
|
-
group=text(elem, "group") or "", constraints=_parse_transactional_mode_constraints(elem)
|
|
137
|
+
group=text(elem, "group") or "", constraints=_parse_transactional_mode_constraints(elem), xml_id=xml_id(elem)
|
|
129
138
|
)
|
|
130
139
|
|
|
131
140
|
|
|
@@ -142,6 +151,30 @@ def _parse_transactional_abstraction_port(elem: etree._Element) -> Transactional
|
|
|
142
151
|
)
|
|
143
152
|
|
|
144
153
|
|
|
154
|
+
def _parse_packet_field(elem: etree._Element) -> PacketField:
|
|
155
|
+
return PacketField(
|
|
156
|
+
name=text(elem, "name") or "",
|
|
157
|
+
width=required_expr(elem, "width"),
|
|
158
|
+
value=expr(elem, "value"),
|
|
159
|
+
endianness=text(elem, "endianness"),
|
|
160
|
+
qualifier=parse_qualifier(elem),
|
|
161
|
+
**parse_name_group(elem),
|
|
162
|
+
xml_id=xml_id(elem),
|
|
163
|
+
vendor_extensions=parse_vendor_extensions(elem),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _parse_packet(elem: etree._Element) -> Packet:
|
|
168
|
+
return Packet(
|
|
169
|
+
name=text(elem, "name") or "",
|
|
170
|
+
packet_fields=parse_children(elem, "packetFields", "packetField", _parse_packet_field),
|
|
171
|
+
endianness=text(elem, "endianness"),
|
|
172
|
+
**parse_name_group(elem),
|
|
173
|
+
xml_id=xml_id(elem),
|
|
174
|
+
vendor_extensions=parse_vendor_extensions(elem),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
145
178
|
def _parse_abstraction_port(elem: etree._Element) -> AbstractionPort:
|
|
146
179
|
wire_elem = child(elem, "wire")
|
|
147
180
|
transactional_elem = child(elem, "transactional")
|
|
@@ -151,9 +184,9 @@ def _parse_abstraction_port(elem: etree._Element) -> AbstractionPort:
|
|
|
151
184
|
transactional=(
|
|
152
185
|
_parse_transactional_abstraction_port(transactional_elem) if transactional_elem is not None else None
|
|
153
186
|
),
|
|
187
|
+
packets=parse_children(elem, "packets", "packet", _parse_packet),
|
|
154
188
|
match=bool_text(elem, "match", False),
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
description=text(elem, "description"),
|
|
189
|
+
**parse_name_group(elem),
|
|
190
|
+
xml_id=xml_id(elem),
|
|
158
191
|
vendor_extensions=parse_vendor_extensions(elem),
|
|
159
192
|
)
|
|
@@ -6,14 +6,17 @@ from ..schema.busdefinition import BusDefinition
|
|
|
6
6
|
from .common_parser import (
|
|
7
7
|
bool_text,
|
|
8
8
|
child,
|
|
9
|
+
expr,
|
|
9
10
|
parse_assertions,
|
|
11
|
+
parse_children,
|
|
10
12
|
parse_choices,
|
|
13
|
+
parse_name_group,
|
|
11
14
|
parse_parameters,
|
|
12
|
-
parse_texts,
|
|
13
15
|
parse_vendor_extensions,
|
|
14
16
|
parse_vlnv,
|
|
15
17
|
parse_vlnv_ref,
|
|
16
|
-
|
|
18
|
+
text_value,
|
|
19
|
+
xml_id,
|
|
17
20
|
)
|
|
18
21
|
|
|
19
22
|
|
|
@@ -26,14 +29,13 @@ def parse_busdefinition(root: etree._Element) -> BusDefinition:
|
|
|
26
29
|
is_addressable=bool_text(root, "isAddressable", False),
|
|
27
30
|
broadcast=bool_text(root, "broadcast"),
|
|
28
31
|
extends=parse_vlnv_ref(extends_elem) if extends_elem is not None else None,
|
|
29
|
-
max_initiators=
|
|
30
|
-
max_targets=
|
|
31
|
-
system_group_names=
|
|
32
|
+
max_initiators=expr(root, "maxInitiators"),
|
|
33
|
+
max_targets=expr(root, "maxTargets"),
|
|
34
|
+
system_group_names=parse_children(root, "systemGroupNames", "systemGroupName", text_value),
|
|
32
35
|
choices=parse_choices(root),
|
|
33
36
|
parameters=parse_parameters(root),
|
|
34
37
|
assertions=parse_assertions(root),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
description=text(root, "description"),
|
|
38
|
+
**parse_name_group(root),
|
|
39
|
+
xml_id=xml_id(root),
|
|
38
40
|
vendor_extensions=parse_vendor_extensions(root),
|
|
39
41
|
)
|