Coverage for pyVHDLModel/__init__.py: 76%
1110 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-07 22:12 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-07 22:12 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2025 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33**An abstract VHDL language model.**
35This package provides a unified abstract language model for VHDL. Projects reading from source files can derive own
36classes and implement additional logic to create a concrete language model for their tools.
38Projects consuming pre-processed VHDL data (parsed, analyzed or elaborated) can build higher level features and services
39on such a model, while supporting multiple frontends.
41.. admonition:: Copyright Information
43 :copyright: Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany
44 :copyright: Copyright 2016-2017 Patrick Lehmann - Dresden, Germany
45 :license: Apache License, Version 2.0
46"""
47__author__ = "Patrick Lehmann"
48__email__ = "Paebbels@gmail.com"
49__copyright__ = "2016-2025, Patrick Lehmann"
50__license__ = "Apache License, Version 2.0"
51__version__ = "0.31.0"
54from enum import unique, Enum, Flag, auto
55from pathlib import Path
56from sys import version_info
58from typing import Union, Dict, cast, List, Generator, Optional as Nullable
60from pyTooling.Common import getFullyQualifiedName
61from pyTooling.Decorators import export, readonly
62from pyTooling.Graph import Graph, Vertex, Edge
64from pyVHDLModel.Exception import VHDLModelException
65from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
66from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
67from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
68from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
69from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
70from pyVHDLModel.Namespace import Namespace
71from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
72from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
73from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
74from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package
75from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
76from pyVHDLModel.Instantiation import PackageInstantiation
77from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
80@export
81@unique
82class VHDLVersion(Enum):
83 """
84 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
86 A version can be given as integer or string and is represented as a unified
87 enumeration value.
89 This enumeration supports compare operators.
90 """
92 Any = -1 #: Any
93 VHDL87 = 87 #: VHDL-1987
94 VHDL93 = 93 #: VHDL-1993
95 AMS93 = 1993 #: VHDL-AMS-1993
96 AMS99 = 1999 #: VHDL-AMS-1999
97 VHDL2000 = 2000 #: VHDL-2000
98 VHDL2002 = 2002 #: VHDL-2002
99 VHDL2008 = 2008 #: VHDL-2008
100 AMS2017 = 2017 #: VHDL-AMS-2017
101 VHDL2019 = 2019 #: VHDL-2019
102 Latest = 10000 #: Latest VHDL (2019)
104 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
105 -1: Any,
106 87: VHDL87,
107 93: VHDL93,
108 # 93: AMS93,
109 99: AMS99,
110 0: VHDL2000,
111 2: VHDL2002,
112 8: VHDL2008,
113 17: AMS2017,
114 19: VHDL2019,
115 1987: VHDL87,
116 # 1993: VHDL93,
117 1993: AMS93,
118 1999: AMS99,
119 2000: VHDL2000,
120 2002: VHDL2002,
121 2008: VHDL2008,
122 2017: AMS2017,
123 2019: VHDL2019,
124 10000: Latest,
125 "Any": Any,
126 "87": VHDL87,
127 "93": VHDL93,
128 # "93": AMS93,
129 "99": AMS99,
130 "00": VHDL2000,
131 "02": VHDL2002,
132 "08": VHDL2008,
133 "17": AMS2017,
134 "19": VHDL2019,
135 "1987": VHDL87,
136 # "1993": VHDL93,
137 "1993": AMS93,
138 "1999": AMS99,
139 "2000": VHDL2000,
140 "2002": VHDL2002,
141 "2008": VHDL2008,
142 "2017": AMS2017,
143 "2019": VHDL2019,
144 "Latest": Latest,
145 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
147 def __init__(self, *_) -> None:
148 """Patch the embedded MAP dictionary"""
149 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
150 if (not isinstance(v, self.__class__)) and (v == self.value):
151 self.__class__.__VERSION_MAPPINGS__[k] = self
153 @classmethod
154 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
155 """
156 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
158 :param value: VHDL/VHDL-AMS year code.
159 :returns: Enumeration value.
160 :raises ValueError: If the year code is not recognized.
161 """
162 try:
163 return cls.__VERSION_MAPPINGS__[value]
164 except KeyError:
165 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
167 def __lt__(self, other: Any) -> bool:
168 """
169 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
171 :param other: Parameter to compare against.
172 :returns: True if version is less than the second operand.
173 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
174 """
175 if isinstance(other, VHDLVersion):
176 return self.value < other.value
177 else:
178 raise TypeError("Second operand is not of type 'VHDLVersion'.")
180 def __le__(self, other: Any) -> bool:
181 """
182 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
184 :param other: Parameter to compare against.
185 :returns: True if version is less or equal than the second operand.
186 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
187 """
188 if isinstance(other, VHDLVersion):
189 return self.value <= other.value
190 else:
191 raise TypeError("Second operand is not of type 'VHDLVersion'.")
193 def __gt__(self, other: Any) -> bool:
194 """
195 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
197 :param other: Parameter to compare against.
198 :returns: True if version is greater than the second operand.
199 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
200 """
201 if isinstance(other, VHDLVersion):
202 return self.value > other.value
203 else:
204 raise TypeError("Second operand is not of type 'VHDLVersion'.")
206 def __ge__(self, other: Any) -> bool:
207 """
208 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
210 :param other: Parameter to compare against.
211 :returns: True if version is greater or equal than the second operand.
212 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
213 """
214 if isinstance(other, VHDLVersion):
215 return self.value >= other.value
216 else:
217 raise TypeError("Second operand is not of type 'VHDLVersion'.")
219 def __ne__(self, other: Any) -> bool:
220 """
221 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
223 :param other: Parameter to compare against.
224 :returns: True if version is unequal to the second operand.
225 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
226 """
227 if isinstance(other, VHDLVersion):
228 return self.value != other.value
229 else:
230 raise TypeError("Second operand is not of type 'VHDLVersion'.")
232 def __eq__(self, other: Any) -> bool:
233 """
234 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
236 :param other: Parameter to compare against.
237 :returns: True if version is equal to the second operand.
238 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
239 """
240 if isinstance(other, VHDLVersion):
241 if (self is self.__class__.Any) or (other is self.__class__.Any):
242 return True
243 else:
244 return self.value == other.value
245 else:
246 raise TypeError("Second operand is not of type 'VHDLVersion'.")
248 @readonly
249 def IsVHDL(self) -> bool:
250 """
251 Checks if the version is a VHDL (not VHDL-AMS) version.
253 :returns: True if version is a VHDL version.
254 """
255 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
257 @readonly
258 def IsAMS(self) -> bool:
259 """
260 Checks if the version is a VHDL-AMS (not VHDL) version.
262 :returns: True if version is a VHDL-AMS version.
263 """
264 return self in (self.AMS93, self.AMS99, self.AMS2017)
266 def __str__(self) -> str:
267 """
268 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
270 :return: Formatted VHDL/VHDL-AMS version.
271 """
272 if self.value == self.Any.value:
273 return "VHDL'Any"
274 elif self.value == self.Latest.value:
275 return "VHDL'Latest"
277 year = str(self.value)[-2:]
278 if self.IsVHDL:
279 return f"VHDL'{year}"
280 else:
281 return f"VHDL-AMS'{year}"
283 def __repr__(self) -> str:
284 """
285 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
287 :return: Formatted VHDL/VHDL-AMS version.
288 """
289 if self.value == self.Any.value:
290 return "Any"
291 elif self.value == self.Latest.value:
292 return "Latest"
293 else:
294 return str(self.value)
297@export
298class IEEEFlavor(Enum):
299 IEEE = 0
300 Synopsys = 1
301 MentorGraphics = 2
304@export
305@unique
306class ObjectClass(Enum):
307 """
308 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
310 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
311 """
313 Default = 0 #: Object class not defined, thus it's context dependent.
314 Constant = 1 #: Constant
315 Variable = 2 #: Variable
316 Signal = 3 #: Signal
317 File = 4 #: File
318 Type = 5 #: Type
319 # FIXME: Package?
320 Procedure = 6 #: Procedure
321 Function = 7 #: Function
323 def __str__(self) -> str:
324 """
325 Formats the object class.
327 :return: Formatted object class.
328 """
329 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
332@export
333@unique
334class DesignUnitKind(Flag):
335 """
336 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
338 """
339 Context = auto() #: Context
340 Package = auto() #: Package
341 PackageBody = auto() #: Package Body
342 Entity = auto() #: Entity
343 Architecture = auto() #: Architecture
344 Configuration = auto() #: Configuration
346 Primary = Context | Configuration | Entity | Package #: List of primary design units.
347 Secondary = PackageBody | Architecture #: List of secondary design units.
348 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
349 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
351 All = Primary | Secondary #: List of all design units.
354@export
355@unique
356class DependencyGraphVertexKind(Flag):
357 """
358 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
359 """
360 Document = auto() #: A document (VHDL source file).
361 Library = auto() #: A VHDL library.
363 Context = auto() #: A context design unit.
364 Package = auto() #: A package design unit.
365 PackageBody = auto() #: A package body design unit.
366 Entity = auto() #: A entity design unit.
367 Architecture = auto() #: A architecture design unit.
368 Component = auto() #: A VHDL component.
369 Configuration = auto() #: A configuration design unit.
372@export
373@unique
374class DependencyGraphEdgeKind(Flag):
375 """
376 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
377 """
378 Document = auto()
379 Library = auto()
380 Context = auto()
381 Package = auto()
382 Entity = auto()
383 # Architecture = auto()
384 Configuration = auto()
385 Component = auto()
387 DeclaredIn = auto()
388 Order = auto()
389 Reference = auto()
390 Implementation = auto()
391 Instantiation = auto()
393 SourceFile = Document | DeclaredIn
394 CompileOrder = Document | Order
396 LibraryClause = Library | Reference
397 UseClause = Package | Reference
398 ContextReference = Context | Reference
400 EntityImplementation = Entity | Implementation
401 PackageImplementation = Package | Implementation
403 EntityInstantiation = Entity | Instantiation
404 ComponentInstantiation = Component | Instantiation
405 ConfigurationInstantiation = Configuration | Instantiation
408@export
409@unique
410class ObjectGraphVertexKind(Flag):
411 """
412 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
413 """
414 Type = auto()
415 Subtype = auto()
417 Constant = auto()
418 DeferredConstant = auto()
419 Variable = auto()
420 Signal = auto()
421 File = auto()
423 Alias = auto()
426@export
427@unique
428class ObjectGraphEdgeKind(Flag):
429 """
430 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
431 """
432 BaseType = auto()
433 Subtype = auto()
435 ReferenceInExpression = auto()
438@export
439class Design(ModelEntity):
440 """
441 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
443 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
444 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
445 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`).
447 The *design* contains references to the following graphs:
449 * :attr:`DependencyGraph`
450 * :attr:`CompileOrderGraph`
451 * :attr:`HierarchyGraph`
452 * :attr:`ObjectGraph`
453 """
454 _name: Nullable[str] #: Name of the design.
455 _allowBlackbox: bool #: Allow blackboxes after linking the design.
456 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
457 _documents: List['Document'] #: List of all documents loaded for a design.
458 _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.
459 _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.
460 _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.
461 _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.
462 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
464 def __init__(
465 self,
466 name: Nullable[str] = None,
467 allowBlackbox: bool = False
468 ) -> None:
469 """
470 Initialize a VHDL design.
472 :param allowBlackbox: Specify if blackboxes are allowed in this design.
473 :param name: Name of the design.
474 """
475 super().__init__()
477 self._name = name
478 self._allowBlackbox = allowBlackbox
480 self._libraries = {}
481 self._documents = []
483 self._compileOrderGraph = Graph()
484 self._dependencyGraph = Graph()
485 self._hierarchyGraph = Graph()
486 self._objectGraph = Graph()
487 self._toplevel = None
489 @readonly
490 def Name(self) -> Nullable[str]:
491 """
492 Read-only property to access the design's name (:attr:`_name`).
494 :returns: The name of the design.
495 """
496 return self._name
498 @property
499 def AllowBlackbox(self) -> bool:
500 """
501 Read-only property to check if a design supports blackboxes (:attr:`_allowBlackbox`).
503 :returns: If blackboxes are allowed.
504 """
505 return self._allowBlackbox
507 @AllowBlackbox.setter
508 def AllowBlackbox(self, value: Nullable[bool]) -> None:
509 if value is None:
510 raise ValueError(f"Property 'AllowBlackbox' doesn't accept value 'None'.")
512 self._allowBlackbox = value
514 @readonly
515 def Libraries(self) -> Dict[str, 'Library']:
516 """
517 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
519 :returns: A dictionary of library names and VHDL libraries.
520 """
521 return self._libraries
523 @readonly
524 def Documents(self) -> List['Document']:
525 """
526 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
528 :returns: A list of all documents.
529 """
530 return self._documents
532 @readonly
533 def CompileOrderGraph(self) -> Graph:
534 """
535 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
537 :returns: Reference to the compile-order graph.
538 """
539 return self._compileOrderGraph
541 @readonly
542 def DependencyGraph(self) -> Graph:
543 """
544 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
546 :returns: Reference to the dependency graph.
547 """
548 return self._dependencyGraph
550 @readonly
551 def HierarchyGraph(self) -> Graph:
552 """
553 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
555 :returns: Reference to the hierarchy graph.
556 """
557 return self._hierarchyGraph
559 @readonly
560 def ObjectGraph(self) -> Graph:
561 """
562 Read-only property to access the object graph (:attr:`_objectGraph`).
564 :returns: Reference to the object graph.
565 """
566 return self._objectGraph
568 @readonly
569 def TopLevel(self) -> Union[Entity, Configuration]:
570 """
571 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
573 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``
574 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
576 :returns: Reference to the design's *top-level*.
577 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
578 :raises VHDLModelException: If there is more than one *top-level*.
579 """
580 # Check for cached result
581 if self._toplevel is not None:
582 return self._toplevel
584 if self._hierarchyGraph.EdgeCount == 0:
585 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
587 roots = tuple(self._hierarchyGraph.IterateRoots())
588 if len(roots) == 1:
589 toplevel = roots[0]
590 self._hierarchyGraph["toplevel"] = toplevel
591 self._toplevel = toplevel.Value
593 return toplevel.Value
594 else:
595 raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}")
597 def LoadStdLibrary(self) -> 'Library':
598 """
599 Load the predefined VHDL library ``std`` into the design.
601 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
603 :returns: The library object of library ``std``.
604 """
605 from pyVHDLModel.STD import Std
607 doc = Document(Path("std.vhdl"), parent=self)
609 library = Std()
610 for designUnit in library.IterateDesignUnits():
611 doc._AddDesignUnit(designUnit)
613 self.AddLibrary(library)
615 return library
617 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library':
618 """
619 Load the predefined VHDL library ``ieee`` into the design.
621 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
623 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics.
624 :returns: The library object of library ``ieee``.
625 """
626 from pyVHDLModel.IEEE import Ieee
628 doc = Document(Path("ieee.vhdl"), parent=self)
630 library = Ieee(flavor)
631 for designUnit in library.IterateDesignUnits():
632 doc._AddDesignUnit(designUnit)
634 self.AddLibrary(library)
636 return library
638 def AddLibrary(self, library: 'Library') -> None:
639 """
640 Add a VHDL library to the design.
642 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
643 If ok, set the libraries parent reference to the design.
645 :param library: Library object to loaded.
646 :raises LibraryExistsInDesignError: If the library already exists in the design.
647 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
648 """
649 libraryIdentifier = library.NormalizedIdentifier
650 if libraryIdentifier in self._libraries:
651 raise LibraryExistsInDesignError(library)
653 if library._parent is not None:
654 raise LibraryRegisteredToForeignDesignError(library)
656 self._libraries[libraryIdentifier] = library
657 library._parent = self
659 def GetLibrary(self, libraryName: str) -> 'Library':
660 """
661 Return an (existing) VHDL library object of name ``libraryName``.
663 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
665 :param libraryName: Name of the requested VHDL library.
666 :returns: The VHDL library object.
667 """
668 libraryIdentifier = libraryName.lower()
669 try:
670 return self._libraries[libraryIdentifier]
671 except KeyError:
672 lib = Library(libraryName, parent=self)
673 self._libraries[libraryIdentifier] = lib
674 lib._parent = self
675 return lib
677 # TODO: allow overloaded parameter library to be str?
678 def AddDocument(self, document: 'Document', library: 'Library') -> None:
679 """
680 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
682 .. rubric:: Algorithm
684 1. Iterate all entities in the document
686 1. Check if entity name might exist in target library.
687 2. Add entity to library and update library membership.
689 2. Iterate all architectures in the document
691 1. Check if architecture name might exist in target library.
692 2. Add architecture to library and update library membership.
694 3. Iterate all packages in the document
696 1. Check if package name might exist in target library.
697 2. Add package to library and update library membership.
699 4. Iterate all package bodies in the document
701 1. Check if package body name might exist in target library.
702 2. Add package body to library and update library membership.
704 5. Iterate all configurations in the document
706 1. Check if configuration name might exist in target library.
707 2. Add configuration to library and update library membership.
709 6. Iterate all contexts in the document
711 1. Check if context name might exist in target library.
712 2. Add context to library and update library membership.
714 :param document: The VHDL source code file.
715 :param library: The VHDL library used to register the embedded design units to.
716 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
717 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
718 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
719 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
720 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
721 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
722 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
723 """
724 # FIXME: this checks for the library name, but not the object
725 # should the libraries parent be checked too?
726 if library._normalizedIdentifier not in self._libraries: 726 ↛ 727line 726 didn't jump to line 727 because the condition on line 726 was never true
727 raise LibraryNotRegisteredError(library)
729 self._documents.append(document)
730 document._parent = self
732 for entityIdentifier, entity in document._entities.items():
733 if entityIdentifier in library._entities: 733 ↛ 734line 733 didn't jump to line 734 because the condition on line 733 was never true
734 raise EntityExistsInLibraryError(entity, library)
736 library._entities[entityIdentifier] = entity
737 entity.Library = library
739 for entityIdentifier, architectures in document._architectures.items():
740 try:
741 architecturesPerEntity = library._architectures[entityIdentifier]
742 for architectureIdentifier, architecture in architectures.items():
743 if architectureIdentifier in architecturesPerEntity:
744 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
746 architecturesPerEntity[architectureIdentifier] = architecture
747 architecture.Library = library
748 except KeyError:
749 architecturesPerEntity = document._architectures[entityIdentifier].copy()
750 library._architectures[entityIdentifier] = architecturesPerEntity
752 for architecture in architecturesPerEntity.values():
753 architecture.Library = library
755 for packageIdentifier, package in document._packages.items():
756 if packageIdentifier in library._packages: 756 ↛ 757line 756 didn't jump to line 757 because the condition on line 756 was never true
757 raise PackageExistsInLibraryError(package, library)
759 library._packages[packageIdentifier] = package
760 package.Library = library
762 for packageBodyIdentifier, packageBody in document._packageBodies.items():
763 if packageBodyIdentifier in library._packageBodies: 763 ↛ 764line 763 didn't jump to line 764 because the condition on line 763 was never true
764 raise PackageBodyExistsError(packageBody, library)
766 library._packageBodies[packageBodyIdentifier] = packageBody
767 packageBody.Library = library
769 for configurationIdentifier, configuration in document._configurations.items():
770 if configurationIdentifier in library._configurations: 770 ↛ 771line 770 didn't jump to line 771 because the condition on line 770 was never true
771 raise ConfigurationExistsInLibraryError(configuration, library)
773 library._configurations[configurationIdentifier] = configuration
774 configuration.Library = library
776 for contextIdentifier, context in document._contexts.items():
777 if contextIdentifier in library._contexts: 777 ↛ 778line 777 didn't jump to line 778 because the condition on line 777 was never true
778 raise ContextExistsInLibraryError(context, library)
780 library._contexts[contextIdentifier] = context
781 context.Library = library
783 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
784 """
785 Iterate all design units in the design.
787 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
789 .. rubric:: Algorithm
791 1. Iterate all VHDL libraries.
793 1. Iterate all contexts in that library.
794 2. Iterate all packages in that library.
795 3. Iterate all package bodies in that library.
796 4. Iterate all entites in that library.
797 5. Iterate all architectures in that library.
798 6. Iterate all configurations in that library.
800 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
801 :returns: A generator to iterate all matched design units in the design.
803 .. seealso::
805 :meth:`pyVHDLModel.Library.IterateDesignUnits`
806 Iterate all design units in the library.
807 :meth:`pyVHDLModel.Document.IterateDesignUnits`
808 Iterate all design units in the document.
809 """
810 for library in self._libraries.values():
811 yield from library.IterateDesignUnits(filter)
813 def Analyze(self) -> None:
814 """
815 Analyze the whole design.
817 .. rubric:: Algorithm
819 1. Analyze dependencies of design units. |br|
820 This will also yield the design hierarchy and the compiler order.
821 2. Analyze dependencies of types and objects.
823 .. seealso::
825 :meth:`AnalyzeDependencies`
826 Analyze the dependencies of design units.
828 :meth:`AnalyzeObjects`
829 Analyze the dependencies of types and objects.
830 """
831 self.AnalyzeDependencies()
832 self.AnalyzeObjects()
834 def AnalyzeDependencies(self) -> None:
835 """
836 Analyze the dependencies of design units.
838 .. rubric:: Algorithm
840 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
841 |rarr| :meth:`CreateDependencyGraph`
842 2. Create the compile order graph. |br|
843 |rarr| :meth:`CreateCompileOrderGraph`
844 3. Index all packages. |br|
845 |rarr| :meth:`IndexPackages`
846 4. Index all architectures. |br|
847 |rarr| :meth:`IndexArchitectures`
848 5. Link all contexts |br|
849 |rarr| :meth:`LinkContexts`
850 6. Link all architectures. |br|
851 |rarr| :meth:`LinkArchitectures`
852 7. Link all package bodies. |br|
853 |rarr| :meth:`LinkPackageBodies`
854 8. Link all library references. |br|
855 |rarr| :meth:`LinkLibraryReferences`
856 9. Link all package references. |br|
857 |rarr| :meth:`LinkPackageReferences`
858 10. Link all context references. |br|
859 |rarr| :meth:`LinkContextReferences`
860 11. Link all components. |br|
861 |rarr| :meth:`LinkComponents`
862 12. Link all instantiations. |br|
863 |rarr| :meth:`LinkInstantiations`
864 13. Create the hierarchy graph. |br|
865 |rarr| :meth:`CreateHierarchyGraph`
866 14. Compute the compile order. |br|
867 |rarr| :meth:`ComputeCompileOrder`
868 """
869 self.CreateDependencyGraph()
870 self.CreateCompileOrderGraph()
872 self.IndexPackages()
873 self.IndexArchitectures()
875 self.LinkContexts()
876 self.LinkArchitectures()
877 self.LinkPackageBodies()
878 self.LinkLibraryReferences()
879 self.LinkPackageReferences()
880 self.LinkContextReferences()
882 self.LinkComponents()
883 self.LinkInstantiations()
884 self.CreateHierarchyGraph()
885 self.ComputeCompileOrder()
887 def AnalyzeObjects(self) -> None:
888 """
889 Analyze the dependencies of types and objects.
891 .. rubric:: Algorithm
893 1. Index all entities. |br|
894 |rarr| :meth:`IndexEntities`
895 2. Index all package bodies. |br|
896 |rarr| :meth:`IndexPackageBodies`
897 3. Import objects. |br|
898 |rarr| :meth:`ImportObjects`
899 4. Create the type and object graph. |br|
900 |rarr| :meth:`CreateTypeAndObjectGraph`
901 """
902 self.IndexEntities()
903 self.IndexPackageBodies()
905 self.ImportObjects()
906 self.CreateTypeAndObjectGraph()
908 def CreateDependencyGraph(self) -> None:
909 """
910 Create all vertices of the dependency graph by iterating all design units in all libraries.
912 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
913 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
915 Each vertex has the following properties:
917 * The vertex' ID is the design unit's identifier.
918 * The vertex' value references the design unit.
919 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
920 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
922 .. rubric:: Algorithm
924 1. Iterate all libraries in the design.
926 * Create a vertex for that library and reference the library by the vertex' value field. |br|
927 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
929 1. Iterate all contexts in that library.
931 * Create a vertex for that context and reference the context by the vertex' value field. |br|
932 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
934 2. Iterate all packages in that library.
936 * Create a vertex for that package and reference the package by the vertex' value field. |br|
937 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
939 3. Iterate all package bodies in that library.
941 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
942 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
944 4. Iterate all entities in that library.
946 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
947 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
949 5. Iterate all architectures in that library.
951 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
952 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
954 6. Iterate all configurations in that library.
956 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
957 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
958 """
959 predefinedLibraries = ("std", "ieee")
961 for libraryIdentifier, library in self._libraries.items():
962 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
963 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
964 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
965 library._dependencyVertex = dependencyVertex
967 for contextIdentifier, context in library._contexts.items():
968 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
969 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
970 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
971 context._dependencyVertex = dependencyVertex
973 for packageIdentifier, package in library._packages.items():
974 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
975 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
976 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
977 package._dependencyVertex = dependencyVertex
979 for packageBodyIdentifier, packageBody in library._packageBodies.items():
980 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
981 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
982 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
983 packageBody._dependencyVertex = dependencyVertex
985 for entityIdentifier, entity in library._entities.items():
986 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
987 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
988 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
989 entity._dependencyVertex = dependencyVertex
991 for entityIdentifier, architectures in library._architectures.items():
992 for architectureIdentifier, architecture in architectures.items():
993 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
994 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
995 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
996 architecture._dependencyVertex = dependencyVertex
998 for configurationIdentifier, configuration in library._configurations.items():
999 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
1000 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
1001 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
1002 configuration._dependencyVertex = dependencyVertex
1004 def CreateCompileOrderGraph(self) -> None:
1005 """
1006 Create a compile-order graph with bidirectional references to the dependency graph.
1008 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
1009 graph and bidirectionally referenced.
1011 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
1012 document relationship.
1014 Each added vertex has the following properties:
1016 * The vertex' ID is the document's filename.
1017 * The vertex' value references the document.
1018 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
1019 * A key-value-pair called ``predefined`` does not exist.
1021 .. rubric:: Algorithm
1023 1. Iterate all documents in the design.
1025 * Create a vertex for that document and reference the document by the vertex' value field. |br|
1026 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
1027 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
1028 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
1030 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
1031 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
1033 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
1034 dependency vertex. This expresses a "design unit is located in document" relation.
1036 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
1037 """
1038 for document in self._documents:
1039 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
1040 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1041 document._dependencyVertex = dependencyVertex
1043 compilerOrderVertex = dependencyVertex.Copy(
1044 self._compileOrderGraph,
1045 copyDict=True,
1046 linkingKeyToOriginalVertex="dependencyVertex",
1047 linkingKeyFromOriginalVertex="compileOrderVertex"
1048 )
1049 document._compileOrderVertex = compilerOrderVertex
1051 for designUnit in document._designUnits:
1052 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1053 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1055 def ImportObjects(self) -> None:
1056 def _ImportObjects(package: Package) -> None:
1057 for referencedLibrary in package._referencedPackages.values():
1058 for referencedPackage in referencedLibrary.values():
1059 for declaredItem in referencedPackage._declaredItems:
1060 if isinstance(declaredItem, MultipleNamedEntityMixin): 1060 ↛ 1061line 1060 didn't jump to line 1061 because the condition on line 1060 was never true
1061 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1062 package._namespace._elements[normalizedIdentifier] = declaredItem
1063 elif isinstance(declaredItem, NamedEntityMixin): 1063 ↛ 1066line 1063 didn't jump to line 1066 because the condition on line 1063 was always true
1064 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1065 else:
1066 raise VHDLModelException(f"Unexpected declared item.")
1068 for libraryName in ("std", "ieee"):
1069 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1070 _ImportObjects(package)
1072 for document in self.IterateDocumentsInCompileOrder():
1073 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1074 _ImportObjects(package)
1076 def CreateTypeAndObjectGraph(self) -> None:
1077 def _HandlePackage(package) -> None:
1078 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1080 for deferredConstant in package._deferredConstants.values(): 1080 ↛ 1081line 1080 didn't jump to line 1081 because the loop on line 1080 never started
1081 print(f"Deferred Constant: {deferredConstant}")
1082 deferredConstantVertex = Vertex(
1083 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1084 value=deferredConstant,
1085 graph=self._objectGraph
1086 )
1087 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1088 deferredConstant._objectVertex = deferredConstantVertex
1090 for constant in package._constants.values(): 1090 ↛ 1091line 1090 didn't jump to line 1091 because the loop on line 1090 never started
1091 print(f"Constant: {constant}")
1092 constantVertex = Vertex(
1093 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1094 value=constant,
1095 graph=self._objectGraph
1096 )
1097 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1098 constant._objectVertex = constantVertex
1100 for type in package._types.values():
1101 print(f"Type: {type}")
1102 typeVertex = Vertex(
1103 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1104 value=type,
1105 graph=self._objectGraph
1106 )
1107 typeVertex["kind"] = ObjectGraphVertexKind.Type
1108 type._objectVertex = typeVertex
1110 for subtype in package._subtypes.values():
1111 print(f"Subtype: {subtype}")
1112 subtypeVertex = Vertex(
1113 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1114 value=subtype,
1115 graph=self._objectGraph
1116 )
1117 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1118 subtype._objectVertex = subtypeVertex
1120 for function in package._functions.values(): 1120 ↛ 1121line 1120 didn't jump to line 1121 because the loop on line 1120 never started
1121 print(f"Function: {function}")
1122 functionVertex = Vertex(
1123 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1124 value=function,
1125 graph=self._objectGraph
1126 )
1127 functionVertex["kind"] = ObjectGraphVertexKind.Function
1128 function._objectVertex = functionVertex
1130 for procedure in package._procedures.values(): 1130 ↛ 1131line 1130 didn't jump to line 1131 because the loop on line 1130 never started
1131 print(f"Procedure: {procedure}")
1132 procedureVertex = Vertex(
1133 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1134 value=procedure,
1135 graph=self._objectGraph
1136 )
1137 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1138 procedure._objectVertex = procedureVertex
1140 for signal in package._signals.values(): 1140 ↛ 1141line 1140 didn't jump to line 1141 because the loop on line 1140 never started
1141 print(f"Signal: {signal}")
1142 signalVertex = Vertex(
1143 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1144 value=signal,
1145 graph=self._objectGraph
1146 )
1147 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1148 signal._objectVertex = signalVertex
1150 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
1151 if isinstance(expression, UnaryExpression): 1151 ↛ 1152line 1151 didn't jump to line 1152 because the condition on line 1151 was never true
1152 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1153 elif isinstance(expression, BinaryExpression): 1153 ↛ 1154line 1153 didn't jump to line 1154 because the condition on line 1153 was never true
1154 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1155 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1156 elif isinstance(expression, TernaryExpression): 1156 ↛ 1157line 1156 didn't jump to line 1157 because the condition on line 1156 was never true
1157 pass
1158 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 1158 ↛ 1159line 1158 didn't jump to line 1159 because the condition on line 1158 was never true
1159 obj = namespace.FindObject(expression)
1160 expression._reference = obj
1162 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1163 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1164 else:
1165 pass
1167 def _LinkItems(package: Package):
1168 for item in package._declaredItems:
1169 if isinstance(item, Constant): 1169 ↛ 1170line 1169 didn't jump to line 1170 because the condition on line 1169 was never true
1170 print(f"constant: {item}")
1171 elif isinstance(item, DeferredConstant): 1171 ↛ 1172line 1171 didn't jump to line 1172 because the condition on line 1171 was never true
1172 print(f"deferred constant: {item}")
1173 elif isinstance(item, Signal): 1173 ↛ 1174line 1173 didn't jump to line 1174 because the condition on line 1173 was never true
1174 print(f"signal: {item}")
1175 elif isinstance(item, IntegerType):
1176 typeNode = item._objectVertex
1178 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1179 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1180 # elif isinstance(item, FloatingType):
1181 # print(f"signal: {item}")
1182 elif isinstance(item, PhysicalType):
1183 typeNode = item._objectVertex
1185 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1186 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1187 elif isinstance(item, ArrayType):
1188 # Resolve dimensions
1189 for dimension in item._dimensions:
1190 subtype = package._namespace.FindSubtype(dimension)
1191 dimension._reference = subtype
1193 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1194 edge["kind"] = ObjectGraphEdgeKind.Subtype
1196 # Resolve element subtype
1197 subtype = package._namespace.FindSubtype(item._elementType)
1198 item._elementType._reference = subtype
1200 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1201 edge["kind"] = ObjectGraphEdgeKind.Subtype
1202 elif isinstance(item, RecordType): 1202 ↛ 1204line 1202 didn't jump to line 1204 because the condition on line 1202 was never true
1203 # Resolve each elements subtype
1204 for element in item._elements:
1205 subtype = package._namespace.FindSubtype(element._subtype)
1206 element._subtype._reference = subtype
1208 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1209 edge["kind"] = ObjectGraphEdgeKind.Subtype
1210 else:
1211 print(f"not handled: {item}")
1213 for libraryName in ("std", "ieee"):
1214 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1215 _HandlePackage(package)
1216 _LinkItems(package)
1218 for document in self.IterateDocumentsInCompileOrder():
1219 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1220 _HandlePackage(package)
1221 _LinkItems(package)
1223 def LinkContexts(self) -> None:
1224 """
1225 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1227 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1228 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1229 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1231 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1232 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1233 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1234 dependency graph is added for that relationship.
1236 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1237 referenced package,
1238 """
1239 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1240 # Create entries in _referenced*** for the current working library under its real name.
1241 workingLibrary: Library = context.Library
1242 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1244 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1245 context._referencedPackages[libraryNormalizedIdentifier] = {}
1246 context._referencedContexts[libraryNormalizedIdentifier] = {}
1248 # Process all library clauses
1249 for libraryReference in context._libraryReferences:
1250 # A library clause can have multiple comma-separated references
1251 for libraryName in libraryReference.Symbols:
1252 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1253 try:
1254 library = self._libraries[libraryNormalizedIdentifier]
1255 except KeyError:
1256 raise ReferencedLibraryNotExistingError(context, libraryName)
1257 # TODO: add position to these messages
1259 libraryName.Library = library
1261 context._referencedLibraries[libraryNormalizedIdentifier] = library
1262 context._referencedPackages[libraryNormalizedIdentifier] = {}
1263 context._referencedContexts[libraryNormalizedIdentifier] = {}
1264 # TODO: warn duplicate library reference
1266 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1267 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1269 # Process all use clauses
1270 for packageReference in context.PackageReferences:
1271 # A use clause can have multiple comma-separated references
1272 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1273 packageName = symbol.Name.Prefix
1274 libraryName = packageName.Prefix
1276 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1277 packageNormalizedIdentifier = packageName._normalizedIdentifier
1279 # In case work is used, resolve to the real library name.
1280 if libraryNormalizedIdentifier == "work": 1280 ↛ 1281line 1280 didn't jump to line 1281 because the condition on line 1280 was never true
1281 library: Library = context._parent
1282 libraryNormalizedIdentifier = library._normalizedIdentifier
1283 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1283 ↛ 1285line 1283 didn't jump to line 1285 because the condition on line 1283 was never true
1284 # TODO: This check doesn't trigger if it's the working library.
1285 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1286 else:
1287 library = self._libraries[libraryNormalizedIdentifier]
1289 try:
1290 package = library._packages[packageNormalizedIdentifier]
1291 except KeyError:
1292 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1294 symbol.Package = package
1296 # TODO: warn duplicate package reference
1297 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1299 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1300 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1302 # TODO: update the namespace with visible members
1303 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1303 ↛ 1306line 1303 didn't jump to line 1306 because the condition on line 1303 was always true
1304 pass
1306 elif isinstance(symbol, PackageMemberReferenceSymbol):
1307 raise NotImplementedError()
1308 else:
1309 raise VHDLModelException()
1311 def LinkArchitectures(self) -> None:
1312 """
1313 Link all architectures to corresponding entities in all libraries.
1315 .. rubric:: Algorithm
1317 1. Iterate all libraries:
1319 1. Iterate all architecture groups (grouped per entity symbol's name).
1320 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1322 * Check if entity symbol's name exists as an entity in this library.
1324 1. For each architecture in the same architecture group:
1326 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1327 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1328 * Set parent namespace of architecture's namespace to the entitie's namespace.
1329 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1331 .. seealso::
1333 :meth:`LinkPackageBodies`
1334 Link all package bodies to corresponding packages in all libraries.
1335 """
1336 for library in self._libraries.values():
1337 library.LinkArchitectures()
1339 def LinkPackageBodies(self) -> None:
1340 """
1341 Link all package bodies to corresponding packages in all libraries.
1343 .. rubric:: Algorithm
1345 1. Iterate all libraries:
1347 1. Iterate all package bodies.
1348 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1350 * Check if package body symbol's name exists as a package in this library.
1351 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1352 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1353 * Set parent namespace of package body's namespace to the package's namespace.
1354 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1356 .. seealso::
1358 :meth:`LinkArchitectures`
1359 Link all architectures to corresponding entities in all libraries.
1360 """
1361 for library in self._libraries.values():
1362 library.LinkPackageBodies()
1364 def LinkLibraryReferences(self) -> None:
1365 DEFAULT_LIBRARIES = ("std",)
1367 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1368 # All primary units supporting a context, have at least one library implicitly referenced
1369 if isinstance(designUnit, PrimaryUnit):
1370 for libraryIdentifier in DEFAULT_LIBRARIES:
1371 referencedLibrary = self._libraries[libraryIdentifier]
1372 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1373 designUnit._referencedPackages[libraryIdentifier] = {}
1374 designUnit._referencedContexts[libraryIdentifier] = {}
1375 # TODO: catch KeyError on self._libraries[libName]
1376 # TODO: warn duplicate library reference
1378 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1379 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1381 workingLibrary: Library = designUnit.Library
1382 libraryIdentifier = workingLibrary.NormalizedIdentifier
1383 referencedLibrary = self._libraries[libraryIdentifier]
1386 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1387 designUnit._referencedPackages[libraryIdentifier] = {}
1388 designUnit._referencedContexts[libraryIdentifier] = {}
1390 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1391 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1393 # All secondary units inherit referenced libraries from their primary units.
1394 else:
1395 if isinstance(designUnit, Architecture):
1396 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1397 elif isinstance(designUnit, PackageBody): 1397 ↛ 1400line 1397 didn't jump to line 1400 because the condition on line 1397 was always true
1398 referencedLibraries = designUnit.Package.Package._referencedLibraries
1399 else:
1400 raise VHDLModelException()
1402 for libraryIdentifier, library in referencedLibraries.items():
1403 designUnit._referencedLibraries[libraryIdentifier] = library
1405 for libraryReference in designUnit._libraryReferences:
1406 # A library clause can have multiple comma-separated references
1407 for librarySymbol in libraryReference.Symbols:
1408 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1409 if libraryIdentifier == "work": 1409 ↛ 1410line 1409 didn't jump to line 1410 because the condition on line 1409 was never true
1410 continue
1412 try:
1413 library = self._libraries[libraryIdentifier]
1414 except KeyError:
1415 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1416 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1417 raise ex
1419 librarySymbol.Library = library
1420 designUnit._referencedLibraries[libraryIdentifier] = library
1421 designUnit._referencedPackages[libraryIdentifier] = {}
1422 designUnit._referencedContexts[libraryIdentifier] = {}
1423 # TODO: warn duplicate library reference
1425 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1426 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1428 def LinkPackageReferences(self) -> None:
1429 DEFAULT_PACKAGES = (
1430 ("std", ("standard",)),
1431 )
1433 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1434 # All primary units supporting a context, have at least one package implicitly referenced
1435 if isinstance(designUnit, PrimaryUnit):
1436 if designUnit.Library.NormalizedIdentifier != "std" and \
1437 designUnit.NormalizedIdentifier != "standard":
1438 for lib in DEFAULT_PACKAGES:
1439 if lib[0] not in designUnit._referencedLibraries: 1439 ↛ 1440line 1439 didn't jump to line 1440 because the condition on line 1439 was never true
1440 raise VHDLModelException()
1441 for pack in lib[1]:
1442 referencedPackage = self._libraries[lib[0]]._packages[pack]
1443 designUnit._referencedPackages[lib[0]][pack] = referencedPackage
1444 # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack]
1445 # TODO: warn duplicate package reference
1447 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1448 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1450 # All secondary units inherit referenced packages from their primary units.
1451 else:
1452 if isinstance(designUnit, Architecture):
1453 referencedPackages = designUnit.Entity.Entity._referencedPackages
1454 elif isinstance(designUnit, PackageBody): 1454 ↛ 1457line 1454 didn't jump to line 1457 because the condition on line 1454 was always true
1455 referencedPackages = designUnit.Package.Package._referencedPackages
1456 else:
1457 raise VHDLModelException()
1459 for packageIdentifier, package in referencedPackages.items():
1460 designUnit._referencedPackages[packageIdentifier] = package
1462 for packageReference in designUnit.PackageReferences:
1463 # A use clause can have multiple comma-separated references
1464 for packageMemberSymbol in packageReference.Symbols:
1465 packageName = packageMemberSymbol.Name.Prefix
1466 libraryName = packageName.Prefix
1468 libraryIdentifier = libraryName.NormalizedIdentifier
1469 packageIdentifier = packageName.NormalizedIdentifier
1471 # In case work is used, resolve to the real library name.
1472 if libraryIdentifier == "work":
1473 library: Library = designUnit.Library
1474 libraryIdentifier = library.NormalizedIdentifier
1475 elif libraryIdentifier not in designUnit._referencedLibraries: 1475 ↛ 1477line 1475 didn't jump to line 1477 because the condition on line 1475 was never true
1476 # TODO: This check doesn't trigger if it's the working library.
1477 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1478 else:
1479 library = self._libraries[libraryIdentifier]
1481 try:
1482 package = library._packages[packageIdentifier]
1483 except KeyError:
1484 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1485 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1486 raise ex
1488 packageMemberSymbol.Package = package
1490 # TODO: warn duplicate package reference
1491 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1493 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1494 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1496 # TODO: update the namespace with visible members
1497 if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1497 ↛ 1501line 1497 didn't jump to line 1501 because the condition on line 1497 was always true
1498 for componentIdentifier, component in package._components.items(): 1498 ↛ 1499line 1498 didn't jump to line 1499 because the loop on line 1498 never started
1499 designUnit._namespace._elements[componentIdentifier] = component
1501 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
1502 raise NotImplementedError()
1503 else:
1504 raise VHDLModelException()
1506 def LinkContextReferences(self) -> None:
1507 for designUnit in self.IterateDesignUnits():
1508 for contextReference in designUnit._contextReferences:
1509 # A context reference can have multiple comma-separated references
1510 for contextSymbol in contextReference.Symbols:
1511 libraryName = contextSymbol.Name.Prefix
1513 libraryIdentifier = libraryName.NormalizedIdentifier
1514 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1516 # In case work is used, resolve to the real library name.
1517 if libraryIdentifier == "work": 1517 ↛ 1520line 1517 didn't jump to line 1520 because the condition on line 1517 was always true
1518 referencedLibrary = designUnit.Library
1519 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1520 elif libraryIdentifier not in designUnit._referencedLibraries:
1521 # TODO: This check doesn't trigger if it's the working library.
1522 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1523 else:
1524 referencedLibrary = self._libraries[libraryIdentifier]
1526 try:
1527 referencedContext = referencedLibrary._contexts[contextIdentifier]
1528 except KeyError:
1529 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1531 contextSymbol.Package = referencedContext
1533 # TODO: warn duplicate referencedContext reference
1534 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1536 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1537 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1539 for vertex in self._dependencyGraph.IterateTopologically():
1540 if vertex["kind"] is DependencyGraphVertexKind.Context:
1541 context: Context = vertex.Value
1542 for designUnitVertex in vertex.IteratePredecessorVertices():
1543 designUnit: DesignUnit = designUnitVertex.Value
1544 for libraryIdentifier, library in context._referencedLibraries.items():
1545 # if libraryIdentifier in designUnit._referencedLibraries:
1546 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1548 designUnit._referencedLibraries[libraryIdentifier] = library
1549 designUnit._referencedPackages[libraryIdentifier] = {}
1551 for libraryIdentifier, packages in context._referencedPackages.items():
1552 for packageIdentifier, package in packages.items():
1553 if packageIdentifier in designUnit._referencedPackages: 1553 ↛ 1554line 1553 didn't jump to line 1554 because the condition on line 1553 was never true
1554 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1556 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1558 def LinkComponents(self) -> None:
1559 for package in self.IterateDesignUnits(DesignUnitKind.Package): # type: Package
1560 library = package._parent
1561 for component in package._components.values(): 1561 ↛ 1562line 1561 didn't jump to line 1562 because the loop on line 1561 never started
1562 try:
1563 entity = library._entities[component.NormalizedIdentifier]
1564 except KeyError:
1565 if not component.AllowBlackbox:
1566 raise VHDLModelException(f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1567 else:
1568 component._isBlackBox = True
1569 continue
1571 component.Entity = entity
1573 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1574 # Currently, component has no _dependencyVertex field
1576 # FIXME: also link components in architectures (and nested structures like generate statements and block statements
1577 # for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture):
1578 # library = architecture._parent
1579 # for component in architecture._components.values():
1580 # pass
1582 def LinkInstantiations(self) -> None:
1583 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1584 for instance in architecture.IterateInstantiations():
1585 if isinstance(instance, EntityInstantiation): 1585 ↛ 1618line 1585 didn't jump to line 1618 because the condition on line 1585 was always true
1586 libraryName = instance.Entity.Name.Prefix
1587 libraryIdentifier = libraryName.Identifier
1588 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1589 if normalizedLibraryIdentifier == "work":
1590 libraryIdentifier = architecture.Library.Identifier
1591 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1592 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1592 ↛ 1593line 1592 didn't jump to line 1593 because the condition on line 1592 was never true
1593 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}'.")
1594 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1595 raise ex
1597 try:
1598 library = self._libraries[normalizedLibraryIdentifier]
1599 except KeyError:
1600 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1601 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1602 raise ex
1604 try:
1605 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1606 except KeyError:
1607 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}'.")
1608 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1609 if libs:
1610 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1611 raise ex
1613 instance.Entity.Entity = entity
1615 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1616 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1618 elif isinstance(instance, ComponentInstantiation):
1619 component = architecture._namespace.FindComponent(instance.Component)
1621 instance.Component.Component = component
1623 if not component.IsBlackbox:
1624 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1625 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1626 else:
1627 print(f"Found a blackbox for '{instance.Label}: {instance.Component.Name}'.")
1629 elif isinstance(instance, ConfigurationInstantiation):
1630 # pass
1631 print(instance.Label, instance.Configuration)
1633 def IndexPackages(self) -> None:
1634 """
1635 Index all declared items in all packages in all libraries.
1637 .. rubric:: Algorithm
1639 1. Iterate all libraries:
1641 1. Iterate all packages |br|
1642 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1644 * Index all declared items in that package. |br|
1645 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1647 .. seealso::
1649 :meth:`IndexPackageBodies`
1650 Index all declared items in all package bodies in all libraries.
1651 :meth:`IndexEntities`
1652 Index all declared items in all entities in all libraries.
1653 :meth:`IndexArchitectures`
1654 Index all declared items in all architectures in all libraries.
1655 """
1656 for library in self._libraries.values():
1657 library.IndexPackages()
1659 def IndexPackageBodies(self) -> None:
1660 """
1661 Index all declared items in all packages in all libraries.
1663 .. rubric:: Algorithm
1665 1. Iterate all libraries:
1667 1. Iterate all packages |br|
1668 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
1670 * Index all declared items in that package body. |br|
1671 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
1673 .. seealso::
1675 :meth:`IndexPackages`
1676 Index all declared items in all packages in all libraries.
1677 :meth:`IndexEntities`
1678 Index all declared items in all entities in all libraries.
1679 :meth:`IndexArchitectures`
1680 Index all declared items in all architectures in all libraries.
1681 """
1682 for library in self._libraries.values():
1683 library.IndexPackageBodies()
1685 def IndexEntities(self) -> None:
1686 """
1687 Index all declared items in all packages in all libraries.
1689 .. rubric:: Algorithm
1691 1. Iterate all libraries:
1693 1. Iterate all packages |br|
1694 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
1696 * Index all declared items in that entity. |br|
1697 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
1699 .. seealso::
1701 :meth:`IndexPackages`
1702 Index all declared items in all packages in all libraries.
1703 :meth:`IndexPackageBodies`
1704 Index all declared items in all package bodies in all libraries.
1705 :meth:`IndexArchitectures`
1706 Index all declared items in all architectures in all libraries.
1707 """
1708 for library in self._libraries.values():
1709 library.IndexEntities()
1711 def IndexArchitectures(self) -> None:
1712 """
1713 Index all declared items in all packages in all libraries.
1715 .. rubric:: Algorithm
1717 1. Iterate all libraries:
1719 1. Iterate all packages |br|
1720 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
1722 * Index all declared items in that architecture. |br|
1723 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
1725 .. seealso::
1727 :meth:`IndexPackages`
1728 Index all declared items in all packages in all libraries.
1729 :meth:`IndexPackageBodies`
1730 Index all declared items in all package bodies in all libraries.
1731 :meth:`IndexEntities`
1732 Index all declared items in all entities in all libraries.
1733 """
1734 for library in self._libraries.values():
1735 library.IndexArchitectures()
1737 def CreateHierarchyGraph(self) -> None:
1738 """
1739 Create the hierarchy graph from dependency graph.
1741 .. rubric:: Algorithm
1743 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
1745 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
1746 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
1748 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
1749 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
1751 2. Iterate all architectures ...
1753 .. todo:: Design::CreateHierarchyGraph describe algorithm
1755 1. Iterate all outbound edges
1757 .. todo:: Design::CreateHierarchyGraph describe algorithm
1758 """
1759 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
1760 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
1761 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
1762 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
1763 vertex.Value._hierarchyVertex = hierarchyVertex
1765 # Copy implementation edges from
1766 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
1767 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
1768 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
1769 if DependencyGraphEdgeKind.Implementation in kind:
1770 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1771 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
1772 elif DependencyGraphEdgeKind.Instantiation in kind:
1773 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1775 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
1776 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
1777 continue
1779 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
1780 else:
1781 continue
1783 newEdge["kind"] = kind
1785 def ComputeCompileOrder(self) -> None:
1786 def predicate(edge: Edge) -> bool:
1787 return (
1788 DependencyGraphEdgeKind.Implementation in edge["kind"] or
1789 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
1790 DependencyGraphEdgeKind.UseClause in edge["kind"] or
1791 DependencyGraphEdgeKind.ContextReference in edge["kind"]
1792 ) and edge.Destination["predefined"] is False
1794 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
1795 sourceDocument: Document = edge.Source.Value.Document
1796 destinationDocument: Document = edge.Destination.Value.Document
1798 sourceVertex = sourceDocument._compileOrderVertex
1799 destinationVertex = destinationDocument._compileOrderVertex
1801 # Don't add self-edges
1802 if sourceVertex is destinationVertex: 1802 ↛ 1805line 1802 didn't jump to line 1805 because the condition on line 1802 was always true
1803 continue
1804 # Don't add parallel edges
1805 elif sourceVertex.HasEdgeToDestination(destinationVertex):
1806 continue
1808 e = sourceVertex.EdgeToVertex(destinationVertex)
1809 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1811 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
1812 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1814 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
1815 """
1816 Iterate all document in compile-order.
1818 .. rubric:: Algorithm
1820 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
1822 1. Iterate compile-order graph in topological order. |br|
1823 :meth:`pyTooling.Graph.Graph.IterateTopologically`
1825 * yield the compiler-order vertex' referenced document.
1827 :returns: A generator to iterate all documents in compile-order in the design.
1828 :raises VHDLModelException: If compile-order was not computed.
1830 .. seealso::
1832 .. todo:: missing text
1834 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
1836 """
1837 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 1837 ↛ 1838line 1837 didn't jump to line 1838 because the condition on line 1837 was never true
1838 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
1840 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
1841 yield compileOrderNode.Value
1843 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
1844 raise NotImplementedError()
1846 def __repr__(self) -> str:
1847 """
1848 Formats a representation of the design.
1850 **Format:** ``Document: 'my_design'``
1852 :returns: String representation of the design.
1853 """
1854 return f"Design: {self._name}"
1856 __str__ = __repr__
1859@export
1860class Library(ModelEntity, NamedEntityMixin):
1861 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
1863 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library.
1864 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
1865 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
1866 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
1867 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
1868 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
1869 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
1871 _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`.
1873 def __init__(
1874 self,
1875 identifier: str,
1876 allowBlackbox: Nullable[bool] = None,
1877 parent: ModelEntity = None
1878 ) -> None:
1879 """
1880 Initialize a VHDL library.
1882 :param identifier: Name of the VHDL library.
1883 :param allowBlackbox: Specify if blackboxes are allowed in this design.
1884 :param parent: The parent model entity (design) of this VHDL library.
1885 """
1886 super().__init__(parent)
1887 NamedEntityMixin.__init__(self, identifier)
1889 self._allowBlackbox = allowBlackbox
1891 self._contexts = {}
1892 self._configurations = {}
1893 self._entities = {}
1894 self._architectures = {}
1895 self._packages = {}
1896 self._packageBodies = {}
1898 self._dependencyVertex = None
1900 @property
1901 def AllowBlackbox(self) -> bool:
1902 """
1903 Read-only property to check if a design supports blackboxes (:attr:`_allowBlackbox`).
1905 :returns: If blackboxes are allowed.
1906 """
1907 if self._allowBlackbox is None:
1908 return self._parent.AllowBlackbox
1909 else:
1910 return self._allowBlackbox
1912 @AllowBlackbox.setter
1913 def AllowBlackbox(self, value: Nullable[bool]) -> None:
1914 self._allowBlackbox = value
1916 @readonly
1917 def Contexts(self) -> Dict[str, Context]:
1918 """Returns a list of all context declarations declared in this library."""
1919 return self._contexts
1921 @readonly
1922 def Configurations(self) -> Dict[str, Configuration]:
1923 """Returns a list of all configuration declarations declared in this library."""
1924 return self._configurations
1926 @readonly
1927 def Entities(self) -> Dict[str, Entity]:
1928 """Returns a list of all entity declarations declared in this library."""
1929 return self._entities
1931 @readonly
1932 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
1933 """Returns a list of all architectures declarations declared in this library."""
1934 return self._architectures
1936 @readonly
1937 def Packages(self) -> Dict[str, Package]:
1938 """Returns a list of all package declarations declared in this library."""
1939 return self._packages
1941 @readonly
1942 def PackageBodies(self) -> Dict[str, PackageBody]:
1943 """Returns a list of all package body declarations declared in this library."""
1944 return self._packageBodies
1946 @readonly
1947 def DependencyVertex(self) -> Vertex:
1948 """
1949 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
1951 The dependency vertex references this library by its value field.
1953 :returns: The corresponding dependency vertex.
1954 """
1955 return self._dependencyVertex
1957 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
1958 """
1959 Iterate all design units in the library.
1961 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
1963 .. rubric:: Algorithm
1965 1. Iterate all contexts in that library.
1966 2. Iterate all packages in that library.
1967 3. Iterate all package bodies in that library.
1968 4. Iterate all entities in that library.
1969 5. Iterate all architectures in that library.
1970 6. Iterate all configurations in that library.
1972 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
1973 :returns: A generator to iterate all matched design units in the library.
1975 .. seealso::
1977 :meth:`pyVHDLModel.Design.IterateDesignUnits`
1978 Iterate all design units in the design.
1979 :meth:`pyVHDLModel.Document.IterateDesignUnits`
1980 Iterate all design units in the document.
1981 """
1982 if DesignUnitKind.Context in filter:
1983 for context in self._contexts.values():
1984 yield context
1986 if DesignUnitKind.Package in filter:
1987 for package in self._packages.values():
1988 yield package
1990 if DesignUnitKind.PackageBody in filter:
1991 for packageBody in self._packageBodies.values():
1992 yield packageBody
1994 if DesignUnitKind.Entity in filter:
1995 for entity in self._entities.values():
1996 yield entity
1998 if DesignUnitKind.Architecture in filter:
1999 for architectures in self._architectures.values():
2000 for architecture in architectures.values():
2001 yield architecture
2003 if DesignUnitKind.Configuration in filter:
2004 for configuration in self._configurations.values():
2005 yield configuration
2007 # for verificationProperty in self._verificationUnits.values():
2008 # yield verificationProperty
2009 # for verificationUnit in self._verificationProperties.values():
2010 # yield entity
2011 # for verificationMode in self._verificationModes.values():
2012 # yield verificationMode
2014 def LinkArchitectures(self) -> None:
2015 """
2016 Link all architectures to corresponding entities.
2018 .. rubric:: Algorithm
2020 1. Iterate all architecture groups (grouped per entity symbol's name).
2022 * Check if entity symbol's name exists as an entity in this library.
2024 1. For each architecture in the same architecture group:
2026 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
2027 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
2028 * Set parent namespace of architecture's namespace to the entitie's namespace.
2029 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
2031 :raises VHDLModelException: If entity name doesn't exist.
2032 :raises VHDLModelException: If architecture name already exists for entity.
2034 .. seealso::
2036 :meth:`LinkPackageBodies`
2037 Link all package bodies to corresponding packages.
2038 """
2039 for entityName, architecturesPerEntity in self._architectures.items():
2040 if entityName not in self._entities: 2040 ↛ 2041line 2040 didn't jump to line 2041 because the condition on line 2040 was never true
2041 architectureNames = "', '".join(architecturesPerEntity.keys())
2042 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
2043 # TODO: search in other libraries to find that entity.
2044 # TODO: add code position
2046 entity = self._entities[entityName]
2047 for architecture in architecturesPerEntity.values():
2048 if architecture._normalizedIdentifier in entity._architectures: 2048 ↛ 2049line 2048 didn't jump to line 2049 because the condition on line 2048 was never true
2049 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
2050 # TODO: add code position of existing and current
2052 entity._architectures[architecture._normalizedIdentifier] = architecture
2053 architecture._entity.Entity = entity
2054 architecture._namespace._parentNamespace = entity._namespace
2056 # add "architecture -> entity" relation in dependency graph
2057 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
2058 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
2060 def LinkPackageBodies(self) -> None:
2061 """
2062 Link all package bodies to corresponding packages.
2064 .. rubric:: Algorithm
2066 1. Iterate all package bodies.
2068 * Check if package body symbol's name exists as a package in this library.
2069 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2070 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2071 * Set parent namespace of package body's namespace to the package's namespace.
2072 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2074 :raises VHDLModelException: If package name doesn't exist.
2076 .. seealso::
2078 :meth:`LinkArchitectures`
2079 Link all architectures to corresponding entities.
2080 """
2081 for packageBodyName, packageBody in self._packageBodies.items():
2082 if packageBodyName not in self._packages: 2082 ↛ 2083line 2082 didn't jump to line 2083 because the condition on line 2082 was never true
2083 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
2085 package = self._packages[packageBodyName]
2086 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
2087 packageBody._package.Package = package
2088 packageBody._namespace._parentNamespace = package._namespace
2090 # add "package body -> package" relation in dependency graph
2091 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2092 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2094 def IndexPackages(self) -> None:
2095 """
2096 Index declared items in all packages.
2098 .. rubric:: Algorithm
2100 1. Iterate all packages:
2102 * Index all declared items. |br|
2103 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2105 .. seealso::
2107 :meth:`IndexPackageBodies`
2108 Index all declared items in a package body.
2109 :meth:`IndexEntities`
2110 Index all declared items in an entity.
2111 :meth:`IndexArchitectures`
2112 Index all declared items in an architecture.
2113 """
2114 for package in self._packages.values():
2115 if isinstance(package, Package): 2115 ↛ 2114line 2115 didn't jump to line 2114 because the condition on line 2115 was always true
2116 package.IndexDeclaredItems()
2118 def IndexPackageBodies(self) -> None:
2119 """
2120 Index declared items in all package bodies.
2122 .. rubric:: Algorithm
2124 1. Iterate all package bodies:
2126 * Index all declared items. |br|
2127 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2129 .. seealso::
2131 :meth:`IndexPackages`
2132 Index all declared items in a package.
2133 :meth:`IndexEntities`
2134 Index all declared items in an entity.
2135 :meth:`IndexArchitectures`
2136 Index all declared items in an architecture.
2137 """
2138 for packageBody in self._packageBodies.values():
2139 packageBody.IndexDeclaredItems()
2141 def IndexEntities(self) -> None:
2142 """
2143 Index declared items in all entities.
2145 .. rubric:: Algorithm
2147 1. Iterate all entities:
2149 * Index all declared items. |br|
2150 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2152 .. seealso::
2154 :meth:`IndexPackages`
2155 Index all declared items in a package.
2156 :meth:`IndexPackageBodies`
2157 Index all declared items in a package body.
2158 :meth:`IndexArchitectures`
2159 Index all declared items in an architecture.
2160 """
2161 for entity in self._entities.values():
2162 entity.IndexDeclaredItems()
2164 def IndexArchitectures(self) -> None:
2165 """
2166 Index declared items in all architectures.
2168 .. rubric:: Algorithm
2170 1. Iterate all architectures:
2172 * Index all declared items. |br|
2173 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2175 .. seealso::
2177 :meth:`IndexPackages`
2178 Index all declared items in a package.
2179 :meth:`IndexPackageBodies`
2180 Index all declared items in a package body.
2181 :meth:`IndexEntities`
2182 Index all declared items in an entity.
2183 """
2184 for architectures in self._architectures.values():
2185 for architecture in architectures.values():
2186 architecture.IndexDeclaredItems()
2187 architecture.IndexStatements()
2189 def __repr__(self) -> str:
2190 """
2191 Formats a representation of the library.
2193 **Format:** ``Library: 'my_library'``
2195 :returns: String representation of the library.
2196 """
2197 return f"Library: '{self._identifier}'"
2199 __str__ = __repr__
2202@export
2203class Document(ModelEntity, DocumentedEntityMixin):
2204 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2206 _path: Path #: path to the document. ``None`` if virtual document.
2207 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2208 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2209 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2210 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2211 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2212 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2213 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2214 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2215 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2216 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2218 _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`.
2219 _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`.
2221 def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
2222 super().__init__(parent)
2223 DocumentedEntityMixin.__init__(self, documentation)
2225 self._path = path
2226 self._designUnits = []
2227 self._contexts = {}
2228 self._configurations = {}
2229 self._entities = {}
2230 self._architectures = {}
2231 self._packages = {}
2232 self._packageBodies = {}
2233 self._verificationUnits = {}
2234 self._verificationProperties = {}
2235 self._verificationModes = {}
2237 self._dependencyVertex = None
2238 self._compileOrderVertex = None
2240 def _AddEntity(self, item: Entity) -> None:
2241 """
2242 Add an entity to the document's lists of design units.
2244 :param item: Entity object to be added to the document.
2245 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
2246 :raises VHDLModelException: If entity name already exists in document.
2247 """
2248 if not isinstance(item, Entity): 2248 ↛ 2249line 2248 didn't jump to line 2249 because the condition on line 2248 was never true
2249 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2250 if version_info >= (3, 11): # pragma: no cover
2251 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2252 raise ex
2254 identifier = item._normalizedIdentifier
2255 if identifier in self._entities: 2255 ↛ 2257line 2255 didn't jump to line 2257 because the condition on line 2255 was never true
2256 # TODO: use a more specific exception
2257 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2259 self._entities[identifier] = item
2260 self._designUnits.append(item)
2261 item._document = self
2263 def _AddArchitecture(self, item: Architecture) -> None:
2264 """
2265 Add an architecture to the document's lists of design units.
2267 :param item: Architecture object to be added to the document.
2268 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
2269 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2270 """
2271 if not isinstance(item, Architecture): 2271 ↛ 2272line 2271 didn't jump to line 2272 because the condition on line 2271 was never true
2272 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2273 if version_info >= (3, 11): # pragma: no cover
2274 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2275 raise ex
2277 entity = item._entity.Name
2278 entityIdentifier = entity._normalizedIdentifier
2279 try:
2280 architectures = self._architectures[entityIdentifier]
2281 if item._normalizedIdentifier in architectures:
2282 # TODO: use a more specific exception
2283 # FIXME: this is allowed and should be a warning or a strict mode.
2284 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2286 architectures[item.Identifier] = item
2287 except KeyError:
2288 self._architectures[entityIdentifier] = {item._identifier: item}
2290 self._designUnits.append(item)
2291 item._document = self
2293 def _AddPackage(self, item: Package) -> None:
2294 """
2295 Add a package to the document's lists of design units.
2297 :param item: Package object to be added to the document.
2298 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
2299 :raises VHDLModelException: If package name already exists in document.
2300 """
2301 if not isinstance(item, (Package, PackageInstantiation)): 2301 ↛ 2302line 2301 didn't jump to line 2302 because the condition on line 2301 was never true
2302 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2303 if version_info >= (3, 11): # pragma: no cover
2304 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2305 raise ex
2307 identifier = item._normalizedIdentifier
2308 if identifier in self._packages: 2308 ↛ 2310line 2308 didn't jump to line 2310 because the condition on line 2308 was never true
2309 # TODO: use a more specific exception
2310 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2312 self._packages[identifier] = item
2313 self._designUnits.append(item)
2314 item._document = self
2316 def _AddPackageBody(self, item: PackageBody) -> None:
2317 """
2318 Add a package body to the document's lists of design units.
2320 :param item: Package body object to be added to the document.
2321 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
2322 :raises VHDLModelException: If package body name already exists in document.
2323 """
2324 if not isinstance(item, PackageBody): 2324 ↛ 2325line 2324 didn't jump to line 2325 because the condition on line 2324 was never true
2325 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2326 if version_info >= (3, 11): # pragma: no cover
2327 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2328 raise ex
2330 identifier = item._normalizedIdentifier
2331 if identifier in self._packageBodies: 2331 ↛ 2333line 2331 didn't jump to line 2333 because the condition on line 2331 was never true
2332 # TODO: use a more specific exception
2333 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2335 self._packageBodies[identifier] = item
2336 self._designUnits.append(item)
2337 item._document = self
2339 def _AddContext(self, item: Context) -> None:
2340 """
2341 Add a context to the document's lists of design units.
2343 :param item: Context object to be added to the document.
2344 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
2345 :raises VHDLModelException: If context name already exists in document.
2346 """
2347 if not isinstance(item, Context): 2347 ↛ 2348line 2347 didn't jump to line 2348 because the condition on line 2347 was never true
2348 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2349 if version_info >= (3, 11): # pragma: no cover
2350 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2351 raise ex
2353 identifier = item._normalizedIdentifier
2354 if identifier in self._contexts: 2354 ↛ 2356line 2354 didn't jump to line 2356 because the condition on line 2354 was never true
2355 # TODO: use a more specific exception
2356 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2358 self._contexts[identifier] = item
2359 self._designUnits.append(item)
2360 item._document = self
2362 def _AddConfiguration(self, item: Configuration) -> None:
2363 """
2364 Add a configuration to the document's lists of design units.
2366 :param item: Configuration object to be added to the document.
2367 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
2368 :raises VHDLModelException: If configuration name already exists in document.
2369 """
2370 if not isinstance(item, Configuration): 2370 ↛ 2371line 2370 didn't jump to line 2371 because the condition on line 2370 was never true
2371 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2372 if version_info >= (3, 11): # pragma: no cover
2373 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2374 raise ex
2376 identifier = item._normalizedIdentifier
2377 if identifier in self._configurations: 2377 ↛ 2379line 2377 didn't jump to line 2379 because the condition on line 2377 was never true
2378 # TODO: use a more specific exception
2379 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2381 self._configurations[identifier] = item
2382 self._designUnits.append(item)
2383 item._document = self
2385 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2386 if not isinstance(item, VerificationUnit):
2387 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2388 if version_info >= (3, 11): # pragma: no cover
2389 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2390 raise ex
2392 identifier = item._normalizedIdentifier
2393 if identifier in self._verificationUnits:
2394 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2396 self._verificationUnits[identifier] = item
2397 self._designUnits.append(item)
2398 item._document = self
2400 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2401 if not isinstance(item, VerificationProperty):
2402 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2403 if version_info >= (3, 11): # pragma: no cover
2404 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2405 raise ex
2407 identifier = item.NormalizedIdentifier
2408 if identifier in self._verificationProperties:
2409 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2411 self._verificationProperties[identifier] = item
2412 self._designUnits.append(item)
2413 item._document = self
2415 def _AddVerificationMode(self, item: VerificationMode) -> None:
2416 if not isinstance(item, VerificationMode):
2417 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2418 if version_info >= (3, 11): # pragma: no cover
2419 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2420 raise ex
2422 identifier = item.NormalizedIdentifier
2423 if identifier in self._verificationModes:
2424 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2426 self._verificationModes[identifier] = item
2427 self._designUnits.append(item)
2428 item._document = self
2430 def _AddDesignUnit(self, item: DesignUnit) -> None:
2431 """
2432 Add a design unit to the document's lists of design units.
2434 :param item: Configuration object to be added to the document.
2435 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2436 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2437 :raises VHDLModelException: If configuration name already exists in document.
2438 """
2439 if not isinstance(item, DesignUnit): 2439 ↛ 2440line 2439 didn't jump to line 2440 because the condition on line 2439 was never true
2440 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2441 if version_info >= (3, 11): # pragma: no cover
2442 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2443 raise ex
2445 if isinstance(item, Entity):
2446 self._AddEntity(item)
2447 elif isinstance(item, Architecture):
2448 self._AddArchitecture(item)
2449 elif isinstance(item, Package):
2450 self._AddPackage(item)
2451 elif isinstance(item, PackageBody):
2452 self._AddPackageBody(item)
2453 elif isinstance(item, Context):
2454 self._AddContext(item)
2455 elif isinstance(item, Configuration): 2455 ↛ 2457line 2455 didn't jump to line 2457 because the condition on line 2455 was always true
2456 self._AddConfiguration(item)
2457 elif isinstance(item, VerificationUnit):
2458 self._AddVerificationUnit(item)
2459 elif isinstance(item, VerificationProperty):
2460 self._AddVerificationProperty(item)
2461 elif isinstance(item, VerificationMode):
2462 self._AddVerificationMode(item)
2463 else:
2464 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2465 if version_info >= (3, 11): # pragma: no cover
2466 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2467 raise ex
2469 @readonly
2470 def Path(self) -> Path:
2471 """
2472 Read-only property to access the document's path (:attr:`_path`).
2474 :returns: The path of this document.
2475 """
2476 return self._path
2478 @readonly
2479 def DesignUnits(self) -> List[DesignUnit]:
2480 """
2481 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2483 :returns: List of all design units.
2484 """
2485 return self._designUnits
2487 @readonly
2488 def Contexts(self) -> Dict[str, Context]:
2489 """
2490 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
2492 :returns: List of all contexts.
2493 """
2494 return self._contexts
2496 @readonly
2497 def Configurations(self) -> Dict[str, Configuration]:
2498 """
2499 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
2501 :returns: List of all configurations.
2502 """
2503 return self._configurations
2505 @readonly
2506 def Entities(self) -> Dict[str, Entity]:
2507 """
2508 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
2510 :returns: List of all entities.
2511 """
2512 return self._entities
2514 @readonly
2515 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2516 """
2517 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
2519 :returns: List of all architectures.
2520 """
2521 return self._architectures
2523 @readonly
2524 def Packages(self) -> Dict[str, Package]:
2525 """
2526 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
2528 :returns: List of all packages.
2529 """
2530 return self._packages
2532 @readonly
2533 def PackageBodies(self) -> Dict[str, PackageBody]:
2534 """
2535 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
2537 :returns: List of all package bodies.
2538 """
2539 return self._packageBodies
2541 @readonly
2542 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
2543 """
2544 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
2546 :returns: List of all verification units.
2547 """
2548 return self._verificationUnits
2550 @readonly
2551 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
2552 """
2553 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
2555 :returns: List of all verification properties.
2556 """
2557 return self._verificationProperties
2559 @readonly
2560 def VerificationModes(self) -> Dict[str, VerificationMode]:
2561 """
2562 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
2564 :returns: List of all verification modes.
2565 """
2566 return self._verificationModes
2568 @readonly
2569 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
2570 """
2571 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
2573 The compile-order vertex references this document by its value field.
2575 :returns: The corresponding compile-order vertex.
2576 """
2577 return self._compileOrderVertex
2579 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2580 """
2581 Iterate all design units in the document.
2583 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2585 .. rubric:: Algorithm
2587 * If contexts are selected in the filter:
2589 1. Iterate all contexts in that library.
2591 * If packages are selected in the filter:
2593 1. Iterate all packages in that library.
2595 * If package bodies are selected in the filter:
2597 1. Iterate all package bodies in that library.
2599 * If entites are selected in the filter:
2601 1. Iterate all entites in that library.
2603 * If architectures are selected in the filter:
2605 1. Iterate all architectures in that library.
2607 * If configurations are selected in the filter:
2609 1. Iterate all configurations in that library.
2611 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2612 :returns: A generator to iterate all matched design units in the document.
2614 .. seealso::
2616 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2617 Iterate all design units in the design.
2618 :meth:`pyVHDLModel.Library.IterateDesignUnits`
2619 Iterate all design units in the library.
2620 """
2621 if DesignUnitKind.Context in filter:
2622 for context in self._contexts.values():
2623 yield context
2625 if DesignUnitKind.Package in filter: 2625 ↛ 2629line 2625 didn't jump to line 2629 because the condition on line 2625 was always true
2626 for package in self._packages.values():
2627 yield package
2629 if DesignUnitKind.PackageBody in filter:
2630 for packageBody in self._packageBodies.values():
2631 yield packageBody
2633 if DesignUnitKind.Entity in filter:
2634 for entity in self._entities.values():
2635 yield entity
2637 if DesignUnitKind.Architecture in filter:
2638 for architectures in self._architectures.values():
2639 for architecture in architectures.values():
2640 yield architecture
2642 if DesignUnitKind.Configuration in filter:
2643 for configuration in self._configurations.values():
2644 yield configuration
2646 # for verificationProperty in self._verificationUnits.values():
2647 # yield verificationProperty
2648 # for verificationUnit in self._verificationProperties.values():
2649 # yield entity
2650 # for verificationMode in self._verificationModes.values():
2651 # yield verificationMode
2653 def __repr__(self) -> str:
2654 """
2655 Formats a representation of the document.
2657 **Format:** ``Document: 'path/to/file.vhdl'``
2659 :returns: String representation of the document.
2660 """
2661 return f"Document: '{self._path}'"
2663 __str__ = __repr__