Coverage for pyVHDLModel/__init__.py: 77%
1075 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:13 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:13 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2024 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-2024 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-2024, Patrick Lehmann"
50__license__ = "Apache License, Version 2.0"
51__version__ = "0.29.2"
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
64from pyVHDLModel.Exception import VHDLModelException
65from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
66from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
67from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
68from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
69from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
70from pyVHDLModel.Namespace import Namespace
71from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
72from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
73from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
74from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package
75from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
76from pyVHDLModel.Instantiation import PackageInstantiation
77from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
80@export
81@unique
82class VHDLVersion(Enum):
83 """
84 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
86 A version can be given as integer or string and is represented as a unified
87 enumeration value.
89 This enumeration supports compare operators.
90 """
92 Any = -1 #: Any
93 VHDL87 = 87 #: VHDL-1987
94 VHDL93 = 93 #: VHDL-1993
95 AMS93 = 1993 #: VHDL-AMS-1993
96 AMS99 = 1999 #: VHDL-AMS-1999
97 VHDL2000 = 2000 #: VHDL-2000
98 VHDL2002 = 2002 #: VHDL-2002
99 VHDL2008 = 2008 #: VHDL-2008
100 AMS2017 = 2017 #: VHDL-AMS-2017
101 VHDL2019 = 2019 #: VHDL-2019
102 Latest = 10000 #: Latest VHDL (2019)
104 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
105 -1: Any,
106 87: VHDL87,
107 93: VHDL93,
108 # 93: AMS93,
109 99: AMS99,
110 0: VHDL2000,
111 2: VHDL2002,
112 8: VHDL2008,
113 17: AMS2017,
114 19: VHDL2019,
115 1987: VHDL87,
116 # 1993: VHDL93,
117 1993: AMS93,
118 1999: AMS99,
119 2000: VHDL2000,
120 2002: VHDL2002,
121 2008: VHDL2008,
122 2017: AMS2017,
123 2019: VHDL2019,
124 10000: Latest,
125 "Any": Any,
126 "87": VHDL87,
127 "93": VHDL93,
128 # "93": AMS93,
129 "99": AMS99,
130 "00": VHDL2000,
131 "02": VHDL2002,
132 "08": VHDL2008,
133 "17": AMS2017,
134 "19": VHDL2019,
135 "1987": VHDL87,
136 # "1993": VHDL93,
137 "1993": AMS93,
138 "1999": AMS99,
139 "2000": VHDL2000,
140 "2002": VHDL2002,
141 "2008": VHDL2008,
142 "2017": AMS2017,
143 "2019": VHDL2019,
144 "Latest": Latest,
145 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
147 def __init__(self, *_) -> None:
148 """Patch the embedded MAP dictionary"""
149 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
150 if (not isinstance(v, self.__class__)) and (v == self.value):
151 self.__class__.__VERSION_MAPPINGS__[k] = self
153 @classmethod
154 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
155 """
156 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
158 :param value: VHDL/VHDL-AMS year code.
159 :returns: Enumeration value.
160 :raises ValueError: If the year code is not recognized.
161 """
162 try:
163 return cls.__VERSION_MAPPINGS__[value]
164 except KeyError:
165 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
167 def __lt__(self, other: Any) -> bool:
168 """
169 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
171 :param other: Parameter to compare against.
172 :returns: True if version is less than the second operand.
173 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
174 """
175 if isinstance(other, VHDLVersion):
176 return self.value < other.value
177 else:
178 raise TypeError("Second operand is not of type 'VHDLVersion'.")
180 def __le__(self, other: Any) -> bool:
181 """
182 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
184 :param other: Parameter to compare against.
185 :returns: True if version is less or equal than the second operand.
186 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
187 """
188 if isinstance(other, VHDLVersion):
189 return self.value <= other.value
190 else:
191 raise TypeError("Second operand is not of type 'VHDLVersion'.")
193 def __gt__(self, other: Any) -> bool:
194 """
195 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
197 :param other: Parameter to compare against.
198 :returns: True if version is greater than the second operand.
199 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
200 """
201 if isinstance(other, VHDLVersion):
202 return self.value > other.value
203 else:
204 raise TypeError("Second operand is not of type 'VHDLVersion'.")
206 def __ge__(self, other: Any) -> bool:
207 """
208 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
210 :param other: Parameter to compare against.
211 :returns: True if version is greater or equal than the second operand.
212 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
213 """
214 if isinstance(other, VHDLVersion):
215 return self.value >= other.value
216 else:
217 raise TypeError("Second operand is not of type 'VHDLVersion'.")
219 def __ne__(self, other: Any) -> bool:
220 """
221 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
223 :param other: Parameter to compare against.
224 :returns: True if version is unequal to the second operand.
225 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
226 """
227 if isinstance(other, VHDLVersion):
228 return self.value != other.value
229 else:
230 raise TypeError("Second operand is not of type 'VHDLVersion'.")
232 def __eq__(self, other: Any) -> bool:
233 """
234 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
236 :param other: Parameter to compare against.
237 :returns: True if version is equal to the second operand.
238 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
239 """
240 if isinstance(other, VHDLVersion):
241 if (self is self.__class__.Any) or (other is self.__class__.Any):
242 return True
243 else:
244 return self.value == other.value
245 else:
246 raise TypeError("Second operand is not of type 'VHDLVersion'.")
248 @readonly
249 def IsVHDL(self) -> bool:
250 """
251 Checks if the version is a VHDL (not VHDL-AMS) version.
253 :returns: True if version is a VHDL version.
254 """
255 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
257 @readonly
258 def IsAMS(self) -> bool:
259 """
260 Checks if the version is a VHDL-AMS (not VHDL) version.
262 :returns: True if version is a VHDL-AMS version.
263 """
264 return self in (self.AMS93, self.AMS99, self.AMS2017)
266 def __str__(self) -> str:
267 """
268 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
270 :return: Formatted VHDL/VHDL-AMS version.
271 """
272 if self.value == self.Any.value:
273 return "VHDL'Any"
274 elif self.value == self.Latest.value:
275 return "VHDL'Latest"
277 year = str(self.value)[-2:]
278 if self.IsVHDL:
279 return f"VHDL'{year}"
280 else:
281 return f"VHDL-AMS'{year}"
283 def __repr__(self) -> str:
284 """
285 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
287 :return: Formatted VHDL/VHDL-AMS version.
288 """
289 if self.value == self.Any.value:
290 return "Any"
291 elif self.value == self.Latest.value:
292 return "Latest"
293 else:
294 return str(self.value)
297@export
298@unique
299class ObjectClass(Enum):
300 """
301 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
303 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
304 """
306 Default = 0 #: Object class not defined, thus it's context dependent.
307 Constant = 1 #: Constant
308 Variable = 2 #: Variable
309 Signal = 3 #: Signal
310 File = 4 #: File
311 Type = 5 #: Type
312 # FIXME: Package?
313 Procedure = 6 #: Procedure
314 Function = 7 #: Function
316 def __str__(self) -> str:
317 """
318 Formats the object class.
320 :return: Formatted object class.
321 """
322 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
325@export
326@unique
327class DesignUnitKind(Flag):
328 """
329 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
331 """
332 Context = auto() #: Context
333 Package = auto() #: Package
334 PackageBody = auto() #: Package Body
335 Entity = auto() #: Entity
336 Architecture = auto() #: Architecture
337 Configuration = auto() #: Configuration
339 Primary = Context | Configuration | Entity | Package #: List of primary design units.
340 Secondary = PackageBody | Architecture #: List of secondary design units.
341 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
342 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
344 All = Primary | Secondary #: List of all design units.
347@export
348@unique
349class DependencyGraphVertexKind(Flag):
350 """
351 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
352 """
353 Document = auto() #: A document (VHDL source file).
354 Library = auto() #: A VHDL library.
356 Context = auto() #: A context design unit.
357 Package = auto() #: A package design unit.
358 PackageBody = auto() #: A package body design unit.
359 Entity = auto() #: A entity design unit.
360 Architecture = auto() #: A architecture design unit.
361 Component = auto() #: A VHDL component.
362 Configuration = auto() #: A configuration design unit.
365@export
366@unique
367class DependencyGraphEdgeKind(Flag):
368 """
369 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
370 """
371 Document = auto()
372 Library = auto()
373 Context = auto()
374 Package = auto()
375 Entity = auto()
376 # Architecture = auto()
377 Configuration = auto()
378 Component = auto()
380 DeclaredIn = auto()
381 Order = auto()
382 Reference = auto()
383 Implementation = auto()
384 Instantiation = auto()
386 SourceFile = Document | DeclaredIn
387 CompileOrder = Document | Order
389 LibraryClause = Library | Reference
390 UseClause = Package | Reference
391 ContextReference = Context | Reference
393 EntityImplementation = Entity | Implementation
394 PackageImplementation = Package | Implementation
396 EntityInstantiation = Entity | Instantiation
397 ComponentInstantiation = Component | Instantiation
398 ConfigurationInstantiation = Configuration | Instantiation
401@export
402@unique
403class ObjectGraphVertexKind(Flag):
404 """
405 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
406 """
407 Type = auto()
408 Subtype = auto()
410 Constant = auto()
411 DeferredConstant = auto()
412 Variable = auto()
413 Signal = auto()
414 File = auto()
416 Alias = auto()
419@export
420@unique
421class ObjectGraphEdgeKind(Flag):
422 """
423 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
424 """
425 BaseType = auto()
426 Subtype = auto()
428 ReferenceInExpression = auto()
431@export
432class Design(ModelEntity):
433 """
434 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
436 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
437 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
438 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`).
440 The *design* contains references to the following graphs:
442 * :attr:`DependencyGraph`
443 * :attr:`CompileOrderGraph`
444 * :attr:`HierarchyGraph`
445 * :attr:`ObjectGraph`
446 """
447 _name: Nullable[str] #: Name of the design
448 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
449 _documents: List['Document'] #: List of all documents loaded for a design.
450 _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.
451 _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.
452 _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.
453 _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.
454 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
456 def __init__(self, name: Nullable[str] = None) -> None:
457 """
458 Initializes a VHDL design.
460 :param name: Name of the design.
461 """
462 super().__init__()
464 self._name = name
465 self._libraries = {}
466 self._documents = []
468 self._compileOrderGraph = Graph()
469 self._dependencyGraph = Graph()
470 self._hierarchyGraph = Graph()
471 self._objectGraph = Graph()
472 self._toplevel = None
474 @readonly
475 def Libraries(self) -> Dict[str, 'Library']:
476 """
477 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
479 :returns: A dictionary of library names and VHDL libraries.
480 """
481 return self._libraries
483 @readonly
484 def Documents(self) -> List['Document']:
485 """
486 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
488 :returns: A list of all documents.
489 """
490 return self._documents
492 @readonly
493 def CompileOrderGraph(self) -> Graph:
494 """
495 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
497 :returns: Reference to the compile-order graph.
498 """
499 return self._compileOrderGraph
501 @readonly
502 def DependencyGraph(self) -> Graph:
503 """
504 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
506 :returns: Reference to the dependency graph.
507 """
508 return self._dependencyGraph
510 @readonly
511 def HierarchyGraph(self) -> Graph:
512 """
513 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
515 :returns: Reference to the hierarchy graph.
516 """
517 return self._hierarchyGraph
519 @readonly
520 def ObjectGraph(self) -> Graph:
521 """
522 Read-only property to access the object graph (:attr:`_objectGraph`).
524 :returns: Reference to the object graph.
525 """
526 return self._objectGraph
528 @readonly
529 def TopLevel(self) -> Union[Entity, Configuration]:
530 """
531 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
533 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``
534 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
536 :returns: Reference to the design's *top-level*.
537 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
538 :raises VHDLModelException: If there is more than one *top-level*.
539 """
540 # Check for cached result
541 if self._toplevel is not None:
542 return self._toplevel
544 if self._hierarchyGraph.EdgeCount == 0:
545 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
547 roots = tuple(self._hierarchyGraph.IterateRoots())
548 if len(roots) == 1:
549 toplevel = roots[0]
550 self._hierarchyGraph["toplevel"] = toplevel
551 self._toplevel = toplevel.Value
553 return toplevel.Value
554 else:
555 raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}")
557 def LoadStdLibrary(self) -> 'Library':
558 """
559 Load the predefined VHDL library ``std`` into the design.
561 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
563 :returns: The library object of library ``std``.
564 """
565 from pyVHDLModel.STD import Std
567 doc = Document(Path("std.vhdl"), parent=self)
569 library = Std()
570 for designUnit in library.IterateDesignUnits():
571 doc._AddDesignUnit(designUnit)
573 self.AddLibrary(library)
575 return library
577 def LoadIEEELibrary(self) -> 'Library':
578 """
579 Load the predefined VHDL library ``ieee`` into the design.
581 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
583 :returns: The library object of library ``ieee``.
584 """
585 from pyVHDLModel.IEEE import Ieee
587 doc = Document(Path("ieee.vhdl"), parent=self)
589 library = Ieee()
590 for designUnit in library.IterateDesignUnits():
591 doc._AddDesignUnit(designUnit)
593 self.AddLibrary(library)
595 return library
597 def AddLibrary(self, library: 'Library') -> None:
598 """
599 Add a VHDL library to the design.
601 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
602 If ok, set the libraries parent reference to the design.
604 :param library: Library object to loaded.
605 :raises LibraryExistsInDesignError: If the library already exists in the design.
606 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
607 """
608 libraryIdentifier = library.NormalizedIdentifier
609 if libraryIdentifier in self._libraries:
610 raise LibraryExistsInDesignError(library)
612 if library._parent is not None:
613 raise LibraryRegisteredToForeignDesignError(library)
615 self._libraries[libraryIdentifier] = library
616 library._parent = self
618 def GetLibrary(self, libraryName: str) -> 'Library':
619 """
620 Return an (existing) VHDL library object of name ``libraryName``.
622 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
624 :param libraryName: Name of the requested VHDL library.
625 :returns: The VHDL library object.
626 """
627 libraryIdentifier = libraryName.lower()
628 try:
629 return self._libraries[libraryIdentifier]
630 except KeyError:
631 lib = Library(libraryName, parent=self)
632 self._libraries[libraryIdentifier] = lib
633 lib._parent = self
634 return lib
636 # TODO: allow overloaded parameter library to be str?
637 def AddDocument(self, document: 'Document', library: 'Library') -> None:
638 """
639 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
641 .. rubric:: Algorithm
643 1. Iterate all entities in the document
645 1. Check if entity name might exist in target library.
646 2. Add entity to library and update library membership.
648 2. Iterate all architectures in the document
650 1. Check if architecture name might exist in target library.
651 2. Add architecture to library and update library membership.
653 3. Iterate all packages in the document
655 1. Check if package name might exist in target library.
656 2. Add package to library and update library membership.
658 4. Iterate all package bodies in the document
660 1. Check if package body name might exist in target library.
661 2. Add package body to library and update library membership.
663 5. Iterate all configurations in the document
665 1. Check if configuration name might exist in target library.
666 2. Add configuration to library and update library membership.
668 6. Iterate all contexts in the document
670 1. Check if context name might exist in target library.
671 2. Add context to library and update library membership.
673 :param document: The VHDL source code file.
674 :param library: The VHDL library used to register the embedded design units to.
675 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
676 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
677 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
678 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
679 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
680 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
681 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
682 """
683 # FIXME: this checks for the library name, but not the object
684 # should the libraries parent be checked too?
685 if library._normalizedIdentifier not in self._libraries: 685 ↛ 686line 685 didn't jump to line 686 because the condition on line 685 was never true
686 raise LibraryNotRegisteredError(library)
688 self._documents.append(document)
689 document._parent = self
691 for entityIdentifier, entity in document._entities.items():
692 if entityIdentifier in library._entities: 692 ↛ 693line 692 didn't jump to line 693 because the condition on line 692 was never true
693 raise EntityExistsInLibraryError(entity, library)
695 library._entities[entityIdentifier] = entity
696 entity.Library = library
698 for entityIdentifier, architectures in document._architectures.items():
699 try:
700 architecturesPerEntity = library._architectures[entityIdentifier]
701 for architectureIdentifier, architecture in architectures.items():
702 if architectureIdentifier in architecturesPerEntity:
703 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
705 architecturesPerEntity[architectureIdentifier] = architecture
706 architecture.Library = library
707 except KeyError:
708 architecturesPerEntity = document._architectures[entityIdentifier].copy()
709 library._architectures[entityIdentifier] = architecturesPerEntity
711 for architecture in architecturesPerEntity.values():
712 architecture.Library = library
714 for packageIdentifier, package in document._packages.items():
715 if packageIdentifier in library._packages: 715 ↛ 716line 715 didn't jump to line 716 because the condition on line 715 was never true
716 raise PackageExistsInLibraryError(package, library)
718 library._packages[packageIdentifier] = package
719 package.Library = library
721 for packageBodyIdentifier, packageBody in document._packageBodies.items():
722 if packageBodyIdentifier in library._packageBodies: 722 ↛ 723line 722 didn't jump to line 723 because the condition on line 722 was never true
723 raise PackageBodyExistsError(packageBody, library)
725 library._packageBodies[packageBodyIdentifier] = packageBody
726 packageBody.Library = library
728 for configurationIdentifier, configuration in document._configurations.items():
729 if configurationIdentifier in library._configurations: 729 ↛ 730line 729 didn't jump to line 730 because the condition on line 729 was never true
730 raise ConfigurationExistsInLibraryError(configuration, library)
732 library._configurations[configurationIdentifier] = configuration
733 configuration.Library = library
735 for contextIdentifier, context in document._contexts.items():
736 if contextIdentifier in library._contexts: 736 ↛ 737line 736 didn't jump to line 737 because the condition on line 736 was never true
737 raise ContextExistsInLibraryError(context, library)
739 library._contexts[contextIdentifier] = context
740 context.Library = library
742 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
743 """
744 Iterate all design units in the design.
746 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
748 .. rubric:: Algorithm
750 1. Iterate all VHDL libraries.
752 1. Iterate all contexts in that library.
753 2. Iterate all packages in that library.
754 3. Iterate all package bodies in that library.
755 4. Iterate all entites in that library.
756 5. Iterate all architectures in that library.
757 6. Iterate all configurations in that library.
759 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
760 :returns: A generator to iterate all matched design units in the design.
762 .. seealso::
764 :meth:`pyVHDLModel.Library.IterateDesignUnits`
765 Iterate all design units in the library.
766 :meth:`pyVHDLModel.Document.IterateDesignUnits`
767 Iterate all design units in the document.
768 """
769 for library in self._libraries.values():
770 yield from library.IterateDesignUnits(filter)
772 def Analyze(self) -> None:
773 """
774 Analyze the whole design.
776 .. rubric:: Algorithm
778 1. Analyze dependencies of design units. |br|
779 This will also yield the design hierarchy and the compiler order.
780 2. Analyze dependencies of types and objects.
782 .. seealso::
784 :meth:`AnalyzeDependencies`
785 Analyze the dependencies of design units.
787 :meth:`AnalyzeObjects`
788 Analyze the dependencies of types and objects.
789 """
790 self.AnalyzeDependencies()
791 self.AnalyzeObjects()
793 def AnalyzeDependencies(self) -> None:
794 """
795 Analyze the dependencies of design units.
797 .. rubric:: Algorithm
799 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
800 |rarr| :meth:`CreateDependencyGraph`
801 2. Create the compile order graph. |br|
802 |rarr| :meth:`CreateCompileOrderGraph`
803 3. Index all packages. |br|
804 |rarr| :meth:`IndexPackages`
805 4. Index all architectures. |br|
806 |rarr| :meth:`IndexArchitectures`
807 5. Link all contexts |br|
808 |rarr| :meth:`LinkContexts`
809 6. Link all architectures. |br|
810 |rarr| :meth:`LinkArchitectures`
811 7. Link all package bodies. |br|
812 |rarr| :meth:`LinkPackageBodies`
813 8. Link all library references. |br|
814 |rarr| :meth:`LinkLibraryReferences`
815 9. Link all package references. |br|
816 |rarr| :meth:`LinkPackageReferences`
817 10. Link all context references. |br|
818 |rarr| :meth:`LinkContextReferences`
819 11. Link all components. |br|
820 |rarr| :meth:`LinkComponents`
821 12. Link all instantiations. |br|
822 |rarr| :meth:`LinkInstantiations`
823 13. Create the hierarchy graph. |br|
824 |rarr| :meth:`CreateHierarchyGraph`
825 14. Compute the compile order. |br|
826 |rarr| :meth:`ComputeCompileOrder`
827 """
828 self.CreateDependencyGraph()
829 self.CreateCompileOrderGraph()
831 self.IndexPackages()
832 self.IndexArchitectures()
834 self.LinkContexts()
835 self.LinkArchitectures()
836 self.LinkPackageBodies()
837 self.LinkLibraryReferences()
838 self.LinkPackageReferences()
839 self.LinkContextReferences()
841 self.LinkComponents()
842 self.LinkInstantiations()
843 self.CreateHierarchyGraph()
844 self.ComputeCompileOrder()
846 def AnalyzeObjects(self) -> None:
847 """
848 Analyze the dependencies of types and objects.
850 .. rubric:: Algorithm
852 1. Index all entities. |br|
853 |rarr| :meth:`IndexEntities`
854 2. Index all package bodies. |br|
855 |rarr| :meth:`IndexPackageBodies`
856 3. Import objects. |br|
857 |rarr| :meth:`ImportObjects`
858 4. Create the type and object graph. |br|
859 |rarr| :meth:`CreateTypeAndObjectGraph`
860 """
861 self.IndexEntities()
862 self.IndexPackageBodies()
864 self.ImportObjects()
865 self.CreateTypeAndObjectGraph()
867 def CreateDependencyGraph(self) -> None:
868 """
869 Create all vertices of the dependency graph by iterating all design units in all libraries.
871 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
872 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
874 Each vertex has the following properties:
876 * The vertex' ID is the design unit's identifier.
877 * The vertex' value references the design unit.
878 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
879 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
881 .. rubric:: Algorithm
883 1. Iterate all libraries in the design.
885 * Create a vertex for that library and reference the library by the vertex' value field. |br|
886 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
888 1. Iterate all contexts in that library.
890 * Create a vertex for that context and reference the context by the vertex' value field. |br|
891 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
893 2. Iterate all packages in that library.
895 * Create a vertex for that package and reference the package by the vertex' value field. |br|
896 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
898 3. Iterate all package bodies in that library.
900 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
901 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
903 4. Iterate all entities in that library.
905 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
906 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
908 5. Iterate all architectures in that library.
910 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
911 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
913 6. Iterate all configurations in that library.
915 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
916 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
917 """
918 predefinedLibraries = ("std", "ieee")
920 for libraryIdentifier, library in self._libraries.items():
921 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
922 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
923 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
924 library._dependencyVertex = dependencyVertex
926 for contextIdentifier, context in library._contexts.items():
927 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
928 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
929 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
930 context._dependencyVertex = dependencyVertex
932 for packageIdentifier, package in library._packages.items():
933 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
934 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
935 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
936 package._dependencyVertex = dependencyVertex
938 for packageBodyIdentifier, packageBody in library._packageBodies.items():
939 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
940 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
941 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
942 packageBody._dependencyVertex = dependencyVertex
944 for entityIdentifier, entity in library._entities.items():
945 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
946 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
947 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
948 entity._dependencyVertex = dependencyVertex
950 for entityIdentifier, architectures in library._architectures.items():
951 for architectureIdentifier, architecture in architectures.items():
952 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
953 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
954 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
955 architecture._dependencyVertex = dependencyVertex
957 for configurationIdentifier, configuration in library._configurations.items():
958 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
959 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
960 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
961 configuration._dependencyVertex = dependencyVertex
963 def CreateCompileOrderGraph(self) -> None:
964 """
965 Create a compile-order graph with bidirectional references to the dependency graph.
967 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
968 graph and bidirectionally referenced.
970 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
971 document relationship.
973 Each added vertex has the following properties:
975 * The vertex' ID is the document's filename.
976 * The vertex' value references the document.
977 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
978 * A key-value-pair called ``predefined`` does not exist.
980 .. rubric:: Algorithm
982 1. Iterate all documents in the design.
984 * Create a vertex for that document and reference the document by the vertex' value field. |br|
985 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
986 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
987 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
989 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
990 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
992 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
993 dependency vertex. This expresses a "design unit is located in document" relation.
995 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
996 """
997 for document in self._documents:
998 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
999 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1000 document._dependencyVertex = dependencyVertex
1002 compilerOrderVertex = dependencyVertex.Copy(
1003 self._compileOrderGraph,
1004 copyDict=True,
1005 linkingKeyToOriginalVertex="dependencyVertex",
1006 linkingKeyFromOriginalVertex="compileOrderVertex"
1007 )
1008 document._compileOrderVertex = compilerOrderVertex
1010 for designUnit in document._designUnits:
1011 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1012 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1014 def ImportObjects(self) -> None:
1015 def _ImportObjects(package: Package) -> None:
1016 for referencedLibrary in package._referencedPackages.values():
1017 for referencedPackage in referencedLibrary.values():
1018 for declaredItem in referencedPackage._declaredItems:
1019 if isinstance(declaredItem, MultipleNamedEntityMixin): 1019 ↛ 1020line 1019 didn't jump to line 1020 because the condition on line 1019 was never true
1020 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1021 package._namespace._elements[normalizedIdentifier] = declaredItem
1022 elif isinstance(declaredItem, NamedEntityMixin): 1022 ↛ 1025line 1022 didn't jump to line 1025 because the condition on line 1022 was always true
1023 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1024 else:
1025 raise VHDLModelException(f"Unexpected declared item.")
1027 for libraryName in ("std", "ieee"):
1028 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1029 _ImportObjects(package)
1031 for document in self.IterateDocumentsInCompileOrder():
1032 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1033 _ImportObjects(package)
1035 def CreateTypeAndObjectGraph(self) -> None:
1036 def _HandlePackage(package) -> None:
1037 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1039 for deferredConstant in package._deferredConstants.values(): 1039 ↛ 1040line 1039 didn't jump to line 1040 because the loop on line 1039 never started
1040 print(f"Deferred Constant: {deferredConstant}")
1041 deferredConstantVertex = Vertex(
1042 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1043 value=deferredConstant,
1044 graph=self._objectGraph
1045 )
1046 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1047 deferredConstant._objectVertex = deferredConstantVertex
1049 for constant in package._constants.values(): 1049 ↛ 1050line 1049 didn't jump to line 1050 because the loop on line 1049 never started
1050 print(f"Constant: {constant}")
1051 constantVertex = Vertex(
1052 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1053 value=constant,
1054 graph=self._objectGraph
1055 )
1056 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1057 constant._objectVertex = constantVertex
1059 for type in package._types.values():
1060 print(f"Type: {type}")
1061 typeVertex = Vertex(
1062 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1063 value=type,
1064 graph=self._objectGraph
1065 )
1066 typeVertex["kind"] = ObjectGraphVertexKind.Type
1067 type._objectVertex = typeVertex
1069 for subtype in package._subtypes.values():
1070 print(f"Subtype: {subtype}")
1071 subtypeVertex = Vertex(
1072 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1073 value=subtype,
1074 graph=self._objectGraph
1075 )
1076 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1077 subtype._objectVertex = subtypeVertex
1079 for function in package._functions.values(): 1079 ↛ 1080line 1079 didn't jump to line 1080 because the loop on line 1079 never started
1080 print(f"Function: {function}")
1081 functionVertex = Vertex(
1082 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1083 value=function,
1084 graph=self._objectGraph
1085 )
1086 functionVertex["kind"] = ObjectGraphVertexKind.Function
1087 function._objectVertex = functionVertex
1089 for procedure in package._procedures.values(): 1089 ↛ 1090line 1089 didn't jump to line 1090 because the loop on line 1089 never started
1090 print(f"Procedure: {procedure}")
1091 procedureVertex = Vertex(
1092 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1093 value=procedure,
1094 graph=self._objectGraph
1095 )
1096 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1097 procedure._objectVertex = procedureVertex
1099 for signal in package._signals.values(): 1099 ↛ 1100line 1099 didn't jump to line 1100 because the loop on line 1099 never started
1100 print(f"Signal: {signal}")
1101 signalVertex = Vertex(
1102 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1103 value=signal,
1104 graph=self._objectGraph
1105 )
1106 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1107 signal._objectVertex = signalVertex
1109 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
1110 if isinstance(expression, UnaryExpression): 1110 ↛ 1111line 1110 didn't jump to line 1111 because the condition on line 1110 was never true
1111 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1112 elif isinstance(expression, BinaryExpression): 1112 ↛ 1113line 1112 didn't jump to line 1113 because the condition on line 1112 was never true
1113 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1114 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1115 elif isinstance(expression, TernaryExpression): 1115 ↛ 1116line 1115 didn't jump to line 1116 because the condition on line 1115 was never true
1116 pass
1117 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 1117 ↛ 1118line 1117 didn't jump to line 1118 because the condition on line 1117 was never true
1118 obj = namespace.FindObject(expression)
1119 expression._reference = obj
1121 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1122 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1123 else:
1124 pass
1126 def _LinkItems(package: Package):
1127 for item in package._declaredItems:
1128 if isinstance(item, Constant): 1128 ↛ 1129line 1128 didn't jump to line 1129 because the condition on line 1128 was never true
1129 print(f"constant: {item}")
1130 elif isinstance(item, DeferredConstant): 1130 ↛ 1131line 1130 didn't jump to line 1131 because the condition on line 1130 was never true
1131 print(f"deferred constant: {item}")
1132 elif isinstance(item, Signal): 1132 ↛ 1133line 1132 didn't jump to line 1133 because the condition on line 1132 was never true
1133 print(f"signal: {item}")
1134 elif isinstance(item, IntegerType):
1135 typeNode = item._objectVertex
1137 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1138 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1139 # elif isinstance(item, FloatingType):
1140 # print(f"signal: {item}")
1141 elif isinstance(item, PhysicalType):
1142 typeNode = item._objectVertex
1144 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1145 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1146 elif isinstance(item, ArrayType):
1147 # Resolve dimensions
1148 for dimension in item._dimensions:
1149 subtype = package._namespace.FindSubtype(dimension)
1150 dimension._reference = subtype
1152 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1153 edge["kind"] = ObjectGraphEdgeKind.Subtype
1155 # Resolve element subtype
1156 subtype = package._namespace.FindSubtype(item._elementType)
1157 item._elementType._reference = subtype
1159 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1160 edge["kind"] = ObjectGraphEdgeKind.Subtype
1161 elif isinstance(item, RecordType): 1161 ↛ 1163line 1161 didn't jump to line 1163 because the condition on line 1161 was never true
1162 # Resolve each elements subtype
1163 for element in item._elements:
1164 subtype = package._namespace.FindSubtype(element._subtype)
1165 element._subtype._reference = subtype
1167 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1168 edge["kind"] = ObjectGraphEdgeKind.Subtype
1169 else:
1170 print(f"not handled: {item}")
1172 for libraryName in ("std", "ieee"):
1173 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1174 _HandlePackage(package)
1175 _LinkItems(package)
1177 for document in self.IterateDocumentsInCompileOrder():
1178 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1179 _HandlePackage(package)
1180 _LinkItems(package)
1182 def LinkContexts(self) -> None:
1183 """
1184 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1186 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1187 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1188 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1190 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1191 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1192 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1193 dependency graph is added for that relationship.
1195 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1196 referenced package,
1197 """
1198 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1199 # Create entries in _referenced*** for the current working library under its real name.
1200 workingLibrary: Library = context.Library
1201 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1203 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1204 context._referencedPackages[libraryNormalizedIdentifier] = {}
1205 context._referencedContexts[libraryNormalizedIdentifier] = {}
1207 # Process all library clauses
1208 for libraryReference in context._libraryReferences:
1209 # A library clause can have multiple comma-separated references
1210 for libraryName in libraryReference.Symbols:
1211 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1212 try:
1213 library = self._libraries[libraryNormalizedIdentifier]
1214 except KeyError:
1215 raise ReferencedLibraryNotExistingError(context, libraryName)
1216 # TODO: add position to these messages
1218 libraryName.Library = library
1220 context._referencedLibraries[libraryNormalizedIdentifier] = library
1221 context._referencedPackages[libraryNormalizedIdentifier] = {}
1222 context._referencedContexts[libraryNormalizedIdentifier] = {}
1223 # TODO: warn duplicate library reference
1225 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1226 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1228 # Process all use clauses
1229 for packageReference in context.PackageReferences:
1230 # A use clause can have multiple comma-separated references
1231 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1232 packageName = symbol.Name.Prefix
1233 libraryName = packageName.Prefix
1235 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1236 packageNormalizedIdentifier = packageName._normalizedIdentifier
1238 # In case work is used, resolve to the real library name.
1239 if libraryNormalizedIdentifier == "work": 1239 ↛ 1240line 1239 didn't jump to line 1240 because the condition on line 1239 was never true
1240 library: Library = context._parent
1241 libraryNormalizedIdentifier = library._normalizedIdentifier
1242 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1242 ↛ 1244line 1242 didn't jump to line 1244 because the condition on line 1242 was never true
1243 # TODO: This check doesn't trigger if it's the working library.
1244 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1245 else:
1246 library = self._libraries[libraryNormalizedIdentifier]
1248 try:
1249 package = library._packages[packageNormalizedIdentifier]
1250 except KeyError:
1251 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1253 symbol.Package = package
1255 # TODO: warn duplicate package reference
1256 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1258 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1259 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1261 # TODO: update the namespace with visible members
1262 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1262 ↛ 1265line 1262 didn't jump to line 1265 because the condition on line 1262 was always true
1263 pass
1265 elif isinstance(symbol, PackageMemberReferenceSymbol):
1266 raise NotImplementedError()
1267 else:
1268 raise VHDLModelException()
1270 def LinkArchitectures(self) -> None:
1271 """
1272 Link all architectures to corresponding entities in all libraries.
1274 .. rubric:: Algorithm
1276 1. Iterate all libraries:
1278 1. Iterate all architecture groups (grouped per entity symbol's name).
1279 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1281 * Check if entity symbol's name exists as an entity in this library.
1283 1. For each architecture in the same architecture group:
1285 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1286 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1287 * Set parent namespace of architecture's namespace to the entitie's namespace.
1288 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1290 .. seealso::
1292 :meth:`LinkPackageBodies`
1293 Link all package bodies to corresponding packages in all libraries.
1294 """
1295 for library in self._libraries.values():
1296 library.LinkArchitectures()
1298 def LinkPackageBodies(self) -> None:
1299 """
1300 Link all package bodies to corresponding packages in all libraries.
1302 .. rubric:: Algorithm
1304 1. Iterate all libraries:
1306 1. Iterate all package bodies.
1307 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1309 * Check if package body symbol's name exists as a package in this library.
1310 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1311 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1312 * Set parent namespace of package body's namespace to the package's namespace.
1313 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1315 .. seealso::
1317 :meth:`LinkArchitectures`
1318 Link all architectures to corresponding entities in all libraries.
1319 """
1320 for library in self._libraries.values():
1321 library.LinkPackageBodies()
1323 def LinkLibraryReferences(self) -> None:
1324 DEFAULT_LIBRARIES = ("std",)
1326 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1327 # All primary units supporting a context, have at least one library implicitly referenced
1328 if isinstance(designUnit, PrimaryUnit):
1329 for libraryIdentifier in DEFAULT_LIBRARIES:
1330 referencedLibrary = self._libraries[libraryIdentifier]
1331 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1332 designUnit._referencedPackages[libraryIdentifier] = {}
1333 designUnit._referencedContexts[libraryIdentifier] = {}
1334 # TODO: catch KeyError on self._libraries[libName]
1335 # TODO: warn duplicate library reference
1337 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1338 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1340 workingLibrary: Library = designUnit.Library
1341 libraryIdentifier = workingLibrary.NormalizedIdentifier
1342 referencedLibrary = self._libraries[libraryIdentifier]
1345 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1346 designUnit._referencedPackages[libraryIdentifier] = {}
1347 designUnit._referencedContexts[libraryIdentifier] = {}
1349 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1350 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1352 # All secondary units inherit referenced libraries from their primary units.
1353 else:
1354 if isinstance(designUnit, Architecture):
1355 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1356 elif isinstance(designUnit, PackageBody): 1356 ↛ 1359line 1356 didn't jump to line 1359 because the condition on line 1356 was always true
1357 referencedLibraries = designUnit.Package.Package._referencedLibraries
1358 else:
1359 raise VHDLModelException()
1361 for libraryIdentifier, library in referencedLibraries.items():
1362 designUnit._referencedLibraries[libraryIdentifier] = library
1364 for libraryReference in designUnit._libraryReferences:
1365 # A library clause can have multiple comma-separated references
1366 for librarySymbol in libraryReference.Symbols:
1367 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1368 try:
1369 library = self._libraries[libraryIdentifier]
1370 except KeyError:
1371 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1372 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1373 raise ex
1375 librarySymbol.Library = library
1376 designUnit._referencedLibraries[libraryIdentifier] = library
1377 designUnit._referencedPackages[libraryIdentifier] = {}
1378 designUnit._referencedContexts[libraryIdentifier] = {}
1379 # TODO: warn duplicate library reference
1381 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1382 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1384 def LinkPackageReferences(self) -> None:
1385 DEFAULT_PACKAGES = (
1386 ("std", ("standard",)),
1387 )
1389 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1390 # All primary units supporting a context, have at least one package implicitly referenced
1391 if isinstance(designUnit, PrimaryUnit):
1392 if designUnit.Library.NormalizedIdentifier != "std" and \
1393 designUnit.NormalizedIdentifier != "standard":
1394 for lib in DEFAULT_PACKAGES:
1395 if lib[0] not in designUnit._referencedLibraries: 1395 ↛ 1396line 1395 didn't jump to line 1396 because the condition on line 1395 was never true
1396 raise VHDLModelException()
1397 for pack in lib[1]:
1398 referencedPackage = self._libraries[lib[0]]._packages[pack]
1399 designUnit._referencedPackages[lib[0]][pack] = referencedPackage
1400 # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack]
1401 # TODO: warn duplicate package reference
1403 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1404 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1406 # All secondary units inherit referenced packages from their primary units.
1407 else:
1408 if isinstance(designUnit, Architecture):
1409 referencedPackages = designUnit.Entity.Entity._referencedPackages
1410 elif isinstance(designUnit, PackageBody): 1410 ↛ 1413line 1410 didn't jump to line 1413 because the condition on line 1410 was always true
1411 referencedPackages = designUnit.Package.Package._referencedPackages
1412 else:
1413 raise VHDLModelException()
1415 for packageIdentifier, package in referencedPackages.items():
1416 designUnit._referencedPackages[packageIdentifier] = package
1418 for packageReference in designUnit.PackageReferences:
1419 # A use clause can have multiple comma-separated references
1420 for packageMemberSymbol in packageReference.Symbols:
1421 packageName = packageMemberSymbol.Name.Prefix
1422 libraryName = packageName.Prefix
1424 libraryIdentifier = libraryName.NormalizedIdentifier
1425 packageIdentifier = packageName.NormalizedIdentifier
1427 # In case work is used, resolve to the real library name.
1428 if libraryIdentifier == "work":
1429 library: Library = designUnit.Library
1430 libraryIdentifier = library.NormalizedIdentifier
1431 elif libraryIdentifier not in designUnit._referencedLibraries: 1431 ↛ 1433line 1431 didn't jump to line 1433 because the condition on line 1431 was never true
1432 # TODO: This check doesn't trigger if it's the working library.
1433 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1434 else:
1435 library = self._libraries[libraryIdentifier]
1437 try:
1438 package = library._packages[packageIdentifier]
1439 except KeyError:
1440 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1441 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1442 raise ex
1444 packageMemberSymbol.Package = package
1446 # TODO: warn duplicate package reference
1447 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1449 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1450 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1452 # TODO: update the namespace with visible members
1453 if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1453 ↛ 1457line 1453 didn't jump to line 1457 because the condition on line 1453 was always true
1454 for componentIdentifier, component in package._components.items(): 1454 ↛ 1455line 1454 didn't jump to line 1455 because the loop on line 1454 never started
1455 designUnit._namespace._elements[componentIdentifier] = component
1457 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
1458 raise NotImplementedError()
1459 else:
1460 raise VHDLModelException()
1462 def LinkContextReferences(self) -> None:
1463 for designUnit in self.IterateDesignUnits():
1464 for contextReference in designUnit._contextReferences:
1465 # A context reference can have multiple comma-separated references
1466 for contextSymbol in contextReference.Symbols:
1467 libraryName = contextSymbol.Name.Prefix
1469 libraryIdentifier = libraryName.NormalizedIdentifier
1470 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1472 # In case work is used, resolve to the real library name.
1473 if libraryIdentifier == "work": 1473 ↛ 1476line 1473 didn't jump to line 1476 because the condition on line 1473 was always true
1474 referencedLibrary = designUnit.Library
1475 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1476 elif libraryIdentifier not in designUnit._referencedLibraries:
1477 # TODO: This check doesn't trigger if it's the working library.
1478 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1479 else:
1480 referencedLibrary = self._libraries[libraryIdentifier]
1482 try:
1483 referencedContext = referencedLibrary._contexts[contextIdentifier]
1484 except KeyError:
1485 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1487 contextSymbol.Package = referencedContext
1489 # TODO: warn duplicate referencedContext reference
1490 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1492 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1493 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1495 for vertex in self._dependencyGraph.IterateTopologically():
1496 if vertex["kind"] is DependencyGraphVertexKind.Context:
1497 context: Context = vertex.Value
1498 for designUnitVertex in vertex.IteratePredecessorVertices():
1499 designUnit: DesignUnit = designUnitVertex.Value
1500 for libraryIdentifier, library in context._referencedLibraries.items():
1501 # if libraryIdentifier in designUnit._referencedLibraries:
1502 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1504 designUnit._referencedLibraries[libraryIdentifier] = library
1505 designUnit._referencedPackages[libraryIdentifier] = {}
1507 for libraryIdentifier, packages in context._referencedPackages.items():
1508 for packageIdentifier, package in packages.items():
1509 if packageIdentifier in designUnit._referencedPackages: 1509 ↛ 1510line 1509 didn't jump to line 1510 because the condition on line 1509 was never true
1510 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1512 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1514 def LinkComponents(self) -> None:
1515 for package in self.IterateDesignUnits(DesignUnitKind.Package): # type: Package
1516 library = package._parent
1517 for component in package._components.values(): 1517 ↛ 1518line 1517 didn't jump to line 1518 because the loop on line 1517 never started
1518 try:
1519 entity = library._entities[component.NormalizedIdentifier]
1520 except KeyError:
1521 print(f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1523 component.Entity = entity
1525 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1526 # Currently, component has no _dependencyVertex field
1528 def LinkInstantiations(self) -> None:
1529 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1530 for instance in architecture.IterateInstantiations():
1531 if isinstance(instance, EntityInstantiation): 1531 ↛ 1564line 1531 didn't jump to line 1564 because the condition on line 1531 was always true
1532 libraryName = instance.Entity.Name.Prefix
1533 libraryIdentifier = libraryName.Identifier
1534 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1535 if normalizedLibraryIdentifier == "work":
1536 libraryIdentifier = architecture.Library.Identifier
1537 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1538 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1538 ↛ 1539line 1538 didn't jump to line 1539 because the condition on line 1538 was never true
1539 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}'.")
1540 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1541 raise ex
1543 try:
1544 library = self._libraries[normalizedLibraryIdentifier]
1545 except KeyError:
1546 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1547 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1548 raise ex
1550 try:
1551 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1552 except KeyError:
1553 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}'.")
1554 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1555 if libs:
1556 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1557 raise ex
1559 instance.Entity.Entity = entity
1561 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1562 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1564 elif isinstance(instance, ComponentInstantiation):
1565 component = architecture._namespace.FindComponent(instance.Component)
1567 instance.Component.Component = component
1569 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1570 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1572 elif isinstance(instance, ConfigurationInstantiation):
1573 # pass
1574 print(instance.Label, instance.Configuration)
1576 def IndexPackages(self) -> None:
1577 """
1578 Index all declared items in all packages in all libraries.
1580 .. rubric:: Algorithm
1582 1. Iterate all libraries:
1584 1. Iterate all packages |br|
1585 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1587 * Index all declared items in that package. |br|
1588 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1590 .. seealso::
1592 :meth:`IndexPackageBodies`
1593 Index all declared items in all package bodies in all libraries.
1594 :meth:`IndexEntities`
1595 Index all declared items in all entities in all libraries.
1596 :meth:`IndexArchitectures`
1597 Index all declared items in all architectures in all libraries.
1598 """
1599 for library in self._libraries.values():
1600 library.IndexPackages()
1602 def IndexPackageBodies(self) -> None:
1603 """
1604 Index all declared items in all packages in all libraries.
1606 .. rubric:: Algorithm
1608 1. Iterate all libraries:
1610 1. Iterate all packages |br|
1611 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
1613 * Index all declared items in that package body. |br|
1614 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
1616 .. seealso::
1618 :meth:`IndexPackages`
1619 Index all declared items in all packages in all libraries.
1620 :meth:`IndexEntities`
1621 Index all declared items in all entities in all libraries.
1622 :meth:`IndexArchitectures`
1623 Index all declared items in all architectures in all libraries.
1624 """
1625 for library in self._libraries.values():
1626 library.IndexPackageBodies()
1628 def IndexEntities(self) -> None:
1629 """
1630 Index all declared items in all packages in all libraries.
1632 .. rubric:: Algorithm
1634 1. Iterate all libraries:
1636 1. Iterate all packages |br|
1637 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
1639 * Index all declared items in that entity. |br|
1640 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
1642 .. seealso::
1644 :meth:`IndexPackages`
1645 Index all declared items in all packages in all libraries.
1646 :meth:`IndexPackageBodies`
1647 Index all declared items in all package bodies in all libraries.
1648 :meth:`IndexArchitectures`
1649 Index all declared items in all architectures in all libraries.
1650 """
1651 for library in self._libraries.values():
1652 library.IndexEntities()
1654 def IndexArchitectures(self) -> None:
1655 """
1656 Index all declared items in all packages in all libraries.
1658 .. rubric:: Algorithm
1660 1. Iterate all libraries:
1662 1. Iterate all packages |br|
1663 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
1665 * Index all declared items in that architecture. |br|
1666 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
1668 .. seealso::
1670 :meth:`IndexPackages`
1671 Index all declared items in all packages in all libraries.
1672 :meth:`IndexPackageBodies`
1673 Index all declared items in all package bodies in all libraries.
1674 :meth:`IndexEntities`
1675 Index all declared items in all entities in all libraries.
1676 """
1677 for library in self._libraries.values():
1678 library.IndexArchitectures()
1680 def CreateHierarchyGraph(self) -> None:
1681 """
1682 Create the hierarchy graph from dependency graph.
1684 .. rubric:: Algorithm
1686 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
1688 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
1689 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
1691 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
1692 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
1694 2. Iterate all architectures ...
1696 .. todo:: Design::CreateHierarchyGraph describe algorithm
1698 1. Iterate all outbound edges
1700 .. todo:: Design::CreateHierarchyGraph describe algorithm
1701 """
1702 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
1703 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
1704 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
1705 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
1706 vertex.Value._hierarchyVertex = hierarchyVertex
1708 # Copy implementation edges from
1709 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
1710 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
1711 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
1712 if DependencyGraphEdgeKind.Implementation in kind:
1713 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1714 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
1715 elif DependencyGraphEdgeKind.Instantiation in kind:
1716 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1718 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
1719 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
1720 continue
1722 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
1723 else:
1724 continue
1726 newEdge["kind"] = kind
1728 def ComputeCompileOrder(self) -> None:
1729 def predicate(edge: Edge) -> bool:
1730 return (
1731 DependencyGraphEdgeKind.Implementation in edge["kind"] or
1732 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
1733 DependencyGraphEdgeKind.UseClause in edge["kind"] or
1734 DependencyGraphEdgeKind.ContextReference in edge["kind"]
1735 ) and edge.Destination["predefined"] is False
1737 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
1738 sourceDocument: Document = edge.Source.Value.Document
1739 destinationDocument: Document = edge.Destination.Value.Document
1741 sourceVertex = sourceDocument._compileOrderVertex
1742 destinationVertex = destinationDocument._compileOrderVertex
1744 # Don't add self-edges
1745 if sourceVertex is destinationVertex: 1745 ↛ 1748line 1745 didn't jump to line 1748 because the condition on line 1745 was always true
1746 continue
1747 # Don't add parallel edges
1748 elif sourceVertex.HasEdgeToDestination(destinationVertex):
1749 continue
1751 e = sourceVertex.EdgeToVertex(destinationVertex)
1752 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1754 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
1755 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1757 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
1758 """
1759 Iterate all document in compile-order.
1761 .. rubric:: Algorithm
1763 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
1765 1. Iterate compile-order graph in topological order. |br|
1766 :meth:`pyTooling.Graph.Graph.IterateTopologically`
1768 * yield the compiler-order vertex' referenced document.
1770 :returns: A generator to iterate all documents in compile-order in the design.
1771 :raises VHDLModelException: If compile-order was not computed.
1773 .. seealso::
1775 .. todo:: missing text
1777 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
1779 """
1780 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 1780 ↛ 1781line 1780 didn't jump to line 1781 because the condition on line 1780 was never true
1781 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
1783 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
1784 yield compileOrderNode.Value
1786 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
1787 raise NotImplementedError()
1789 def __repr__(self) -> str:
1790 """
1791 Formats a representation of the design.
1793 **Format:** ``Document: 'my_design'``
1795 :returns: String representation of the design.
1796 """
1797 return f"Design: {self._name}"
1799 __str__ = __repr__
1802@export
1803class Library(ModelEntity, NamedEntityMixin):
1804 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
1806 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
1807 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
1808 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
1809 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
1810 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
1811 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
1813 _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`.
1815 def __init__(self, identifier: str, parent: ModelEntity = None) -> None:
1816 super().__init__(parent)
1817 NamedEntityMixin.__init__(self, identifier)
1819 self._contexts = {}
1820 self._configurations = {}
1821 self._entities = {}
1822 self._architectures = {}
1823 self._packages = {}
1824 self._packageBodies = {}
1826 self._dependencyVertex = None
1828 @readonly
1829 def Contexts(self) -> Dict[str, Context]:
1830 """Returns a list of all context declarations declared in this library."""
1831 return self._contexts
1833 @readonly
1834 def Configurations(self) -> Dict[str, Configuration]:
1835 """Returns a list of all configuration declarations declared in this library."""
1836 return self._configurations
1838 @readonly
1839 def Entities(self) -> Dict[str, Entity]:
1840 """Returns a list of all entity declarations declared in this library."""
1841 return self._entities
1843 @readonly
1844 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
1845 """Returns a list of all architectures declarations declared in this library."""
1846 return self._architectures
1848 @readonly
1849 def Packages(self) -> Dict[str, Package]:
1850 """Returns a list of all package declarations declared in this library."""
1851 return self._packages
1853 @readonly
1854 def PackageBodies(self) -> Dict[str, PackageBody]:
1855 """Returns a list of all package body declarations declared in this library."""
1856 return self._packageBodies
1858 @readonly
1859 def DependencyVertex(self) -> Vertex:
1860 """
1861 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
1863 The dependency vertex references this library by its value field.
1865 :returns: The corresponding dependency vertex.
1866 """
1867 return self._dependencyVertex
1869 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
1870 """
1871 Iterate all design units in the library.
1873 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
1875 .. rubric:: Algorithm
1877 1. Iterate all contexts in that library.
1878 2. Iterate all packages in that library.
1879 3. Iterate all package bodies in that library.
1880 4. Iterate all entites in that library.
1881 5. Iterate all architectures in that library.
1882 6. Iterate all configurations in that library.
1884 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
1885 :returns: A generator to iterate all matched design units in the library.
1887 .. seealso::
1889 :meth:`pyVHDLModel.Design.IterateDesignUnits`
1890 Iterate all design units in the design.
1891 :meth:`pyVHDLModel.Document.IterateDesignUnits`
1892 Iterate all design units in the document.
1893 """
1894 if DesignUnitKind.Context in filter:
1895 for context in self._contexts.values():
1896 yield context
1898 if DesignUnitKind.Package in filter:
1899 for package in self._packages.values():
1900 yield package
1902 if DesignUnitKind.PackageBody in filter:
1903 for packageBody in self._packageBodies.values():
1904 yield packageBody
1906 if DesignUnitKind.Entity in filter:
1907 for entity in self._entities.values():
1908 yield entity
1910 if DesignUnitKind.Architecture in filter:
1911 for architectures in self._architectures.values():
1912 for architecture in architectures.values():
1913 yield architecture
1915 if DesignUnitKind.Configuration in filter:
1916 for configuration in self._configurations.values():
1917 yield configuration
1919 # for verificationProperty in self._verificationUnits.values():
1920 # yield verificationProperty
1921 # for verificationUnit in self._verificationProperties.values():
1922 # yield entity
1923 # for verificationMode in self._verificationModes.values():
1924 # yield verificationMode
1926 def LinkArchitectures(self) -> None:
1927 """
1928 Link all architectures to corresponding entities.
1930 .. rubric:: Algorithm
1932 1. Iterate all architecture groups (grouped per entity symbol's name).
1934 * Check if entity symbol's name exists as an entity in this library.
1936 1. For each architecture in the same architecture group:
1938 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1939 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1940 * Set parent namespace of architecture's namespace to the entitie's namespace.
1941 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1943 :raises VHDLModelException: If entity name doesn't exist.
1944 :raises VHDLModelException: If architecture name already exists for entity.
1946 .. seealso::
1948 :meth:`LinkPackageBodies`
1949 Link all package bodies to corresponding packages.
1950 """
1951 for entityName, architecturesPerEntity in self._architectures.items():
1952 if entityName not in self._entities: 1952 ↛ 1953line 1952 didn't jump to line 1953 because the condition on line 1952 was never true
1953 architectureNames = "', '".join(architecturesPerEntity.keys())
1954 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
1955 # TODO: search in other libraries to find that entity.
1956 # TODO: add code position
1958 entity = self._entities[entityName]
1959 for architecture in architecturesPerEntity.values():
1960 if architecture._normalizedIdentifier in entity._architectures: 1960 ↛ 1961line 1960 didn't jump to line 1961 because the condition on line 1960 was never true
1961 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
1962 # TODO: add code position of existing and current
1964 entity._architectures[architecture._normalizedIdentifier] = architecture
1965 architecture._entity.Entity = entity
1966 architecture._namespace._parentNamespace = entity._namespace
1968 # add "architecture -> entity" relation in dependency graph
1969 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
1970 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
1972 def LinkPackageBodies(self) -> None:
1973 """
1974 Link all package bodies to corresponding packages.
1976 .. rubric:: Algorithm
1978 1. Iterate all package bodies.
1980 * Check if package body symbol's name exists as a package in this library.
1981 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1982 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1983 * Set parent namespace of package body's namespace to the package's namespace.
1984 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1986 :raises VHDLModelException: If package name doesn't exist.
1988 .. seealso::
1990 :meth:`LinkArchitectures`
1991 Link all architectures to corresponding entities.
1992 """
1993 for packageBodyName, packageBody in self._packageBodies.items():
1994 if packageBodyName not in self._packages: 1994 ↛ 1995line 1994 didn't jump to line 1995 because the condition on line 1994 was never true
1995 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
1997 package = self._packages[packageBodyName]
1998 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
1999 packageBody._package.Package = package
2000 packageBody._namespace._parentNamespace = package._namespace
2002 # add "package body -> package" relation in dependency graph
2003 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2004 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2006 def IndexPackages(self) -> None:
2007 """
2008 Index declared items in all packages.
2010 .. rubric:: Algorithm
2012 1. Iterate all packages:
2014 * Index all declared items. |br|
2015 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2017 .. seealso::
2019 :meth:`IndexPackageBodies`
2020 Index all declared items in a package body.
2021 :meth:`IndexEntities`
2022 Index all declared items in an entity.
2023 :meth:`IndexArchitectures`
2024 Index all declared items in an architecture.
2025 """
2026 for package in self._packages.values():
2027 if isinstance(package, Package): 2027 ↛ 2026line 2027 didn't jump to line 2026 because the condition on line 2027 was always true
2028 package.IndexDeclaredItems()
2030 def IndexPackageBodies(self) -> None:
2031 """
2032 Index declared items in all package bodies.
2034 .. rubric:: Algorithm
2036 1. Iterate all package bodies:
2038 * Index all declared items. |br|
2039 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2041 .. seealso::
2043 :meth:`IndexPackages`
2044 Index all declared items in a package.
2045 :meth:`IndexEntities`
2046 Index all declared items in an entity.
2047 :meth:`IndexArchitectures`
2048 Index all declared items in an architecture.
2049 """
2050 for packageBody in self._packageBodies.values():
2051 packageBody.IndexDeclaredItems()
2053 def IndexEntities(self) -> None:
2054 """
2055 Index declared items in all entities.
2057 .. rubric:: Algorithm
2059 1. Iterate all entities:
2061 * Index all declared items. |br|
2062 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2064 .. seealso::
2066 :meth:`IndexPackages`
2067 Index all declared items in a package.
2068 :meth:`IndexPackageBodies`
2069 Index all declared items in a package body.
2070 :meth:`IndexArchitectures`
2071 Index all declared items in an architecture.
2072 """
2073 for entity in self._entities.values():
2074 entity.IndexDeclaredItems()
2076 def IndexArchitectures(self) -> None:
2077 """
2078 Index declared items in all architectures.
2080 .. rubric:: Algorithm
2082 1. Iterate all architectures:
2084 * Index all declared items. |br|
2085 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2087 .. seealso::
2089 :meth:`IndexPackages`
2090 Index all declared items in a package.
2091 :meth:`IndexPackageBodies`
2092 Index all declared items in a package body.
2093 :meth:`IndexEntities`
2094 Index all declared items in an entity.
2095 """
2096 for architectures in self._architectures.values():
2097 for architecture in architectures.values():
2098 architecture.IndexDeclaredItems()
2099 architecture.IndexStatements()
2101 def __repr__(self) -> str:
2102 """
2103 Formats a representation of the library.
2105 **Format:** ``Library: 'my_library'``
2107 :returns: String representation of the library.
2108 """
2109 return f"Library: '{self._identifier}'"
2111 __str__ = __repr__
2114@export
2115class Document(ModelEntity, DocumentedEntityMixin):
2116 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2118 _path: Path #: path to the document. ``None`` if virtual document.
2119 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2120 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2121 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2122 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2123 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2124 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2125 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2126 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2127 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2128 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2130 _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`.
2131 _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`.
2133 def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
2134 super().__init__(parent)
2135 DocumentedEntityMixin.__init__(self, documentation)
2137 self._path = path
2138 self._designUnits = []
2139 self._contexts = {}
2140 self._configurations = {}
2141 self._entities = {}
2142 self._architectures = {}
2143 self._packages = {}
2144 self._packageBodies = {}
2145 self._verificationUnits = {}
2146 self._verificationProperties = {}
2147 self._verificationModes = {}
2149 self._dependencyVertex = None
2150 self._compileOrderVertex = None
2152 def _AddEntity(self, item: Entity) -> None:
2153 """
2154 Add an entity to the document's lists of design units.
2156 :param item: Entity object to be added to the document.
2157 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
2158 :raises VHDLModelException: If entity name already exists in document.
2159 """
2160 if not isinstance(item, Entity): 2160 ↛ 2161line 2160 didn't jump to line 2161 because the condition on line 2160 was never true
2161 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2162 if version_info >= (3, 11): # pragma: no cover
2163 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2164 raise ex
2166 identifier = item._normalizedIdentifier
2167 if identifier in self._entities: 2167 ↛ 2169line 2167 didn't jump to line 2169 because the condition on line 2167 was never true
2168 # TODO: use a more specific exception
2169 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2171 self._entities[identifier] = item
2172 self._designUnits.append(item)
2173 item._document = self
2175 def _AddArchitecture(self, item: Architecture) -> None:
2176 """
2177 Add an architecture to the document's lists of design units.
2179 :param item: Architecture object to be added to the document.
2180 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
2181 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2182 """
2183 if not isinstance(item, Architecture): 2183 ↛ 2184line 2183 didn't jump to line 2184 because the condition on line 2183 was never true
2184 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2185 if version_info >= (3, 11): # pragma: no cover
2186 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2187 raise ex
2189 entity = item._entity.Name
2190 entityIdentifier = entity._normalizedIdentifier
2191 try:
2192 architectures = self._architectures[entityIdentifier]
2193 if item._normalizedIdentifier in architectures:
2194 # TODO: use a more specific exception
2195 # FIXME: this is allowed and should be a warning or a strict mode.
2196 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2198 architectures[item.Identifier] = item
2199 except KeyError:
2200 self._architectures[entityIdentifier] = {item._identifier: item}
2202 self._designUnits.append(item)
2203 item._document = self
2205 def _AddPackage(self, item: Package) -> None:
2206 """
2207 Add a package to the document's lists of design units.
2209 :param item: Package object to be added to the document.
2210 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
2211 :raises VHDLModelException: If package name already exists in document.
2212 """
2213 if not isinstance(item, (Package, PackageInstantiation)): 2213 ↛ 2214line 2213 didn't jump to line 2214 because the condition on line 2213 was never true
2214 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2215 if version_info >= (3, 11): # pragma: no cover
2216 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2217 raise ex
2219 identifier = item._normalizedIdentifier
2220 if identifier in self._packages: 2220 ↛ 2222line 2220 didn't jump to line 2222 because the condition on line 2220 was never true
2221 # TODO: use a more specific exception
2222 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2224 self._packages[identifier] = item
2225 self._designUnits.append(item)
2226 item._document = self
2228 def _AddPackageBody(self, item: PackageBody) -> None:
2229 """
2230 Add a package body to the document's lists of design units.
2232 :param item: Package body object to be added to the document.
2233 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
2234 :raises VHDLModelException: If package body name already exists in document.
2235 """
2236 if not isinstance(item, PackageBody): 2236 ↛ 2237line 2236 didn't jump to line 2237 because the condition on line 2236 was never true
2237 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2238 if version_info >= (3, 11): # pragma: no cover
2239 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2240 raise ex
2242 identifier = item._normalizedIdentifier
2243 if identifier in self._packageBodies: 2243 ↛ 2245line 2243 didn't jump to line 2245 because the condition on line 2243 was never true
2244 # TODO: use a more specific exception
2245 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2247 self._packageBodies[identifier] = item
2248 self._designUnits.append(item)
2249 item._document = self
2251 def _AddContext(self, item: Context) -> None:
2252 """
2253 Add a context to the document's lists of design units.
2255 :param item: Context object to be added to the document.
2256 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
2257 :raises VHDLModelException: If context name already exists in document.
2258 """
2259 if not isinstance(item, Context): 2259 ↛ 2260line 2259 didn't jump to line 2260 because the condition on line 2259 was never true
2260 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2261 if version_info >= (3, 11): # pragma: no cover
2262 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2263 raise ex
2265 identifier = item._normalizedIdentifier
2266 if identifier in self._contexts: 2266 ↛ 2268line 2266 didn't jump to line 2268 because the condition on line 2266 was never true
2267 # TODO: use a more specific exception
2268 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2270 self._contexts[identifier] = item
2271 self._designUnits.append(item)
2272 item._document = self
2274 def _AddConfiguration(self, item: Configuration) -> None:
2275 """
2276 Add a configuration to the document's lists of design units.
2278 :param item: Configuration object to be added to the document.
2279 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
2280 :raises VHDLModelException: If configuration name already exists in document.
2281 """
2282 if not isinstance(item, Configuration): 2282 ↛ 2283line 2282 didn't jump to line 2283 because the condition on line 2282 was never true
2283 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2284 if version_info >= (3, 11): # pragma: no cover
2285 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2286 raise ex
2288 identifier = item._normalizedIdentifier
2289 if identifier in self._configurations: 2289 ↛ 2291line 2289 didn't jump to line 2291 because the condition on line 2289 was never true
2290 # TODO: use a more specific exception
2291 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2293 self._configurations[identifier] = item
2294 self._designUnits.append(item)
2295 item._document = self
2297 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2298 if not isinstance(item, VerificationUnit):
2299 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2300 if version_info >= (3, 11): # pragma: no cover
2301 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2302 raise ex
2304 identifier = item._normalizedIdentifier
2305 if identifier in self._verificationUnits:
2306 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2308 self._verificationUnits[identifier] = item
2309 self._designUnits.append(item)
2310 item._document = self
2312 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2313 if not isinstance(item, VerificationProperty):
2314 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2315 if version_info >= (3, 11): # pragma: no cover
2316 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2317 raise ex
2319 identifier = item.NormalizedIdentifier
2320 if identifier in self._verificationProperties:
2321 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2323 self._verificationProperties[identifier] = item
2324 self._designUnits.append(item)
2325 item._document = self
2327 def _AddVerificationMode(self, item: VerificationMode) -> None:
2328 if not isinstance(item, VerificationMode):
2329 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2330 if version_info >= (3, 11): # pragma: no cover
2331 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2332 raise ex
2334 identifier = item.NormalizedIdentifier
2335 if identifier in self._verificationModes:
2336 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2338 self._verificationModes[identifier] = item
2339 self._designUnits.append(item)
2340 item._document = self
2342 def _AddDesignUnit(self, item: DesignUnit) -> None:
2343 """
2344 Add a design unit to the document's lists of design units.
2346 :param item: Configuration object to be added to the document.
2347 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2348 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2349 :raises VHDLModelException: If configuration name already exists in document.
2350 """
2351 if not isinstance(item, DesignUnit): 2351 ↛ 2352line 2351 didn't jump to line 2352 because the condition on line 2351 was never true
2352 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2353 if version_info >= (3, 11): # pragma: no cover
2354 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2355 raise ex
2357 if isinstance(item, Entity):
2358 self._AddEntity(item)
2359 elif isinstance(item, Architecture):
2360 self._AddArchitecture(item)
2361 elif isinstance(item, Package):
2362 self._AddPackage(item)
2363 elif isinstance(item, PackageBody):
2364 self._AddPackageBody(item)
2365 elif isinstance(item, Context):
2366 self._AddContext(item)
2367 elif isinstance(item, Configuration): 2367 ↛ 2369line 2367 didn't jump to line 2369 because the condition on line 2367 was always true
2368 self._AddConfiguration(item)
2369 elif isinstance(item, VerificationUnit):
2370 self._AddVerificationUnit(item)
2371 elif isinstance(item, VerificationProperty):
2372 self._AddVerificationProperty(item)
2373 elif isinstance(item, VerificationMode):
2374 self._AddVerificationMode(item)
2375 else:
2376 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2377 if version_info >= (3, 11): # pragma: no cover
2378 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2379 raise ex
2381 @readonly
2382 def Path(self) -> Path:
2383 """
2384 Read-only property to access the document's path (:attr:`_path`).
2386 :returns: The path of this document.
2387 """
2388 return self._path
2390 @readonly
2391 def DesignUnits(self) -> List[DesignUnit]:
2392 """
2393 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2395 :returns: List of all design units.
2396 """
2397 return self._designUnits
2399 @readonly
2400 def Contexts(self) -> Dict[str, Context]:
2401 """
2402 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
2404 :returns: List of all contexts.
2405 """
2406 return self._contexts
2408 @readonly
2409 def Configurations(self) -> Dict[str, Configuration]:
2410 """
2411 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
2413 :returns: List of all configurations.
2414 """
2415 return self._configurations
2417 @readonly
2418 def Entities(self) -> Dict[str, Entity]:
2419 """
2420 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
2422 :returns: List of all entities.
2423 """
2424 return self._entities
2426 @readonly
2427 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2428 """
2429 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
2431 :returns: List of all architectures.
2432 """
2433 return self._architectures
2435 @readonly
2436 def Packages(self) -> Dict[str, Package]:
2437 """
2438 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
2440 :returns: List of all packages.
2441 """
2442 return self._packages
2444 @readonly
2445 def PackageBodies(self) -> Dict[str, PackageBody]:
2446 """
2447 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
2449 :returns: List of all package bodies.
2450 """
2451 return self._packageBodies
2453 @readonly
2454 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
2455 """
2456 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
2458 :returns: List of all verification units.
2459 """
2460 return self._verificationUnits
2462 @readonly
2463 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
2464 """
2465 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
2467 :returns: List of all verification properties.
2468 """
2469 return self._verificationProperties
2471 @readonly
2472 def VerificationModes(self) -> Dict[str, VerificationMode]:
2473 """
2474 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
2476 :returns: List of all verification modes.
2477 """
2478 return self._verificationModes
2480 @readonly
2481 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
2482 """
2483 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
2485 The compile-order vertex references this document by its value field.
2487 :returns: The corresponding compile-order vertex.
2488 """
2489 return self._compileOrderVertex
2491 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2492 """
2493 Iterate all design units in the document.
2495 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2497 .. rubric:: Algorithm
2499 * If contexts are selected in the filter:
2501 1. Iterate all contexts in that library.
2503 * If packages are selected in the filter:
2505 1. Iterate all packages in that library.
2507 * If package bodies are selected in the filter:
2509 1. Iterate all package bodies in that library.
2511 * If entites are selected in the filter:
2513 1. Iterate all entites in that library.
2515 * If architectures are selected in the filter:
2517 1. Iterate all architectures in that library.
2519 * If configurations are selected in the filter:
2521 1. Iterate all configurations in that library.
2523 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2524 :returns: A generator to iterate all matched design units in the document.
2526 .. seealso::
2528 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2529 Iterate all design units in the design.
2530 :meth:`pyVHDLModel.Library.IterateDesignUnits`
2531 Iterate all design units in the library.
2532 """
2533 if DesignUnitKind.Context in filter:
2534 for context in self._contexts.values():
2535 yield context
2537 if DesignUnitKind.Package in filter: 2537 ↛ 2541line 2537 didn't jump to line 2541 because the condition on line 2537 was always true
2538 for package in self._packages.values():
2539 yield package
2541 if DesignUnitKind.PackageBody in filter:
2542 for packageBody in self._packageBodies.values():
2543 yield packageBody
2545 if DesignUnitKind.Entity in filter:
2546 for entity in self._entities.values():
2547 yield entity
2549 if DesignUnitKind.Architecture in filter:
2550 for architectures in self._architectures.values():
2551 for architecture in architectures.values():
2552 yield architecture
2554 if DesignUnitKind.Configuration in filter:
2555 for configuration in self._configurations.values():
2556 yield configuration
2558 # for verificationProperty in self._verificationUnits.values():
2559 # yield verificationProperty
2560 # for verificationUnit in self._verificationProperties.values():
2561 # yield entity
2562 # for verificationMode in self._verificationModes.values():
2563 # yield verificationMode
2565 def __repr__(self) -> str:
2566 """
2567 Formats a representation of the document.
2569 **Format:** ``Document: 'path/to/file.vhdl'``
2571 :returns: String representation of the document.
2572 """
2573 return f"Document: '{self._path}'"
2575 __str__ = __repr__