Coverage for pyVHDLModel / __init__.py: 76%
1118 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 22:17 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 22:17 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2025 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 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#
32"""
33**An abstract VHDL language model.**
35This package provides a unified abstract language model for VHDL. Projects reading from source files can derive own
36classes and implement additional logic to create a concrete language model for their tools.
38Projects consuming pre-processed VHDL data (parsed, analyzed or elaborated) can build higher level features and services
39on such a model, while supporting multiple frontends.
41.. admonition:: Copyright Information
43 :copyright: Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany
44 :copyright: Copyright 2016-2017 Patrick Lehmann - Dresden, Germany
45 :license: Apache License, Version 2.0
46"""
47__author__ = "Patrick Lehmann"
48__email__ = "Paebbels@gmail.com"
49__copyright__ = "2016-2025, Patrick Lehmann"
50__license__ = "Apache License, Version 2.0"
51__version__ = "0.33.0"
54from enum import unique, Enum, Flag, auto
55from pathlib import Path
56from sys import version_info
58from typing import Union, Dict, cast, List, Generator, Optional as Nullable
60from pyTooling.Common import getFullyQualifiedName
61from pyTooling.Decorators import export, readonly
62from pyTooling.Graph import Graph, Vertex, Edge
63from pyTooling.Warning import WarningCollector
65from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning
66from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
67from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
68from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
69from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
70from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
71from pyVHDLModel.Namespace import Namespace
72from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
73from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
74from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
75from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package
76from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
77from pyVHDLModel.Instantiation import PackageInstantiation
78from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
81@export
82@unique
83class VHDLVersion(Enum):
84 """
85 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
87 A version can be given as integer or string and is represented as a unified
88 enumeration value.
90 This enumeration supports compare operators.
91 """
93 Any = -1 #: Any
94 VHDL87 = 87 #: VHDL-1987
95 VHDL93 = 93 #: VHDL-1993
96 AMS93 = 1993 #: VHDL-AMS-1993
97 AMS99 = 1999 #: VHDL-AMS-1999
98 VHDL2000 = 2000 #: VHDL-2000
99 VHDL2002 = 2002 #: VHDL-2002
100 VHDL2008 = 2008 #: VHDL-2008
101 AMS2017 = 2017 #: VHDL-AMS-2017
102 VHDL2019 = 2019 #: VHDL-2019
103 Latest = 10000 #: Latest VHDL (2019)
105 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
106 -1: Any,
107 87: VHDL87,
108 93: VHDL93,
109 # 93: AMS93,
110 99: AMS99,
111 0: VHDL2000,
112 2: VHDL2002,
113 8: VHDL2008,
114 17: AMS2017,
115 19: VHDL2019,
116 1987: VHDL87,
117 # 1993: VHDL93,
118 1993: AMS93,
119 1999: AMS99,
120 2000: VHDL2000,
121 2002: VHDL2002,
122 2008: VHDL2008,
123 2017: AMS2017,
124 2019: VHDL2019,
125 10000: Latest,
126 "Any": Any,
127 "87": VHDL87,
128 "93": VHDL93,
129 # "93": AMS93,
130 "99": AMS99,
131 "00": VHDL2000,
132 "02": VHDL2002,
133 "08": VHDL2008,
134 "17": AMS2017,
135 "19": VHDL2019,
136 "1987": VHDL87,
137 # "1993": VHDL93,
138 "1993": AMS93,
139 "1999": AMS99,
140 "2000": VHDL2000,
141 "2002": VHDL2002,
142 "2008": VHDL2008,
143 "2017": AMS2017,
144 "2019": VHDL2019,
145 "Latest": Latest,
146 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
148 def __init__(self, *_) -> None:
149 """Patch the embedded MAP dictionary"""
150 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
151 if (not isinstance(v, self.__class__)) and (v == self.value):
152 self.__class__.__VERSION_MAPPINGS__[k] = self
154 @classmethod
155 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
156 """
157 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
159 :param value: VHDL/VHDL-AMS year code.
160 :returns: Enumeration value.
161 :raises ValueError: If the year code is not recognized.
162 """
163 try:
164 return cls.__VERSION_MAPPINGS__[value]
165 except KeyError:
166 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
168 def __lt__(self, other: Any) -> bool:
169 """
170 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
172 :param other: Parameter to compare against.
173 :returns: True if version is less than the second operand.
174 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
175 """
176 if isinstance(other, VHDLVersion):
177 return self.value < other.value
178 else:
179 raise TypeError("Second operand is not of type 'VHDLVersion'.")
181 def __le__(self, other: Any) -> bool:
182 """
183 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
185 :param other: Parameter to compare against.
186 :returns: True if version is less or equal than the second operand.
187 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
188 """
189 if isinstance(other, VHDLVersion):
190 return self.value <= other.value
191 else:
192 raise TypeError("Second operand is not of type 'VHDLVersion'.")
194 def __gt__(self, other: Any) -> bool:
195 """
196 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
198 :param other: Parameter to compare against.
199 :returns: True if version is greater than the second operand.
200 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
201 """
202 if isinstance(other, VHDLVersion):
203 return self.value > other.value
204 else:
205 raise TypeError("Second operand is not of type 'VHDLVersion'.")
207 def __ge__(self, other: Any) -> bool:
208 """
209 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
211 :param other: Parameter to compare against.
212 :returns: True if version is greater or equal than the second operand.
213 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
214 """
215 if isinstance(other, VHDLVersion):
216 return self.value >= other.value
217 else:
218 raise TypeError("Second operand is not of type 'VHDLVersion'.")
220 def __ne__(self, other: Any) -> bool:
221 """
222 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
224 :param other: Parameter to compare against.
225 :returns: True if version is unequal to the second operand.
226 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
227 """
228 if isinstance(other, VHDLVersion):
229 return self.value != other.value
230 else:
231 raise TypeError("Second operand is not of type 'VHDLVersion'.")
233 def __eq__(self, other: Any) -> bool:
234 """
235 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
237 :param other: Parameter to compare against.
238 :returns: True if version is equal to the second operand.
239 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
240 """
241 if isinstance(other, VHDLVersion):
242 if (self is self.__class__.Any) or (other is self.__class__.Any):
243 return True
244 else:
245 return self.value == other.value
246 else:
247 raise TypeError("Second operand is not of type 'VHDLVersion'.")
249 @readonly
250 def IsVHDL(self) -> bool:
251 """
252 Checks if the version is a VHDL (not VHDL-AMS) version.
254 :returns: True if version is a VHDL version.
255 """
256 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
258 @readonly
259 def IsAMS(self) -> bool:
260 """
261 Checks if the version is a VHDL-AMS (not VHDL) version.
263 :returns: True if version is a VHDL-AMS version.
264 """
265 return self in (self.AMS93, self.AMS99, self.AMS2017)
267 def __str__(self) -> str:
268 """
269 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
271 :return: Formatted VHDL/VHDL-AMS version.
272 """
273 if self.value == self.Any.value:
274 return "VHDL'Any"
275 elif self.value == self.Latest.value:
276 return "VHDL'Latest"
278 year = str(self.value)[-2:]
279 if self.IsVHDL:
280 return f"VHDL'{year}"
281 else:
282 return f"VHDL-AMS'{year}"
284 def __repr__(self) -> str:
285 """
286 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
288 :return: Formatted VHDL/VHDL-AMS version.
289 """
290 if self.value == self.Any.value:
291 return "Any"
292 elif self.value == self.Latest.value:
293 return "Latest"
294 else:
295 return str(self.value)
298@export
299class IEEEFlavor(Enum):
300 IEEE = 0
301 Synopsys = 1
302 MentorGraphics = 2
305@export
306@unique
307class ObjectClass(Enum):
308 """
309 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
311 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
312 """
314 Default = 0 #: Object class not defined, thus it's context dependent.
315 Constant = 1 #: Constant
316 Variable = 2 #: Variable
317 Signal = 3 #: Signal
318 File = 4 #: File
319 Type = 5 #: Type
320 # FIXME: Package?
321 Procedure = 6 #: Procedure
322 Function = 7 #: Function
324 def __str__(self) -> str:
325 """
326 Formats the object class.
328 :return: Formatted object class.
329 """
330 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
333@export
334@unique
335class DesignUnitKind(Flag):
336 """
337 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
339 """
340 Context = auto() #: Context
341 Package = auto() #: Package
342 PackageBody = auto() #: Package Body
343 Entity = auto() #: Entity
344 Architecture = auto() #: Architecture
345 Configuration = auto() #: Configuration
347 Primary = Context | Configuration | Entity | Package #: List of primary design units.
348 Secondary = PackageBody | Architecture #: List of secondary design units.
349 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
350 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
352 All = Primary | Secondary #: List of all design units.
355@export
356@unique
357class DependencyGraphVertexKind(Flag):
358 """
359 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
360 """
361 Document = auto() #: A document (VHDL source file).
362 Library = auto() #: A VHDL library.
364 Context = auto() #: A context design unit.
365 Package = auto() #: A package design unit.
366 PackageBody = auto() #: A package body design unit.
367 Entity = auto() #: A entity design unit.
368 Architecture = auto() #: A architecture design unit.
369 Component = auto() #: A VHDL component.
370 Configuration = auto() #: A configuration design unit.
373@export
374@unique
375class DependencyGraphEdgeKind(Flag):
376 """
377 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
378 """
379 Document = auto()
380 Library = auto()
381 Context = auto()
382 Package = auto()
383 Entity = auto()
384 # Architecture = auto()
385 Configuration = auto()
386 Component = auto()
388 DeclaredIn = auto()
389 Order = auto()
390 Reference = auto()
391 Implementation = auto()
392 Instantiation = auto()
394 SourceFile = Document | DeclaredIn
395 CompileOrder = Document | Order
397 LibraryClause = Library | Reference
398 UseClause = Package | Reference
399 ContextReference = Context | Reference
401 EntityImplementation = Entity | Implementation
402 PackageImplementation = Package | Implementation
404 EntityInstantiation = Entity | Instantiation
405 ComponentInstantiation = Component | Instantiation
406 ConfigurationInstantiation = Configuration | Instantiation
409@export
410@unique
411class ObjectGraphVertexKind(Flag):
412 """
413 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
414 """
415 Type = auto()
416 Subtype = auto()
418 Constant = auto()
419 DeferredConstant = auto()
420 Variable = auto()
421 Signal = auto()
422 File = auto()
424 Alias = auto()
427@export
428@unique
429class ObjectGraphEdgeKind(Flag):
430 """
431 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
432 """
433 BaseType = auto()
434 Subtype = auto()
436 ReferenceInExpression = auto()
439@export
440class Design(ModelEntity):
441 """
442 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
444 It's the root of this code document-object-model (CodeDOM). It contains at least one VHDL library (see :class:`~pyVHDLModel.Library`). When the design is
445 analysed (see :meth:`Analyze`), multiple graph data structures will be created and populated with vertices and edges. As a first result, the design's compile
446 order and hierarchy can be iterated. As a second result, the design's *top-level* is identified and referenced from the design (see :attr:`TopLevel`).
448 The *design* contains references to the following graphs:
450 * :attr:`DependencyGraph`
451 * :attr:`CompileOrderGraph`
452 * :attr:`HierarchyGraph`
453 * :attr:`ObjectGraph`
454 """
455 _name: Nullable[str] #: Name of the design.
456 _allowBlackbox: bool #: Allow blackboxes after linking the design.
457 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
458 _documents: List['Document'] #: List of all documents loaded for a design.
459 _dependencyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all dependencies in the designs.
460 _compileOrderGraph: Graph[None, None, None, None, None, None, None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the order of documents for compilation.
461 _hierarchyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the design hierarchy.
462 _objectGraph: Graph[None, None, None, None, None, None, None, None, str, Obj, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all types and objects in the design.
463 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
465 def __init__(
466 self,
467 name: Nullable[str] = None,
468 allowBlackbox: bool = False
469 ) -> None:
470 """
471 Initialize a VHDL design.
473 :param allowBlackbox: Specify if blackboxes are allowed in this design.
474 :param name: Name of the design.
475 """
476 super().__init__()
478 self._name = name
479 self._allowBlackbox = allowBlackbox
481 self._libraries = {}
482 self._documents = []
484 self._compileOrderGraph = Graph()
485 self._dependencyGraph = Graph()
486 self._hierarchyGraph = Graph()
487 self._objectGraph = Graph()
488 self._toplevel = None
490 @readonly
491 def Name(self) -> Nullable[str]:
492 """
493 Read-only property to access the design's name (:attr:`_name`).
495 :returns: The name of the design.
496 """
497 return self._name
499 @property
500 def AllowBlackbox(self) -> bool:
501 """
502 Read-only property to check if a design supports blackboxes (:attr:`_allowBlackbox`).
504 :returns: If blackboxes are allowed.
505 """
506 return self._allowBlackbox
508 @AllowBlackbox.setter
509 def AllowBlackbox(self, value: Nullable[bool]) -> None:
510 if value is None:
511 raise ValueError(f"Property 'AllowBlackbox' doesn't accept value 'None'.")
513 self._allowBlackbox = value
515 @readonly
516 def Libraries(self) -> Dict[str, 'Library']:
517 """
518 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
520 :returns: A dictionary of library names and VHDL libraries.
521 """
522 return self._libraries
524 @readonly
525 def Documents(self) -> List['Document']:
526 """
527 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
529 :returns: A list of all documents.
530 """
531 return self._documents
533 @readonly
534 def CompileOrderGraph(self) -> Graph:
535 """
536 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
538 :returns: Reference to the compile-order graph.
539 """
540 return self._compileOrderGraph
542 @readonly
543 def DependencyGraph(self) -> Graph:
544 """
545 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
547 :returns: Reference to the dependency graph.
548 """
549 return self._dependencyGraph
551 @readonly
552 def HierarchyGraph(self) -> Graph:
553 """
554 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
556 :returns: Reference to the hierarchy graph.
557 """
558 return self._hierarchyGraph
560 @readonly
561 def ObjectGraph(self) -> Graph:
562 """
563 Read-only property to access the object graph (:attr:`_objectGraph`).
565 :returns: Reference to the object graph.
566 """
567 return self._objectGraph
569 @readonly
570 def TopLevel(self) -> Union[Entity, Configuration]:
571 """
572 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
574 When called the first time, the hierarchy graph is checked for its root elements. When there is only one root element in the graph, a new field ``toplevel``
575 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
577 :returns: Reference to the design's *top-level*.
578 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
579 :raises VHDLModelException: If there is more than one *top-level*.
580 """
581 # Check for cached result
582 if self._toplevel is not None:
583 return self._toplevel
585 if self._hierarchyGraph.EdgeCount == 0:
586 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
588 roots = tuple(self._hierarchyGraph.IterateRoots())
589 if len(roots) == 1:
590 toplevel = roots[0]
591 self._hierarchyGraph["toplevel"] = toplevel
592 self._toplevel = toplevel.Value
594 return toplevel.Value
595 else:
596 raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}")
598 def LoadStdLibrary(self) -> 'Library':
599 """
600 Load the predefined VHDL library ``std`` into the design.
602 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
604 :returns: The library object of library ``std``.
605 """
606 from pyVHDLModel.STD import Std
608 doc = Document(Path("std.vhdl"), parent=self)
610 library = Std()
611 for designUnit in library.IterateDesignUnits():
612 doc._AddDesignUnit(designUnit)
614 self.AddLibrary(library)
616 return library
618 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library':
619 """
620 Load the predefined VHDL library ``ieee`` into the design.
622 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
624 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics.
625 :returns: The library object of library ``ieee``.
626 """
627 from pyVHDLModel.IEEE import Ieee
629 doc = Document(Path("ieee.vhdl"), parent=self)
631 library = Ieee(flavor)
632 for designUnit in library.IterateDesignUnits():
633 doc._AddDesignUnit(designUnit)
635 self.AddLibrary(library)
637 return library
639 def AddLibrary(self, library: 'Library') -> None:
640 """
641 Add a VHDL library to the design.
643 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
644 If ok, set the libraries parent reference to the design.
646 :param library: Library object to loaded.
647 :raises LibraryExistsInDesignError: If the library already exists in the design.
648 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
649 """
650 libraryIdentifier = library.NormalizedIdentifier
651 if libraryIdentifier in self._libraries:
652 raise LibraryExistsInDesignError(library)
654 if library._parent is not None:
655 raise LibraryRegisteredToForeignDesignError(library)
657 self._libraries[libraryIdentifier] = library
658 library._parent = self
660 def GetLibrary(self, libraryName: str) -> 'Library':
661 """
662 Return an (existing) VHDL library object of name ``libraryName``.
664 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
666 :param libraryName: Name of the requested VHDL library.
667 :returns: The VHDL library object.
668 """
669 libraryIdentifier = libraryName.lower()
670 try:
671 return self._libraries[libraryIdentifier]
672 except KeyError:
673 lib = Library(libraryName, parent=self)
674 self._libraries[libraryIdentifier] = lib
675 lib._parent = self
676 return lib
678 # TODO: allow overloaded parameter library to be str?
679 def AddDocument(self, document: 'Document', library: 'Library') -> None:
680 """
681 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
683 .. rubric:: Algorithm
685 1. Iterate all entities in the document
687 1. Check if entity name might exist in target library.
688 2. Add entity to library and update library membership.
690 2. Iterate all architectures in the document
692 1. Check if architecture name might exist in target library.
693 2. Add architecture to library and update library membership.
695 3. Iterate all packages in the document
697 1. Check if package name might exist in target library.
698 2. Add package to library and update library membership.
700 4. Iterate all package bodies in the document
702 1. Check if package body name might exist in target library.
703 2. Add package body to library and update library membership.
705 5. Iterate all configurations in the document
707 1. Check if configuration name might exist in target library.
708 2. Add configuration to library and update library membership.
710 6. Iterate all contexts in the document
712 1. Check if context name might exist in target library.
713 2. Add context to library and update library membership.
715 :param document: The VHDL source code file.
716 :param library: The VHDL library used to register the embedded design units to.
717 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
718 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
719 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
720 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
721 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
722 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
723 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
724 """
725 # FIXME: this checks for the library name, but not the object
726 # should the libraries parent be checked too?
727 if library._normalizedIdentifier not in self._libraries: 727 ↛ 728line 727 didn't jump to line 728 because the condition on line 727 was never true
728 raise LibraryNotRegisteredError(library)
730 self._documents.append(document)
731 document._parent = self
733 for entityIdentifier, entity in document._entities.items():
734 if entityIdentifier in library._entities: 734 ↛ 735line 734 didn't jump to line 735 because the condition on line 734 was never true
735 raise EntityExistsInLibraryError(entity, library)
737 library._entities[entityIdentifier] = entity
738 entity.Library = library
740 for entityIdentifier, architectures in document._architectures.items():
741 try:
742 architecturesPerEntity = library._architectures[entityIdentifier]
743 for architectureIdentifier, architecture in architectures.items():
744 if architectureIdentifier in architecturesPerEntity:
745 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
747 architecturesPerEntity[architectureIdentifier] = architecture
748 architecture.Library = library
749 except KeyError:
750 architecturesPerEntity = document._architectures[entityIdentifier].copy()
751 library._architectures[entityIdentifier] = architecturesPerEntity
753 for architecture in architecturesPerEntity.values():
754 architecture.Library = library
756 for packageIdentifier, package in document._packages.items():
757 if packageIdentifier in library._packages: 757 ↛ 758line 757 didn't jump to line 758 because the condition on line 757 was never true
758 raise PackageExistsInLibraryError(package, library)
760 library._packages[packageIdentifier] = package
761 package.Library = library
763 for packageBodyIdentifier, packageBody in document._packageBodies.items():
764 if packageBodyIdentifier in library._packageBodies: 764 ↛ 765line 764 didn't jump to line 765 because the condition on line 764 was never true
765 raise PackageBodyExistsError(packageBody, library)
767 library._packageBodies[packageBodyIdentifier] = packageBody
768 packageBody.Library = library
770 for configurationIdentifier, configuration in document._configurations.items():
771 if configurationIdentifier in library._configurations: 771 ↛ 772line 771 didn't jump to line 772 because the condition on line 771 was never true
772 raise ConfigurationExistsInLibraryError(configuration, library)
774 library._configurations[configurationIdentifier] = configuration
775 configuration.Library = library
777 for contextIdentifier, context in document._contexts.items():
778 if contextIdentifier in library._contexts: 778 ↛ 779line 778 didn't jump to line 779 because the condition on line 778 was never true
779 raise ContextExistsInLibraryError(context, library)
781 library._contexts[contextIdentifier] = context
782 context.Library = library
784 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
785 """
786 Iterate all design units in the design.
788 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
790 .. rubric:: Algorithm
792 1. Iterate all VHDL libraries.
794 1. Iterate all contexts in that library.
795 2. Iterate all packages in that library.
796 3. Iterate all package bodies in that library.
797 4. Iterate all entites in that library.
798 5. Iterate all architectures in that library.
799 6. Iterate all configurations in that library.
801 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
802 :returns: A generator to iterate all matched design units in the design.
804 .. seealso::
806 :meth:`pyVHDLModel.Library.IterateDesignUnits`
807 Iterate all design units in the library.
808 :meth:`pyVHDLModel.Document.IterateDesignUnits`
809 Iterate all design units in the document.
810 """
811 for library in self._libraries.values():
812 yield from library.IterateDesignUnits(filter)
814 def Analyze(self) -> None:
815 """
816 Analyze the whole design.
818 .. rubric:: Algorithm
820 1. Analyze dependencies of design units. |br|
821 This will also yield the design hierarchy and the compiler order.
822 2. Analyze dependencies of types and objects.
824 .. seealso::
826 :meth:`AnalyzeDependencies`
827 Analyze the dependencies of design units.
829 :meth:`AnalyzeObjects`
830 Analyze the dependencies of types and objects.
831 """
832 self.AnalyzeDependencies()
833 self.AnalyzeObjects()
835 def AnalyzeDependencies(self) -> None:
836 """
837 Analyze the dependencies of design units.
839 .. rubric:: Algorithm
841 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
842 |rarr| :meth:`CreateDependencyGraph`
843 2. Create the compile order graph. |br|
844 |rarr| :meth:`CreateCompileOrderGraph`
845 3. Index all packages. |br|
846 |rarr| :meth:`IndexPackages`
847 4. Index all architectures. |br|
848 |rarr| :meth:`IndexArchitectures`
849 5. Link all contexts |br|
850 |rarr| :meth:`LinkContexts`
851 6. Link all architectures. |br|
852 |rarr| :meth:`LinkArchitectures`
853 7. Link all package bodies. |br|
854 |rarr| :meth:`LinkPackageBodies`
855 8. Link all library references. |br|
856 |rarr| :meth:`LinkLibraryReferences`
857 9. Link all package references. |br|
858 |rarr| :meth:`LinkPackageReferences`
859 10. Link all context references. |br|
860 |rarr| :meth:`LinkContextReferences`
861 11. Link all components. |br|
862 |rarr| :meth:`LinkComponents`
863 12. Link all instantiations. |br|
864 |rarr| :meth:`LinkInstantiations`
865 13. Create the hierarchy graph. |br|
866 |rarr| :meth:`CreateHierarchyGraph`
867 14. Compute the compile order. |br|
868 |rarr| :meth:`ComputeCompileOrder`
869 """
870 self.CreateDependencyGraph()
871 self.CreateCompileOrderGraph()
873 self.IndexPackages()
874 self.IndexArchitectures()
876 self.LinkContexts()
877 self.LinkArchitectures()
878 self.LinkPackageBodies()
879 self.LinkLibraryReferences()
880 self.LinkPackageReferences()
881 self.LinkContextReferences()
883 self.LinkComponents()
884 self.LinkInstantiations()
885 self.CreateHierarchyGraph()
886 self.ComputeCompileOrder()
888 def AnalyzeObjects(self) -> None:
889 """
890 Analyze the dependencies of types and objects.
892 .. rubric:: Algorithm
894 1. Index all entities. |br|
895 |rarr| :meth:`IndexEntities`
896 2. Index all package bodies. |br|
897 |rarr| :meth:`IndexPackageBodies`
898 3. Import objects. |br|
899 |rarr| :meth:`ImportObjects`
900 4. Create the type and object graph. |br|
901 |rarr| :meth:`CreateTypeAndObjectGraph`
902 """
903 self.IndexEntities()
904 self.IndexPackageBodies()
906 self.ImportObjects()
907 self.CreateTypeAndObjectGraph()
909 def CreateDependencyGraph(self) -> None:
910 """
911 Create all vertices of the dependency graph by iterating all design units in all libraries.
913 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
914 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
916 Each vertex has the following properties:
918 * The vertex' ID is the design unit's identifier.
919 * The vertex' value references the design unit.
920 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
921 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
923 .. rubric:: Algorithm
925 1. Iterate all libraries in the design.
927 * Create a vertex for that library and reference the library by the vertex' value field. |br|
928 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
930 1. Iterate all contexts in that library.
932 * Create a vertex for that context and reference the context by the vertex' value field. |br|
933 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
935 2. Iterate all packages in that library.
937 * Create a vertex for that package and reference the package by the vertex' value field. |br|
938 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
940 3. Iterate all package bodies in that library.
942 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
943 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
945 4. Iterate all entities in that library.
947 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
948 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
950 5. Iterate all architectures in that library.
952 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
953 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
955 6. Iterate all configurations in that library.
957 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
958 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
959 """
960 predefinedLibraries = ("std", "ieee")
962 for libraryIdentifier, library in self._libraries.items():
963 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
964 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
965 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
966 library._dependencyVertex = dependencyVertex
968 for contextIdentifier, context in library._contexts.items():
969 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
970 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
971 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
972 context._dependencyVertex = dependencyVertex
974 for packageIdentifier, package in library._packages.items():
975 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
976 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
977 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
978 package._dependencyVertex = dependencyVertex
980 for packageBodyIdentifier, packageBody in library._packageBodies.items():
981 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
982 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
983 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
984 packageBody._dependencyVertex = dependencyVertex
986 for entityIdentifier, entity in library._entities.items():
987 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
988 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
989 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
990 entity._dependencyVertex = dependencyVertex
992 for entityIdentifier, architectures in library._architectures.items():
993 for architectureIdentifier, architecture in architectures.items():
994 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
995 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
996 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
997 architecture._dependencyVertex = dependencyVertex
999 for configurationIdentifier, configuration in library._configurations.items():
1000 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
1001 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
1002 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
1003 configuration._dependencyVertex = dependencyVertex
1005 def CreateCompileOrderGraph(self) -> None:
1006 """
1007 Create a compile-order graph with bidirectional references to the dependency graph.
1009 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
1010 graph and bidirectionally referenced.
1012 In addition, each vertex of a corresponding design unit in a document is linked to the vertex representing that document to express the design unit in
1013 document relationship.
1015 Each added vertex has the following properties:
1017 * The vertex' ID is the document's filename.
1018 * The vertex' value references the document.
1019 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
1020 * A key-value-pair called ``predefined`` does not exist.
1022 .. rubric:: Algorithm
1024 1. Iterate all documents in the design.
1026 * Create a vertex for that document and reference the document by the vertex' value field. |br|
1027 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
1028 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
1029 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
1031 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
1032 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
1034 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
1035 dependency vertex. This expresses a "design unit is located in document" relation.
1037 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
1038 """
1039 for document in self._documents:
1040 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
1041 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1042 document._dependencyVertex = dependencyVertex
1044 compilerOrderVertex = dependencyVertex.Copy(
1045 self._compileOrderGraph,
1046 copyDict=True,
1047 linkingKeyToOriginalVertex="dependencyVertex",
1048 linkingKeyFromOriginalVertex="compileOrderVertex"
1049 )
1050 document._compileOrderVertex = compilerOrderVertex
1052 for designUnit in document._designUnits:
1053 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1054 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1056 def ImportObjects(self) -> None:
1057 def _ImportObjects(package: Package) -> None:
1058 from pyVHDLModel.Declaration import AttributeSpecification
1060 for referencedLibrary in package._referencedPackages.values():
1061 for referencedPackage in referencedLibrary.values():
1062 for declaredItem in referencedPackage._declaredItems:
1063 if isinstance(declaredItem, MultipleNamedEntityMixin): 1063 ↛ 1064line 1063 didn't jump to line 1064 because the condition on line 1063 was never true
1064 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1065 package._namespace._elements[normalizedIdentifier] = declaredItem
1066 elif isinstance(declaredItem, NamedEntityMixin): 1066 ↛ 1068line 1066 didn't jump to line 1068 because the condition on line 1066 was always true
1067 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1068 elif isinstance(declaredItem, AttributeSpecification):
1069 # FIXME: actually, this is not a declared item, but a application of an attribute to named entities
1070 WarningCollector.Raise(NotImplementedWarning(f"Attribute specification."))
1072 else:
1073 raise VHDLModelException(f"Unexpected declared item.")
1075 for libraryName in ("std", "ieee"):
1076 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1077 _ImportObjects(package)
1079 for document in self.IterateDocumentsInCompileOrder():
1080 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1081 _ImportObjects(package)
1083 def CreateTypeAndObjectGraph(self) -> None:
1084 def _HandlePackage(package) -> None:
1085 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1087 for deferredConstant in package._deferredConstants.values(): 1087 ↛ 1088line 1087 didn't jump to line 1088 because the loop on line 1087 never started
1088 print(f"Deferred Constant: {deferredConstant}")
1089 deferredConstantVertex = Vertex(
1090 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1091 value=deferredConstant,
1092 graph=self._objectGraph
1093 )
1094 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1095 deferredConstant._objectVertex = deferredConstantVertex
1097 for constant in package._constants.values(): 1097 ↛ 1098line 1097 didn't jump to line 1098 because the loop on line 1097 never started
1098 print(f"Constant: {constant}")
1099 constantVertex = Vertex(
1100 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1101 value=constant,
1102 graph=self._objectGraph
1103 )
1104 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1105 constant._objectVertex = constantVertex
1107 for type in package._types.values():
1108 print(f"Type: {type}")
1109 typeVertex = Vertex(
1110 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1111 value=type,
1112 graph=self._objectGraph
1113 )
1114 typeVertex["kind"] = ObjectGraphVertexKind.Type
1115 type._objectVertex = typeVertex
1117 for subtype in package._subtypes.values():
1118 print(f"Subtype: {subtype}")
1119 subtypeVertex = Vertex(
1120 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1121 value=subtype,
1122 graph=self._objectGraph
1123 )
1124 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1125 subtype._objectVertex = subtypeVertex
1127 for function in package._functions.values(): 1127 ↛ 1128line 1127 didn't jump to line 1128 because the loop on line 1127 never started
1128 print(f"Function: {function}")
1129 functionVertex = Vertex(
1130 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1131 value=function,
1132 graph=self._objectGraph
1133 )
1134 functionVertex["kind"] = ObjectGraphVertexKind.Function
1135 function._objectVertex = functionVertex
1137 for procedure in package._procedures.values(): 1137 ↛ 1138line 1137 didn't jump to line 1138 because the loop on line 1137 never started
1138 print(f"Procedure: {procedure}")
1139 procedureVertex = Vertex(
1140 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1141 value=procedure,
1142 graph=self._objectGraph
1143 )
1144 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1145 procedure._objectVertex = procedureVertex
1147 for signal in package._signals.values(): 1147 ↛ 1148line 1147 didn't jump to line 1148 because the loop on line 1147 never started
1148 print(f"Signal: {signal}")
1149 signalVertex = Vertex(
1150 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1151 value=signal,
1152 graph=self._objectGraph
1153 )
1154 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1155 signal._objectVertex = signalVertex
1157 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
1158 if isinstance(expression, UnaryExpression): 1158 ↛ 1159line 1158 didn't jump to line 1159 because the condition on line 1158 was never true
1159 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1160 elif isinstance(expression, BinaryExpression): 1160 ↛ 1161line 1160 didn't jump to line 1161 because the condition on line 1160 was never true
1161 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1162 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1163 elif isinstance(expression, TernaryExpression): 1163 ↛ 1164line 1163 didn't jump to line 1164 because the condition on line 1163 was never true
1164 WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression."))
1165 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 1165 ↛ 1166line 1165 didn't jump to line 1166 because the condition on line 1165 was never true
1166 obj = namespace.FindObject(expression)
1167 expression._reference = obj
1169 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1170 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1171 else:
1172 WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch"))
1174 def _LinkItems(package: Package):
1175 for item in package._declaredItems:
1176 if isinstance(item, Constant): 1176 ↛ 1177line 1176 didn't jump to line 1177 because the condition on line 1176 was never true
1177 print(f"constant: {item}")
1178 elif isinstance(item, DeferredConstant): 1178 ↛ 1179line 1178 didn't jump to line 1179 because the condition on line 1178 was never true
1179 print(f"deferred constant: {item}")
1180 elif isinstance(item, Signal): 1180 ↛ 1181line 1180 didn't jump to line 1181 because the condition on line 1180 was never true
1181 print(f"signal: {item}")
1182 elif isinstance(item, IntegerType):
1183 typeNode = item._objectVertex
1185 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1186 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1187 # elif isinstance(item, FloatingType):
1188 # print(f"signal: {item}")
1189 elif isinstance(item, PhysicalType):
1190 typeNode = item._objectVertex
1192 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1193 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1194 elif isinstance(item, ArrayType):
1195 # Resolve dimensions
1196 for dimension in item._dimensions:
1197 subtype = package._namespace.FindSubtype(dimension)
1198 dimension._reference = subtype
1200 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1201 edge["kind"] = ObjectGraphEdgeKind.Subtype
1203 # Resolve element subtype
1204 subtype = package._namespace.FindSubtype(item._elementType)
1205 item._elementType._reference = subtype
1207 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1208 edge["kind"] = ObjectGraphEdgeKind.Subtype
1209 elif isinstance(item, RecordType): 1209 ↛ 1211line 1209 didn't jump to line 1211 because the condition on line 1209 was never true
1210 # Resolve each elements subtype
1211 for element in item._elements:
1212 subtype = package._namespace.FindSubtype(element._subtype)
1213 element._subtype._reference = subtype
1215 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1216 edge["kind"] = ObjectGraphEdgeKind.Subtype
1217 else:
1218 print(f"not handled: {item}")
1220 for libraryName in ("std", "ieee"):
1221 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1222 _HandlePackage(package)
1223 _LinkItems(package)
1225 for document in self.IterateDocumentsInCompileOrder():
1226 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1227 _HandlePackage(package)
1228 _LinkItems(package)
1230 def LinkContexts(self) -> None:
1231 """
1232 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1234 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1235 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1236 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1238 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1239 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1240 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1241 dependency graph is added for that relationship.
1243 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1244 referenced package,
1245 """
1246 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1247 # Create entries in _referenced*** for the current working library under its real name.
1248 workingLibrary: Library = context.Library
1249 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1251 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1252 context._referencedPackages[libraryNormalizedIdentifier] = {}
1253 context._referencedContexts[libraryNormalizedIdentifier] = {}
1255 # Process all library clauses
1256 for libraryReference in context._libraryReferences:
1257 # A library clause can have multiple comma-separated references
1258 for libraryName in libraryReference.Symbols:
1259 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1260 try:
1261 library = self._libraries[libraryNormalizedIdentifier]
1262 except KeyError:
1263 raise ReferencedLibraryNotExistingError(context, libraryName)
1264 # TODO: add position to these messages
1266 libraryName.Library = library
1268 context._referencedLibraries[libraryNormalizedIdentifier] = library
1269 context._referencedPackages[libraryNormalizedIdentifier] = {}
1270 context._referencedContexts[libraryNormalizedIdentifier] = {}
1271 # TODO: warn duplicate library reference
1273 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1274 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1276 # Process all use clauses
1277 for packageReference in context.PackageReferences:
1278 # A use clause can have multiple comma-separated references
1279 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1280 packageName = symbol.Name.Prefix
1281 libraryName = packageName.Prefix
1283 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1284 packageNormalizedIdentifier = packageName._normalizedIdentifier
1286 # In case work is used, resolve to the real library name.
1287 if libraryNormalizedIdentifier == "work": 1287 ↛ 1288line 1287 didn't jump to line 1288 because the condition on line 1287 was never true
1288 library: Library = context._parent
1289 libraryNormalizedIdentifier = library._normalizedIdentifier
1290 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1290 ↛ 1292line 1290 didn't jump to line 1292 because the condition on line 1290 was never true
1291 # TODO: This check doesn't trigger if it's the working library.
1292 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1293 else:
1294 library = self._libraries[libraryNormalizedIdentifier]
1296 try:
1297 package = library._packages[packageNormalizedIdentifier]
1298 except KeyError:
1299 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1301 symbol.Package = package
1303 # TODO: warn duplicate package reference
1304 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1306 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1307 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1309 # TODO: update the namespace with visible members
1310 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1310 ↛ 1313line 1310 didn't jump to line 1313 because the condition on line 1310 was always true
1311 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'."))
1313 elif isinstance(symbol, PackageMemberReferenceSymbol):
1314 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1316 else:
1317 raise VHDLModelException()
1319 def LinkArchitectures(self) -> None:
1320 """
1321 Link all architectures to corresponding entities in all libraries.
1323 .. rubric:: Algorithm
1325 1. Iterate all libraries:
1327 1. Iterate all architecture groups (grouped per entity symbol's name).
1328 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1330 * Check if entity symbol's name exists as an entity in this library.
1332 1. For each architecture in the same architecture group:
1334 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1335 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1336 * Set parent namespace of architecture's namespace to the entitie's namespace.
1337 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1339 .. seealso::
1341 :meth:`LinkPackageBodies`
1342 Link all package bodies to corresponding packages in all libraries.
1343 """
1344 for library in self._libraries.values():
1345 library.LinkArchitectures()
1347 def LinkPackageBodies(self) -> None:
1348 """
1349 Link all package bodies to corresponding packages in all libraries.
1351 .. rubric:: Algorithm
1353 1. Iterate all libraries:
1355 1. Iterate all package bodies.
1356 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1358 * Check if package body symbol's name exists as a package in this library.
1359 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1360 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1361 * Set parent namespace of package body's namespace to the package's namespace.
1362 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1364 .. seealso::
1366 :meth:`LinkArchitectures`
1367 Link all architectures to corresponding entities in all libraries.
1368 """
1369 for library in self._libraries.values():
1370 library.LinkPackageBodies()
1372 def LinkLibraryReferences(self) -> None:
1373 DEFAULT_LIBRARIES = ("std",)
1375 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1376 # All primary units supporting a context, have at least one library implicitly referenced
1377 if isinstance(designUnit, PrimaryUnit):
1378 for libraryIdentifier in DEFAULT_LIBRARIES:
1379 referencedLibrary = self._libraries[libraryIdentifier]
1380 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1381 designUnit._referencedPackages[libraryIdentifier] = {}
1382 designUnit._referencedContexts[libraryIdentifier] = {}
1383 # TODO: catch KeyError on self._libraries[libName]
1384 # TODO: warn duplicate library reference
1386 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1387 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1389 workingLibrary: Library = designUnit.Library
1390 libraryIdentifier = workingLibrary.NormalizedIdentifier
1391 referencedLibrary = self._libraries[libraryIdentifier]
1394 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1395 designUnit._referencedPackages[libraryIdentifier] = {}
1396 designUnit._referencedContexts[libraryIdentifier] = {}
1398 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1399 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1401 # All secondary units inherit referenced libraries from their primary units.
1402 else:
1403 if isinstance(designUnit, Architecture):
1404 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1405 elif isinstance(designUnit, PackageBody): 1405 ↛ 1408line 1405 didn't jump to line 1408 because the condition on line 1405 was always true
1406 referencedLibraries = designUnit.Package.Package._referencedLibraries
1407 else:
1408 raise VHDLModelException()
1410 for libraryIdentifier, library in referencedLibraries.items():
1411 designUnit._referencedLibraries[libraryIdentifier] = library
1413 for libraryReference in designUnit._libraryReferences:
1414 # A library clause can have multiple comma-separated references
1415 for librarySymbol in libraryReference.Symbols:
1416 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1417 if libraryIdentifier == "work": 1417 ↛ 1418line 1417 didn't jump to line 1418 because the condition on line 1417 was never true
1418 continue
1420 try:
1421 library = self._libraries[libraryIdentifier]
1422 except KeyError:
1423 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1424 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1425 raise ex
1427 librarySymbol.Library = library
1428 designUnit._referencedLibraries[libraryIdentifier] = library
1429 designUnit._referencedPackages[libraryIdentifier] = {}
1430 designUnit._referencedContexts[libraryIdentifier] = {}
1431 # TODO: warn duplicate library reference
1433 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1434 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1436 def LinkPackageReferences(self) -> None:
1437 DEFAULT_PACKAGES = (
1438 ("std", ("standard",)),
1439 )
1441 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1442 # All primary units supporting a context, have at least one package implicitly referenced
1443 if isinstance(designUnit, PrimaryUnit):
1444 if designUnit.Library.NormalizedIdentifier != "std" and \
1445 designUnit.NormalizedIdentifier != "standard":
1446 for lib in DEFAULT_PACKAGES:
1447 if lib[0] not in designUnit._referencedLibraries: 1447 ↛ 1448line 1447 didn't jump to line 1448 because the condition on line 1447 was never true
1448 raise VHDLModelException()
1449 for pack in lib[1]:
1450 referencedPackage = self._libraries[lib[0]]._packages[pack]
1451 designUnit._referencedPackages[lib[0]][pack] = referencedPackage
1452 # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack]
1453 # TODO: warn duplicate package reference
1455 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1456 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1458 # All secondary units inherit referenced packages from their primary units.
1459 else:
1460 if isinstance(designUnit, Architecture):
1461 referencedPackages = designUnit.Entity.Entity._referencedPackages
1462 elif isinstance(designUnit, PackageBody): 1462 ↛ 1465line 1462 didn't jump to line 1465 because the condition on line 1462 was always true
1463 referencedPackages = designUnit.Package.Package._referencedPackages
1464 else:
1465 raise VHDLModelException()
1467 for packageIdentifier, package in referencedPackages.items():
1468 designUnit._referencedPackages[packageIdentifier] = package
1470 for packageReference in designUnit.PackageReferences:
1471 # A use clause can have multiple comma-separated references
1472 for packageMemberSymbol in packageReference.Symbols:
1473 packageName = packageMemberSymbol.Name.Prefix
1474 libraryName = packageName.Prefix
1476 libraryIdentifier = libraryName.NormalizedIdentifier
1477 packageIdentifier = packageName.NormalizedIdentifier
1479 # In case work is used, resolve to the real library name.
1480 if libraryIdentifier == "work":
1481 library: Library = designUnit.Library
1482 libraryIdentifier = library.NormalizedIdentifier
1483 elif libraryIdentifier not in designUnit._referencedLibraries: 1483 ↛ 1485line 1483 didn't jump to line 1485 because the condition on line 1483 was never true
1484 # TODO: This check doesn't trigger if it's the working library.
1485 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1486 else:
1487 library = self._libraries[libraryIdentifier]
1489 try:
1490 package = library._packages[packageIdentifier]
1491 except KeyError:
1492 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1493 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1494 raise ex
1496 packageMemberSymbol.Package = package
1498 # TODO: warn duplicate package reference
1499 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1501 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1502 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1504 # TODO: update the namespace with visible members
1505 if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1505 ↛ 1511line 1505 didn't jump to line 1511 because the condition on line 1505 was always true
1506 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled."))
1508 for componentIdentifier, component in package._components.items(): 1508 ↛ 1509line 1508 didn't jump to line 1509 because the loop on line 1508 never started
1509 designUnit._namespace._elements[componentIdentifier] = component
1511 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
1512 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1514 else:
1515 raise VHDLModelException()
1517 def LinkContextReferences(self) -> None:
1518 for designUnit in self.IterateDesignUnits():
1519 for contextReference in designUnit._contextReferences:
1520 # A context reference can have multiple comma-separated references
1521 for contextSymbol in contextReference.Symbols:
1522 libraryName = contextSymbol.Name.Prefix
1524 libraryIdentifier = libraryName.NormalizedIdentifier
1525 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1527 # In case work is used, resolve to the real library name.
1528 if libraryIdentifier == "work": 1528 ↛ 1531line 1528 didn't jump to line 1531 because the condition on line 1528 was always true
1529 referencedLibrary = designUnit.Library
1530 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1531 elif libraryIdentifier not in designUnit._referencedLibraries:
1532 # TODO: This check doesn't trigger if it's the working library.
1533 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1534 else:
1535 referencedLibrary = self._libraries[libraryIdentifier]
1537 try:
1538 referencedContext = referencedLibrary._contexts[contextIdentifier]
1539 except KeyError:
1540 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1542 contextSymbol.Package = referencedContext
1544 # TODO: warn duplicate referencedContext reference
1545 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1547 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1548 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1550 for vertex in self._dependencyGraph.IterateTopologically():
1551 if vertex["kind"] is DependencyGraphVertexKind.Context:
1552 context: Context = vertex.Value
1553 for designUnitVertex in vertex.IteratePredecessorVertices():
1554 designUnit: DesignUnit = designUnitVertex.Value
1555 for libraryIdentifier, library in context._referencedLibraries.items():
1556 # if libraryIdentifier in designUnit._referencedLibraries:
1557 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1559 designUnit._referencedLibraries[libraryIdentifier] = library
1560 designUnit._referencedPackages[libraryIdentifier] = {}
1562 for libraryIdentifier, packages in context._referencedPackages.items():
1563 for packageIdentifier, package in packages.items():
1564 if packageIdentifier in designUnit._referencedPackages: 1564 ↛ 1565line 1564 didn't jump to line 1565 because the condition on line 1564 was never true
1565 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1567 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1569 def LinkComponents(self) -> None:
1570 for package in self.IterateDesignUnits(DesignUnitKind.Package): # type: Package
1571 library = package._parent
1572 for component in package._components.values(): 1572 ↛ 1573line 1572 didn't jump to line 1573 because the loop on line 1572 never started
1573 try:
1574 entity = library._entities[component.NormalizedIdentifier]
1575 except KeyError:
1576 if not component.AllowBlackbox:
1577 raise VHDLModelException(f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1578 else:
1579 component._isBlackBox = True
1580 continue
1582 component.Entity = entity
1584 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1585 # Currently, component has no _dependencyVertex field
1587 # FIXME: also link components in architectures (and nested structures like generate statements and block statements
1588 # for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture):
1589 # library = architecture._parent
1590 # for component in architecture._components.values():
1591 # pass
1593 def LinkInstantiations(self) -> None:
1594 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1595 for instance in architecture.IterateInstantiations():
1596 if isinstance(instance, EntityInstantiation): 1596 ↛ 1629line 1596 didn't jump to line 1629 because the condition on line 1596 was always true
1597 libraryName = instance.Entity.Name.Prefix
1598 libraryIdentifier = libraryName.Identifier
1599 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1600 if normalizedLibraryIdentifier == "work":
1601 libraryIdentifier = architecture.Library.Identifier
1602 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1603 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1603 ↛ 1604line 1603 didn't jump to line 1604 because the condition on line 1603 was never true
1604 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in architecture '{architecture!r}'.")
1605 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1606 raise ex
1608 try:
1609 library = self._libraries[normalizedLibraryIdentifier]
1610 except KeyError:
1611 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1612 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1613 raise ex
1615 try:
1616 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1617 except KeyError:
1618 ex = VHDLModelException(f"Referenced entity '{instance.Entity.Name.Identifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Name.Prefix.Identifier}.{instance.Entity.Name.Identifier}' not found in {'working ' if instance.Entity.Name.Prefix.NormalizedIdentifier == 'work' else ''}library '{libraryIdentifier}'.")
1619 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1620 if libs:
1621 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1622 raise ex
1624 instance.Entity.Entity = entity
1626 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1627 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1629 elif isinstance(instance, ComponentInstantiation):
1630 component = architecture._namespace.FindComponent(instance.Component)
1632 instance.Component.Component = component
1634 if not component.IsBlackbox:
1635 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1636 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1637 else:
1638 WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'."))
1640 elif isinstance(instance, ConfigurationInstantiation):
1641 WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'."))
1643 def IndexPackages(self) -> None:
1644 """
1645 Index all declared items in all packages in all libraries.
1647 .. rubric:: Algorithm
1649 1. Iterate all libraries:
1651 1. Iterate all packages |br|
1652 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1654 * Index all declared items in that package. |br|
1655 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1657 .. seealso::
1659 :meth:`IndexPackageBodies`
1660 Index all declared items in all package bodies in all libraries.
1661 :meth:`IndexEntities`
1662 Index all declared items in all entities in all libraries.
1663 :meth:`IndexArchitectures`
1664 Index all declared items in all architectures in all libraries.
1665 """
1666 for library in self._libraries.values():
1667 library.IndexPackages()
1669 def IndexPackageBodies(self) -> None:
1670 """
1671 Index all declared items in all packages in all libraries.
1673 .. rubric:: Algorithm
1675 1. Iterate all libraries:
1677 1. Iterate all packages |br|
1678 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
1680 * Index all declared items in that package body. |br|
1681 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
1683 .. seealso::
1685 :meth:`IndexPackages`
1686 Index all declared items in all packages in all libraries.
1687 :meth:`IndexEntities`
1688 Index all declared items in all entities in all libraries.
1689 :meth:`IndexArchitectures`
1690 Index all declared items in all architectures in all libraries.
1691 """
1692 for library in self._libraries.values():
1693 library.IndexPackageBodies()
1695 def IndexEntities(self) -> None:
1696 """
1697 Index all declared items in all packages in all libraries.
1699 .. rubric:: Algorithm
1701 1. Iterate all libraries:
1703 1. Iterate all packages |br|
1704 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
1706 * Index all declared items in that entity. |br|
1707 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
1709 .. seealso::
1711 :meth:`IndexPackages`
1712 Index all declared items in all packages in all libraries.
1713 :meth:`IndexPackageBodies`
1714 Index all declared items in all package bodies in all libraries.
1715 :meth:`IndexArchitectures`
1716 Index all declared items in all architectures in all libraries.
1717 """
1718 for library in self._libraries.values():
1719 library.IndexEntities()
1721 def IndexArchitectures(self) -> None:
1722 """
1723 Index all declared items in all packages in all libraries.
1725 .. rubric:: Algorithm
1727 1. Iterate all libraries:
1729 1. Iterate all packages |br|
1730 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
1732 * Index all declared items in that architecture. |br|
1733 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
1735 .. seealso::
1737 :meth:`IndexPackages`
1738 Index all declared items in all packages in all libraries.
1739 :meth:`IndexPackageBodies`
1740 Index all declared items in all package bodies in all libraries.
1741 :meth:`IndexEntities`
1742 Index all declared items in all entities in all libraries.
1743 """
1744 for library in self._libraries.values():
1745 library.IndexArchitectures()
1747 def CreateHierarchyGraph(self) -> None:
1748 """
1749 Create the hierarchy graph from dependency graph.
1751 .. rubric:: Algorithm
1753 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
1755 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
1756 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
1758 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
1759 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
1761 2. Iterate all architectures ...
1763 .. todo:: Design::CreateHierarchyGraph describe algorithm
1765 1. Iterate all outbound edges
1767 .. todo:: Design::CreateHierarchyGraph describe algorithm
1768 """
1769 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
1770 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
1771 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
1772 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
1773 vertex.Value._hierarchyVertex = hierarchyVertex
1775 # Copy implementation edges from
1776 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
1777 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
1778 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
1779 if DependencyGraphEdgeKind.Implementation in kind:
1780 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1781 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
1782 elif DependencyGraphEdgeKind.Instantiation in kind:
1783 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1785 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
1786 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
1787 continue
1789 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
1790 else:
1791 continue
1793 newEdge["kind"] = kind
1795 def ComputeCompileOrder(self) -> None:
1796 def predicate(edge: Edge) -> bool:
1797 return (
1798 DependencyGraphEdgeKind.Implementation in edge["kind"] or
1799 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
1800 DependencyGraphEdgeKind.UseClause in edge["kind"] or
1801 DependencyGraphEdgeKind.ContextReference in edge["kind"]
1802 ) and edge.Destination["predefined"] is False
1804 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
1805 sourceDocument: Document = edge.Source.Value.Document
1806 destinationDocument: Document = edge.Destination.Value.Document
1808 sourceVertex = sourceDocument._compileOrderVertex
1809 destinationVertex = destinationDocument._compileOrderVertex
1811 # Don't add self-edges
1812 if sourceVertex is destinationVertex: 1812 ↛ 1815line 1812 didn't jump to line 1815 because the condition on line 1812 was always true
1813 continue
1814 # Don't add parallel edges
1815 elif sourceVertex.HasEdgeToDestination(destinationVertex):
1816 continue
1818 e = sourceVertex.EdgeToVertex(destinationVertex)
1819 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1821 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
1822 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1824 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
1825 """
1826 Iterate all document in compile-order.
1828 .. rubric:: Algorithm
1830 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
1832 1. Iterate compile-order graph in topological order. |br|
1833 :meth:`pyTooling.Graph.Graph.IterateTopologically`
1835 * yield the compiler-order vertex' referenced document.
1837 :returns: A generator to iterate all documents in compile-order in the design.
1838 :raises VHDLModelException: If compile-order was not computed.
1840 .. seealso::
1842 .. todo:: missing text
1844 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
1846 """
1847 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 1847 ↛ 1848line 1847 didn't jump to line 1848 because the condition on line 1847 was never true
1848 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
1850 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
1851 yield compileOrderNode.Value
1853 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
1854 WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units."))
1856 def __repr__(self) -> str:
1857 """
1858 Formats a representation of the design.
1860 **Format:** ``Document: 'my_design'``
1862 :returns: String representation of the design.
1863 """
1864 return f"Design: {self._name}"
1866 __str__ = __repr__
1869@export
1870class Library(ModelEntity, NamedEntityMixin):
1871 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
1873 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library.
1874 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
1875 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
1876 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
1877 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
1878 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
1879 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
1881 _dependencyVertex: Vertex[None, None, str, Union['Library', DesignUnit], None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the library. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateDependencyGraph`.
1883 def __init__(
1884 self,
1885 identifier: str,
1886 allowBlackbox: Nullable[bool] = None,
1887 parent: ModelEntity = None
1888 ) -> None:
1889 """
1890 Initialize a VHDL library.
1892 :param identifier: Name of the VHDL library.
1893 :param allowBlackbox: Specify if blackboxes are allowed in this design.
1894 :param parent: The parent model entity (design) of this VHDL library.
1895 """
1896 super().__init__(parent)
1897 NamedEntityMixin.__init__(self, identifier)
1899 self._allowBlackbox = allowBlackbox
1901 self._contexts = {}
1902 self._configurations = {}
1903 self._entities = {}
1904 self._architectures = {}
1905 self._packages = {}
1906 self._packageBodies = {}
1908 self._dependencyVertex = None
1910 @property
1911 def AllowBlackbox(self) -> bool:
1912 """
1913 Read-only property to check if a design supports blackboxes (:attr:`_allowBlackbox`).
1915 :returns: If blackboxes are allowed.
1916 """
1917 if self._allowBlackbox is None:
1918 return self._parent.AllowBlackbox
1919 else:
1920 return self._allowBlackbox
1922 @AllowBlackbox.setter
1923 def AllowBlackbox(self, value: Nullable[bool]) -> None:
1924 self._allowBlackbox = value
1926 @readonly
1927 def Contexts(self) -> Dict[str, Context]:
1928 """Returns a list of all context declarations declared in this library."""
1929 return self._contexts
1931 @readonly
1932 def Configurations(self) -> Dict[str, Configuration]:
1933 """Returns a list of all configuration declarations declared in this library."""
1934 return self._configurations
1936 @readonly
1937 def Entities(self) -> Dict[str, Entity]:
1938 """Returns a list of all entity declarations declared in this library."""
1939 return self._entities
1941 @readonly
1942 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
1943 """Returns a list of all architectures declarations declared in this library."""
1944 return self._architectures
1946 @readonly
1947 def Packages(self) -> Dict[str, Package]:
1948 """Returns a list of all package declarations declared in this library."""
1949 return self._packages
1951 @readonly
1952 def PackageBodies(self) -> Dict[str, PackageBody]:
1953 """Returns a list of all package body declarations declared in this library."""
1954 return self._packageBodies
1956 @readonly
1957 def DependencyVertex(self) -> Vertex:
1958 """
1959 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
1961 The dependency vertex references this library by its value field.
1963 :returns: The corresponding dependency vertex.
1964 """
1965 return self._dependencyVertex
1967 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
1968 """
1969 Iterate all design units in the library.
1971 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
1973 .. rubric:: Algorithm
1975 1. Iterate all contexts in that library.
1976 2. Iterate all packages in that library.
1977 3. Iterate all package bodies in that library.
1978 4. Iterate all entities in that library.
1979 5. Iterate all architectures in that library.
1980 6. Iterate all configurations in that library.
1982 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
1983 :returns: A generator to iterate all matched design units in the library.
1985 .. seealso::
1987 :meth:`pyVHDLModel.Design.IterateDesignUnits`
1988 Iterate all design units in the design.
1989 :meth:`pyVHDLModel.Document.IterateDesignUnits`
1990 Iterate all design units in the document.
1991 """
1992 if DesignUnitKind.Context in filter:
1993 for context in self._contexts.values():
1994 yield context
1996 if DesignUnitKind.Package in filter:
1997 for package in self._packages.values():
1998 yield package
2000 if DesignUnitKind.PackageBody in filter:
2001 for packageBody in self._packageBodies.values():
2002 yield packageBody
2004 if DesignUnitKind.Entity in filter:
2005 for entity in self._entities.values():
2006 yield entity
2008 if DesignUnitKind.Architecture in filter:
2009 for architectures in self._architectures.values():
2010 for architecture in architectures.values():
2011 yield architecture
2013 if DesignUnitKind.Configuration in filter:
2014 for configuration in self._configurations.values():
2015 yield configuration
2017 # for verificationProperty in self._verificationUnits.values():
2018 # yield verificationProperty
2019 # for verificationUnit in self._verificationProperties.values():
2020 # yield entity
2021 # for verificationMode in self._verificationModes.values():
2022 # yield verificationMode
2024 def LinkArchitectures(self) -> None:
2025 """
2026 Link all architectures to corresponding entities.
2028 .. rubric:: Algorithm
2030 1. Iterate all architecture groups (grouped per entity symbol's name).
2032 * Check if entity symbol's name exists as an entity in this library.
2034 1. For each architecture in the same architecture group:
2036 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
2037 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
2038 * Set parent namespace of architecture's namespace to the entitie's namespace.
2039 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
2041 :raises VHDLModelException: If entity name doesn't exist.
2042 :raises VHDLModelException: If architecture name already exists for entity.
2044 .. seealso::
2046 :meth:`LinkPackageBodies`
2047 Link all package bodies to corresponding packages.
2048 """
2049 for entityName, architecturesPerEntity in self._architectures.items():
2050 if entityName not in self._entities: 2050 ↛ 2051line 2050 didn't jump to line 2051 because the condition on line 2050 was never true
2051 architectureNames = "', '".join(architecturesPerEntity.keys())
2052 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
2053 # TODO: search in other libraries to find that entity.
2054 # TODO: add code position
2056 entity = self._entities[entityName]
2057 for architecture in architecturesPerEntity.values():
2058 if architecture._normalizedIdentifier in entity._architectures: 2058 ↛ 2059line 2058 didn't jump to line 2059 because the condition on line 2058 was never true
2059 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
2060 # TODO: add code position of existing and current
2062 entity._architectures[architecture._normalizedIdentifier] = architecture
2063 architecture._entity.Entity = entity
2064 architecture._namespace._parentNamespace = entity._namespace
2066 # add "architecture -> entity" relation in dependency graph
2067 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
2068 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
2070 def LinkPackageBodies(self) -> None:
2071 """
2072 Link all package bodies to corresponding packages.
2074 .. rubric:: Algorithm
2076 1. Iterate all package bodies.
2078 * Check if package body symbol's name exists as a package in this library.
2079 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2080 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2081 * Set parent namespace of package body's namespace to the package's namespace.
2082 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2084 :raises VHDLModelException: If package name doesn't exist.
2086 .. seealso::
2088 :meth:`LinkArchitectures`
2089 Link all architectures to corresponding entities.
2090 """
2091 for packageBodyName, packageBody in self._packageBodies.items():
2092 if packageBodyName not in self._packages: 2092 ↛ 2093line 2092 didn't jump to line 2093 because the condition on line 2092 was never true
2093 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
2095 package = self._packages[packageBodyName]
2096 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
2097 packageBody._package.Package = package
2098 packageBody._namespace._parentNamespace = package._namespace
2100 # add "package body -> package" relation in dependency graph
2101 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2102 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2104 def IndexPackages(self) -> None:
2105 """
2106 Index declared items in all packages.
2108 .. rubric:: Algorithm
2110 1. Iterate all packages:
2112 * Index all declared items. |br|
2113 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2115 .. seealso::
2117 :meth:`IndexPackageBodies`
2118 Index all declared items in a package body.
2119 :meth:`IndexEntities`
2120 Index all declared items in an entity.
2121 :meth:`IndexArchitectures`
2122 Index all declared items in an architecture.
2123 """
2124 for package in self._packages.values():
2125 if isinstance(package, Package): 2125 ↛ 2124line 2125 didn't jump to line 2124 because the condition on line 2125 was always true
2126 package.IndexDeclaredItems()
2128 def IndexPackageBodies(self) -> None:
2129 """
2130 Index declared items in all package bodies.
2132 .. rubric:: Algorithm
2134 1. Iterate all package bodies:
2136 * Index all declared items. |br|
2137 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2139 .. seealso::
2141 :meth:`IndexPackages`
2142 Index all declared items in a package.
2143 :meth:`IndexEntities`
2144 Index all declared items in an entity.
2145 :meth:`IndexArchitectures`
2146 Index all declared items in an architecture.
2147 """
2148 for packageBody in self._packageBodies.values():
2149 packageBody.IndexDeclaredItems()
2151 def IndexEntities(self) -> None:
2152 """
2153 Index declared items in all entities.
2155 .. rubric:: Algorithm
2157 1. Iterate all entities:
2159 * Index all declared items. |br|
2160 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2162 .. seealso::
2164 :meth:`IndexPackages`
2165 Index all declared items in a package.
2166 :meth:`IndexPackageBodies`
2167 Index all declared items in a package body.
2168 :meth:`IndexArchitectures`
2169 Index all declared items in an architecture.
2170 """
2171 for entity in self._entities.values():
2172 entity.IndexDeclaredItems()
2174 def IndexArchitectures(self) -> None:
2175 """
2176 Index declared items in all architectures.
2178 .. rubric:: Algorithm
2180 1. Iterate all architectures:
2182 * Index all declared items. |br|
2183 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2185 .. seealso::
2187 :meth:`IndexPackages`
2188 Index all declared items in a package.
2189 :meth:`IndexPackageBodies`
2190 Index all declared items in a package body.
2191 :meth:`IndexEntities`
2192 Index all declared items in an entity.
2193 """
2194 for architectures in self._architectures.values():
2195 for architecture in architectures.values():
2196 architecture.IndexDeclaredItems()
2197 architecture.IndexStatements()
2199 def __repr__(self) -> str:
2200 """
2201 Formats a representation of the library.
2203 **Format:** ``Library: 'my_library'``
2205 :returns: String representation of the library.
2206 """
2207 return f"Library: '{self._identifier}'"
2209 __str__ = __repr__
2212@export
2213class Document(ModelEntity, DocumentedEntityMixin):
2214 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2216 _path: Path #: path to the document. ``None`` if virtual document.
2217 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2218 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2219 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2220 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2221 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2222 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2223 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2224 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2225 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2226 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2228 _dependencyVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the document. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateCompileOrderGraph`.
2229 _compileOrderVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the compile-order graph representing the document. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateCompileOrderGraph`.
2231 def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
2232 super().__init__(parent)
2233 DocumentedEntityMixin.__init__(self, documentation)
2235 self._path = path
2236 self._designUnits = []
2237 self._contexts = {}
2238 self._configurations = {}
2239 self._entities = {}
2240 self._architectures = {}
2241 self._packages = {}
2242 self._packageBodies = {}
2243 self._verificationUnits = {}
2244 self._verificationProperties = {}
2245 self._verificationModes = {}
2247 self._dependencyVertex = None
2248 self._compileOrderVertex = None
2250 def _AddEntity(self, item: Entity) -> None:
2251 """
2252 Add an entity to the document's lists of design units.
2254 :param item: Entity object to be added to the document.
2255 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
2256 :raises VHDLModelException: If entity name already exists in document.
2257 """
2258 if not isinstance(item, Entity): 2258 ↛ 2259line 2258 didn't jump to line 2259 because the condition on line 2258 was never true
2259 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2260 if version_info >= (3, 11): # pragma: no cover
2261 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2262 raise ex
2264 identifier = item._normalizedIdentifier
2265 if identifier in self._entities: 2265 ↛ 2267line 2265 didn't jump to line 2267 because the condition on line 2265 was never true
2266 # TODO: use a more specific exception
2267 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2269 self._entities[identifier] = item
2270 self._designUnits.append(item)
2271 item._document = self
2273 def _AddArchitecture(self, item: Architecture) -> None:
2274 """
2275 Add an architecture to the document's lists of design units.
2277 :param item: Architecture object to be added to the document.
2278 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
2279 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2280 """
2281 if not isinstance(item, Architecture): 2281 ↛ 2282line 2281 didn't jump to line 2282 because the condition on line 2281 was never true
2282 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2283 if version_info >= (3, 11): # pragma: no cover
2284 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2285 raise ex
2287 entity = item._entity.Name
2288 entityIdentifier = entity._normalizedIdentifier
2289 try:
2290 architectures = self._architectures[entityIdentifier]
2291 if item._normalizedIdentifier in architectures:
2292 # TODO: use a more specific exception
2293 # FIXME: this is allowed and should be a warning or a strict mode.
2294 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2296 architectures[item.Identifier] = item
2297 except KeyError:
2298 self._architectures[entityIdentifier] = {item._identifier: item}
2300 self._designUnits.append(item)
2301 item._document = self
2303 def _AddPackage(self, item: Package) -> None:
2304 """
2305 Add a package to the document's lists of design units.
2307 :param item: Package object to be added to the document.
2308 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
2309 :raises VHDLModelException: If package name already exists in document.
2310 """
2311 if not isinstance(item, (Package, PackageInstantiation)): 2311 ↛ 2312line 2311 didn't jump to line 2312 because the condition on line 2311 was never true
2312 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2313 if version_info >= (3, 11): # pragma: no cover
2314 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2315 raise ex
2317 identifier = item._normalizedIdentifier
2318 if identifier in self._packages: 2318 ↛ 2320line 2318 didn't jump to line 2320 because the condition on line 2318 was never true
2319 # TODO: use a more specific exception
2320 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2322 self._packages[identifier] = item
2323 self._designUnits.append(item)
2324 item._document = self
2326 def _AddPackageBody(self, item: PackageBody) -> None:
2327 """
2328 Add a package body to the document's lists of design units.
2330 :param item: Package body object to be added to the document.
2331 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
2332 :raises VHDLModelException: If package body name already exists in document.
2333 """
2334 if not isinstance(item, PackageBody): 2334 ↛ 2335line 2334 didn't jump to line 2335 because the condition on line 2334 was never true
2335 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2336 if version_info >= (3, 11): # pragma: no cover
2337 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2338 raise ex
2340 identifier = item._normalizedIdentifier
2341 if identifier in self._packageBodies: 2341 ↛ 2343line 2341 didn't jump to line 2343 because the condition on line 2341 was never true
2342 # TODO: use a more specific exception
2343 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2345 self._packageBodies[identifier] = item
2346 self._designUnits.append(item)
2347 item._document = self
2349 def _AddContext(self, item: Context) -> None:
2350 """
2351 Add a context to the document's lists of design units.
2353 :param item: Context object to be added to the document.
2354 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
2355 :raises VHDLModelException: If context name already exists in document.
2356 """
2357 if not isinstance(item, Context): 2357 ↛ 2358line 2357 didn't jump to line 2358 because the condition on line 2357 was never true
2358 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2359 if version_info >= (3, 11): # pragma: no cover
2360 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2361 raise ex
2363 identifier = item._normalizedIdentifier
2364 if identifier in self._contexts: 2364 ↛ 2366line 2364 didn't jump to line 2366 because the condition on line 2364 was never true
2365 # TODO: use a more specific exception
2366 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2368 self._contexts[identifier] = item
2369 self._designUnits.append(item)
2370 item._document = self
2372 def _AddConfiguration(self, item: Configuration) -> None:
2373 """
2374 Add a configuration to the document's lists of design units.
2376 :param item: Configuration object to be added to the document.
2377 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
2378 :raises VHDLModelException: If configuration name already exists in document.
2379 """
2380 if not isinstance(item, Configuration): 2380 ↛ 2381line 2380 didn't jump to line 2381 because the condition on line 2380 was never true
2381 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2382 if version_info >= (3, 11): # pragma: no cover
2383 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2384 raise ex
2386 identifier = item._normalizedIdentifier
2387 if identifier in self._configurations: 2387 ↛ 2389line 2387 didn't jump to line 2389 because the condition on line 2387 was never true
2388 # TODO: use a more specific exception
2389 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2391 self._configurations[identifier] = item
2392 self._designUnits.append(item)
2393 item._document = self
2395 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2396 if not isinstance(item, VerificationUnit):
2397 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2398 if version_info >= (3, 11): # pragma: no cover
2399 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2400 raise ex
2402 identifier = item._normalizedIdentifier
2403 if identifier in self._verificationUnits:
2404 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2406 self._verificationUnits[identifier] = item
2407 self._designUnits.append(item)
2408 item._document = self
2410 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2411 if not isinstance(item, VerificationProperty):
2412 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2413 if version_info >= (3, 11): # pragma: no cover
2414 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2415 raise ex
2417 identifier = item.NormalizedIdentifier
2418 if identifier in self._verificationProperties:
2419 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2421 self._verificationProperties[identifier] = item
2422 self._designUnits.append(item)
2423 item._document = self
2425 def _AddVerificationMode(self, item: VerificationMode) -> None:
2426 if not isinstance(item, VerificationMode):
2427 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2428 if version_info >= (3, 11): # pragma: no cover
2429 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2430 raise ex
2432 identifier = item.NormalizedIdentifier
2433 if identifier in self._verificationModes:
2434 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2436 self._verificationModes[identifier] = item
2437 self._designUnits.append(item)
2438 item._document = self
2440 def _AddDesignUnit(self, item: DesignUnit) -> None:
2441 """
2442 Add a design unit to the document's lists of design units.
2444 :param item: Configuration object to be added to the document.
2445 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2446 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2447 :raises VHDLModelException: If configuration name already exists in document.
2448 """
2449 if not isinstance(item, DesignUnit): 2449 ↛ 2450line 2449 didn't jump to line 2450 because the condition on line 2449 was never true
2450 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2451 if version_info >= (3, 11): # pragma: no cover
2452 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2453 raise ex
2455 if isinstance(item, Entity):
2456 self._AddEntity(item)
2457 elif isinstance(item, Architecture):
2458 self._AddArchitecture(item)
2459 elif isinstance(item, Package):
2460 self._AddPackage(item)
2461 elif isinstance(item, PackageBody):
2462 self._AddPackageBody(item)
2463 elif isinstance(item, Context):
2464 self._AddContext(item)
2465 elif isinstance(item, Configuration): 2465 ↛ 2467line 2465 didn't jump to line 2467 because the condition on line 2465 was always true
2466 self._AddConfiguration(item)
2467 elif isinstance(item, VerificationUnit):
2468 self._AddVerificationUnit(item)
2469 elif isinstance(item, VerificationProperty):
2470 self._AddVerificationProperty(item)
2471 elif isinstance(item, VerificationMode):
2472 self._AddVerificationMode(item)
2473 else:
2474 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2475 if version_info >= (3, 11): # pragma: no cover
2476 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2477 raise ex
2479 @readonly
2480 def Path(self) -> Path:
2481 """
2482 Read-only property to access the document's path (:attr:`_path`).
2484 :returns: The path of this document.
2485 """
2486 return self._path
2488 @readonly
2489 def DesignUnits(self) -> List[DesignUnit]:
2490 """
2491 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2493 :returns: List of all design units.
2494 """
2495 return self._designUnits
2497 @readonly
2498 def Contexts(self) -> Dict[str, Context]:
2499 """
2500 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
2502 :returns: List of all contexts.
2503 """
2504 return self._contexts
2506 @readonly
2507 def Configurations(self) -> Dict[str, Configuration]:
2508 """
2509 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
2511 :returns: List of all configurations.
2512 """
2513 return self._configurations
2515 @readonly
2516 def Entities(self) -> Dict[str, Entity]:
2517 """
2518 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
2520 :returns: List of all entities.
2521 """
2522 return self._entities
2524 @readonly
2525 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2526 """
2527 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
2529 :returns: List of all architectures.
2530 """
2531 return self._architectures
2533 @readonly
2534 def Packages(self) -> Dict[str, Package]:
2535 """
2536 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
2538 :returns: List of all packages.
2539 """
2540 return self._packages
2542 @readonly
2543 def PackageBodies(self) -> Dict[str, PackageBody]:
2544 """
2545 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
2547 :returns: List of all package bodies.
2548 """
2549 return self._packageBodies
2551 @readonly
2552 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
2553 """
2554 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
2556 :returns: List of all verification units.
2557 """
2558 return self._verificationUnits
2560 @readonly
2561 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
2562 """
2563 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
2565 :returns: List of all verification properties.
2566 """
2567 return self._verificationProperties
2569 @readonly
2570 def VerificationModes(self) -> Dict[str, VerificationMode]:
2571 """
2572 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
2574 :returns: List of all verification modes.
2575 """
2576 return self._verificationModes
2578 @readonly
2579 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
2580 """
2581 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
2583 The compile-order vertex references this document by its value field.
2585 :returns: The corresponding compile-order vertex.
2586 """
2587 return self._compileOrderVertex
2589 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2590 """
2591 Iterate all design units in the document.
2593 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2595 .. rubric:: Algorithm
2597 * If contexts are selected in the filter:
2599 1. Iterate all contexts in that library.
2601 * If packages are selected in the filter:
2603 1. Iterate all packages in that library.
2605 * If package bodies are selected in the filter:
2607 1. Iterate all package bodies in that library.
2609 * If entites are selected in the filter:
2611 1. Iterate all entites in that library.
2613 * If architectures are selected in the filter:
2615 1. Iterate all architectures in that library.
2617 * If configurations are selected in the filter:
2619 1. Iterate all configurations in that library.
2621 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2622 :returns: A generator to iterate all matched design units in the document.
2624 .. seealso::
2626 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2627 Iterate all design units in the design.
2628 :meth:`pyVHDLModel.Library.IterateDesignUnits`
2629 Iterate all design units in the library.
2630 """
2631 if DesignUnitKind.Context in filter:
2632 for context in self._contexts.values():
2633 yield context
2635 if DesignUnitKind.Package in filter: 2635 ↛ 2639line 2635 didn't jump to line 2639 because the condition on line 2635 was always true
2636 for package in self._packages.values():
2637 yield package
2639 if DesignUnitKind.PackageBody in filter:
2640 for packageBody in self._packageBodies.values():
2641 yield packageBody
2643 if DesignUnitKind.Entity in filter:
2644 for entity in self._entities.values():
2645 yield entity
2647 if DesignUnitKind.Architecture in filter:
2648 for architectures in self._architectures.values():
2649 for architecture in architectures.values():
2650 yield architecture
2652 if DesignUnitKind.Configuration in filter:
2653 for configuration in self._configurations.values():
2654 yield configuration
2656 # for verificationProperty in self._verificationUnits.values():
2657 # yield verificationProperty
2658 # for verificationUnit in self._verificationProperties.values():
2659 # yield entity
2660 # for verificationMode in self._verificationModes.values():
2661 # yield verificationMode
2663 def __repr__(self) -> str:
2664 """
2665 Formats a representation of the document.
2667 **Format:** ``Document: 'path/to/file.vhdl'``
2669 :returns: String representation of the document.
2670 """
2671 return f"Document: '{self._path}'"
2673 __str__ = __repr__