Coverage for pyVHDLModel/__init__.py: 63%
1155 statements
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +0000
« prev ^ index » next coverage.py v7.15.1, created at 2026-07-13 17:58 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 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-2026 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-2026, Patrick Lehmann"
50__license__ = "Apache License, Version 2.0"
51__version__ = "0.37.0"
52# __keywords__ = []
53__project_url__ = "https://github.com/VHDL/pyVHDLModel"
54__documentation_url__ = "https://vhdl.github.io/pyVHDLModel"
55__issue_tracker_url__ = "https://GitHub.com/VHDL/pyVHDLModel/issues"
58from enum import unique, Enum, Flag, auto
59from pathlib import Path
60from sys import version_info
62from typing import Union, Dict, cast, List, Generator, Optional as Nullable
64from pyTooling.Common import getFullyQualifiedName
65from pyTooling.Decorators import export, readonly
66from pyTooling.Graph import Graph, Vertex, Edge
67from pyTooling.Warning import WarningCollector
69from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning
70from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
71from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
72from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
73from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
74from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
75from pyVHDLModel.Namespace import Namespace
76from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
77from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
78from pyVHDLModel.Common import AllowBlackboxMixin
79from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin
80from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
81from pyVHDLModel.Concurrent import GenerateStatement, IfGenerateStatement, ForGenerateStatement, CaseGenerateStatement
82from pyVHDLModel.Concurrent import GenerateBranch, ConcurrentStatementsMixin, ConcurrentBlockStatement
83from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package, Component
84from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
85from pyVHDLModel.Instantiation import PackageInstantiation
86from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
89@export
90@unique
91class VHDLVersion(Enum):
92 """
93 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
95 A version can be given as integer or string and is represented as a unified
96 enumeration value.
98 This enumeration supports compare operators.
99 """
101 Any = -1 #: Any
102 VHDL87 = 87 #: VHDL-1987
103 VHDL93 = 93 #: VHDL-1993
104 AMS93 = 1993 #: VHDL-AMS-1993
105 AMS99 = 1999 #: VHDL-AMS-1999
106 VHDL2000 = 2000 #: VHDL-2000
107 VHDL2002 = 2002 #: VHDL-2002
108 VHDL2008 = 2008 #: VHDL-2008
109 AMS2017 = 2017 #: VHDL-AMS-2017
110 VHDL2019 = 2019 #: VHDL-2019
111 Latest = 10000 #: Latest VHDL (2019)
113 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
114 -1: Any,
115 87: VHDL87,
116 93: VHDL93,
117 # 93: AMS93,
118 99: AMS99,
119 0: VHDL2000,
120 2: VHDL2002,
121 8: VHDL2008,
122 17: AMS2017,
123 19: VHDL2019,
124 1987: VHDL87,
125 # 1993: VHDL93,
126 1993: AMS93,
127 1999: AMS99,
128 2000: VHDL2000,
129 2002: VHDL2002,
130 2008: VHDL2008,
131 2017: AMS2017,
132 2019: VHDL2019,
133 10000: Latest,
134 "Any": Any,
135 "87": VHDL87,
136 "93": VHDL93,
137 # "93": AMS93,
138 "99": AMS99,
139 "00": VHDL2000,
140 "02": VHDL2002,
141 "08": VHDL2008,
142 "17": AMS2017,
143 "19": VHDL2019,
144 "1987": VHDL87,
145 # "1993": VHDL93,
146 "1993": AMS93,
147 "1999": AMS99,
148 "2000": VHDL2000,
149 "2002": VHDL2002,
150 "2008": VHDL2008,
151 "2017": AMS2017,
152 "2019": VHDL2019,
153 "Latest": Latest,
154 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
156 def __init__(self, *_) -> None:
157 """Patch the embedded MAP dictionary"""
158 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
159 if (not isinstance(v, self.__class__)) and (v == self.value):
160 self.__class__.__VERSION_MAPPINGS__[k] = self
162 @classmethod
163 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
164 """
165 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
167 :param value: VHDL/VHDL-AMS year code.
168 :returns: Enumeration value.
169 :raises ValueError: If the year code is not recognized.
170 """
171 try:
172 return cls.__VERSION_MAPPINGS__[value]
173 except KeyError:
174 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
176 def __lt__(self, other: Any) -> bool:
177 """
178 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
180 :param other: Parameter to compare against.
181 :returns: True if version is less than the second operand.
182 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
183 """
184 if isinstance(other, VHDLVersion):
185 return self.value < other.value
186 else:
187 raise TypeError("Second operand is not of type 'VHDLVersion'.")
189 def __le__(self, other: Any) -> bool:
190 """
191 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
193 :param other: Parameter to compare against.
194 :returns: True if version is less or equal than the second operand.
195 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
196 """
197 if isinstance(other, VHDLVersion):
198 return self.value <= other.value
199 else:
200 raise TypeError("Second operand is not of type 'VHDLVersion'.")
202 def __gt__(self, other: Any) -> bool:
203 """
204 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
206 :param other: Parameter to compare against.
207 :returns: True if version is greater than the second operand.
208 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
209 """
210 if isinstance(other, VHDLVersion):
211 return self.value > other.value
212 else:
213 raise TypeError("Second operand is not of type 'VHDLVersion'.")
215 def __ge__(self, other: Any) -> bool:
216 """
217 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
219 :param other: Parameter to compare against.
220 :returns: True if version is greater or equal than the second operand.
221 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
222 """
223 if isinstance(other, VHDLVersion):
224 return self.value >= other.value
225 else:
226 raise TypeError("Second operand is not of type 'VHDLVersion'.")
228 def __ne__(self, other: Any) -> bool:
229 """
230 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
232 :param other: Parameter to compare against.
233 :returns: True if version is unequal to the second operand.
234 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
235 """
236 if isinstance(other, VHDLVersion):
237 return self.value != other.value
238 else:
239 raise TypeError("Second operand is not of type 'VHDLVersion'.")
241 def __eq__(self, other: Any) -> bool:
242 """
243 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
245 :param other: Parameter to compare against.
246 :returns: True if version is equal to the second operand.
247 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
248 """
249 if isinstance(other, VHDLVersion):
250 if (self is self.__class__.Any) or (other is self.__class__.Any):
251 return True
252 else:
253 return self.value == other.value
254 else:
255 raise TypeError("Second operand is not of type 'VHDLVersion'.")
257 @readonly
258 def IsVHDL(self) -> bool:
259 """
260 Checks if the version is a VHDL (not VHDL-AMS) version.
262 :returns: True if version is a VHDL version.
263 """
264 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
266 @readonly
267 def IsAMS(self) -> bool:
268 """
269 Checks if the version is a VHDL-AMS (not VHDL) version.
271 :returns: True if version is a VHDL-AMS version.
272 """
273 return self in (self.AMS93, self.AMS99, self.AMS2017)
275 def __str__(self) -> str:
276 """
277 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
279 :returns: Formatted VHDL/VHDL-AMS version.
280 """
281 if self.value == self.Any.value:
282 return "VHDL'Any"
283 elif self.value == self.Latest.value:
284 return "VHDL'Latest"
286 year = str(self.value)[-2:]
287 if self.IsVHDL:
288 return f"VHDL'{year}"
289 else:
290 return f"VHDL-AMS'{year}"
292 def __repr__(self) -> str:
293 """
294 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
296 :returns: Formatted VHDL/VHDL-AMS version.
297 """
298 if self.value == self.Any.value:
299 return "Any"
300 elif self.value == self.Latest.value:
301 return "Latest"
302 else:
303 return str(self.value)
306@export
307class IEEEFlavor(Flag):
308 """
309 The ``IEEE`` VHDL library as a fixed set of predefined VHDL packages according to IEEE Std. 1076.
311 Nonetheless, some vendors decided to sneak in additional packages into the ``IEEE`` namespace. |br|
312 Supported flavors are:
314 * ``Synopsys``
315 * ``MentorGraphics``
317 In addition, IEEE Std. 1076.X extensions can be loaded. |br|
318 Supported extensions are:
320 * ``WithVITAL`` - IEEE Std. 1076.4
322 """
323 Unknown = 0 #: Unknown IEEE flavor
324 IEEE = 1 #: IEEE Std. 1076 compliant list of IEEE packages.
325 Synopsys = 2 #: Additional packages created by Synopsys are visible within the IEEE library.
326 MentorGraphics = 4 #: Additional packages created by Mentor Graphics are visible within the IEEE library.
327 WithVITAL = 32 #: Additionally load IEEE Std 1076.4 VITAL packages. (VITAL = VHDL Initiative Towards ASIC Libraries)
330@export
331@unique
332class ObjectClass(Enum):
333 """
334 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
336 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
337 """
339 Default = 0 #: Object class not defined, thus it's context dependent.
340 Constant = 1 #: Constant
341 Variable = 2 #: Variable
342 Signal = 3 #: Signal
343 File = 4 #: File
344 Type = 5 #: Type
345 # FIXME: Package?
346 Procedure = 6 #: Procedure
347 Function = 7 #: Function
349 def __str__(self) -> str:
350 """
351 Formats the object class.
353 :returns: Formatted object class.
354 """
355 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
358@export
359@unique
360class DesignUnitKind(Flag):
361 """
362 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
364 """
365 Context = auto() #: Context
366 Package = auto() #: Package
367 PackageBody = auto() #: Package Body
368 Entity = auto() #: Entity
369 Architecture = auto() #: Architecture
370 Configuration = auto() #: Configuration
372 Primary = Context | Configuration | Entity | Package #: List of primary design units.
373 Secondary = PackageBody | Architecture #: List of secondary design units.
374 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
375 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
377 All = Primary | Secondary #: List of all design units.
380@export
381@unique
382class DependencyGraphVertexKind(Flag):
383 """
384 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
385 """
386 Document = auto() #: A document (VHDL source file).
387 Library = auto() #: A VHDL library.
389 Context = auto() #: A context design unit.
390 Package = auto() #: A package design unit.
391 PackageBody = auto() #: A package body design unit.
392 Entity = auto() #: A entity design unit.
393 Architecture = auto() #: A architecture design unit.
394 Component = auto() #: A VHDL component.
395 Configuration = auto() #: A configuration design unit.
398@export
399@unique
400class DependencyGraphEdgeKind(Flag):
401 """
402 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
403 """
404 Document = auto()
405 Library = auto()
406 Context = auto()
407 Package = auto()
408 Entity = auto()
409 # Architecture = auto()
410 Configuration = auto()
411 Component = auto()
413 DeclaredIn = auto()
414 Order = auto()
415 Reference = auto()
416 Implementation = auto()
417 Instantiation = auto()
419 SourceFile = Document | DeclaredIn
420 CompileOrder = Document | Order
422 LibraryClause = Library | Reference
423 UseClause = Package | Reference
424 ContextReference = Context | Reference
426 EntityImplementation = Entity | Implementation
427 PackageImplementation = Package | Implementation
429 EntityInstantiation = Entity | Instantiation
430 ComponentInstantiation = Component | Instantiation
431 ConfigurationInstantiation = Configuration | Instantiation
433 PackageInstantiation = Package | Instantiation
436@export
437@unique
438class ObjectGraphVertexKind(Flag):
439 """
440 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
441 """
442 Type = auto()
443 Subtype = auto()
445 Constant = auto()
446 DeferredConstant = auto()
447 Variable = auto()
448 Signal = auto()
449 File = auto()
451 Alias = auto()
454@export
455@unique
456class ObjectGraphEdgeKind(Flag):
457 """
458 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
459 """
460 BaseType = auto()
461 Subtype = auto()
463 ReferenceInExpression = auto()
466@export
467class Design(ModelEntity, AllowBlackboxMixin):
468 """
469 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
471 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
472 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
473 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`).
475 The *design* contains references to the following graphs:
477 * :attr:`DependencyGraph`
478 * :attr:`CompileOrderGraph`
479 * :attr:`HierarchyGraph`
480 * :attr:`ObjectGraph`
481 """
482 _name: Nullable[str] #: Name of the design.
483 _allowBlackbox: bool #: Allow blackboxes after linking the design.
484 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
485 _documents: List['Document'] #: List of all documents loaded for a design.
486 _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.
487 _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.
488 _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.
489 _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.
490 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
492 def __init__(
493 self,
494 name: Nullable[str] = None,
495 allowBlackbox: bool = False
496 ) -> None:
497 """
498 Initialize a VHDL design.
500 :param allowBlackbox: Specify if blackboxes are allowed in this design.
501 :param name: Name of the design.
502 """
503 super().__init__()
504 AllowBlackboxMixin.__init__(self, allowBlackbox)
506 self._name = name
508 self._libraries = {}
509 self._documents = []
511 self._compileOrderGraph = Graph()
512 self._dependencyGraph = Graph()
513 self._hierarchyGraph = Graph()
514 self._objectGraph = Graph()
515 self._toplevel = None
517 @readonly
518 def Name(self) -> Nullable[str]:
519 """
520 Read-only property to access the design's name (:attr:`_name`).
522 :returns: The name of the design.
523 """
524 return self._name
526 @readonly
527 def Libraries(self) -> Dict[str, 'Library']:
528 """
529 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
531 :returns: A dictionary of library names and VHDL libraries.
532 """
533 return self._libraries
535 @readonly
536 def Documents(self) -> List['Document']:
537 """
538 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
540 :returns: A list of all documents.
541 """
542 return self._documents
544 @readonly
545 def CompileOrderGraph(self) -> Graph:
546 """
547 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
549 :returns: Reference to the compile-order graph.
550 """
551 return self._compileOrderGraph
553 @readonly
554 def DependencyGraph(self) -> Graph:
555 """
556 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
558 :returns: Reference to the dependency graph.
559 """
560 return self._dependencyGraph
562 @readonly
563 def HierarchyGraph(self) -> Graph:
564 """
565 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
567 :returns: Reference to the hierarchy graph.
568 """
569 return self._hierarchyGraph
571 @readonly
572 def ObjectGraph(self) -> Graph:
573 """
574 Read-only property to access the object graph (:attr:`_objectGraph`).
576 :returns: Reference to the object graph.
577 """
578 return self._objectGraph
580 @readonly
581 def TopLevel(self) -> Union[Entity, Configuration]:
582 """
583 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
585 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``
586 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
588 :returns: Reference to the design's *top-level*.
589 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
590 :raises VHDLModelException: If there is more than one *top-level*.
591 """
592 # Check for cached result
593 if self._toplevel is not None:
594 return self._toplevel
596 if self._hierarchyGraph.EdgeCount == 0:
597 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
599 roots = tuple(self._hierarchyGraph.IterateRoots())
600 if len(roots) == 1:
601 toplevel = roots[0]
602 self._hierarchyGraph["toplevel"] = toplevel
603 self._toplevel = toplevel.Value
605 return toplevel.Value
606 else:
607 raise VHDLModelException(f"Found more than one toplevel: {', '.join(str(r) for r in roots)}")
609 def LoadStdLibrary(self) -> 'Library':
610 """
611 Load the predefined VHDL library ``std`` into the design.
613 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
615 :returns: The library object of library ``std``.
616 """
617 from pyVHDLModel.STD import Std
619 doc = Document(Path("std.vhdl"), parent=self)
621 library = Std()
622 for designUnit in library.IterateDesignUnits():
623 doc._AddDesignUnit(designUnit)
625 self.AddLibrary(library)
627 return library
629 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library':
630 """
631 Load the predefined VHDL library ``ieee`` into the design.
633 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
635 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics.
636 :returns: The library object of library ``ieee``.
637 """
638 from pyVHDLModel.IEEE import Ieee
640 doc = Document(Path("ieee.vhdl"), parent=self)
642 library = Ieee(flavor)
643 for designUnit in library.IterateDesignUnits():
644 doc._AddDesignUnit(designUnit)
646 self.AddLibrary(library)
648 return library
650 def AddLibrary(self, library: 'Library') -> None:
651 """
652 Add a VHDL library to the design.
654 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
655 If ok, set the libraries parent reference to the design.
657 :param library: Library object to loaded.
658 :raises LibraryExistsInDesignError: If the library already exists in the design.
659 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
660 """
661 libraryIdentifier = library.NormalizedIdentifier
662 if libraryIdentifier in self._libraries:
663 raise LibraryExistsInDesignError(library)
665 if library._parent is not None:
666 raise LibraryRegisteredToForeignDesignError(library)
668 self._libraries[libraryIdentifier] = library
669 library.Parent = self
671 def GetLibrary(self, libraryName: str) -> 'Library':
672 """
673 Return an (existing) VHDL library object of name ``libraryName``.
675 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
677 :param libraryName: Name of the requested VHDL library.
678 :returns: The VHDL library object.
679 """
680 libraryIdentifier = libraryName.lower()
681 try:
682 return self._libraries[libraryIdentifier]
683 except KeyError:
684 lib = Library(libraryName, parent=self)
685 self._libraries[libraryIdentifier] = lib
686 lib.Parent = self
687 return lib
689 # TODO: allow overloaded parameter library to be str?
690 def AddDocument(self, document: 'Document', library: 'Library') -> None:
691 """
692 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
694 .. rubric:: Algorithm
696 1. Iterate all entities in the document
698 1. Check if entity name might exist in target library.
699 2. Add entity to library and update library membership.
701 2. Iterate all architectures in the document
703 1. Check if architecture name might exist in target library.
704 2. Add architecture to library and update library membership.
706 3. Iterate all packages in the document
708 1. Check if package name might exist in target library.
709 2. Add package to library and update library membership.
711 4. Iterate all package bodies in the document
713 1. Check if package body name might exist in target library.
714 2. Add package body to library and update library membership.
716 5. Iterate all configurations in the document
718 1. Check if configuration name might exist in target library.
719 2. Add configuration to library and update library membership.
721 6. Iterate all contexts in the document
723 1. Check if context name might exist in target library.
724 2. Add context to library and update library membership.
726 :param document: The VHDL source code file.
727 :param library: The VHDL library used to register the embedded design units to.
728 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
729 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
730 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
731 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
732 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
733 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
734 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
735 """
736 # FIXME: this checks for the library name, but not the object
737 # should the libraries parent be checked too?
738 if library._normalizedIdentifier not in self._libraries: 738 ↛ 739line 738 didn't jump to line 739 because the condition on line 738 was never true
739 raise LibraryNotRegisteredError(library)
741 self._documents.append(document)
742 document.Parent = self
743 #document.Library = library
745 document._library = library
747 for entityIdentifier, entity in document._entities.items():
748 if entityIdentifier in library._entities: 748 ↛ 749line 748 didn't jump to line 749 because the condition on line 748 was never true
749 raise EntityExistsInLibraryError(entity, library)
751 library._entities[entityIdentifier] = entity
752 entity.Library = library
754 for entityIdentifier, architectures in document._architectures.items():
755 try:
756 architecturesPerEntity = library._architectures[entityIdentifier]
757 for architectureIdentifier, architecture in architectures.items():
758 if architectureIdentifier in architecturesPerEntity:
759 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
761 architecturesPerEntity[architectureIdentifier] = architecture
762 architecture.Library = library
763 except KeyError:
764 architecturesPerEntity = document._architectures[entityIdentifier].copy()
765 library._architectures[entityIdentifier] = architecturesPerEntity
767 for architecture in architecturesPerEntity.values():
768 architecture.Library = library
770 for packageIdentifier, package in document._packages.items():
771 if packageIdentifier in library._packages: 771 ↛ 772line 771 didn't jump to line 772 because the condition on line 771 was never true
772 raise PackageExistsInLibraryError(package, library)
774 library._packages[packageIdentifier] = package
775 package.Library = library
777 for packageBodyIdentifier, packageBody in document._packageBodies.items():
778 if packageBodyIdentifier in library._packageBodies: 778 ↛ 779line 778 didn't jump to line 779 because the condition on line 778 was never true
779 raise PackageBodyExistsError(packageBody, library)
781 library._packageBodies[packageBodyIdentifier] = packageBody
782 packageBody.Library = library
784 for configurationIdentifier, configuration in document._configurations.items():
785 if configurationIdentifier in library._configurations: 785 ↛ 786line 785 didn't jump to line 786 because the condition on line 785 was never true
786 raise ConfigurationExistsInLibraryError(configuration, library)
788 library._configurations[configurationIdentifier] = configuration
789 configuration.Library = library
791 for contextIdentifier, context in document._contexts.items():
792 if contextIdentifier in library._contexts: 792 ↛ 793line 792 didn't jump to line 793 because the condition on line 792 was never true
793 raise ContextExistsInLibraryError(context, library)
795 library._contexts[contextIdentifier] = context
796 context.Library = library
798 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
799 """
800 Iterate all design units in the design.
802 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
804 .. rubric:: Algorithm
806 1. Iterate all VHDL libraries.
808 1. Iterate all contexts in that library.
809 2. Iterate all packages in that library.
810 3. Iterate all package bodies in that library.
811 4. Iterate all entites in that library.
812 5. Iterate all architectures in that library.
813 6. Iterate all configurations in that library.
815 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
816 :returns: A generator to iterate all matched design units in the design.
818 .. seealso::
820 :meth:`pyVHDLModel.Library.IterateDesignUnits`
821 Iterate all design units in the library.
822 :meth:`pyVHDLModel.Document.IterateDesignUnits`
823 Iterate all design units in the document.
824 """
825 for library in self._libraries.values():
826 yield from library.IterateDesignUnits(filter)
828 def Analyze(self) -> None:
829 """
830 Analyze the whole design.
832 .. rubric:: Algorithm
834 1. Analyze dependencies of design units. |br|
835 This will also yield the design hierarchy and the compiler order.
836 2. Analyze dependencies of types and objects.
838 .. seealso::
840 :meth:`AnalyzeDependencies`
841 Analyze the dependencies of design units.
843 :meth:`AnalyzeObjects`
844 Analyze the dependencies of types and objects.
845 """
846 self.AnalyzeDependencies()
847 # self.AnalyzeObjects()
849 def AnalyzeDependencies(self) -> None:
850 """
851 Analyze the dependencies of design units.
853 .. rubric:: Algorithm
855 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
856 |rarr| :meth:`CreateDependencyGraph`
857 2. Create the compile order graph. |br|
858 |rarr| :meth:`CreateCompileOrderGraph`
859 3. Index all packages. |br|
860 |rarr| :meth:`IndexPackages`
861 4. Index all architectures. |br|
862 |rarr| :meth:`IndexArchitectures`
863 5. Link all contexts |br|
864 |rarr| :meth:`LinkContexts`
865 6. Link all architectures. |br|
866 |rarr| :meth:`LinkArchitectures`
867 7. Link all package bodies. |br|
868 |rarr| :meth:`LinkPackageBodies`
869 8. Link all package instances. |br|
870 |rarr| :meth:`LinkPackageInstances`
871 9. Link all library references. |br|
872 |rarr| :meth:`LinkLibraryReferences`
873 10. Link all package references. |br|
874 |rarr| :meth:`LinkPackageReferences`
875 11. Link all context references. |br|
876 |rarr| :meth:`LinkContextReferences`
877 12. Link all components. |br|
878 |rarr| :meth:`LinkComponents`
879 13. Link all instantiations. |br|
880 |rarr| :meth:`LinkInstantiations`
881 14. Create the hierarchy graph. |br|
882 |rarr| :meth:`CreateHierarchyGraph`
883 15. Compute the compile order. |br|
884 |rarr| :meth:`ComputeCompileOrder`
885 """
886 self.CreateDependencyGraph()
887 self.CreateCompileOrderGraph()
889 self.IndexPackages()
890 self.IndexArchitectures()
892 self.LinkContexts()
893 self.LinkArchitectures()
894 self.LinkPackageBodies()
895 self.LinkPackageInstances()
896 self.LinkLibraryReferences()
897 self.LinkPackageReferences()
898 self.LinkContextReferences()
900 self.LinkComponents()
901 self.LinkInstantiations()
902 self.CreateHierarchyGraph()
903 self.ComputeCompileOrder()
905 def AnalyzeObjects(self) -> None:
906 """
907 Analyze the dependencies of types and objects.
909 .. rubric:: Algorithm
911 1. Index all entities. |br|
912 |rarr| :meth:`IndexEntities`
913 2. Index all package bodies. |br|
914 |rarr| :meth:`IndexPackageBodies`
915 3. Import objects. |br|
916 |rarr| :meth:`ImportObjects`
917 4. Create the type and object graph. |br|
918 |rarr| :meth:`CreateTypeAndObjectGraph`
919 """
920 self.IndexEntities()
921 self.IndexPackageBodies()
923 self.ImportObjects()
924 self.CreateTypeAndObjectGraph()
926 def CreateDependencyGraph(self) -> None:
927 """
928 Create all vertices of the dependency graph by iterating all design units in all libraries.
930 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
931 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
933 Each vertex has the following properties:
935 * The vertex' ID is the design unit's identifier.
936 * The vertex' value references the design unit.
937 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
938 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
940 .. rubric:: Algorithm
942 1. Iterate all libraries in the design.
944 * Create a vertex for that library and reference the library by the vertex' value field. |br|
945 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
947 1. Iterate all contexts in that library.
949 * Create a vertex for that context and reference the context by the vertex' value field. |br|
950 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
952 2. Iterate all packages in that library.
954 * Create a vertex for that package and reference the package by the vertex' value field. |br|
955 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
957 3. Iterate all package bodies in that library.
959 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
960 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
962 4. Iterate all entities in that library.
964 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
965 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
967 5. Iterate all architectures in that library.
969 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
970 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
972 6. Iterate all configurations in that library.
974 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
975 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
976 """
977 predefinedLibraries = ("std", "ieee")
979 for libraryIdentifier, library in self._libraries.items():
980 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
981 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
982 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
983 library._dependencyVertex = dependencyVertex
985 for contextIdentifier, context in library._contexts.items():
986 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
987 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
988 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
989 context._dependencyVertex = dependencyVertex
991 for packageIdentifier, package in library._packages.items():
992 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
993 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
994 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
995 package._dependencyVertex = dependencyVertex
997 for packageBodyIdentifier, packageBody in library._packageBodies.items():
998 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
999 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
1000 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
1001 packageBody._dependencyVertex = dependencyVertex
1003 for entityIdentifier, entity in library._entities.items():
1004 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
1005 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
1006 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
1007 entity._dependencyVertex = dependencyVertex
1009 for entityIdentifier, architectures in library._architectures.items():
1010 for architectureIdentifier, architecture in architectures.items():
1011 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
1012 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
1013 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
1014 architecture._dependencyVertex = dependencyVertex
1016 for configurationIdentifier, configuration in library._configurations.items():
1017 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
1018 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
1019 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
1020 configuration._dependencyVertex = dependencyVertex
1022 def CreateCompileOrderGraph(self) -> None:
1023 """
1024 Create a compile-order graph with bidirectional references to the dependency graph.
1026 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
1027 graph and bidirectionally referenced.
1029 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
1030 document relationship.
1032 Each added vertex has the following properties:
1034 * The vertex' ID is the document's filename.
1035 * The vertex' value references the document.
1036 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
1037 * A key-value-pair called ``predefined`` does not exist.
1039 .. rubric:: Algorithm
1041 1. Iterate all documents in the design.
1043 * Create a vertex for that document and reference the document by the vertex' value field. |br|
1044 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
1045 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
1046 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
1048 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
1049 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
1051 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
1052 dependency vertex. This expresses a "design unit is located in document" relation.
1054 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
1055 """
1056 for document in self._documents:
1057 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
1058 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1059 document._dependencyVertex = dependencyVertex
1061 compilerOrderVertex = dependencyVertex.Copy(
1062 self._compileOrderGraph,
1063 copyDict=True,
1064 linkingKeyToOriginalVertex="dependencyVertex",
1065 linkingKeyFromOriginalVertex="compileOrderVertex"
1066 )
1067 document._compileOrderVertex = compilerOrderVertex
1069 for designUnit in document._designUnits:
1070 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1071 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1073 def ImportObjects(self) -> None:
1074 def _ImportObjects(package: Package) -> None:
1075 from pyVHDLModel.Declaration import AttributeSpecification
1077 for referencedLibrary in package._referencedPackages.values():
1078 for referencedPackage in referencedLibrary.values():
1079 for declaredItem in referencedPackage._declaredItems:
1080 if isinstance(declaredItem, MultipleNamedEntityMixin):
1081 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1082 package._namespace._elements[normalizedIdentifier] = declaredItem
1083 elif isinstance(declaredItem, NamedEntityMixin):
1084 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1085 elif isinstance(declaredItem, AttributeSpecification):
1086 # FIXME: actually, this is not a declared item, but a application of an attribute to named entities
1087 WarningCollector.Raise(NotImplementedWarning(f"Attribute specification."))
1089 else:
1090 raise VHDLModelException(f"Unexpected declared item.")
1092 for libraryName in ("std", "ieee"):
1093 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1094 _ImportObjects(package)
1096 for document in self.IterateDocumentsInCompileOrder():
1097 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1098 _ImportObjects(package)
1100 def CreateTypeAndObjectGraph(self) -> None:
1101 def _HandlePackage(package) -> None:
1102 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1104 for deferredConstant in package._deferredConstants.values():
1105 print(f"Deferred Constant: {deferredConstant}")
1106 deferredConstantVertex = Vertex(
1107 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1108 value=deferredConstant,
1109 graph=self._objectGraph
1110 )
1111 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1112 deferredConstant._objectVertex = deferredConstantVertex
1114 for constant in package._constants.values():
1115 print(f"Constant: {constant}")
1116 constantVertex = Vertex(
1117 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1118 value=constant,
1119 graph=self._objectGraph
1120 )
1121 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1122 constant._objectVertex = constantVertex
1124 for type in package._types.values():
1125 print(f"Type: {type}")
1126 typeVertex = Vertex(
1127 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1128 value=type,
1129 graph=self._objectGraph
1130 )
1131 typeVertex["kind"] = ObjectGraphVertexKind.Type
1132 type._objectVertex = typeVertex
1134 for subtype in package._subtypes.values():
1135 print(f"Subtype: {subtype}")
1136 subtypeVertex = Vertex(
1137 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1138 value=subtype,
1139 graph=self._objectGraph
1140 )
1141 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1142 subtype._objectVertex = subtypeVertex
1144 for function in package._functions.values():
1145 print(f"Function: {function}")
1146 functionVertex = Vertex(
1147 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1148 value=function,
1149 graph=self._objectGraph
1150 )
1151 functionVertex["kind"] = ObjectGraphVertexKind.Function
1152 function._objectVertex = functionVertex
1154 for procedure in package._procedures.values():
1155 print(f"Procedure: {procedure}")
1156 procedureVertex = Vertex(
1157 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1158 value=procedure,
1159 graph=self._objectGraph
1160 )
1161 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1162 procedure._objectVertex = procedureVertex
1164 for signal in package._signals.values():
1165 print(f"Signal: {signal}")
1166 signalVertex = Vertex(
1167 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1168 value=signal,
1169 graph=self._objectGraph
1170 )
1171 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1172 signal._objectVertex = signalVertex
1174 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
1175 if isinstance(expression, UnaryExpression):
1176 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1177 elif isinstance(expression, BinaryExpression):
1178 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1179 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1180 elif isinstance(expression, TernaryExpression):
1181 WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression."))
1182 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol):
1183 obj = namespace.FindObject(expression)
1184 expression._reference = obj
1186 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1187 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1188 else:
1189 WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch"))
1191 def _LinkItems(package: Package):
1192 for item in package._declaredItems:
1193 if isinstance(item, Constant):
1194 print(f"constant: {item}")
1195 elif isinstance(item, DeferredConstant):
1196 print(f"deferred constant: {item}")
1197 elif isinstance(item, Signal):
1198 print(f"signal: {item}")
1199 elif isinstance(item, IntegerType):
1200 typeNode = item._objectVertex
1202 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1203 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1204 # elif isinstance(item, FloatingType):
1205 # print(f"signal: {item}")
1206 elif isinstance(item, PhysicalType):
1207 typeNode = item._objectVertex
1209 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1210 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1211 elif isinstance(item, ArrayType):
1212 # Resolve dimensions
1213 for dimension in item._dimensions:
1214 subtype = package._namespace.FindSubtype(dimension)
1215 dimension._reference = subtype
1217 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1218 edge["kind"] = ObjectGraphEdgeKind.Subtype
1220 # Resolve element subtype
1221 subtype = package._namespace.FindSubtype(item._elementType)
1222 item._elementType._reference = subtype
1224 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1225 edge["kind"] = ObjectGraphEdgeKind.Subtype
1226 elif isinstance(item, RecordType):
1227 # Resolve each elements subtype
1228 for element in item._elements:
1229 subtype = package._namespace.FindSubtype(element._subtype)
1230 element._subtype._reference = subtype
1232 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1233 edge["kind"] = ObjectGraphEdgeKind.Subtype
1234 else:
1235 print(f"not handled: {item}")
1237 for libraryName in ("std", "ieee"):
1238 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1239 _HandlePackage(package)
1240 _LinkItems(package)
1242 for document in self.IterateDocumentsInCompileOrder():
1243 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1244 _HandlePackage(package)
1245 _LinkItems(package)
1247 def LinkContexts(self) -> None:
1248 """
1249 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1251 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1252 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1253 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1255 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1256 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1257 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1258 dependency graph is added for that relationship.
1260 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1261 referenced package,
1262 """
1263 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1264 # Create entries in _referenced*** for the current working library under its real name.
1265 workingLibrary: Library = context.Library
1266 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1268 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1269 context._referencedPackages[libraryNormalizedIdentifier] = {}
1270 context._referencedContexts[libraryNormalizedIdentifier] = {}
1272 # Process all library clauses
1273 for libraryReference in context._libraryReferences:
1274 # A library clause can have multiple comma-separated references
1275 for libraryName in libraryReference.Symbols:
1276 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1277 try:
1278 library = self._libraries[libraryNormalizedIdentifier]
1279 except KeyError:
1280 raise ReferencedLibraryNotExistingError(context, libraryName)
1281 # TODO: add position to these messages
1283 libraryName.Library = library
1285 context._referencedLibraries[libraryNormalizedIdentifier] = library
1286 context._referencedPackages[libraryNormalizedIdentifier] = {}
1287 context._referencedContexts[libraryNormalizedIdentifier] = {}
1288 # TODO: warn duplicate library reference
1290 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1291 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1293 # Process all use clauses
1294 for packageReference in context.PackageReferences:
1295 # A use clause can have multiple comma-separated references
1296 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1297 packageName = symbol.Name.Prefix
1298 libraryName = packageName.Prefix
1300 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1301 packageNormalizedIdentifier = packageName._normalizedIdentifier
1303 # In case work is used, resolve to the real library name.
1304 if libraryNormalizedIdentifier == "work": 1304 ↛ 1305line 1304 didn't jump to line 1305 because the condition on line 1304 was never true
1305 library: Library = context._parent
1306 libraryNormalizedIdentifier = library._normalizedIdentifier
1307 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1307 ↛ 1309line 1307 didn't jump to line 1309 because the condition on line 1307 was never true
1308 # TODO: This check doesn't trigger if it's the working library.
1309 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1310 else:
1311 library = self._libraries[libraryNormalizedIdentifier]
1313 try:
1314 package = library._packages[packageNormalizedIdentifier]
1315 except KeyError:
1316 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1318 # FIXME: check if package isn't a generic package
1319 symbol.Package = package
1321 # TODO: warn duplicate package reference
1322 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1324 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1325 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1327 # TODO: update the namespace with visible members
1328 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1328 ↛ 1331line 1328 didn't jump to line 1331 because the condition on line 1328 was always true
1329 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'."))
1331 elif isinstance(symbol, PackageMemberReferenceSymbol):
1332 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1334 else:
1335 raise VHDLModelException()
1337 def LinkArchitectures(self) -> None:
1338 """
1339 Link all architectures to corresponding entities in all libraries.
1341 .. rubric:: Algorithm
1343 1. Iterate all libraries:
1345 1. Iterate all architecture groups (grouped per entity symbol's name).
1346 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1348 * Check if entity symbol's name exists as an entity in this library.
1350 1. For each architecture in the same architecture group:
1352 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1353 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1354 * Set parent namespace of architecture's namespace to the entitie's namespace.
1355 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1357 .. seealso::
1359 :meth:`LinkPackageBodies`
1360 Link all package bodies to corresponding packages in all libraries.
1361 :meth:`LinkPackageInstances`
1362 Link all package instances to corresponding generic packages in all libraries.
1363 """
1364 for library in self._libraries.values():
1365 library.LinkArchitectures()
1367 def LinkPackageBodies(self) -> None:
1368 """
1369 Link all package bodies to corresponding packages in all libraries.
1371 .. rubric:: Algorithm
1373 1. Iterate all libraries:
1375 1. Iterate all package bodies.
1376 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1378 * Check if package body symbol's name exists as a package in this library.
1379 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1380 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1381 * Set parent namespace of package body's namespace to the package's namespace.
1382 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1384 .. seealso::
1386 :meth:`LinkArchitectures`
1387 Link all architectures to corresponding entities in all libraries.
1388 :meth:`LinkPackageInstances`
1389 Link all package instances to corresponding generic packages in all libraries.
1390 """
1391 for library in self._libraries.values():
1392 library.LinkPackageBodies()
1394 def LinkPackageInstances(self) -> None:
1395 """
1396 Link all package instances to corresponding generic packages in all libraries.
1398 .. rubric:: Algorithm
1400 1. Iterate all libraries:
1402 1. Iterate all package instances.
1403 |rarr| :meth:`pyVHDLModel.Library.LinkPackageInstances`
1405 .. todo::
1407 * Check if package instance's symbol's name exists as a generic package in this library.
1408 * Add generic package to package instance :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1409 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1410 * Set parent namespace of package body's namespace to the package's namespace.
1411 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1413 .. seealso::
1415 :meth:`LinkArchitectures`
1416 Link all architectures to corresponding entities in all libraries.
1417 :meth:`LinkPackageBodies`
1418 Link all package bodies to corresponding packages in all libraries.
1419 """
1420 for library in self._libraries.values():
1421 library.LinkPackageInstances()
1423 def LinkLibraryReferences(self) -> None:
1424 """
1425 Link all library references (library clause) to the matching VHDL library.
1427 .. rubric:: Algorithm
1429 1. Iterate all design units with contexts:
1431 * If the design unit is a primary unit:
1433 1. Iterate all library identifiers in ``DEFAULT_LIBRARIES`` (``std``):
1435 * Get the referenced library by name from the design.
1436 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1437 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1438 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1439 * Add an edge in the dependency graph from design unit to the referenced library.
1441 2. Get the design unit's library:
1443 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1444 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1445 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1446 * Add an edge in the dependency graph from design unit to the referenced library.
1448 * If the design unit is a secondary unit:
1450 * If design unit is an architecture, get the corresponding entity's referenced libraries.
1451 * If design unit is a package body, get the corresponding package's referenced libraries.
1452 * Otherwise, raise an exception
1454 For every referenced library create new dictionary entries in the design unit's ``_referencedLibraries``.
1456 2. Iterate every library reference (library clause) in the design unit:
1458 * Iterate every library symbol within the library reference:
1460 * Get the library identifier from the symbol.
1461 * Continue the inner loop, if identifier is ``work``.
1462 * Get the referenced library from the design or raise an exception.
1463 * Update the library symbol's target with the referenced library.
1464 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1465 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1466 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1467 * Add an edge in the dependency graph from design unit to the referenced library.
1469 .. seealso::
1471 :meth:`LinkPackageReferences`
1472 Link *use clause*.
1473 :meth:`LinkContextReferences`
1474 Link *context clause*.
1475 :meth:`AnalyzeDependencies`
1476 Analyze dependencies and link relations.
1477 """
1478 DEFAULT_LIBRARIES = ("std",)
1480 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1481 # All primary units supporting a context, have at least one library implicitly referenced
1482 if isinstance(designUnit, PrimaryUnit):
1483 for libraryIdentifier in DEFAULT_LIBRARIES:
1484 referencedLibrary = self._libraries[libraryIdentifier]
1485 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1486 designUnit._referencedPackages[libraryIdentifier] = {}
1487 designUnit._referencedContexts[libraryIdentifier] = {}
1488 # TODO: catch KeyError on self._libraries[libName]
1489 # TODO: warn duplicate library reference
1491 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1492 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1494 # TODO: this could create a duplicate linking, if primary unit is put into library 'std'
1495 workingLibrary: Library = designUnit.Library
1496 libraryIdentifier = workingLibrary.NormalizedIdentifier
1497 referencedLibrary = self._libraries[libraryIdentifier] # TODO: isn't this the same as the workingLibrary from 2 lines before?
1499 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1500 designUnit._referencedPackages[libraryIdentifier] = {}
1501 designUnit._referencedContexts[libraryIdentifier] = {}
1503 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1504 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1506 # All secondary units inherit referenced libraries from their primary units.
1507 else:
1508 if isinstance(designUnit, Architecture):
1509 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1510 elif isinstance(designUnit, PackageBody): 1510 ↛ 1513line 1510 didn't jump to line 1513 because the condition on line 1510 was always true
1511 referencedLibraries = designUnit.Package.Package._referencedLibraries
1512 else:
1513 raise VHDLModelException() # FIXME: exception message
1515 for libraryIdentifier, library in referencedLibraries.items():
1516 designUnit._referencedLibraries[libraryIdentifier] = library # TODO: Could we use the .update() method
1518 for libraryReference in designUnit._libraryReferences:
1519 # A library clause can have multiple comma-separated references
1520 for librarySymbol in libraryReference.Symbols:
1521 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1522 if libraryIdentifier == "work": 1522 ↛ 1523line 1522 didn't jump to line 1523 because the condition on line 1522 was never true
1523 continue
1525 try:
1526 library = self._libraries[libraryIdentifier]
1527 except KeyError:
1528 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1529 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1530 raise ex
1532 librarySymbol.Library = library
1533 designUnit._referencedLibraries[libraryIdentifier] = library
1534 designUnit._referencedPackages[libraryIdentifier] = {}
1535 designUnit._referencedContexts[libraryIdentifier] = {}
1536 # TODO: warn duplicate library reference
1538 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1539 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1541 def LinkPackageReferences(self) -> None:
1542 """
1543 Link all package references (use clause) to the matching packages.
1545 .. rubric:: Algorithm
1547 1. Iterate all design units with contexts:
1549 * If the design unit is a primary unit:
1551 * If primary unit isn't package ``std.standard``:
1553 1. Iterate all library, packages tuples in ``DEFAULT_PACKAGES`` (``std``: [``standard``]):
1555 * Raise an exception, if library isn't listed in design unit's ``_referencedLibraries``.
1556 * For every package in packages:
1558 * Get the referenced package by library name and package name from the design.
1559 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1560 * Add an edge in the dependency graph from design unit to the referenced package.
1562 * If the design unit is a secondary unit:
1564 * If design unit is an architecture, get the corresponding entity's referenced packages.
1565 * If design unit is a package body, get the corresponding package's referenced packages.
1566 * Otherwise, raise an exception
1568 For every referenced package create new dictionary entries in the design unit's ``_referencedPackages``.
1570 2. Iterate every package reference (use clause) in the design unit:
1572 * Iterate every package symbol within the package reference:
1574 1. Get the library identifier from the symbol.
1575 2. Get the package identifier from the symbol.
1576 3. Resolve library:
1578 * If library name is ``work``, get library from design unit.
1579 * If library name is not in design unit's ``_referencedLibraries``, raise an exception.
1580 * Otherwise, lookup library by name in design.
1582 4. Resolve package:
1584 * Lookup package by name in library.
1586 5. Update design unit:
1588 * Update the package symbol's target with the referenced package.
1589 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1590 * Add an edge in the dependency graph from design unit to the referenced package.
1592 6. Import public package members.
1594 * If package symbol is a ``AllPackageMembersReferenceSymbol``:
1596 * Iterate all components within the referenced package and add entries for each component in the design unit's ``_namespace``.
1598 .. todo:: Other elements are not implemented.
1600 * If package symbol is a ``PackageMemberReferenceSymbol``
1602 .. todo:: Not implemented.
1604 * Otherwise, raise an exception.
1606 .. seealso::
1608 :meth:`LinkLibraryReferences`
1609 Link *library clause*.
1610 :meth:`LinkContextReferences`
1611 Link *context clause*.
1612 :meth:`AnalyzeDependencies`
1613 Analyze dependencies and link relations.
1614 """
1615 DEFAULT_PACKAGES = (
1616 ("std", ("standard",)),
1617 )
1619 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1620 # All primary units supporting a context, have at least one package implicitly referenced
1621 if isinstance(designUnit, PrimaryUnit):
1622 if not (designUnit.Library.NormalizedIdentifier == "std" and designUnit.NormalizedIdentifier == "standard"):
1623 for lib, packages in DEFAULT_PACKAGES:
1624 if lib not in designUnit._referencedLibraries: 1624 ↛ 1625line 1624 didn't jump to line 1625 because the condition on line 1624 was never true
1625 raise VHDLModelException() # TODO: missing exception message
1626 for package in packages:
1627 referencedPackage = self._libraries[lib]._packages[package]
1628 designUnit._referencedPackages[lib][package] = referencedPackage
1629 # TODO: catch KeyError on self._libraries[lib[0]]._packages[package]
1630 # TODO: warn duplicate package reference
1632 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1633 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1635 # All secondary units inherit referenced packages from their primary units.
1636 else:
1637 if isinstance(designUnit, Architecture):
1638 referencedPackages = designUnit.Entity.Entity._referencedPackages
1639 elif isinstance(designUnit, PackageBody): 1639 ↛ 1642line 1639 didn't jump to line 1642 because the condition on line 1639 was always true
1640 referencedPackages = designUnit.Package.Package._referencedPackages
1641 else:
1642 raise VHDLModelException() # FIXME: exception message
1644 for packageIdentifier, package in referencedPackages.items():
1645 designUnit._referencedPackages[packageIdentifier] = package
1647 for packageReference in designUnit.PackageReferences:
1648 # A use clause can have multiple comma-separated references
1649 for packageMemberSymbol in packageReference.Symbols:
1650 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1650 ↛ 1651line 1650 didn't jump to line 1651 because the condition on line 1650 was never true
1651 packageName = packageMemberSymbol.Name
1652 elif isinstance(packageMemberSymbol, (AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol)): 1652 ↛ 1655line 1652 didn't jump to line 1655 because the condition on line 1652 was always true
1653 packageName = packageMemberSymbol.Name.Prefix
1655 libraryName = packageName.Prefix
1657 libraryIdentifier = libraryName.NormalizedIdentifier
1658 packageIdentifier = packageName.NormalizedIdentifier
1660 # In case work is used, resolve to the real library name.
1661 if libraryIdentifier == "work":
1662 library: Library = designUnit.Library
1663 libraryIdentifier = library.NormalizedIdentifier
1664 elif libraryIdentifier not in designUnit._referencedLibraries: 1664 ↛ 1666line 1664 didn't jump to line 1666 because the condition on line 1664 was never true
1665 # TODO: This check doesn't trigger if it's the working library.
1666 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1667 else:
1668 library = self._libraries[libraryIdentifier]
1670 try:
1671 package = library._packages[packageIdentifier]
1672 except KeyError:
1673 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1674 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1675 raise ex
1677 # FIXME: check if package isn't a generic package
1678 packageMemberSymbol.Package = package
1680 # TODO: warn duplicate package reference
1681 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1683 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1684 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1686 # TODO: update the namespace with visible members
1687 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1687 ↛ 1688line 1687 didn't jump to line 1688 because the condition on line 1687 was never true
1688 designUnit._namespace._elements[packageIdentifier] = package
1690 elif isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1690 ↛ 1696line 1690 didn't jump to line 1696 because the condition on line 1690 was always true
1691 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled."))
1693 for componentIdentifier, component in package._components.items(): 1693 ↛ 1694line 1693 didn't jump to line 1694 because the loop on line 1693 never started
1694 designUnit._namespace._elements[componentIdentifier] = component
1696 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
1697 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1699 else:
1700 ex = VHDLModelException(f"Unknown package reference symbol type.")
1701 ex.add_note(f"Got type '{getFullyQualifiedName(packageMemberSymbol)}'.")
1702 raise ex
1704 def LinkContextReferences(self) -> None:
1705 """
1706 Link all context references (context clause) to the matching context.
1708 .. rubric:: Algorithm
1710 1. Iterate all design units:
1712 * Iterate all context references in the design unit:
1714 * Iterate each context symbol within the context reference.
1716 1. Get the library identifier from the symbol.
1717 2. Get the context identifier from the symbol.
1718 3. Resolve library:
1720 * If library name is ``work``, get library from design unit.
1721 * If library name is not in design unit's ``_referencedLibraries``, raise an exception.
1722 * Otherwise, lookup library by name in design.
1724 4. Resolve context:
1726 * Lookup context by name in library.
1728 5. Update design unit:
1730 * Update the context symbol's target with the referenced context.
1731 * Add an entry in the design unit's ``_referencedContexts`` dictionary referencing the referenced context.
1732 * Add an edge in the dependency graph from design unit to the referenced context.
1734 2. Iterate all context vertices in the dependency graph (``_dependencyGraph``) in topological order:
1736 * Get the context from the context vertex.
1737 * Iterate all predecessor vertices (design unit vertices) of the context vertex:
1739 1. Get the design unit from design unit vertex.
1740 2. Iterate referenced libraries of the context:
1742 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1743 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1745 3. Iterate referenced packages of the context:
1747 * Raise an exception if package name is already listed in ``_referencedPackages``.
1748 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1750 .. seealso::
1752 :meth:`LinkLibraryReferences`
1753 Link *library clause*.
1754 :meth:`LinkPackageReferences`
1755 Link *use clause*.
1756 :meth:`AnalyzeDependencies`
1757 Analyze dependencies and link relations.
1758 """
1759 for designUnit in self.IterateDesignUnits():
1760 for contextReference in designUnit._contextReferences:
1761 # A context reference can have multiple comma-separated references
1762 for contextSymbol in contextReference.Symbols:
1763 libraryName = contextSymbol.Name.Prefix
1765 libraryIdentifier = libraryName.NormalizedIdentifier
1766 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1768 # In case work is used, resolve to the real library name.
1769 if libraryIdentifier == "work": 1769 ↛ 1772line 1769 didn't jump to line 1772 because the condition on line 1769 was always true
1770 referencedLibrary = designUnit.Library
1771 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1772 elif libraryIdentifier not in designUnit._referencedLibraries:
1773 # TODO: This check doesn't trigger if it's the working library.
1774 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1775 else:
1776 referencedLibrary = self._libraries[libraryIdentifier]
1778 try:
1779 referencedContext = referencedLibrary._contexts[contextIdentifier]
1780 except KeyError:
1781 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1783 contextSymbol.Package = referencedContext
1785 # TODO: warn duplicate referencedContext reference
1786 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1788 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1789 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1791 for vertex in self._dependencyGraph.IterateTopologically(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Context):
1792 context: Context = vertex.Value
1793 for designUnitVertex in vertex.IteratePredecessorVertices(): # TODO: should this be filtered to exclude non-contexts?
1794 designUnit: DesignUnit = designUnitVertex.Value
1795 for libraryIdentifier, library in context._referencedLibraries.items():
1796 # if libraryIdentifier in designUnit._referencedLibraries:
1797 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1799 designUnit._referencedLibraries[libraryIdentifier] = library
1800 designUnit._referencedPackages[libraryIdentifier] = {}
1802 for libraryIdentifier, packages in context._referencedPackages.items():
1803 for packageIdentifier, package in packages.items():
1804 if packageIdentifier in designUnit._referencedPackages: 1804 ↛ 1805line 1804 didn't jump to line 1805 because the condition on line 1804 was never true
1805 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1807 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1809 def LinkComponents(self) -> None:
1810 """
1811 Link components to matching entities found in same VHDL library.
1813 .. rubric:: Algorithm
1815 1. Iterate all design units with component declarations (packages and architectures):
1817 1. Iterate all component declarations in a package or architecture:
1819 * Check if an entity with matching name can be found in the VHDL library the package is declared within. If
1820 found, set the component's entity reference to that entity, otherwise check if blackboxes are allowed for
1821 that component. If so, mark the component as a blackbox, otherwise, raise an exception.
1823 2. Iterate concurrent statements with declaration regions (block statements, generate statements) if the design
1824 unit is an architecture:
1826 * If the statement is an :class:`IfGenerateStatement`:
1828 1. Iterate declared components in the :class:`IfGenerateBranch`.
1829 2. Iterate declared components in each :class:`ElIfGenerateBranch`.
1830 3. Iterate declared components in the :class:`ElseGenerateBranch` if it exists.
1832 * If the statement is an :class:`ForGenerateStatement`:
1834 1. Iterate declared components.
1836 * If the statement is an :class:`CaseGenerateStatement`:
1838 1. Iterate declared components.
1839 2. Iterate
1841 .. seealso::
1843 :meth:`LinkInstantiations`
1844 Link instantiations to components and entities.
1845 :meth:`AnalyzeDependencies`
1846 Analyze dependencies in a design (calls this method).
1847 """
1848 def linkStatements(library: Library, concurrent: ConcurrentStatementsMixin) -> None:
1849 for statement in concurrent._statements:
1850 if isinstance(statement, IfGenerateStatement): 1850 ↛ 1851line 1850 didn't jump to line 1851 because the condition on line 1850 was never true
1851 linkComponents(library, statement._ifBranch)
1852 linkStatements(library, statement._ifBranch)
1853 for branch in statement._elsifBranches:
1854 linkComponents(library, branch)
1855 linkStatements(library, branch)
1856 if (branch := statement._elseBranch) is not None:
1857 linkComponents(library, branch)
1858 linkStatements(library, branch)
1859 elif isinstance(statement, ForGenerateStatement): 1859 ↛ 1860line 1859 didn't jump to line 1860 because the condition on line 1859 was never true
1860 linkComponents(library, statement)
1861 linkStatements(library, statement)
1862 elif isinstance(statement, CaseGenerateStatement): 1862 ↛ 1863line 1862 didn't jump to line 1863 because the condition on line 1862 was never true
1863 for case in statement._cases:
1864 linkComponents(library, case)
1865 linkStatements(library, case)
1866 elif isinstance(statement, ConcurrentBlockStatement): 1866 ↛ 1867line 1866 didn't jump to line 1867 because the condition on line 1866 was never true
1867 linkComponents(library, statement)
1868 linkStatements(library, statement)
1870 def searchEntityAndLinkComponent(library: Library, component: Component) -> None:
1871 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1872 # Currently, component has no _dependencyVertex field
1873 try:
1874 entity = library._entities[component.NormalizedIdentifier]
1875 except KeyError:
1876 if component.AllowBlackbox:
1877 component._isBlackBox = True
1878 return
1879 else:
1880 raise VHDLModelException(
1881 f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1883 component.Entity = entity
1885 def linkComponents(library: Library, declarationRegion: ConcurrentDeclarationRegionMixin) -> None:
1886 for item in declarationRegion._declaredItems:
1887 if isinstance(item, Component):
1888 searchEntityAndLinkComponent(library, item)
1890 for designUnit in self.IterateDesignUnits(DesignUnitKind.Package | DesignUnitKind.Architecture): # type: Union[Package, Architecture]
1891 library = designUnit._parent
1892 for component in designUnit._components.values(): 1892 ↛ 1893line 1892 didn't jump to line 1893 because the loop on line 1892 never started
1893 searchEntityAndLinkComponent(library, component)
1895 if isinstance(designUnit, Architecture):
1896 linkStatements(library, designUnit)
1898 def LinkInstantiations(self) -> None:
1899 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1900 for instance in architecture.IterateInstantiations():
1901 if isinstance(instance, EntityInstantiation): 1901 ↛ 1934line 1901 didn't jump to line 1934 because the condition on line 1901 was always true
1902 libraryName = instance.Entity.Name.Prefix
1903 libraryIdentifier = libraryName.Identifier
1904 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1905 if normalizedLibraryIdentifier == "work":
1906 libraryIdentifier = architecture.Library.Identifier
1907 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1908 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1908 ↛ 1909line 1908 didn't jump to line 1909 because the condition on line 1908 was never true
1909 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}'.")
1910 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1911 raise ex
1913 try:
1914 library = self._libraries[normalizedLibraryIdentifier]
1915 except KeyError:
1916 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1917 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1918 raise ex
1920 try:
1921 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1922 except KeyError:
1923 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}'.")
1924 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1925 if libs:
1926 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1927 raise ex
1929 instance.Entity.Entity = entity
1931 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1932 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1934 elif isinstance(instance, ComponentInstantiation):
1935 component = instance._parent._namespace.FindComponent(instance.Component)
1937 instance.Component.Component = component
1939 if not component.IsBlackbox:
1940 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1941 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1942 else:
1943 WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'."))
1945 elif isinstance(instance, ConfigurationInstantiation):
1946 WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'."))
1948 def IndexPackages(self) -> None:
1949 """
1950 Index all declared items in all packages in all libraries.
1952 .. rubric:: Algorithm
1954 1. Iterate all libraries:
1956 1. Iterate all packages |br|
1957 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1959 * Index all declared items in that package. |br|
1960 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1962 .. seealso::
1964 :meth:`IndexPackageBodies`
1965 Index all declared items in all package bodies in all libraries.
1966 :meth:`IndexEntities`
1967 Index all declared items in all entities in all libraries.
1968 :meth:`IndexArchitectures`
1969 Index all declared items in all architectures in all libraries.
1970 """
1971 for library in self._libraries.values():
1972 library.IndexPackages()
1974 def IndexPackageBodies(self) -> None:
1975 """
1976 Index all declared items in all packages in all libraries.
1978 .. rubric:: Algorithm
1980 1. Iterate all libraries:
1982 1. Iterate all packages |br|
1983 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
1985 * Index all declared items in that package body. |br|
1986 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
1988 .. seealso::
1990 :meth:`IndexPackages`
1991 Index all declared items in all packages in all libraries.
1992 :meth:`IndexEntities`
1993 Index all declared items in all entities in all libraries.
1994 :meth:`IndexArchitectures`
1995 Index all declared items in all architectures in all libraries.
1996 """
1997 for library in self._libraries.values():
1998 library.IndexPackageBodies()
2000 def IndexEntities(self) -> None:
2001 """
2002 Index all declared items in all packages in all libraries.
2004 .. rubric:: Algorithm
2006 1. Iterate all libraries:
2008 1. Iterate all packages |br|
2009 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
2011 * Index all declared items in that entity. |br|
2012 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2014 .. seealso::
2016 :meth:`IndexPackages`
2017 Index all declared items in all packages in all libraries.
2018 :meth:`IndexPackageBodies`
2019 Index all declared items in all package bodies in all libraries.
2020 :meth:`IndexArchitectures`
2021 Index all declared items in all architectures in all libraries.
2022 """
2023 for library in self._libraries.values():
2024 library.IndexEntities()
2026 def IndexArchitectures(self) -> None:
2027 """
2028 Index all declared items in all packages in all libraries.
2030 .. rubric:: Algorithm
2032 1. Iterate all libraries:
2034 1. Iterate all packages |br|
2035 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
2037 * Index all declared items in that architecture. |br|
2038 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2040 .. seealso::
2042 :meth:`IndexPackages`
2043 Index all declared items in all packages in all libraries.
2044 :meth:`IndexPackageBodies`
2045 Index all declared items in all package bodies in all libraries.
2046 :meth:`IndexEntities`
2047 Index all declared items in all entities in all libraries.
2048 """
2049 for library in self._libraries.values():
2050 library.IndexArchitectures()
2052 def CreateHierarchyGraph(self) -> None:
2053 """
2054 Create the hierarchy graph from dependency graph.
2056 .. rubric:: Algorithm
2058 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
2060 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
2061 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
2063 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
2064 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
2066 2. Iterate all architectures ...
2068 .. todo:: Design::CreateHierarchyGraph describe algorithm
2070 1. Iterate all outbound edges
2072 .. todo:: Design::CreateHierarchyGraph describe algorithm
2073 """
2074 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
2075 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
2076 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
2077 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
2078 vertex.Value._hierarchyVertex = hierarchyVertex
2080 # Copy implementation edges from
2081 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
2082 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
2083 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
2084 if DependencyGraphEdgeKind.Implementation in kind:
2085 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
2086 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
2087 elif DependencyGraphEdgeKind.Instantiation in kind:
2088 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
2090 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
2091 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
2092 continue
2094 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
2095 else:
2096 continue
2098 newEdge["kind"] = kind
2100 def ComputeCompileOrder(self) -> None:
2101 def predicate(edge: Edge) -> bool:
2102 return (
2103 DependencyGraphEdgeKind.Implementation in edge["kind"] or
2104 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
2105 DependencyGraphEdgeKind.UseClause in edge["kind"] or
2106 DependencyGraphEdgeKind.ContextReference in edge["kind"]
2107 ) and edge.Destination["predefined"] is False
2109 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
2110 sourceDocument: Document = edge.Source.Value.Document
2111 destinationDocument: Document = edge.Destination.Value.Document
2113 sourceVertex = sourceDocument._compileOrderVertex
2114 destinationVertex = destinationDocument._compileOrderVertex
2116 # Don't add self-edges
2117 if sourceVertex is destinationVertex: 2117 ↛ 2120line 2117 didn't jump to line 2120 because the condition on line 2117 was always true
2118 continue
2119 # Don't add parallel edges
2120 elif sourceVertex.HasEdgeToDestination(destinationVertex):
2121 continue
2123 e = sourceVertex.EdgeToVertex(destinationVertex)
2124 e["kind"] = DependencyGraphEdgeKind.CompileOrder
2126 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
2127 e["kind"] = DependencyGraphEdgeKind.CompileOrder
2129 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
2130 """
2131 Iterate all document in compile-order.
2133 .. rubric:: Algorithm
2135 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
2137 1. Iterate compile-order graph in topological order. |br|
2138 :meth:`pyTooling.Graph.Graph.IterateTopologically`
2140 * yield the compiler-order vertex' referenced document.
2142 :returns: A generator to iterate all documents in compile-order in the design.
2143 :raises VHDLModelException: If compile-order was not computed.
2145 .. seealso::
2147 .. todo:: missing text
2149 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
2151 """
2152 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1:
2153 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
2155 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
2156 yield compileOrderNode.Value
2158 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
2159 WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units."))
2161 def __repr__(self) -> str:
2162 """
2163 Formats a representation of the design.
2165 **Format:** ``Document: 'my_design'``
2167 :returns: String representation of the design.
2168 """
2169 return f"Design: {self._name}"
2171 __str__ = __repr__
2174@export
2175class Library(ModelEntity, NamedEntityMixin, AllowBlackboxMixin):
2176 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
2178 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library.
2179 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
2180 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
2181 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
2182 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
2183 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
2184 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
2186 _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`.
2188 def __init__(
2189 self,
2190 identifier: str,
2191 allowBlackbox: Nullable[bool] = None,
2192 parent: Nullable[ModelEntity] = None
2193 ) -> None:
2194 """
2195 Initialize a VHDL library.
2197 :param identifier: Name of the VHDL library.
2198 :param allowBlackbox: Specify if blackboxes are allowed in this design.
2199 :param parent: The parent model entity (design) of this VHDL library.
2200 """
2201 super().__init__(parent)
2202 NamedEntityMixin.__init__(self, identifier)
2203 AllowBlackboxMixin.__init__(self, allowBlackbox)
2205 self._contexts = {}
2206 self._configurations = {}
2207 self._entities = {}
2208 self._architectures = {}
2209 self._packages = {}
2210 self._packageBodies = {}
2212 self._dependencyVertex = None
2214 @readonly
2215 def Contexts(self) -> Dict[str, Context]:
2216 """Returns a list of all context declarations declared in this library."""
2217 return self._contexts
2219 @readonly
2220 def Configurations(self) -> Dict[str, Configuration]:
2221 """Returns a list of all configuration declarations declared in this library."""
2222 return self._configurations
2224 @readonly
2225 def Entities(self) -> Dict[str, Entity]:
2226 """Returns a list of all entity declarations declared in this library."""
2227 return self._entities
2229 @readonly
2230 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2231 """Returns a list of all architectures declarations declared in this library."""
2232 return self._architectures
2234 @readonly
2235 def Packages(self) -> Dict[str, Package]:
2236 """Returns a list of all package declarations declared in this library."""
2237 return self._packages
2239 @readonly
2240 def PackageBodies(self) -> Dict[str, PackageBody]:
2241 """Returns a list of all package body declarations declared in this library."""
2242 return self._packageBodies
2244 @readonly
2245 def DependencyVertex(self) -> Vertex:
2246 """
2247 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
2249 The dependency vertex references this library by its value field.
2251 :returns: The corresponding dependency vertex.
2252 """
2253 return self._dependencyVertex
2255 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2256 """
2257 Iterate all design units in the library.
2259 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2261 .. rubric:: Algorithm
2263 1. Iterate all contexts in that library.
2264 2. Iterate all packages in that library.
2265 3. Iterate all package bodies in that library.
2266 4. Iterate all entities in that library.
2267 5. Iterate all architectures in that library.
2268 6. Iterate all configurations in that library.
2270 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2271 :returns: A generator to iterate all matched design units in the library.
2273 .. seealso::
2275 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2276 Iterate all design units in the design.
2277 :meth:`pyVHDLModel.Document.IterateDesignUnits`
2278 Iterate all design units in the document.
2279 """
2280 if DesignUnitKind.Context in filter:
2281 for context in self._contexts.values():
2282 yield context
2284 if DesignUnitKind.Package in filter:
2285 for package in self._packages.values():
2286 yield package
2288 if DesignUnitKind.PackageBody in filter:
2289 for packageBody in self._packageBodies.values():
2290 yield packageBody
2292 if DesignUnitKind.Entity in filter:
2293 for entity in self._entities.values():
2294 yield entity
2296 if DesignUnitKind.Architecture in filter:
2297 for architectures in self._architectures.values():
2298 for architecture in architectures.values():
2299 yield architecture
2301 if DesignUnitKind.Configuration in filter:
2302 for configuration in self._configurations.values():
2303 yield configuration
2305 # for verificationProperty in self._verificationUnits.values():
2306 # yield verificationProperty
2307 # for verificationUnit in self._verificationProperties.values():
2308 # yield entity
2309 # for verificationMode in self._verificationModes.values():
2310 # yield verificationMode
2312 def LinkArchitectures(self) -> None:
2313 """
2314 Link all architectures to corresponding entities.
2316 .. rubric:: Algorithm
2318 1. Iterate all architecture groups (grouped per entity symbol's name).
2320 * Check if entity symbol's name exists as an entity in this library.
2322 1. For each architecture in the same architecture group:
2324 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
2325 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
2326 * Set parent namespace of architecture's namespace to the entitie's namespace.
2327 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
2329 :raises VHDLModelException: If entity name doesn't exist.
2330 :raises VHDLModelException: If architecture name already exists for entity.
2332 .. seealso::
2334 :meth:`LinkPackageBodies`
2335 Link all package bodies to corresponding packages.
2336 :meth:`LinkPackageInstances`
2337 Link all package instances to corresponding generic packages.
2338 """
2339 for entityName, architecturesPerEntity in self._architectures.items():
2340 if entityName not in self._entities: 2340 ↛ 2341line 2340 didn't jump to line 2341 because the condition on line 2340 was never true
2341 architectureNames = "', '".join(architecturesPerEntity.keys())
2342 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
2343 # TODO: search in other libraries to find that entity.
2344 # TODO: add code position
2346 entity = self._entities[entityName]
2347 for architecture in architecturesPerEntity.values():
2348 if architecture._normalizedIdentifier in entity._architectures: 2348 ↛ 2349line 2348 didn't jump to line 2349 because the condition on line 2348 was never true
2349 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
2350 # TODO: add code position of existing and current
2352 entity._architectures[architecture._normalizedIdentifier] = architecture
2353 architecture._entity.Entity = entity
2354 architecture._namespace._parentNamespace = entity._namespace
2356 # add "architecture -> entity" relation in dependency graph
2357 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
2358 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
2360 def LinkPackageBodies(self) -> None:
2361 """
2362 Link all package bodies to corresponding packages.
2364 .. rubric:: Algorithm
2366 1. Iterate all package bodies.
2368 * Check if package body symbol's name exists as a package in this library.
2369 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2370 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2371 * Set parent namespace of package body's namespace to the package's namespace.
2372 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2374 :raises VHDLModelException: If package name doesn't exist.
2376 .. seealso::
2378 :meth:`LinkArchitectures`
2379 Link all architectures to corresponding entities.
2380 :meth:`LinkPackageInstances`
2381 Link all package instances to corresponding generic packages.
2382 """
2383 for packageBodyName, packageBody in self._packageBodies.items():
2384 if packageBodyName not in self._packages: 2384 ↛ 2385line 2384 didn't jump to line 2385 because the condition on line 2384 was never true
2385 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
2387 package = self._packages[packageBodyName]
2388 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
2389 packageBody._package.Package = package
2390 packageBody._namespace._parentNamespace = package._namespace
2392 # add "package body -> package" relation in dependency graph
2393 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2394 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2396 def LinkPackageInstances(self) -> None:
2397 """
2398 Link all package instances to corresponding generic packages.
2400 .. rubric:: Algorithm
2402 1. Iterate all package instances.
2404 .. todo::
2406 * Check if package body symbol's name exists as a package in this library.
2407 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2408 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2409 * Set parent namespace of package body's namespace to the package's namespace.
2410 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2412 :raises VHDLModelException: If generic package name doesn't exist.
2414 .. seealso::
2416 :meth:`LinkArchitectures`
2417 Link all architectures to corresponding entities.
2418 :meth:`LinkPackageBodies`
2419 Link all package bodies to corresponding packages.
2420 """
2421 for packageInstanceName, packageInstance in self._packages.items():
2422 if isinstance(packageInstance, PackageInstantiation): 2422 ↛ 2423line 2422 didn't jump to line 2423 because the condition on line 2422 was never true
2423 packageSymbol = packageInstance._packageReference
2424 packageName = packageSymbol.Name
2425 libraryName = packageName.Prefix
2427 libraryIdentifier = libraryName.NormalizedIdentifier
2428 packageIdentifier = packageName.NormalizedIdentifier
2430 # In case work is used, resolve to the real library name.
2431 if libraryIdentifier == "work":
2432 library: Library = self
2433 libraryIdentifier = library.NormalizedIdentifier
2434 elif libraryIdentifier not in self._parent._libraries:
2435 # TODO: This check doesn't trigger if it's the working library.
2436 raise VHDLModelException(f"Package instantiation of '{packageInstanceName}' references library '{libraryName.Identifier}', which cannot be found in design.")
2437 else:
2438 library = self._parent._libraries[libraryIdentifier]
2440 try:
2441 package = library._packages[packageIdentifier]
2442 except KeyError:
2443 ex = VHDLModelException(
2444 f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
2445 ex.add_note(f"Caused in library '{self}' in file '{packageInstance.Document}'.")
2446 raise ex
2448 # FIXME: check if package is a generic package
2449 if package.GenericCount == 0:
2450 raise VHDLModelException(f"Package '{libraryName.Identifier}.{packageName.Identifier}' referenced by '{self._identifier}.{packageInstanceName}' is not a generic package.")
2452 packageSymbol.Package = package
2454 dependency = packageInstance._dependencyVertex.EdgeToVertex(package._dependencyVertex) # , edgeValue=packageReference)
2455 dependency["kind"] = DependencyGraphEdgeKind.PackageInstantiation
2457 packageInstance.Instantiate()
2459 def IndexPackages(self) -> None:
2460 """
2461 Index declared items in all packages.
2463 .. rubric:: Algorithm
2465 1. Iterate all packages:
2467 * Index all declared items. |br|
2468 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2470 .. seealso::
2472 :meth:`IndexPackageBodies`
2473 Index all declared items in a package body.
2474 :meth:`IndexEntities`
2475 Index all declared items in an entity.
2476 :meth:`IndexArchitectures`
2477 Index all declared items in an architecture.
2478 """
2479 for package in self._packages.values():
2480 if isinstance(package, Package): 2480 ↛ 2479line 2480 didn't jump to line 2479 because the condition on line 2480 was always true
2481 package.IndexDeclaredItems()
2483 def IndexPackageBodies(self) -> None:
2484 """
2485 Index declared items in all package bodies.
2487 .. rubric:: Algorithm
2489 1. Iterate all package bodies:
2491 * Index all declared items. |br|
2492 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2494 .. seealso::
2496 :meth:`IndexPackages`
2497 Index all declared items in a package.
2498 :meth:`IndexEntities`
2499 Index all declared items in an entity.
2500 :meth:`IndexArchitectures`
2501 Index all declared items in an architecture.
2502 """
2503 for packageBody in self._packageBodies.values():
2504 packageBody.IndexDeclaredItems()
2506 def IndexEntities(self) -> None:
2507 """
2508 Index declared items in all entities.
2510 .. rubric:: Algorithm
2512 1. Iterate all entities:
2514 * Index all declared items. |br|
2515 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2517 .. seealso::
2519 :meth:`IndexPackages`
2520 Index all declared items in a package.
2521 :meth:`IndexPackageBodies`
2522 Index all declared items in a package body.
2523 :meth:`IndexArchitectures`
2524 Index all declared items in an architecture.
2525 """
2526 for entity in self._entities.values():
2527 entity.IndexDeclaredItems()
2529 def IndexArchitectures(self) -> None:
2530 """
2531 Index declared items in all architectures.
2533 .. rubric:: Algorithm
2535 1. Iterate all architectures:
2537 * Index all declared items. |br|
2538 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2540 .. seealso::
2542 :meth:`IndexPackages`
2543 Index all declared items in a package.
2544 :meth:`IndexPackageBodies`
2545 Index all declared items in a package body.
2546 :meth:`IndexEntities`
2547 Index all declared items in an entity.
2548 """
2549 for architectures in self._architectures.values():
2550 for architecture in architectures.values():
2551 architecture.IndexDeclaredItems()
2552 architecture.IndexStatements()
2554 def __repr__(self) -> str:
2555 """
2556 Formats a representation of the library.
2558 **Format:** ``Library: 'my_library'``
2560 :returns: String representation of the library.
2561 """
2562 return f"Library: '{self._identifier}'"
2564 __str__ = __repr__
2567@export
2568class Document(ModelEntity, DocumentedEntityMixin):
2569 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2571 _path: Path #: path to the document. ``None`` if virtual document.
2572 _vhdlVersion: VHDLVersion #: VHDL version used for analyzing this source file.
2573 _library: Library #: VHDL library used for analyzing the source file's content into.
2574 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2575 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2576 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2577 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2578 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2579 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2580 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2581 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2582 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2583 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2585 _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`.
2586 _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`.
2588 def __init__(
2589 self,
2590 path: Path,
2591 documentation: Nullable[str] = None,
2592 vhdlVersion: VHDLVersion = VHDLVersion.VHDL2008,
2593 library: Nullable[Library] = None,
2594 parent: Nullable[ModelEntity] = None
2595 ) -> None:
2596 super().__init__(parent)
2597 DocumentedEntityMixin.__init__(self, documentation)
2599 self._path = path
2600 self._vhdlVersion = vhdlVersion
2601 self._library = library
2602 self._designUnits = []
2603 self._contexts = {}
2604 self._configurations = {}
2605 self._entities = {}
2606 self._architectures = {}
2607 self._packages = {}
2608 self._packageBodies = {}
2609 self._verificationUnits = {}
2610 self._verificationProperties = {}
2611 self._verificationModes = {}
2613 self._dependencyVertex = None
2614 self._compileOrderVertex = None
2616 def _AddEntity(self, item: Entity) -> None:
2617 """
2618 Add an entity to the document's lists of design units.
2620 :param item: Entity object to be added to the document.
2621 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
2622 :raises VHDLModelException: If entity name already exists in document.
2623 """
2624 if not isinstance(item, Entity): 2624 ↛ 2625line 2624 didn't jump to line 2625 because the condition on line 2624 was never true
2625 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2626 if version_info >= (3, 11): # pragma: no cover
2627 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2628 raise ex
2630 identifier = item._normalizedIdentifier
2631 if identifier in self._entities: 2631 ↛ 2633line 2631 didn't jump to line 2633 because the condition on line 2631 was never true
2632 # TODO: use a more specific exception
2633 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2635 self._entities[identifier] = item
2636 self._designUnits.append(item)
2637 item._document = self
2639 # TODO: add entity to _library and vice versa
2641 def _AddArchitecture(self, item: Architecture) -> None:
2642 """
2643 Add an architecture to the document's lists of design units.
2645 :param item: Architecture object to be added to the document.
2646 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
2647 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2648 """
2649 if not isinstance(item, Architecture): 2649 ↛ 2650line 2649 didn't jump to line 2650 because the condition on line 2649 was never true
2650 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2651 if version_info >= (3, 11): # pragma: no cover
2652 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2653 raise ex
2655 entity = item._entity.Name
2656 entityIdentifier = entity._normalizedIdentifier
2657 try:
2658 architectures = self._architectures[entityIdentifier]
2659 if item._normalizedIdentifier in architectures:
2660 # TODO: use a more specific exception
2661 # FIXME: this is allowed and should be a warning or a strict mode.
2662 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2664 architectures[item.Identifier] = item
2665 except KeyError:
2666 self._architectures[entityIdentifier] = {item._identifier: item}
2668 self._designUnits.append(item)
2669 item._document = self
2671 # TODO: add architecture to _library and vice versa
2673 def _AddPackage(self, item: Package) -> None:
2674 """
2675 Add a package to the document's lists of design units.
2677 :param item: Package object to be added to the document.
2678 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
2679 :raises VHDLModelException: If package name already exists in document.
2680 """
2681 if not isinstance(item, (Package, PackageInstantiation)): 2681 ↛ 2682line 2681 didn't jump to line 2682 because the condition on line 2681 was never true
2682 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2683 if version_info >= (3, 11): # pragma: no cover
2684 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2685 raise ex
2687 identifier = item._normalizedIdentifier
2688 if identifier in self._packages: 2688 ↛ 2690line 2688 didn't jump to line 2690 because the condition on line 2688 was never true
2689 # TODO: use a more specific exception
2690 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2692 self._packages[identifier] = item
2693 self._designUnits.append(item)
2694 item._document = self
2696 # TODO: add package to _library and vice versa
2698 def _AddPackageBody(self, item: PackageBody) -> None:
2699 """
2700 Add a package body to the document's lists of design units.
2702 :param item: Package body object to be added to the document.
2703 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
2704 :raises VHDLModelException: If package body name already exists in document.
2705 """
2706 if not isinstance(item, PackageBody): 2706 ↛ 2707line 2706 didn't jump to line 2707 because the condition on line 2706 was never true
2707 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2708 if version_info >= (3, 11): # pragma: no cover
2709 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2710 raise ex
2712 identifier = item._normalizedIdentifier
2713 if identifier in self._packageBodies: 2713 ↛ 2715line 2713 didn't jump to line 2715 because the condition on line 2713 was never true
2714 # TODO: use a more specific exception
2715 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2717 self._packageBodies[identifier] = item
2718 self._designUnits.append(item)
2719 item._document = self
2721 # TODO: add packagebody to _library and vice versa
2723 def _AddContext(self, item: Context) -> None:
2724 """
2725 Add a context to the document's lists of design units.
2727 :param item: Context object to be added to the document.
2728 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
2729 :raises VHDLModelException: If context name already exists in document.
2730 """
2731 if not isinstance(item, Context): 2731 ↛ 2732line 2731 didn't jump to line 2732 because the condition on line 2731 was never true
2732 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2733 if version_info >= (3, 11): # pragma: no cover
2734 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2735 raise ex
2737 identifier = item._normalizedIdentifier
2738 if identifier in self._contexts: 2738 ↛ 2740line 2738 didn't jump to line 2740 because the condition on line 2738 was never true
2739 # TODO: use a more specific exception
2740 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2742 self._contexts[identifier] = item
2743 self._designUnits.append(item)
2744 item._document = self
2746 # TODO: add context to _library and vice versa
2748 def _AddConfiguration(self, item: Configuration) -> None:
2749 """
2750 Add a configuration to the document's lists of design units.
2752 :param item: Configuration object to be added to the document.
2753 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
2754 :raises VHDLModelException: If configuration name already exists in document.
2755 """
2756 if not isinstance(item, Configuration): 2756 ↛ 2757line 2756 didn't jump to line 2757 because the condition on line 2756 was never true
2757 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2758 if version_info >= (3, 11): # pragma: no cover
2759 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2760 raise ex
2762 identifier = item._normalizedIdentifier
2763 if identifier in self._configurations: 2763 ↛ 2765line 2763 didn't jump to line 2765 because the condition on line 2763 was never true
2764 # TODO: use a more specific exception
2765 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2767 self._configurations[identifier] = item
2768 self._designUnits.append(item)
2769 item._document = self
2771 # TODO: add configuration to _library and vice versa
2773 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2774 if not isinstance(item, VerificationUnit):
2775 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2776 if version_info >= (3, 11): # pragma: no cover
2777 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2778 raise ex
2780 identifier = item._normalizedIdentifier
2781 if identifier in self._verificationUnits:
2782 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2784 self._verificationUnits[identifier] = item
2785 self._designUnits.append(item)
2786 item._document = self
2788 # TODO: add vunit to _library and vice versa
2790 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2791 if not isinstance(item, VerificationProperty):
2792 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2793 if version_info >= (3, 11): # pragma: no cover
2794 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2795 raise ex
2797 identifier = item.NormalizedIdentifier
2798 if identifier in self._verificationProperties:
2799 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2801 self._verificationProperties[identifier] = item
2802 self._designUnits.append(item)
2803 item._document = self
2805 # TODO: add vprop to _library and vice versa
2807 def _AddVerificationMode(self, item: VerificationMode) -> None:
2808 if not isinstance(item, VerificationMode):
2809 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2810 if version_info >= (3, 11): # pragma: no cover
2811 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2812 raise ex
2814 identifier = item.NormalizedIdentifier
2815 if identifier in self._verificationModes:
2816 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2818 self._verificationModes[identifier] = item
2819 self._designUnits.append(item)
2820 item._document = self
2822 # TODO: add vmode to _library and vice versa
2824 def _AddDesignUnit(self, item: DesignUnit) -> None:
2825 """
2826 Add a design unit to the document's lists of design units.
2828 :param item: Configuration object to be added to the document.
2829 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2830 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2831 :raises VHDLModelException: If configuration name already exists in document.
2832 """
2833 if not isinstance(item, DesignUnit): 2833 ↛ 2834line 2833 didn't jump to line 2834 because the condition on line 2833 was never true
2834 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2835 if version_info >= (3, 11): # pragma: no cover
2836 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2837 raise ex
2839 if isinstance(item, Entity):
2840 self._AddEntity(item)
2841 elif isinstance(item, Architecture):
2842 self._AddArchitecture(item)
2843 elif isinstance(item, Package):
2844 self._AddPackage(item)
2845 elif isinstance(item, PackageBody):
2846 self._AddPackageBody(item)
2847 elif isinstance(item, Context):
2848 self._AddContext(item)
2849 elif isinstance(item, Configuration): 2849 ↛ 2851line 2849 didn't jump to line 2851 because the condition on line 2849 was always true
2850 self._AddConfiguration(item)
2851 elif isinstance(item, VerificationUnit):
2852 self._AddVerificationUnit(item)
2853 elif isinstance(item, VerificationProperty):
2854 self._AddVerificationProperty(item)
2855 elif isinstance(item, VerificationMode):
2856 self._AddVerificationMode(item)
2857 else:
2858 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2859 if version_info >= (3, 11): # pragma: no cover
2860 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2861 raise ex
2863 @readonly
2864 def Path(self) -> Path:
2865 """
2866 Read-only property to access the document's path (:attr:`_path`).
2868 :returns: The path of this document.
2869 """
2870 return self._path
2872 @readonly
2873 def VHDLVersion(self) -> VHDLVersion:
2874 """
2875 Read-only property to access the document's VHDL version (:attr:`_vhdlVersion`).
2877 :returns: VHDL version used to analyze this VHDL file.
2878 """
2879 return self._vhdlVersion
2881 # @property
2882 @readonly
2883 def Library(self) -> Library:
2884 """
2885 Read-only property to access the document's VHDL library (:attr:`_library`).
2887 :returns: VHDL library used to analyze the VHDL file's design units into.
2888 """
2889 return self._library
2891 # @Library.setter
2892 # def Library(self, library: Library) -> None:
2893 # self._library = library
2894 #
2895 # # TODO: check and set library to design unit?
2897 @readonly
2898 def DesignUnits(self) -> List[DesignUnit]:
2899 """
2900 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2902 :returns: List of all design units.
2903 """
2904 return self._designUnits
2906 @readonly
2907 def Contexts(self) -> Dict[str, Context]:
2908 """
2909 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
2911 :returns: List of all contexts.
2912 """
2913 return self._contexts
2915 @readonly
2916 def Configurations(self) -> Dict[str, Configuration]:
2917 """
2918 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
2920 :returns: List of all configurations.
2921 """
2922 return self._configurations
2924 @readonly
2925 def Entities(self) -> Dict[str, Entity]:
2926 """
2927 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
2929 :returns: List of all entities.
2930 """
2931 return self._entities
2933 @readonly
2934 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2935 """
2936 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
2938 :returns: List of all architectures.
2939 """
2940 return self._architectures
2942 @readonly
2943 def Packages(self) -> Dict[str, Package]:
2944 """
2945 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
2947 :returns: List of all packages.
2948 """
2949 return self._packages
2951 @readonly
2952 def PackageBodies(self) -> Dict[str, PackageBody]:
2953 """
2954 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
2956 :returns: List of all package bodies.
2957 """
2958 return self._packageBodies
2960 @readonly
2961 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
2962 """
2963 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
2965 :returns: List of all verification units.
2966 """
2967 return self._verificationUnits
2969 @readonly
2970 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
2971 """
2972 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
2974 :returns: List of all verification properties.
2975 """
2976 return self._verificationProperties
2978 @readonly
2979 def VerificationModes(self) -> Dict[str, VerificationMode]:
2980 """
2981 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
2983 :returns: List of all verification modes.
2984 """
2985 return self._verificationModes
2987 @readonly
2988 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
2989 """
2990 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
2992 The compile-order vertex references this document by its value field.
2994 :returns: The corresponding compile-order vertex.
2995 """
2996 return self._compileOrderVertex
2998 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2999 """
3000 Iterate all design units in the document.
3002 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
3004 .. rubric:: Algorithm
3006 * If contexts are selected in the filter:
3008 1. Iterate all contexts in that library.
3010 * If packages are selected in the filter:
3012 1. Iterate all packages in that library.
3014 * If package bodies are selected in the filter:
3016 1. Iterate all package bodies in that library.
3018 * If entites are selected in the filter:
3020 1. Iterate all entites in that library.
3022 * If architectures are selected in the filter:
3024 1. Iterate all architectures in that library.
3026 * If configurations are selected in the filter:
3028 1. Iterate all configurations in that library.
3030 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
3031 :returns: A generator to iterate all matched design units in the document.
3033 .. seealso::
3035 :meth:`pyVHDLModel.Design.IterateDesignUnits`
3036 Iterate all design units in the design.
3037 :meth:`pyVHDLModel.Library.IterateDesignUnits`
3038 Iterate all design units in the library.
3039 """
3040 if DesignUnitKind.Context in filter: 3040 ↛ 3044line 3040 didn't jump to line 3044 because the condition on line 3040 was always true
3041 for context in self._contexts.values():
3042 yield context
3044 if DesignUnitKind.Package in filter: 3044 ↛ 3048line 3044 didn't jump to line 3048 because the condition on line 3044 was always true
3045 for package in self._packages.values():
3046 yield package
3048 if DesignUnitKind.PackageBody in filter: 3048 ↛ 3052line 3048 didn't jump to line 3052 because the condition on line 3048 was always true
3049 for packageBody in self._packageBodies.values():
3050 yield packageBody
3052 if DesignUnitKind.Entity in filter: 3052 ↛ 3056line 3052 didn't jump to line 3056 because the condition on line 3052 was always true
3053 for entity in self._entities.values():
3054 yield entity
3056 if DesignUnitKind.Architecture in filter: 3056 ↛ 3061line 3056 didn't jump to line 3061 because the condition on line 3056 was always true
3057 for architectures in self._architectures.values():
3058 for architecture in architectures.values():
3059 yield architecture
3061 if DesignUnitKind.Configuration in filter: 3061 ↛ exitline 3061 didn't return from function 'IterateDesignUnits' because the condition on line 3061 was always true
3062 for configuration in self._configurations.values():
3063 yield configuration
3065 # for verificationProperty in self._verificationUnits.values():
3066 # yield verificationProperty
3067 # for verificationUnit in self._verificationProperties.values():
3068 # yield entity
3069 # for verificationMode in self._verificationModes.values():
3070 # yield verificationMode
3072 def __repr__(self) -> str:
3073 """
3074 Formats a representation of the document.
3076 **Format:** ``Document: 'path/to/file.vhdl'``
3078 :returns: String representation of the document.
3079 """
3080 return f"Document: '{self._path}'"
3082 __str__ = __repr__