Coverage for pyEDAA/IPXACT/Component.py: 50%
369 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-05-30 22:17 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-05-30 22:17 +0000
1# ==================================================================================================================== #
2# _____ ____ _ _ ___ ______ __ _ ____ _____ #
3# _ __ _ _| ____| _ \ / \ / \ |_ _| _ \ \/ / / \ / ___|_ _| #
4# | '_ \| | | | _| | | | |/ _ \ / _ \ | || |_) \ / / _ \| | | | #
5# | |_) | |_| | |___| |_| / ___ \ / ___ \ _ | || __// \ / ___ \ |___ | | #
6# | .__/ \__, |_____|____/_/ \_\/_/ \_(_)___|_| /_/\_\/_/ \_\____| |_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2025 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 sys import version_info
34from textwrap import dedent
35from typing import List, Optional as Nullable, ClassVar, Dict, Union
37from lxml.etree import _Element, QName, _Comment
38from pyTooling.Decorators import export, readonly
39from pyTooling.Common import getFullyQualifiedName
41from pyEDAA.IPXACT import __DEFAULT_SCHEMA__, RootElement, VLNV, IPXACTSchema, Element, IPXACTException
44@export
45class BusInterface(Element):
46 """Represents an IP-XACT bus interface."""
48 def __init__(self, vlnv: VLNV) -> None:
49 super().__init__(vlnv)
51 @classmethod
52 def FromXml(cls, element: _Element) -> "BusInterface":
53 pass
55 def ToXml(self, indent=0):
56 """Converts the object's data into XML format."""
58 return ""
61@export
62class IndirectInterface(Element):
63 """Represents an IP-XACT indirect interface."""
65 def __init__(self, vlnv: VLNV) -> None:
66 super().__init__(vlnv)
68 def ToXml(self, indent=0):
69 """Converts the object's data into XML format."""
71 return ""
74@export
75class Channel(Element):
76 """Represents an IP-XACT channel."""
78 def __init__(self, vlnv: VLNV) -> None:
79 super().__init__(vlnv)
81 def ToXml(self, indent=0):
82 """Converts the object's data into XML format."""
84 return ""
87@export
88class RemapState(Element):
89 """Represents an IP-XACT remap state."""
91 def __init__(self, vlnv: VLNV) -> None:
92 super().__init__(vlnv)
94 def ToXml(self, indent=0):
95 """Converts the object's data into XML format."""
97 return ""
100@export
101class AddressSpace(Element):
102 """Represents an IP-XACT address space."""
104 def __init__(self, vlnv: VLNV) -> None:
105 super().__init__(vlnv)
107 def ToXml(self, indent=0):
108 """Converts the object's data into XML format."""
110 return ""
113@export
114class MemoryMap(Element):
115 """Represents an IP-XACT memory map."""
117 def __init__(self, vlnv: VLNV) -> None:
118 super().__init__(vlnv)
120 def ToXml(self, indent=0):
121 """Converts the object's data into XML format."""
123 return ""
126@export
127class Model(Element):
128 """Represents an IP-XACT model."""
130 def __init__(self, vlnv: VLNV) -> None:
131 super().__init__(vlnv)
133 def ToXml(self, indent=0):
134 """Converts the object's data into XML format."""
136 return ""
139@export
140class ComponentGenerator:
141 """Represents an IP-XACT component generator."""
143 def __init__(self, vlnv: VLNV) -> None:
144 super().__init__(vlnv)
146 def ToXml(self, indent=0):
147 """Converts the object's data into XML format."""
149 return ""
152@export
153class Choice(Element):
154 """Represents an IP-XACT choice."""
156 def __init__(self, vlnv: VLNV) -> None:
157 super().__init__(vlnv)
159 def ToXml(self, indent=0):
160 """Converts the object's data into XML format."""
162 return ""
165@export
166class File(Element):
167 _path: Path
169 def __init__(self, path: Path) -> None:
170 self._path = Path
172 @readonly
173 def Path(self) -> Path:
174 return self._path
176 @classmethod
177 def FromXml(cls, fileElement: _Element) -> "FileSet":
178 fileName = None
179 fileType = None
180 for element in fileElement:
181 if isinstance(element, _Comment): 181 ↛ 182line 181 didn't jump to line 182 because the condition on line 181 was never true
182 continue
184 elementLocalname = QName(element).localname
185 if elementLocalname == "name":
186 fileName = element.text
187 elif elementLocalname == "fileType":
188 fileType = element.text
189 elif elementLocalname == "isStructural": 189 ↛ 192line 189 didn't jump to line 192 because the condition on line 189 was always true
190 pass
191 else:
192 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at component → fileSets → fileSet → file.")
194 return cls(Path(fileName))
196 def ToXml(self, indent=0):
197 """Converts the object's data into XML format."""
199 return ""
201 def __str__(self) -> str:
202 return str(self._path)
205@export
206class FileSet(Element):
207 """Represents an IP-XACT fileset."""
209 _name: str
210 _files: List[File]
212 def __init__(self, name: str, files: List[File]) -> None:
213 self._name = name
214 self._files = [file for file in files]
216 @readonly
217 def Name(self) -> str:
218 return self._name
220 @readonly
221 def Files(self) -> List[File]:
222 return self._files
224 @readonly
225 def FileCount(self) -> int:
226 return len(self._files)
228 @classmethod
229 def FromXml(cls, fileSetElement: _Element) -> "FileSet":
230 files = []
231 fileSetName = None
232 for element in fileSetElement:
233 if isinstance(element, _Comment):
234 continue
236 elementLocalname = QName(element).localname
237 if elementLocalname == "name":
238 fileSetName = element.text
239 elif elementLocalname == "file": 239 ↛ 242line 239 didn't jump to line 242 because the condition on line 239 was always true
240 files.append(File.FromXml(element))
241 else:
242 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at component → fileSets → fileSet.")
244 return cls(fileSetName, files)
246 def ToXml(self, indent=0):
247 """Converts the object's data into XML format."""
249 return ""
251 def __str__(self) -> str:
252 return f"FileSet {self._name} ({len(self._files)})"
255@export
256class WhiteboxElement(Element):
257 """Represents an IP-XACT whitebos element."""
259 def __init__(self, vlnv: VLNV) -> None:
260 super().__init__(vlnv)
262 def ToXml(self, indent=0):
263 """Converts the object's data into XML format."""
265 return ""
268@export
269class Cpu(Element):
270 """Represents an IP-XACT cpu."""
272 def __init__(self, vlnv: VLNV) -> None:
273 super().__init__(vlnv)
275 def ToXml(self, indent=0):
276 """Converts the object's data into XML format."""
278 return ""
281@export
282class OtherClockDriver(Element):
283 """Represents an IP-XACT *other* clock driver."""
285 def __init__(self, vlnv: VLNV) -> None:
286 super().__init__(vlnv)
288 def ToXml(self, indent=0):
289 """Converts the object's data into XML format."""
291 return ""
294@export
295class ResetType(Element):
296 """Represents an IP-XACT reset type."""
298 def __init__(self, vlnv: VLNV) -> None:
299 super().__init__(vlnv)
301 def ToXml(self, indent=0):
302 """Converts the object's data into XML format."""
304 return ""
307@export
308class Parameter(Element):
309 """Represents an IP-XACT parameter.""""""Represents an IP-XACT assertion."""
311 def __init__(self, vlnv: VLNV) -> None:
312 super().__init__(vlnv)
314 def ToXml(self, indent=0):
315 """Converts the object's data into XML format."""
317 return ""
320@export
321class Assertion(Element):
322 """Represents an IP-XACT assertion."""
324 def __init__(self, vlnv: VLNV) -> None:
325 super().__init__(vlnv)
327 def ToXml(self, indent=0):
328 """Converts the object's data into XML format."""
330 return ""
333@export
334class Component(RootElement):
335 """Represents an IP-XACT components."""
337 _rootTagName: ClassVar[str] = "component"
339 _busInterfaces: List
340 _indirectInterfaces: List
341 _channels: List
342 _remapStates: List
343 _addressSpaces: List
344 _memoryMaps: List
345 _model: Nullable[Model]
346 _componentGenerators: List
347 _choices: List
348 _fileSets: Dict[str, FileSet]
349 _whiteboxElements: List
350 _cpus: List
351 _otherClockDrivers: List
352 _resetTypes: List
353 _parameters: List
354 _assertions: List
356 def __init__(
357 self,
358 componentFile: Nullable[Path] = None,
359 parse: bool = False,
360 vlnv: Nullable[VLNV] = None,
361 description: Nullable[str] = None
362 ):
363 self._busInterfaces = []
364 self._indirectInterfaces = []
365 self._channels = []
366 self._remapStates = []
367 self._addressSpaces = []
368 self._memoryMaps = []
369 self._model = None
370 self._componentGenerators = []
371 self._choices = []
372 self._fileSets = {}
373 self._whiteboxElements = []
374 self._cpus = []
375 self._otherClockDrivers = []
376 self._resetTypes = []
377 self._parameters = []
378 self._assertions = []
380 super().__init__(componentFile, parse, vlnv, description)
382 @readonly
383 def FileSets(self) -> Dict[str, FileSet]:
384 return self._fileSets
386 def Parse(self, element: _Element) -> None:
387 elementLocalname = QName(element).localname
388 if elementLocalname == "busInterfaces":
389 pass
390 # for busInterfaceElement in element:
391 # self.AddItem(BusInterface.FromXml(busInterfaceElement))
392 elif elementLocalname == "indirectInterfaces":
393 pass
394 elif elementLocalname == "channels":
395 pass
396 elif elementLocalname == "remapStates":
397 pass
398 elif elementLocalname == "addressSpaces":
399 pass
400 elif elementLocalname == "memoryMaps":
401 pass
402 elif elementLocalname == "model":
403 pass
404 elif elementLocalname == "componentGenerators":
405 pass
406 elif elementLocalname == "choices":
407 pass
408 elif elementLocalname == "fileSets":
409 for fileSetElement in element:
410 if isinstance(fileSetElement, _Comment):
411 continue
413 self.AddFileSet(FileSet.FromXml(fileSetElement))
414 elif elementLocalname == "whiteboxElements":
415 pass
416 elif elementLocalname == "cpus":
417 pass
418 elif elementLocalname == "otherClockDrivers":
419 pass
420 elif elementLocalname == "resetTypes":
421 pass
422 elif elementLocalname == "parameters":
423 pass
424 elif elementLocalname == "assertions": 424 ↛ 427line 424 didn't jump to line 427 because the condition on line 424 was always true
425 pass
426 else:
427 raise IPXACTException(f"Unsupported tag '{elementLocalname}' at root-level.")
429 def SetItem(self, item):
430 if isinstance(item, Model):
431 self._model = item
432 else:
433 raise ValueError()
435 def AddItem(self, item) -> None:
436 if isinstance(item, BusInterface):
437 self._busInterfaces.append(item)
438 elif isinstance(item, IndirectInterface):
439 self._indirectInterfaces.append(item)
440 elif isinstance(item, Channel):
441 self._channels.append(item)
442 elif isinstance(item, RemapState):
443 self._remapStates.append(item)
444 elif isinstance(item, AddressSpace):
445 self._addressSpaces.append(item)
446 elif isinstance(item, MemoryMap):
447 self._memoryMaps.append(item)
448 elif isinstance(item, ComponentGenerator):
449 self._componentGenerators.append(item)
450 elif isinstance(item, Choice):
451 self._choices.append(item)
452 elif isinstance(item, FileSet):
453 self.AddFileSet(item)
454 elif isinstance(item, WhiteboxElement):
455 self._whiteboxElements.append(item)
456 elif isinstance(item, Cpu):
457 self._cpus.append(item)
458 elif isinstance(item, OtherClockDriver):
459 self._otherClockDrivers.append(item)
460 elif isinstance(item, ResetType):
461 self._resetTypes.append(item)
462 elif isinstance(item, Parameter):
463 self._parameters.append(item)
464 elif isinstance(item, Assertion):
465 self._assertions.append(item)
466 else:
467 ex = TypeError("Parameter 'item' is not a BusInterface, IndirectInterface, Channel, RemapState, AddressSpace, MemoryMap, ComponentGenerator, Choice, FileSet, WhiteboxElement, Cpu, OtherClockDriver, ResetType, Parameter, or Assertion.")
468 if version_info >= (3, 11): # pragma: no cover
469 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
470 raise ex
472 def AddFileSet(self, fileset: FileSet):
473 if not isinstance(fileset, FileSet): 473 ↛ 474line 473 didn't jump to line 474 because the condition on line 473 was never true
474 ex = TypeError("Parameter 'fileset' is not a FileSet.")
475 if version_info >= (3, 11): # pragma: no cover
476 ex.add_note(f"Got type '{getFullyQualifiedName(fileset)}'.")
477 raise ex
479 if fileset._name in self._fileSets: 479 ↛ 480line 479 didn't jump to line 480 because the condition on line 479 was never true
480 raise ValueError(f"Duplicate fileset '{fileset._name}'.")
482 self._fileSets[fileset._name] = fileset
484 def ToXml(self, schema: IPXACTSchema = __DEFAULT_SCHEMA__) -> str:
485 """Converts the object's data into XML format."""
487 xmlns = schema.NamespacePrefix
488 buffer = dedent(f"""\
489 <?xml version="1.0" encoding="UTF-8" ?>
490 <{xmlns}:component
491 \txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
492 \txmlns:{xmlns}="{schema.SchemaUri}"
493 \txsi:schemaLocation="{schema.SchemaUri} {schema.SchemaUrl}">
494 {self._vlnv.ToXml(schema, isVersionedIdentifier=True)}
495 \t<{xmlns}:description>{self._description}</{xmlns}:description>
496 """)
498 if self._busInterfaces:
499 buffer += f"\t<{xmlns}:busInterfaces>\n"
500 for busInterface in self._busInterfaces:
501 buffer += busInterface.ToXml(2, schema)
502 buffer += f"\t</{xmlns}:busInterfaces>\n"
504 if self._indirectInterfaces:
505 buffer += f"\t<{xmlns}:indirectInterfaces>\n"
506 for indirectInterface in self._indirectInterfaces:
507 buffer += indirectInterface.ToXml(2, schema)
508 buffer += f"\t</{xmlns}:indirectInterfaces>\n"
510 if self._channels:
511 buffer += f"\t<{xmlns}:channels>\n"
512 for channel in self._channels:
513 buffer += channel.ToXml(2, schema)
514 buffer += f"\t</{xmlns}:channels>\n"
516 if self._remapStates:
517 buffer += f"\t<{xmlns}:remapStates>\n"
518 for remapState in self._remapStates:
519 buffer += remapState.ToXml(2, schema)
520 buffer += f"\t</{xmlns}:remapStates>\n"
522 if self._addressSpaces:
523 buffer += f"\t<{xmlns}:addressSpaces>\n"
524 for addressSpace in self._addressSpaces:
525 buffer += addressSpace.ToXml(2, schema)
526 buffer += f"\t</{xmlns}:addressSpaces>\n"
528 if self._memoryMaps:
529 buffer += f"\t<{xmlns}:memoryMaps>\n"
530 for memoryMap in self._memoryMaps:
531 buffer += memoryMap.ToXml(2, schema)
532 buffer += f"\t</{xmlns}:memoryMaps>\n"
534 if self._model:
535 buffer += f"\t<{xmlns}:model>\n"
536 buffer += self._model.ToXml(2, schema)
537 buffer += f"\t</{xmlns}:model>\n"
539 if self._componentGenerators:
540 buffer += f"\t<{xmlns}:componentGenerators>\n"
541 for componentGenerator in self._componentGenerators:
542 buffer += componentGenerator.ToXml(2, schema)
543 buffer += f"\t</{xmlns}:componentGenerators>\n"
545 if self._choices:
546 buffer += f"\t<{xmlns}:choices>\n"
547 for choice in self._choices:
548 buffer += choice.ToXml(2, schema)
549 buffer += f"\t</{xmlns}:choices>\n"
551 if self._fileSets:
552 buffer += f"\t<{xmlns}:fileSets>\n"
553 for fileSet in self._fileSets:
554 buffer += fileSet.ToXml(2, schema)
555 buffer += f"\t</{xmlns}:fileSets>\n"
557 if self._whiteboxElements:
558 buffer += f"\t<{xmlns}:whiteboxElements>\n"
559 for whiteboxElement in self._whiteboxElements:
560 buffer += whiteboxElement.ToXml(2, schema)
561 buffer += f"\t</{xmlns}:whiteboxElements>\n"
563 if self._cpus:
564 buffer += f"\t<{xmlns}:cpus>\n"
565 for cpu in self._cpus:
566 buffer += cpu.ToXml(2, schema)
567 buffer += f"\t</{xmlns}:cpus>\n"
569 if self._otherClockDrivers:
570 buffer += f"\t<{xmlns}:otherClockDrivers>\n"
571 for otherClockDriver in self._otherClockDrivers:
572 buffer += otherClockDriver.ToXml(2, schema)
573 buffer += f"\t</{xmlns}:otherClockDrivers>\n"
575 if self._resetTypes:
576 buffer += f"\t<{xmlns}:resetTypes>\n"
577 for resetType in self._resetTypes:
578 buffer += resetType.ToXml(2, schema)
579 buffer += f"\t</{xmlns}:resetTypes>\n"
581 if self._parameters:
582 buffer += f"\t<{xmlns}:parameters>\n"
583 for parameter in self._parameters:
584 buffer += parameter.ToXml(2, schema)
585 buffer += f"\t</{xmlns}:parameters>\n"
587 if self._assertions:
588 buffer += f"\t<{xmlns}:assertions>\n"
589 for assertion in self._assertions:
590 buffer += assertion.ToXml(2, schema)
591 buffer += f"\t</{xmlns}:assertions>\n"
593 buffer += dedent(f"""\
594 </{xmlns}:component>
595 """)
597 return buffer