Coverage for pyEDAA/IPXACT/Component.py: 47%
351 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 17:18 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 17:18 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ ___ ______ __ _ ____ _____ #
3# _ __ _ _| ____| _ \ / \ / \ |_ _| _ \ \/ / / \ / ___|_ _| #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | || |_) \ / / _ \| | | | #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _ | || __// \ / ___ \ |___ | | #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___|_| /_/\_\/_/ \_\____| |_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 Patrick Lehmann - Bötzingen, Germany #
15# Copyright 2016-2016 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32from pathlib import Path
33from textwrap import dedent
34from typing import List, Optional as Nullable, ClassVar, Dict, Union
36from lxml.etree import _Element, QName, _Comment
37from pyTooling.Decorators import export, readonly
38from pyTooling.Common import getFullyQualifiedName
40from pyEDAA.IPXACT import __DEFAULT_SCHEMA__, RootElement, VLNV, IPXACTSchema, Element, IPXACTException
43@export
44class BusInterface(Element):
45 """Represents an IP-XACT bus interface."""
47 def __init__(self, vlnv: VLNV) -> None:
48 super().__init__(vlnv)
50 @classmethod
51 def FromXml(cls, element: _Element) -> "BusInterface":
52 pass
54 def ToXml(self, indent=0):
55 """Converts the object's data into XML format."""
57 return ""
60@export
61class IndirectInterface(Element):
62 """Represents an IP-XACT indirect interface."""
64 def __init__(self, vlnv: VLNV) -> None:
65 super().__init__(vlnv)
67 def ToXml(self, indent=0):
68 """Converts the object's data into XML format."""
70 return ""
73@export
74class Channel(Element):
75 """Represents an IP-XACT channel."""
77 def __init__(self, vlnv: VLNV) -> None:
78 super().__init__(vlnv)
80 def ToXml(self, indent=0):
81 """Converts the object's data into XML format."""
83 return ""
86@export
87class RemapState(Element):
88 """Represents an IP-XACT remap state."""
90 def __init__(self, vlnv: VLNV) -> None:
91 super().__init__(vlnv)
93 def ToXml(self, indent=0):
94 """Converts the object's data into XML format."""
96 return ""
99@export
100class AddressSpace(Element):
101 """Represents an IP-XACT address space."""
103 def __init__(self, vlnv: VLNV) -> None:
104 super().__init__(vlnv)
106 def ToXml(self, indent=0):
107 """Converts the object's data into XML format."""
109 return ""
112@export
113class MemoryMap(Element):
114 """Represents an IP-XACT memory map."""
116 def __init__(self, vlnv: VLNV) -> None:
117 super().__init__(vlnv)
119 def ToXml(self, indent=0):
120 """Converts the object's data into XML format."""
122 return ""
125@export
126class Model(Element):
127 """Represents an IP-XACT model."""
129 def __init__(self, vlnv: VLNV) -> None:
130 super().__init__(vlnv)
132 def ToXml(self, indent=0):
133 """Converts the object's data into XML format."""
135 return ""
138@export
139class ComponentGenerator:
140 """Represents an IP-XACT component generator."""
142 def __init__(self, vlnv: VLNV) -> None:
143 super().__init__(vlnv)
145 def ToXml(self, indent=0):
146 """Converts the object's data into XML format."""
148 return ""
151@export
152class Choice(Element):
153 """Represents an IP-XACT choice."""
155 def __init__(self, vlnv: VLNV) -> None:
156 super().__init__(vlnv)
158 def ToXml(self, indent=0):
159 """Converts the object's data into XML format."""
161 return ""
164@export
165class File(Element):
166 _path: Path
168 def __init__(self, path: Path) -> None:
169 self._path = Path
171 @readonly
172 def Path(self) -> Path:
173 return self._path
175 @classmethod
176 def FromXml(cls, fileElement: _Element) -> "FileSet":
177 fileName = None
178 fileType = None
179 for element in fileElement:
180 if isinstance(element, _Comment): 180 ↛ 181line 180 didn't jump to line 181 because the condition on line 180 was never true
181 continue
183 elementLocalname = QName(element).localname
184 if elementLocalname == "name":
185 fileName = element.text
186 elif elementLocalname == "fileType":
187 fileType = element.text
188 elif elementLocalname == "isStructural": 188 ↛ 191line 188 didn't jump to line 191 because the condition on line 188 was always true
189 pass
190 else:
191 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at component → fileSets → fileSet → file.")
193 return cls(Path(fileName))
195 def ToXml(self, indent=0):
196 """Converts the object's data into XML format."""
198 return ""
200 def __str__(self) -> str:
201 return str(self._path)
204@export
205class FileSet(Element):
206 """Represents an IP-XACT fileset."""
208 _name: str
209 _files: List[File]
211 def __init__(self, name: str, files: List[File]) -> None:
212 self._name = name
213 self._files = list(files)
215 @readonly
216 def Name(self) -> str:
217 return self._name
219 @readonly
220 def Files(self) -> List[File]:
221 return self._files
223 @readonly
224 def FileCount(self) -> int:
225 return len(self._files)
227 @classmethod
228 def FromXml(cls, fileSetElement: _Element) -> "FileSet":
229 files = []
230 fileSetName = None
231 for element in fileSetElement:
232 if isinstance(element, _Comment):
233 continue
235 elementLocalname = QName(element).localname
236 if elementLocalname == "name":
237 fileSetName = element.text
238 elif elementLocalname == "file": 238 ↛ 241line 238 didn't jump to line 241 because the condition on line 238 was always true
239 files.append(File.FromXml(element))
240 else:
241 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at component → fileSets → fileSet.")
243 return cls(fileSetName, files)
245 def ToXml(self, indent=0):
246 """Converts the object's data into XML format."""
248 return ""
250 def __str__(self) -> str:
251 return f"FileSet {self._name} ({len(self._files)})"
254@export
255class WhiteboxElement(Element):
256 """Represents an IP-XACT whitebos element."""
258 def __init__(self, vlnv: VLNV) -> None:
259 super().__init__(vlnv)
261 def ToXml(self, indent=0):
262 """Converts the object's data into XML format."""
264 return ""
267@export
268class Cpu(Element):
269 """Represents an IP-XACT cpu."""
271 def __init__(self, vlnv: VLNV) -> None:
272 super().__init__(vlnv)
274 def ToXml(self, indent=0):
275 """Converts the object's data into XML format."""
277 return ""
280@export
281class OtherClockDriver(Element):
282 """Represents an IP-XACT *other* clock driver."""
284 def __init__(self, vlnv: VLNV) -> None:
285 super().__init__(vlnv)
287 def ToXml(self, indent=0):
288 """Converts the object's data into XML format."""
290 return ""
293@export
294class ResetType(Element):
295 """Represents an IP-XACT reset type."""
297 def __init__(self, vlnv: VLNV) -> None:
298 super().__init__(vlnv)
300 def ToXml(self, indent=0):
301 """Converts the object's data into XML format."""
303 return ""
306@export
307class Parameter(Element):
308 """Represents an IP-XACT parameter.""""""Represents an IP-XACT assertion."""
310 def __init__(self, vlnv: VLNV) -> None:
311 super().__init__(vlnv)
313 def ToXml(self, indent=0):
314 """Converts the object's data into XML format."""
316 return ""
319@export
320class Assertion(Element):
321 """Represents an IP-XACT assertion."""
323 def __init__(self, vlnv: VLNV) -> None:
324 super().__init__(vlnv)
326 def ToXml(self, indent=0):
327 """Converts the object's data into XML format."""
329 return ""
332@export
333class Component(RootElement):
334 """Represents an IP-XACT components."""
336 _ROOT_TAG_NAME: ClassVar[str] = "component"
338 _busInterfaces: List
339 _indirectInterfaces: List
340 _channels: List
341 _remapStates: List
342 _addressSpaces: List
343 _memoryMaps: List
344 _model: Nullable[Model]
345 _componentGenerators: List
346 _choices: List
347 _fileSets: Dict[str, FileSet]
348 _whiteboxElements: List
349 _cpus: List
350 _otherClockDrivers: List
351 _resetTypes: List
352 _parameters: List
353 _assertions: List
355 def __init__(
356 self,
357 componentFile: Nullable[Path] = None,
358 parse: bool = False,
359 vlnv: Nullable[VLNV] = None,
360 description: Nullable[str] = None
361 ) -> None:
362 self._busInterfaces = []
363 self._indirectInterfaces = []
364 self._channels = []
365 self._remapStates = []
366 self._addressSpaces = []
367 self._memoryMaps = []
368 self._model = None
369 self._componentGenerators = []
370 self._choices = []
371 self._fileSets = {}
372 self._whiteboxElements = []
373 self._cpus = []
374 self._otherClockDrivers = []
375 self._resetTypes = []
376 self._parameters = []
377 self._assertions = []
379 super().__init__(componentFile, parse, vlnv, description)
381 @readonly
382 def FileSets(self) -> Dict[str, FileSet]:
383 return self._fileSets
385 def Parse(self, element: _Element) -> None:
386 elementLocalname = QName(element).localname
387 if elementLocalname == "busInterfaces":
388 pass
389 # for busInterfaceElement in element:
390 # self.AddItem(BusInterface.FromXml(busInterfaceElement))
391 elif elementLocalname == "indirectInterfaces":
392 pass
393 elif elementLocalname == "channels":
394 pass
395 elif elementLocalname == "remapStates":
396 pass
397 elif elementLocalname == "addressSpaces":
398 pass
399 elif elementLocalname == "memoryMaps":
400 pass
401 elif elementLocalname == "model":
402 pass
403 elif elementLocalname == "componentGenerators":
404 pass
405 elif elementLocalname == "choices":
406 pass
407 elif elementLocalname == "fileSets":
408 for fileSetElement in element:
409 if isinstance(fileSetElement, _Comment):
410 continue
412 self.AddFileSet(FileSet.FromXml(fileSetElement))
413 elif elementLocalname == "whiteboxElements":
414 pass
415 elif elementLocalname == "cpus":
416 pass
417 elif elementLocalname == "otherClockDrivers":
418 pass
419 elif elementLocalname == "resetTypes":
420 pass
421 elif elementLocalname == "parameters":
422 pass
423 elif elementLocalname == "assertions": 423 ↛ 426line 423 didn't jump to line 426 because the condition on line 423 was always true
424 pass
425 else:
426 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at root-level.")
428 def SetItem(self, item):
429 if isinstance(item, Model):
430 self._model = item
431 else:
432 raise ValueError()
434 def AddItem(self, item) -> None:
435 if isinstance(item, BusInterface):
436 self._busInterfaces.append(item)
437 elif isinstance(item, IndirectInterface):
438 self._indirectInterfaces.append(item)
439 elif isinstance(item, Channel):
440 self._channels.append(item)
441 elif isinstance(item, RemapState):
442 self._remapStates.append(item)
443 elif isinstance(item, AddressSpace):
444 self._addressSpaces.append(item)
445 elif isinstance(item, MemoryMap):
446 self._memoryMaps.append(item)
447 elif isinstance(item, ComponentGenerator):
448 self._componentGenerators.append(item)
449 elif isinstance(item, Choice):
450 self._choices.append(item)
451 elif isinstance(item, FileSet):
452 self.AddFileSet(item)
453 elif isinstance(item, WhiteboxElement):
454 self._whiteboxElements.append(item)
455 elif isinstance(item, Cpu):
456 self._cpus.append(item)
457 elif isinstance(item, OtherClockDriver):
458 self._otherClockDrivers.append(item)
459 elif isinstance(item, ResetType):
460 self._resetTypes.append(item)
461 elif isinstance(item, Parameter):
462 self._parameters.append(item)
463 elif isinstance(item, Assertion):
464 self._assertions.append(item)
465 else:
466 ex = TypeError("Parameter 'item' is not a BusInterface, IndirectInterface, Channel, RemapState, AddressSpace, MemoryMap, ComponentGenerator, Choice, FileSet, WhiteboxElement, Cpu, OtherClockDriver, ResetType, Parameter, or Assertion.")
467 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
468 raise ex
470 def AddFileSet(self, fileset: FileSet):
471 if not isinstance(fileset, FileSet): 471 ↛ 472line 471 didn't jump to line 472 because the condition on line 471 was never true
472 ex = TypeError("Parameter 'fileset' is not a FileSet.")
473 ex.add_note(f"Got type '{getFullyQualifiedName(fileset)}'.")
474 raise ex
476 if fileset._name in self._fileSets: 476 ↛ 477line 476 didn't jump to line 477 because the condition on line 476 was never true
477 raise ValueError(f"Duplicate fileset '{fileset._name}'.")
479 self._fileSets[fileset._name] = fileset
481 def ToXml(self, schema: IPXACTSchema = __DEFAULT_SCHEMA__) -> str:
482 """Converts the object's data into XML format."""
484 xmlns = schema.NamespacePrefix
485 buffer = dedent(f"""\
486 <?xml version="1.0" encoding="UTF-8" ?>
487 <{xmlns}:component
488 \txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
489 \txmlns:{xmlns}="{schema.SchemaUri}"
490 \txsi:schemaLocation="{schema.SchemaUri} {schema.SchemaUrl}">
491 {self._vlnv.ToXml(schema, isVersionedIdentifier=True)}
492 \t<{xmlns}:description>{self._description}</{xmlns}:description>
493 """)
495 if self._busInterfaces:
496 buffer += f"\t<{xmlns}:busInterfaces>\n"
497 for busInterface in self._busInterfaces:
498 buffer += busInterface.ToXml(2, schema)
499 buffer += f"\t</{xmlns}:busInterfaces>\n"
501 if self._indirectInterfaces:
502 buffer += f"\t<{xmlns}:indirectInterfaces>\n"
503 for indirectInterface in self._indirectInterfaces:
504 buffer += indirectInterface.ToXml(2, schema)
505 buffer += f"\t</{xmlns}:indirectInterfaces>\n"
507 if self._channels:
508 buffer += f"\t<{xmlns}:channels>\n"
509 for channel in self._channels:
510 buffer += channel.ToXml(2, schema)
511 buffer += f"\t</{xmlns}:channels>\n"
513 if self._remapStates:
514 buffer += f"\t<{xmlns}:remapStates>\n"
515 for remapState in self._remapStates:
516 buffer += remapState.ToXml(2, schema)
517 buffer += f"\t</{xmlns}:remapStates>\n"
519 if self._addressSpaces:
520 buffer += f"\t<{xmlns}:addressSpaces>\n"
521 for addressSpace in self._addressSpaces:
522 buffer += addressSpace.ToXml(2, schema)
523 buffer += f"\t</{xmlns}:addressSpaces>\n"
525 if self._memoryMaps:
526 buffer += f"\t<{xmlns}:memoryMaps>\n"
527 for memoryMap in self._memoryMaps:
528 buffer += memoryMap.ToXml(2, schema)
529 buffer += f"\t</{xmlns}:memoryMaps>\n"
531 if self._model:
532 buffer += f"\t<{xmlns}:model>\n"
533 buffer += self._model.ToXml(2, schema)
534 buffer += f"\t</{xmlns}:model>\n"
536 if self._componentGenerators:
537 buffer += f"\t<{xmlns}:componentGenerators>\n"
538 for componentGenerator in self._componentGenerators:
539 buffer += componentGenerator.ToXml(2, schema)
540 buffer += f"\t</{xmlns}:componentGenerators>\n"
542 if self._choices:
543 buffer += f"\t<{xmlns}:choices>\n"
544 for choice in self._choices:
545 buffer += choice.ToXml(2, schema)
546 buffer += f"\t</{xmlns}:choices>\n"
548 if self._fileSets:
549 buffer += f"\t<{xmlns}:fileSets>\n"
550 for fileSet in self._fileSets:
551 buffer += fileSet.ToXml(2, schema)
552 buffer += f"\t</{xmlns}:fileSets>\n"
554 if self._whiteboxElements:
555 buffer += f"\t<{xmlns}:whiteboxElements>\n"
556 for whiteboxElement in self._whiteboxElements:
557 buffer += whiteboxElement.ToXml(2, schema)
558 buffer += f"\t</{xmlns}:whiteboxElements>\n"
560 if self._cpus:
561 buffer += f"\t<{xmlns}:cpus>\n"
562 for cpu in self._cpus:
563 buffer += cpu.ToXml(2, schema)
564 buffer += f"\t</{xmlns}:cpus>\n"
566 if self._otherClockDrivers:
567 buffer += f"\t<{xmlns}:otherClockDrivers>\n"
568 for otherClockDriver in self._otherClockDrivers:
569 buffer += otherClockDriver.ToXml(2, schema)
570 buffer += f"\t</{xmlns}:otherClockDrivers>\n"
572 if self._resetTypes:
573 buffer += f"\t<{xmlns}:resetTypes>\n"
574 for resetType in self._resetTypes:
575 buffer += resetType.ToXml(2, schema)
576 buffer += f"\t</{xmlns}:resetTypes>\n"
578 if self._parameters:
579 buffer += f"\t<{xmlns}:parameters>\n"
580 for parameter in self._parameters:
581 buffer += parameter.ToXml(2, schema)
582 buffer += f"\t</{xmlns}:parameters>\n"
584 if self._assertions:
585 buffer += f"\t<{xmlns}:assertions>\n"
586 for assertion in self._assertions:
587 buffer += assertion.ToXml(2, schema)
588 buffer += f"\t</{xmlns}:assertions>\n"
590 buffer += dedent(f"""\
591 </{xmlns}:component>
592 """)
594 return buffer