xactflow-component 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ from pathlib import Path
6
+
7
+ import ipxact
8
+ from xactflow import Exporter
9
+
10
+ from .component_writer import component_to_bytes, write_component, write_component_file
11
+
12
+ __all__ = [
13
+ "ComponentExporter",
14
+ "__version__",
15
+ "component_to_bytes",
16
+ "write_component",
17
+ "write_component_file",
18
+ ]
19
+
20
+
21
+ class ComponentExporter(Exporter):
22
+ """Serialize an ipxact.Component into an IEEE 1685-2022 IP-XACT component XML file.
23
+
24
+ The output file is named after the component's VLNV name into output_dir.
25
+ """
26
+
27
+ name = "component"
28
+
29
+ def export(self, subject: object, output_dir: Path, **options: object) -> None:
30
+ if not isinstance(subject, ipxact.Component):
31
+ # ElaboratedDesign support (flattening a resolved multi-instance design into one
32
+ # boundary Component) is an agreed-on later addition.
33
+ raise TypeError(
34
+ f"xactflow-component only supports ipxact.Component, got {type(subject).__name__}"
35
+ )
36
+ output_dir = Path(output_dir)
37
+ output_dir.mkdir(parents=True, exist_ok=True)
38
+ write_component_file(subject, output_dir / f"{subject.vlnv.name}.xml")
@@ -0,0 +1,202 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Sequence
4
+
5
+ from lxml import etree
6
+
7
+ from ipxact.schema.businterface import (
8
+ AbstractionType,
9
+ BusInterface,
10
+ Channel,
11
+ IndirectInterface,
12
+ InitiatorInterface,
13
+ InterfaceMode,
14
+ MirroredTargetInterface,
15
+ MonitorInterface,
16
+ PortMap,
17
+ SystemInterface,
18
+ TargetInterface,
19
+ TransparentBridge,
20
+ )
21
+
22
+ from .common_writer import (
23
+ add_field_reference_group,
24
+ add_items,
25
+ add_local_name_refs,
26
+ add_mode_refs,
27
+ add_name_group,
28
+ add_parameters,
29
+ add_text,
30
+ add_texts,
31
+ bool_str,
32
+ element,
33
+ sub,
34
+ write_vendor_extensions,
35
+ write_vlnv_ref,
36
+ )
37
+
38
+
39
+ def _add_transparent_bridges(parent: etree._Element, bridges: Sequence[TransparentBridge]) -> None:
40
+ for bridge in bridges:
41
+ sub(parent, "transparentBridge", initiatorRef=bridge.initiator_ref)
42
+
43
+
44
+ def _add_port_map(parent: etree._Element, port_map: PortMap) -> None:
45
+ elem = sub(parent, "portMap", invert=bool_str(True) if port_map.invert else None)
46
+ logical_port = sub(elem, "logicalPort")
47
+ sub(logical_port, "name", port_map.logical_port)
48
+ # physicalPort and logicalTieOff are the two arms of a required choice.
49
+ if port_map.physical_port is not None:
50
+ physical_port = sub(elem, "physicalPort")
51
+ sub(physical_port, "name", port_map.physical_port)
52
+ elif port_map.logical_tie_off is not None:
53
+ sub(elem, "logicalTieOff", port_map.logical_tie_off)
54
+ else:
55
+ raise ValueError("a port map requires physical_port or logical_tie_off")
56
+ if port_map.is_informative:
57
+ sub(elem, "isInformative", bool_str(True))
58
+
59
+
60
+ def _add_abstraction_type(parent: etree._Element, abstraction_type: AbstractionType) -> None:
61
+ elem = sub(parent, "abstractionType")
62
+ add_texts(elem, "viewRef", abstraction_type.view_refs)
63
+ elem.append(write_vlnv_ref("abstractionRef", abstraction_type.abstraction_ref))
64
+ if abstraction_type.port_maps:
65
+ port_maps = sub(elem, "portMaps")
66
+ for port_map in abstraction_type.port_maps:
67
+ _add_port_map(port_maps, port_map)
68
+
69
+
70
+ def _add_initiator(parent: etree._Element, initiator: InitiatorInterface) -> None:
71
+ elem = sub(parent, "initiator")
72
+ if initiator.address_space_ref is None:
73
+ return
74
+ ref_elem = sub(elem, "addressSpaceRef", addressSpaceRef=initiator.address_space_ref)
75
+ add_text(ref_elem, "baseAddress", initiator.base_address)
76
+ add_mode_refs(ref_elem, initiator.mode_refs, with_priority=False)
77
+
78
+
79
+ def _add_target(parent: etree._Element, target: TargetInterface) -> None:
80
+ elem = sub(parent, "target")
81
+ # memoryMapRef and transparentBridge are the two arms of an optional choice.
82
+ if target.memory_map_ref is not None:
83
+ ref_elem = sub(elem, "memoryMapRef", memoryMapRef=target.memory_map_ref)
84
+ add_mode_refs(ref_elem, target.mode_refs, with_priority=False)
85
+ else:
86
+ _add_transparent_bridges(elem, target.transparent_bridges)
87
+ for group in target.file_set_ref_groups:
88
+ group_elem = sub(elem, "fileSetRefGroup")
89
+ add_text(group_elem, "group", group.group)
90
+ add_local_name_refs(group_elem, "fileSetRef", group.file_set_refs)
91
+
92
+
93
+ def _add_mirrored_target(parent: etree._Element, mirrored_target: MirroredTargetInterface) -> None:
94
+ elem = sub(parent, "mirroredTarget")
95
+ if not mirrored_target.remap_addresses and mirrored_target.range is None:
96
+ return
97
+ if not mirrored_target.remap_addresses or mirrored_target.range is None:
98
+ raise ValueError("a mirrored target's base addresses require both remap_addresses and range")
99
+ base_addresses = sub(elem, "baseAddresses")
100
+ for remap_address in mirrored_target.remap_addresses:
101
+ remap_elem = sub(base_addresses, "remapAddresses")
102
+ sub(remap_elem, "remapAddress", remap_address.value)
103
+ add_mode_refs(remap_elem, remap_address.mode_refs)
104
+ add_text(base_addresses, "range", mirrored_target.range)
105
+
106
+
107
+ def _add_system(parent: etree._Element, tag: str, system: SystemInterface) -> None:
108
+ sub(sub(parent, tag), "group", system.group)
109
+
110
+
111
+ def _add_monitor(parent: etree._Element, monitor: MonitorInterface) -> None:
112
+ elem = sub(parent, "monitor", interfaceMode=monitor.interface_mode.value)
113
+ add_text(elem, "group", monitor.group)
114
+
115
+
116
+ def _add_interface_mode(parent: etree._Element, bus_interface: BusInterface) -> None:
117
+ mode = bus_interface.mode
118
+ if mode is InterfaceMode.INITIATOR:
119
+ _add_initiator(parent, bus_interface.initiator or InitiatorInterface())
120
+ elif mode is InterfaceMode.TARGET:
121
+ _add_target(parent, bus_interface.target or TargetInterface())
122
+ elif mode is InterfaceMode.SYSTEM:
123
+ if bus_interface.system is None:
124
+ raise ValueError("mode is SYSTEM but system is not set")
125
+ _add_system(parent, "system", bus_interface.system)
126
+ elif mode is InterfaceMode.MIRRORED_TARGET:
127
+ _add_mirrored_target(parent, bus_interface.mirrored_target or MirroredTargetInterface())
128
+ elif mode is InterfaceMode.MIRRORED_INITIATOR:
129
+ sub(parent, "mirroredInitiator")
130
+ elif mode is InterfaceMode.MIRRORED_SYSTEM:
131
+ if bus_interface.mirrored_system is None:
132
+ raise ValueError("mode is MIRRORED_SYSTEM but mirrored_system is not set")
133
+ _add_system(parent, "mirroredSystem", bus_interface.mirrored_system)
134
+ elif mode is InterfaceMode.MONITOR:
135
+ if bus_interface.monitor is None:
136
+ raise ValueError("mode is MONITOR but monitor is not set")
137
+ _add_monitor(parent, bus_interface.monitor)
138
+ else:
139
+ raise ValueError(f"unrecognized bus interface mode: {mode!r}")
140
+
141
+
142
+ def write_bus_interface(bus_interface: BusInterface) -> etree._Element:
143
+ elem = element("busInterface")
144
+ add_name_group(elem, bus_interface.name, bus_interface.display_name, description=bus_interface.description)
145
+ elem.append(write_vlnv_ref("busType", bus_interface.bus_type))
146
+ if bus_interface.abstraction_types:
147
+ abstraction_types = sub(elem, "abstractionTypes")
148
+ for abstraction_type in bus_interface.abstraction_types:
149
+ _add_abstraction_type(abstraction_types, abstraction_type)
150
+ _add_interface_mode(elem, bus_interface)
151
+ if bus_interface.connection_required:
152
+ sub(elem, "connectionRequired", bool_str(True))
153
+ add_text(elem, "bitsInLau", bus_interface.bits_in_lau)
154
+ add_text(elem, "bitSteering", bus_interface.bit_steering)
155
+ add_text(elem, "endianness", bus_interface.endianness)
156
+ add_parameters(elem, bus_interface.parameters)
157
+ write_vendor_extensions(elem, bus_interface.vendor_extensions)
158
+ return elem
159
+
160
+
161
+ def add_bus_interfaces(parent: etree._Element, bus_interfaces: Sequence[BusInterface]) -> None:
162
+ add_items(parent, "busInterfaces", bus_interfaces, write_bus_interface)
163
+
164
+
165
+ def write_indirect_interface(indirect_interface: IndirectInterface) -> etree._Element:
166
+ elem = element("indirectInterface")
167
+ add_name_group(
168
+ elem,
169
+ indirect_interface.name,
170
+ indirect_interface.display_name,
171
+ description=indirect_interface.description,
172
+ )
173
+ add_field_reference_group(sub(elem, "indirectAddressRef"), indirect_interface.indirect_address_ref)
174
+ add_field_reference_group(sub(elem, "indirectDataRef"), indirect_interface.indirect_data_ref)
175
+ # memoryMapRef and transparentBridge are the two arms of a required choice.
176
+ if indirect_interface.memory_map_ref is not None:
177
+ sub(elem, "memoryMapRef", indirect_interface.memory_map_ref)
178
+ elif indirect_interface.transparent_bridges:
179
+ _add_transparent_bridges(elem, indirect_interface.transparent_bridges)
180
+ else:
181
+ raise ValueError("an indirect interface requires memory_map_ref or transparent_bridges")
182
+ add_text(elem, "bitsInLau", indirect_interface.bits_in_lau)
183
+ add_text(elem, "endianness", indirect_interface.endianness)
184
+ add_parameters(elem, indirect_interface.parameters)
185
+ write_vendor_extensions(elem, indirect_interface.vendor_extensions)
186
+ return elem
187
+
188
+
189
+ def add_indirect_interfaces(parent: etree._Element, indirect_interfaces: Sequence[IndirectInterface]) -> None:
190
+ add_items(parent, "indirectInterfaces", indirect_interfaces, write_indirect_interface)
191
+
192
+
193
+ def write_channel(channel: Channel) -> etree._Element:
194
+ elem = element("channel")
195
+ add_name_group(elem, channel.name, channel.display_name, description=channel.description)
196
+ add_local_name_refs(elem, "busInterfaceRef", channel.bus_interface_refs)
197
+ write_vendor_extensions(elem, channel.vendor_extensions)
198
+ return elem
199
+
200
+
201
+ def add_channels(parent: etree._Element, channels: Sequence[Channel]) -> None:
202
+ add_items(parent, "channels", channels, write_channel)