Coverage for pyVHDLModel/__init__.py: 74%
1137 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-05 23:04 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-05 23:04 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33**An abstract VHDL language model.**
35This package provides a unified abstract language model for VHDL. Projects reading from source files can derive own
36classes and implement additional logic to create a concrete language model for their tools.
38Projects consuming pre-processed VHDL data (parsed, analyzed or elaborated) can build higher level features and services
39on such a model, while supporting multiple frontends.
41.. admonition:: Copyright Information
43 :copyright: Copyright 2017-2026 Patrick Lehmann - Bötzingen, Germany
44 :copyright: Copyright 2016-2017 Patrick Lehmann - Dresden, Germany
45 :license: Apache License, Version 2.0
46"""
47__author__ = "Patrick Lehmann"
48__email__ = "Paebbels@gmail.com"
49__copyright__ = "2016-2026, Patrick Lehmann"
50__license__ = "Apache License, Version 2.0"
51__version__ = "0.34.0"
54from enum import unique, Enum, Flag, auto
55from pathlib import Path
56from sys import version_info
58from typing import Union, Dict, cast, List, Generator, Optional as Nullable
60from pyTooling.Common import getFullyQualifiedName
61from pyTooling.Decorators import export, readonly
62from pyTooling.Graph import Graph, Vertex, Edge
63from pyTooling.Warning import WarningCollector
65from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning
66from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
67from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
68from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
69from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
70from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
71from pyVHDLModel.Namespace import Namespace
72from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
73from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
74from pyVHDLModel.Common import AllowBlackboxMixin
75from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin
76from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
77from pyVHDLModel.Concurrent import GenerateStatement, IfGenerateStatement, ForGenerateStatement, CaseGenerateStatement
78from pyVHDLModel.Concurrent import GenerateBranch, ConcurrentStatementsMixin, ConcurrentBlockStatement
79from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package, Component
80from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
81from pyVHDLModel.Instantiation import PackageInstantiation
82from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
85@export
86@unique
87class VHDLVersion(Enum):
88 """
89 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
91 A version can be given as integer or string and is represented as a unified
92 enumeration value.
94 This enumeration supports compare operators.
95 """
97 Any = -1 #: Any
98 VHDL87 = 87 #: VHDL-1987
99 VHDL93 = 93 #: VHDL-1993
100 AMS93 = 1993 #: VHDL-AMS-1993
101 AMS99 = 1999 #: VHDL-AMS-1999
102 VHDL2000 = 2000 #: VHDL-2000
103 VHDL2002 = 2002 #: VHDL-2002
104 VHDL2008 = 2008 #: VHDL-2008
105 AMS2017 = 2017 #: VHDL-AMS-2017
106 VHDL2019 = 2019 #: VHDL-2019
107 Latest = 10000 #: Latest VHDL (2019)
109 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
110 -1: Any,
111 87: VHDL87,
112 93: VHDL93,
113 # 93: AMS93,
114 99: AMS99,
115 0: VHDL2000,
116 2: VHDL2002,
117 8: VHDL2008,
118 17: AMS2017,
119 19: VHDL2019,
120 1987: VHDL87,
121 # 1993: VHDL93,
122 1993: AMS93,
123 1999: AMS99,
124 2000: VHDL2000,
125 2002: VHDL2002,
126 2008: VHDL2008,
127 2017: AMS2017,
128 2019: VHDL2019,
129 10000: Latest,
130 "Any": Any,
131 "87": VHDL87,
132 "93": VHDL93,
133 # "93": AMS93,
134 "99": AMS99,
135 "00": VHDL2000,
136 "02": VHDL2002,
137 "08": VHDL2008,
138 "17": AMS2017,
139 "19": VHDL2019,
140 "1987": VHDL87,
141 # "1993": VHDL93,
142 "1993": AMS93,
143 "1999": AMS99,
144 "2000": VHDL2000,
145 "2002": VHDL2002,
146 "2008": VHDL2008,
147 "2017": AMS2017,
148 "2019": VHDL2019,
149 "Latest": Latest,
150 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
152 def __init__(self, *_) -> None:
153 """Patch the embedded MAP dictionary"""
154 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
155 if (not isinstance(v, self.__class__)) and (v == self.value):
156 self.__class__.__VERSION_MAPPINGS__[k] = self
158 @classmethod
159 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
160 """
161 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
163 :param value: VHDL/VHDL-AMS year code.
164 :returns: Enumeration value.
165 :raises ValueError: If the year code is not recognized.
166 """
167 try:
168 return cls.__VERSION_MAPPINGS__[value]
169 except KeyError:
170 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
172 def __lt__(self, other: Any) -> bool:
173 """
174 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
176 :param other: Parameter to compare against.
177 :returns: True if version is less than the second operand.
178 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
179 """
180 if isinstance(other, VHDLVersion):
181 return self.value < other.value
182 else:
183 raise TypeError("Second operand is not of type 'VHDLVersion'.")
185 def __le__(self, other: Any) -> bool:
186 """
187 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
189 :param other: Parameter to compare against.
190 :returns: True if version is less or equal than the second operand.
191 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
192 """
193 if isinstance(other, VHDLVersion):
194 return self.value <= other.value
195 else:
196 raise TypeError("Second operand is not of type 'VHDLVersion'.")
198 def __gt__(self, other: Any) -> bool:
199 """
200 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
202 :param other: Parameter to compare against.
203 :returns: True if version is greater than the second operand.
204 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
205 """
206 if isinstance(other, VHDLVersion):
207 return self.value > other.value
208 else:
209 raise TypeError("Second operand is not of type 'VHDLVersion'.")
211 def __ge__(self, other: Any) -> bool:
212 """
213 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
215 :param other: Parameter to compare against.
216 :returns: True if version is greater or equal than the second operand.
217 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
218 """
219 if isinstance(other, VHDLVersion):
220 return self.value >= other.value
221 else:
222 raise TypeError("Second operand is not of type 'VHDLVersion'.")
224 def __ne__(self, other: Any) -> bool:
225 """
226 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
228 :param other: Parameter to compare against.
229 :returns: True if version is unequal to the second operand.
230 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
231 """
232 if isinstance(other, VHDLVersion):
233 return self.value != other.value
234 else:
235 raise TypeError("Second operand is not of type 'VHDLVersion'.")
237 def __eq__(self, other: Any) -> bool:
238 """
239 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
241 :param other: Parameter to compare against.
242 :returns: True if version is equal to the second operand.
243 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
244 """
245 if isinstance(other, VHDLVersion):
246 if (self is self.__class__.Any) or (other is self.__class__.Any):
247 return True
248 else:
249 return self.value == other.value
250 else:
251 raise TypeError("Second operand is not of type 'VHDLVersion'.")
253 @readonly
254 def IsVHDL(self) -> bool:
255 """
256 Checks if the version is a VHDL (not VHDL-AMS) version.
258 :returns: True if version is a VHDL version.
259 """
260 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
262 @readonly
263 def IsAMS(self) -> bool:
264 """
265 Checks if the version is a VHDL-AMS (not VHDL) version.
267 :returns: True if version is a VHDL-AMS version.
268 """
269 return self in (self.AMS93, self.AMS99, self.AMS2017)
271 def __str__(self) -> str:
272 """
273 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
275 :returns: Formatted VHDL/VHDL-AMS version.
276 """
277 if self.value == self.Any.value:
278 return "VHDL'Any"
279 elif self.value == self.Latest.value:
280 return "VHDL'Latest"
282 year = str(self.value)[-2:]
283 if self.IsVHDL:
284 return f"VHDL'{year}"
285 else:
286 return f"VHDL-AMS'{year}"
288 def __repr__(self) -> str:
289 """
290 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
292 :returns: Formatted VHDL/VHDL-AMS version.
293 """
294 if self.value == self.Any.value:
295 return "Any"
296 elif self.value == self.Latest.value:
297 return "Latest"
298 else:
299 return str(self.value)
302@export
303class IEEEFlavor(Flag):
304 Unknown = 0
305 IEEE = 1
306 Synopsys = 2
307 MentorGraphics = 4
308 WithVITAL = 32 # VITAL = VHDL Initiative Towards ASIC Libraries
311@export
312@unique
313class ObjectClass(Enum):
314 """
315 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
317 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
318 """
320 Default = 0 #: Object class not defined, thus it's context dependent.
321 Constant = 1 #: Constant
322 Variable = 2 #: Variable
323 Signal = 3 #: Signal
324 File = 4 #: File
325 Type = 5 #: Type
326 # FIXME: Package?
327 Procedure = 6 #: Procedure
328 Function = 7 #: Function
330 def __str__(self) -> str:
331 """
332 Formats the object class.
334 :returns: Formatted object class.
335 """
336 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
339@export
340@unique
341class DesignUnitKind(Flag):
342 """
343 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
345 """
346 Context = auto() #: Context
347 Package = auto() #: Package
348 PackageBody = auto() #: Package Body
349 Entity = auto() #: Entity
350 Architecture = auto() #: Architecture
351 Configuration = auto() #: Configuration
353 Primary = Context | Configuration | Entity | Package #: List of primary design units.
354 Secondary = PackageBody | Architecture #: List of secondary design units.
355 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
356 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
358 All = Primary | Secondary #: List of all design units.
361@export
362@unique
363class DependencyGraphVertexKind(Flag):
364 """
365 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
366 """
367 Document = auto() #: A document (VHDL source file).
368 Library = auto() #: A VHDL library.
370 Context = auto() #: A context design unit.
371 Package = auto() #: A package design unit.
372 PackageBody = auto() #: A package body design unit.
373 Entity = auto() #: A entity design unit.
374 Architecture = auto() #: A architecture design unit.
375 Component = auto() #: A VHDL component.
376 Configuration = auto() #: A configuration design unit.
379@export
380@unique
381class DependencyGraphEdgeKind(Flag):
382 """
383 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
384 """
385 Document = auto()
386 Library = auto()
387 Context = auto()
388 Package = auto()
389 Entity = auto()
390 # Architecture = auto()
391 Configuration = auto()
392 Component = auto()
394 DeclaredIn = auto()
395 Order = auto()
396 Reference = auto()
397 Implementation = auto()
398 Instantiation = auto()
400 SourceFile = Document | DeclaredIn
401 CompileOrder = Document | Order
403 LibraryClause = Library | Reference
404 UseClause = Package | Reference
405 ContextReference = Context | Reference
407 EntityImplementation = Entity | Implementation
408 PackageImplementation = Package | Implementation
410 EntityInstantiation = Entity | Instantiation
411 ComponentInstantiation = Component | Instantiation
412 ConfigurationInstantiation = Configuration | Instantiation
415@export
416@unique
417class ObjectGraphVertexKind(Flag):
418 """
419 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
420 """
421 Type = auto()
422 Subtype = auto()
424 Constant = auto()
425 DeferredConstant = auto()
426 Variable = auto()
427 Signal = auto()
428 File = auto()
430 Alias = auto()
433@export
434@unique
435class ObjectGraphEdgeKind(Flag):
436 """
437 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
438 """
439 BaseType = auto()
440 Subtype = auto()
442 ReferenceInExpression = auto()
445@export
446class Design(ModelEntity, AllowBlackboxMixin):
447 """
448 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
450 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
451 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
452 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`).
454 The *design* contains references to the following graphs:
456 * :attr:`DependencyGraph`
457 * :attr:`CompileOrderGraph`
458 * :attr:`HierarchyGraph`
459 * :attr:`ObjectGraph`
460 """
461 _name: Nullable[str] #: Name of the design.
462 _allowBlackbox: bool #: Allow blackboxes after linking the design.
463 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
464 _documents: List['Document'] #: List of all documents loaded for a design.
465 _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.
466 _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.
467 _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.
468 _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.
469 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
471 def __init__(
472 self,
473 name: Nullable[str] = None,
474 allowBlackbox: bool = False
475 ) -> None:
476 """
477 Initialize a VHDL design.
479 :param allowBlackbox: Specify if blackboxes are allowed in this design.
480 :param name: Name of the design.
481 """
482 super().__init__()
483 AllowBlackboxMixin.__init__(self, allowBlackbox)
485 self._name = name
487 self._libraries = {}
488 self._documents = []
490 self._compileOrderGraph = Graph()
491 self._dependencyGraph = Graph()
492 self._hierarchyGraph = Graph()
493 self._objectGraph = Graph()
494 self._toplevel = None
496 @readonly
497 def Name(self) -> Nullable[str]:
498 """
499 Read-only property to access the design's name (:attr:`_name`).
501 :returns: The name of the design.
502 """
503 return self._name
505 @readonly
506 def Libraries(self) -> Dict[str, 'Library']:
507 """
508 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
510 :returns: A dictionary of library names and VHDL libraries.
511 """
512 return self._libraries
514 @readonly
515 def Documents(self) -> List['Document']:
516 """
517 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
519 :returns: A list of all documents.
520 """
521 return self._documents
523 @readonly
524 def CompileOrderGraph(self) -> Graph:
525 """
526 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
528 :returns: Reference to the compile-order graph.
529 """
530 return self._compileOrderGraph
532 @readonly
533 def DependencyGraph(self) -> Graph:
534 """
535 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
537 :returns: Reference to the dependency graph.
538 """
539 return self._dependencyGraph
541 @readonly
542 def HierarchyGraph(self) -> Graph:
543 """
544 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
546 :returns: Reference to the hierarchy graph.
547 """
548 return self._hierarchyGraph
550 @readonly
551 def ObjectGraph(self) -> Graph:
552 """
553 Read-only property to access the object graph (:attr:`_objectGraph`).
555 :returns: Reference to the object graph.
556 """
557 return self._objectGraph
559 @readonly
560 def TopLevel(self) -> Union[Entity, Configuration]:
561 """
562 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
564 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``
565 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
567 :returns: Reference to the design's *top-level*.
568 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
569 :raises VHDLModelException: If there is more than one *top-level*.
570 """
571 # Check for cached result
572 if self._toplevel is not None:
573 return self._toplevel
575 if self._hierarchyGraph.EdgeCount == 0:
576 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
578 roots = tuple(self._hierarchyGraph.IterateRoots())
579 if len(roots) == 1:
580 toplevel = roots[0]
581 self._hierarchyGraph["toplevel"] = toplevel
582 self._toplevel = toplevel.Value
584 return toplevel.Value
585 else:
586 raise VHDLModelException(f"Found more than one toplevel: {', '.join(str(r) for r in roots)}")
588 def LoadStdLibrary(self) -> 'Library':
589 """
590 Load the predefined VHDL library ``std`` into the design.
592 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
594 :returns: The library object of library ``std``.
595 """
596 from pyVHDLModel.STD import Std
598 doc = Document(Path("std.vhdl"), parent=self)
600 library = Std()
601 for designUnit in library.IterateDesignUnits():
602 doc._AddDesignUnit(designUnit)
604 self.AddLibrary(library)
606 return library
608 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library':
609 """
610 Load the predefined VHDL library ``ieee`` into the design.
612 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
614 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics.
615 :returns: The library object of library ``ieee``.
616 """
617 from pyVHDLModel.IEEE import Ieee
619 doc = Document(Path("ieee.vhdl"), parent=self)
621 library = Ieee(flavor)
622 for designUnit in library.IterateDesignUnits():
623 doc._AddDesignUnit(designUnit)
625 self.AddLibrary(library)
627 return library
629 def AddLibrary(self, library: 'Library') -> None:
630 """
631 Add a VHDL library to the design.
633 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
634 If ok, set the libraries parent reference to the design.
636 :param library: Library object to loaded.
637 :raises LibraryExistsInDesignError: If the library already exists in the design.
638 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
639 """
640 libraryIdentifier = library.NormalizedIdentifier
641 if libraryIdentifier in self._libraries:
642 raise LibraryExistsInDesignError(library)
644 if library._parent is not None:
645 raise LibraryRegisteredToForeignDesignError(library)
647 self._libraries[libraryIdentifier] = library
648 library._parent = self
650 def GetLibrary(self, libraryName: str) -> 'Library':
651 """
652 Return an (existing) VHDL library object of name ``libraryName``.
654 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
656 :param libraryName: Name of the requested VHDL library.
657 :returns: The VHDL library object.
658 """
659 libraryIdentifier = libraryName.lower()
660 try:
661 return self._libraries[libraryIdentifier]
662 except KeyError:
663 lib = Library(libraryName, parent=self)
664 self._libraries[libraryIdentifier] = lib
665 lib._parent = self
666 return lib
668 # TODO: allow overloaded parameter library to be str?
669 def AddDocument(self, document: 'Document', library: 'Library') -> None:
670 """
671 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
673 .. rubric:: Algorithm
675 1. Iterate all entities in the document
677 1. Check if entity name might exist in target library.
678 2. Add entity to library and update library membership.
680 2. Iterate all architectures in the document
682 1. Check if architecture name might exist in target library.
683 2. Add architecture to library and update library membership.
685 3. Iterate all packages in the document
687 1. Check if package name might exist in target library.
688 2. Add package to library and update library membership.
690 4. Iterate all package bodies in the document
692 1. Check if package body name might exist in target library.
693 2. Add package body to library and update library membership.
695 5. Iterate all configurations in the document
697 1. Check if configuration name might exist in target library.
698 2. Add configuration to library and update library membership.
700 6. Iterate all contexts in the document
702 1. Check if context name might exist in target library.
703 2. Add context to library and update library membership.
705 :param document: The VHDL source code file.
706 :param library: The VHDL library used to register the embedded design units to.
707 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
708 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
709 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
710 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
711 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
712 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
713 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
714 """
715 # FIXME: this checks for the library name, but not the object
716 # should the libraries parent be checked too?
717 if library._normalizedIdentifier not in self._libraries: 717 ↛ 718line 717 didn't jump to line 718 because the condition on line 717 was never true
718 raise LibraryNotRegisteredError(library)
720 self._documents.append(document)
721 document._parent = self
723 for entityIdentifier, entity in document._entities.items():
724 if entityIdentifier in library._entities: 724 ↛ 725line 724 didn't jump to line 725 because the condition on line 724 was never true
725 raise EntityExistsInLibraryError(entity, library)
727 library._entities[entityIdentifier] = entity
728 entity.Library = library
730 for entityIdentifier, architectures in document._architectures.items():
731 try:
732 architecturesPerEntity = library._architectures[entityIdentifier]
733 for architectureIdentifier, architecture in architectures.items():
734 if architectureIdentifier in architecturesPerEntity:
735 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
737 architecturesPerEntity[architectureIdentifier] = architecture
738 architecture.Library = library
739 except KeyError:
740 architecturesPerEntity = document._architectures[entityIdentifier].copy()
741 library._architectures[entityIdentifier] = architecturesPerEntity
743 for architecture in architecturesPerEntity.values():
744 architecture.Library = library
746 for packageIdentifier, package in document._packages.items():
747 if packageIdentifier in library._packages: 747 ↛ 748line 747 didn't jump to line 748 because the condition on line 747 was never true
748 raise PackageExistsInLibraryError(package, library)
750 library._packages[packageIdentifier] = package
751 package.Library = library
753 for packageBodyIdentifier, packageBody in document._packageBodies.items():
754 if packageBodyIdentifier in library._packageBodies: 754 ↛ 755line 754 didn't jump to line 755 because the condition on line 754 was never true
755 raise PackageBodyExistsError(packageBody, library)
757 library._packageBodies[packageBodyIdentifier] = packageBody
758 packageBody.Library = library
760 for configurationIdentifier, configuration in document._configurations.items():
761 if configurationIdentifier in library._configurations: 761 ↛ 762line 761 didn't jump to line 762 because the condition on line 761 was never true
762 raise ConfigurationExistsInLibraryError(configuration, library)
764 library._configurations[configurationIdentifier] = configuration
765 configuration.Library = library
767 for contextIdentifier, context in document._contexts.items():
768 if contextIdentifier in library._contexts: 768 ↛ 769line 768 didn't jump to line 769 because the condition on line 768 was never true
769 raise ContextExistsInLibraryError(context, library)
771 library._contexts[contextIdentifier] = context
772 context.Library = library
774 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
775 """
776 Iterate all design units in the design.
778 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
780 .. rubric:: Algorithm
782 1. Iterate all VHDL libraries.
784 1. Iterate all contexts in that library.
785 2. Iterate all packages in that library.
786 3. Iterate all package bodies in that library.
787 4. Iterate all entites in that library.
788 5. Iterate all architectures in that library.
789 6. Iterate all configurations in that library.
791 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
792 :returns: A generator to iterate all matched design units in the design.
794 .. seealso::
796 :meth:`pyVHDLModel.Library.IterateDesignUnits`
797 Iterate all design units in the library.
798 :meth:`pyVHDLModel.Document.IterateDesignUnits`
799 Iterate all design units in the document.
800 """
801 for library in self._libraries.values():
802 yield from library.IterateDesignUnits(filter)
804 def Analyze(self) -> None:
805 """
806 Analyze the whole design.
808 .. rubric:: Algorithm
810 1. Analyze dependencies of design units. |br|
811 This will also yield the design hierarchy and the compiler order.
812 2. Analyze dependencies of types and objects.
814 .. seealso::
816 :meth:`AnalyzeDependencies`
817 Analyze the dependencies of design units.
819 :meth:`AnalyzeObjects`
820 Analyze the dependencies of types and objects.
821 """
822 self.AnalyzeDependencies()
823 self.AnalyzeObjects()
825 def AnalyzeDependencies(self) -> None:
826 """
827 Analyze the dependencies of design units.
829 .. rubric:: Algorithm
831 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
832 |rarr| :meth:`CreateDependencyGraph`
833 2. Create the compile order graph. |br|
834 |rarr| :meth:`CreateCompileOrderGraph`
835 3. Index all packages. |br|
836 |rarr| :meth:`IndexPackages`
837 4. Index all architectures. |br|
838 |rarr| :meth:`IndexArchitectures`
839 5. Link all contexts |br|
840 |rarr| :meth:`LinkContexts`
841 6. Link all architectures. |br|
842 |rarr| :meth:`LinkArchitectures`
843 7. Link all package bodies. |br|
844 |rarr| :meth:`LinkPackageBodies`
845 8. Link all library references. |br|
846 |rarr| :meth:`LinkLibraryReferences`
847 9. Link all package references. |br|
848 |rarr| :meth:`LinkPackageReferences`
849 10. Link all context references. |br|
850 |rarr| :meth:`LinkContextReferences`
851 11. Link all components. |br|
852 |rarr| :meth:`LinkComponents`
853 12. Link all instantiations. |br|
854 |rarr| :meth:`LinkInstantiations`
855 13. Create the hierarchy graph. |br|
856 |rarr| :meth:`CreateHierarchyGraph`
857 14. Compute the compile order. |br|
858 |rarr| :meth:`ComputeCompileOrder`
859 """
860 self.CreateDependencyGraph()
861 self.CreateCompileOrderGraph()
863 self.IndexPackages()
864 self.IndexArchitectures()
866 self.LinkContexts()
867 self.LinkArchitectures()
868 self.LinkPackageBodies()
869 self.LinkLibraryReferences()
870 self.LinkPackageReferences()
871 self.LinkContextReferences()
873 self.LinkComponents()
874 self.LinkInstantiations()
875 self.CreateHierarchyGraph()
876 self.ComputeCompileOrder()
878 def AnalyzeObjects(self) -> None:
879 """
880 Analyze the dependencies of types and objects.
882 .. rubric:: Algorithm
884 1. Index all entities. |br|
885 |rarr| :meth:`IndexEntities`
886 2. Index all package bodies. |br|
887 |rarr| :meth:`IndexPackageBodies`
888 3. Import objects. |br|
889 |rarr| :meth:`ImportObjects`
890 4. Create the type and object graph. |br|
891 |rarr| :meth:`CreateTypeAndObjectGraph`
892 """
893 self.IndexEntities()
894 self.IndexPackageBodies()
896 self.ImportObjects()
897 self.CreateTypeAndObjectGraph()
899 def CreateDependencyGraph(self) -> None:
900 """
901 Create all vertices of the dependency graph by iterating all design units in all libraries.
903 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
904 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
906 Each vertex has the following properties:
908 * The vertex' ID is the design unit's identifier.
909 * The vertex' value references the design unit.
910 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
911 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
913 .. rubric:: Algorithm
915 1. Iterate all libraries in the design.
917 * Create a vertex for that library and reference the library by the vertex' value field. |br|
918 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
920 1. Iterate all contexts in that library.
922 * Create a vertex for that context and reference the context by the vertex' value field. |br|
923 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
925 2. Iterate all packages in that library.
927 * Create a vertex for that package and reference the package by the vertex' value field. |br|
928 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
930 3. Iterate all package bodies in that library.
932 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
933 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
935 4. Iterate all entities in that library.
937 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
938 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
940 5. Iterate all architectures in that library.
942 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
943 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
945 6. Iterate all configurations in that library.
947 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
948 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
949 """
950 predefinedLibraries = ("std", "ieee")
952 for libraryIdentifier, library in self._libraries.items():
953 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
954 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
955 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
956 library._dependencyVertex = dependencyVertex
958 for contextIdentifier, context in library._contexts.items():
959 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
960 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
961 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
962 context._dependencyVertex = dependencyVertex
964 for packageIdentifier, package in library._packages.items():
965 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
966 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
967 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
968 package._dependencyVertex = dependencyVertex
970 for packageBodyIdentifier, packageBody in library._packageBodies.items():
971 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
972 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
973 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
974 packageBody._dependencyVertex = dependencyVertex
976 for entityIdentifier, entity in library._entities.items():
977 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
978 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
979 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
980 entity._dependencyVertex = dependencyVertex
982 for entityIdentifier, architectures in library._architectures.items():
983 for architectureIdentifier, architecture in architectures.items():
984 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
985 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
986 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
987 architecture._dependencyVertex = dependencyVertex
989 for configurationIdentifier, configuration in library._configurations.items():
990 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
991 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
992 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
993 configuration._dependencyVertex = dependencyVertex
995 def CreateCompileOrderGraph(self) -> None:
996 """
997 Create a compile-order graph with bidirectional references to the dependency graph.
999 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
1000 graph and bidirectionally referenced.
1002 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
1003 document relationship.
1005 Each added vertex has the following properties:
1007 * The vertex' ID is the document's filename.
1008 * The vertex' value references the document.
1009 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
1010 * A key-value-pair called ``predefined`` does not exist.
1012 .. rubric:: Algorithm
1014 1. Iterate all documents in the design.
1016 * Create a vertex for that document and reference the document by the vertex' value field. |br|
1017 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
1018 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
1019 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
1021 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
1022 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
1024 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
1025 dependency vertex. This expresses a "design unit is located in document" relation.
1027 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
1028 """
1029 for document in self._documents:
1030 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
1031 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1032 document._dependencyVertex = dependencyVertex
1034 compilerOrderVertex = dependencyVertex.Copy(
1035 self._compileOrderGraph,
1036 copyDict=True,
1037 linkingKeyToOriginalVertex="dependencyVertex",
1038 linkingKeyFromOriginalVertex="compileOrderVertex"
1039 )
1040 document._compileOrderVertex = compilerOrderVertex
1042 for designUnit in document._designUnits:
1043 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1044 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1046 def ImportObjects(self) -> None:
1047 def _ImportObjects(package: Package) -> None:
1048 from pyVHDLModel.Declaration import AttributeSpecification
1050 for referencedLibrary in package._referencedPackages.values():
1051 for referencedPackage in referencedLibrary.values():
1052 for declaredItem in referencedPackage._declaredItems:
1053 if isinstance(declaredItem, MultipleNamedEntityMixin): 1053 ↛ 1054line 1053 didn't jump to line 1054 because the condition on line 1053 was never true
1054 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1055 package._namespace._elements[normalizedIdentifier] = declaredItem
1056 elif isinstance(declaredItem, NamedEntityMixin): 1056 ↛ 1058line 1056 didn't jump to line 1058 because the condition on line 1056 was always true
1057 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1058 elif isinstance(declaredItem, AttributeSpecification):
1059 # FIXME: actually, this is not a declared item, but a application of an attribute to named entities
1060 WarningCollector.Raise(NotImplementedWarning(f"Attribute specification."))
1062 else:
1063 raise VHDLModelException(f"Unexpected declared item.")
1065 for libraryName in ("std", "ieee"):
1066 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1067 _ImportObjects(package)
1069 for document in self.IterateDocumentsInCompileOrder():
1070 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1071 _ImportObjects(package)
1073 def CreateTypeAndObjectGraph(self) -> None:
1074 def _HandlePackage(package) -> None:
1075 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1077 for deferredConstant in package._deferredConstants.values(): 1077 ↛ 1078line 1077 didn't jump to line 1078 because the loop on line 1077 never started
1078 print(f"Deferred Constant: {deferredConstant}")
1079 deferredConstantVertex = Vertex(
1080 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1081 value=deferredConstant,
1082 graph=self._objectGraph
1083 )
1084 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1085 deferredConstant._objectVertex = deferredConstantVertex
1087 for constant in package._constants.values(): 1087 ↛ 1088line 1087 didn't jump to line 1088 because the loop on line 1087 never started
1088 print(f"Constant: {constant}")
1089 constantVertex = Vertex(
1090 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1091 value=constant,
1092 graph=self._objectGraph
1093 )
1094 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1095 constant._objectVertex = constantVertex
1097 for type in package._types.values():
1098 print(f"Type: {type}")
1099 typeVertex = Vertex(
1100 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1101 value=type,
1102 graph=self._objectGraph
1103 )
1104 typeVertex["kind"] = ObjectGraphVertexKind.Type
1105 type._objectVertex = typeVertex
1107 for subtype in package._subtypes.values():
1108 print(f"Subtype: {subtype}")
1109 subtypeVertex = Vertex(
1110 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1111 value=subtype,
1112 graph=self._objectGraph
1113 )
1114 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1115 subtype._objectVertex = subtypeVertex
1117 for function in package._functions.values(): 1117 ↛ 1118line 1117 didn't jump to line 1118 because the loop on line 1117 never started
1118 print(f"Function: {function}")
1119 functionVertex = Vertex(
1120 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1121 value=function,
1122 graph=self._objectGraph
1123 )
1124 functionVertex["kind"] = ObjectGraphVertexKind.Function
1125 function._objectVertex = functionVertex
1127 for procedure in package._procedures.values(): 1127 ↛ 1128line 1127 didn't jump to line 1128 because the loop on line 1127 never started
1128 print(f"Procedure: {procedure}")
1129 procedureVertex = Vertex(
1130 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1131 value=procedure,
1132 graph=self._objectGraph
1133 )
1134 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1135 procedure._objectVertex = procedureVertex
1137 for signal in package._signals.values(): 1137 ↛ 1138line 1137 didn't jump to line 1138 because the loop on line 1137 never started
1138 print(f"Signal: {signal}")
1139 signalVertex = Vertex(
1140 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1141 value=signal,
1142 graph=self._objectGraph
1143 )
1144 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1145 signal._objectVertex = signalVertex
1147 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex):
1148 if isinstance(expression, UnaryExpression): 1148 ↛ 1149line 1148 didn't jump to line 1149 because the condition on line 1148 was never true
1149 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1150 elif isinstance(expression, BinaryExpression): 1150 ↛ 1151line 1150 didn't jump to line 1151 because the condition on line 1150 was never true
1151 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1152 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1153 elif isinstance(expression, TernaryExpression): 1153 ↛ 1154line 1153 didn't jump to line 1154 because the condition on line 1153 was never true
1154 WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression."))
1155 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol): 1155 ↛ 1156line 1155 didn't jump to line 1156 because the condition on line 1155 was never true
1156 obj = namespace.FindObject(expression)
1157 expression._reference = obj
1159 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1160 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1161 else:
1162 WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch"))
1164 def _LinkItems(package: Package):
1165 for item in package._declaredItems:
1166 if isinstance(item, Constant): 1166 ↛ 1167line 1166 didn't jump to line 1167 because the condition on line 1166 was never true
1167 print(f"constant: {item}")
1168 elif isinstance(item, DeferredConstant): 1168 ↛ 1169line 1168 didn't jump to line 1169 because the condition on line 1168 was never true
1169 print(f"deferred constant: {item}")
1170 elif isinstance(item, Signal): 1170 ↛ 1171line 1170 didn't jump to line 1171 because the condition on line 1170 was never true
1171 print(f"signal: {item}")
1172 elif isinstance(item, IntegerType):
1173 typeNode = item._objectVertex
1175 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1176 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1177 # elif isinstance(item, FloatingType):
1178 # print(f"signal: {item}")
1179 elif isinstance(item, PhysicalType):
1180 typeNode = item._objectVertex
1182 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1183 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1184 elif isinstance(item, ArrayType):
1185 # Resolve dimensions
1186 for dimension in item._dimensions:
1187 subtype = package._namespace.FindSubtype(dimension)
1188 dimension._reference = subtype
1190 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1191 edge["kind"] = ObjectGraphEdgeKind.Subtype
1193 # Resolve element subtype
1194 subtype = package._namespace.FindSubtype(item._elementType)
1195 item._elementType._reference = subtype
1197 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1198 edge["kind"] = ObjectGraphEdgeKind.Subtype
1199 elif isinstance(item, RecordType): 1199 ↛ 1201line 1199 didn't jump to line 1201 because the condition on line 1199 was never true
1200 # Resolve each elements subtype
1201 for element in item._elements:
1202 subtype = package._namespace.FindSubtype(element._subtype)
1203 element._subtype._reference = subtype
1205 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1206 edge["kind"] = ObjectGraphEdgeKind.Subtype
1207 else:
1208 print(f"not handled: {item}")
1210 for libraryName in ("std", "ieee"):
1211 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1212 _HandlePackage(package)
1213 _LinkItems(package)
1215 for document in self.IterateDocumentsInCompileOrder():
1216 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1217 _HandlePackage(package)
1218 _LinkItems(package)
1220 def LinkContexts(self) -> None:
1221 """
1222 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1224 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1225 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1226 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1228 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1229 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1230 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1231 dependency graph is added for that relationship.
1233 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1234 referenced package,
1235 """
1236 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1237 # Create entries in _referenced*** for the current working library under its real name.
1238 workingLibrary: Library = context.Library
1239 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1241 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1242 context._referencedPackages[libraryNormalizedIdentifier] = {}
1243 context._referencedContexts[libraryNormalizedIdentifier] = {}
1245 # Process all library clauses
1246 for libraryReference in context._libraryReferences:
1247 # A library clause can have multiple comma-separated references
1248 for libraryName in libraryReference.Symbols:
1249 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1250 try:
1251 library = self._libraries[libraryNormalizedIdentifier]
1252 except KeyError:
1253 raise ReferencedLibraryNotExistingError(context, libraryName)
1254 # TODO: add position to these messages
1256 libraryName.Library = library
1258 context._referencedLibraries[libraryNormalizedIdentifier] = library
1259 context._referencedPackages[libraryNormalizedIdentifier] = {}
1260 context._referencedContexts[libraryNormalizedIdentifier] = {}
1261 # TODO: warn duplicate library reference
1263 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1264 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1266 # Process all use clauses
1267 for packageReference in context.PackageReferences:
1268 # A use clause can have multiple comma-separated references
1269 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1270 packageName = symbol.Name.Prefix
1271 libraryName = packageName.Prefix
1273 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1274 packageNormalizedIdentifier = packageName._normalizedIdentifier
1276 # In case work is used, resolve to the real library name.
1277 if libraryNormalizedIdentifier == "work": 1277 ↛ 1278line 1277 didn't jump to line 1278 because the condition on line 1277 was never true
1278 library: Library = context._parent
1279 libraryNormalizedIdentifier = library._normalizedIdentifier
1280 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1280 ↛ 1282line 1280 didn't jump to line 1282 because the condition on line 1280 was never true
1281 # TODO: This check doesn't trigger if it's the working library.
1282 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1283 else:
1284 library = self._libraries[libraryNormalizedIdentifier]
1286 try:
1287 package = library._packages[packageNormalizedIdentifier]
1288 except KeyError:
1289 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1291 symbol.Package = package
1293 # TODO: warn duplicate package reference
1294 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1296 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1297 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1299 # TODO: update the namespace with visible members
1300 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1300 ↛ 1303line 1300 didn't jump to line 1303 because the condition on line 1300 was always true
1301 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'."))
1303 elif isinstance(symbol, PackageMemberReferenceSymbol):
1304 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1306 else:
1307 raise VHDLModelException()
1309 def LinkArchitectures(self) -> None:
1310 """
1311 Link all architectures to corresponding entities in all libraries.
1313 .. rubric:: Algorithm
1315 1. Iterate all libraries:
1317 1. Iterate all architecture groups (grouped per entity symbol's name).
1318 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1320 * Check if entity symbol's name exists as an entity in this library.
1322 1. For each architecture in the same architecture group:
1324 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1325 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1326 * Set parent namespace of architecture's namespace to the entitie's namespace.
1327 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1329 .. seealso::
1331 :meth:`LinkPackageBodies`
1332 Link all package bodies to corresponding packages in all libraries.
1333 """
1334 for library in self._libraries.values():
1335 library.LinkArchitectures()
1337 def LinkPackageBodies(self) -> None:
1338 """
1339 Link all package bodies to corresponding packages in all libraries.
1341 .. rubric:: Algorithm
1343 1. Iterate all libraries:
1345 1. Iterate all package bodies.
1346 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1348 * Check if package body symbol's name exists as a package in this library.
1349 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1350 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1351 * Set parent namespace of package body's namespace to the package's namespace.
1352 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1354 .. seealso::
1356 :meth:`LinkArchitectures`
1357 Link all architectures to corresponding entities in all libraries.
1358 """
1359 for library in self._libraries.values():
1360 library.LinkPackageBodies()
1362 def LinkLibraryReferences(self) -> None:
1363 DEFAULT_LIBRARIES = ("std",)
1365 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1366 # All primary units supporting a context, have at least one library implicitly referenced
1367 if isinstance(designUnit, PrimaryUnit):
1368 for libraryIdentifier in DEFAULT_LIBRARIES:
1369 referencedLibrary = self._libraries[libraryIdentifier]
1370 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1371 designUnit._referencedPackages[libraryIdentifier] = {}
1372 designUnit._referencedContexts[libraryIdentifier] = {}
1373 # TODO: catch KeyError on self._libraries[libName]
1374 # TODO: warn duplicate library reference
1376 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1377 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1379 workingLibrary: Library = designUnit.Library
1380 libraryIdentifier = workingLibrary.NormalizedIdentifier
1381 referencedLibrary = self._libraries[libraryIdentifier]
1384 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1385 designUnit._referencedPackages[libraryIdentifier] = {}
1386 designUnit._referencedContexts[libraryIdentifier] = {}
1388 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1389 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1391 # All secondary units inherit referenced libraries from their primary units.
1392 else:
1393 if isinstance(designUnit, Architecture):
1394 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1395 elif isinstance(designUnit, PackageBody): 1395 ↛ 1398line 1395 didn't jump to line 1398 because the condition on line 1395 was always true
1396 referencedLibraries = designUnit.Package.Package._referencedLibraries
1397 else:
1398 raise VHDLModelException()
1400 for libraryIdentifier, library in referencedLibraries.items():
1401 designUnit._referencedLibraries[libraryIdentifier] = library
1403 for libraryReference in designUnit._libraryReferences:
1404 # A library clause can have multiple comma-separated references
1405 for librarySymbol in libraryReference.Symbols:
1406 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1407 if libraryIdentifier == "work": 1407 ↛ 1408line 1407 didn't jump to line 1408 because the condition on line 1407 was never true
1408 continue
1410 try:
1411 library = self._libraries[libraryIdentifier]
1412 except KeyError:
1413 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1414 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1415 raise ex
1417 librarySymbol.Library = library
1418 designUnit._referencedLibraries[libraryIdentifier] = library
1419 designUnit._referencedPackages[libraryIdentifier] = {}
1420 designUnit._referencedContexts[libraryIdentifier] = {}
1421 # TODO: warn duplicate library reference
1423 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1424 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1426 def LinkPackageReferences(self) -> None:
1427 DEFAULT_PACKAGES = (
1428 ("std", ("standard",)),
1429 )
1431 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1432 # All primary units supporting a context, have at least one package implicitly referenced
1433 if isinstance(designUnit, PrimaryUnit):
1434 if designUnit.Library.NormalizedIdentifier != "std" and \
1435 designUnit.NormalizedIdentifier != "standard":
1436 for lib in DEFAULT_PACKAGES:
1437 if lib[0] not in designUnit._referencedLibraries: 1437 ↛ 1438line 1437 didn't jump to line 1438 because the condition on line 1437 was never true
1438 raise VHDLModelException()
1439 for pack in lib[1]:
1440 referencedPackage = self._libraries[lib[0]]._packages[pack]
1441 designUnit._referencedPackages[lib[0]][pack] = referencedPackage
1442 # TODO: catch KeyError on self._libraries[lib[0]]._packages[pack]
1443 # TODO: warn duplicate package reference
1445 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1446 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1448 # All secondary units inherit referenced packages from their primary units.
1449 else:
1450 if isinstance(designUnit, Architecture):
1451 referencedPackages = designUnit.Entity.Entity._referencedPackages
1452 elif isinstance(designUnit, PackageBody): 1452 ↛ 1455line 1452 didn't jump to line 1455 because the condition on line 1452 was always true
1453 referencedPackages = designUnit.Package.Package._referencedPackages
1454 else:
1455 raise VHDLModelException()
1457 for packageIdentifier, package in referencedPackages.items():
1458 designUnit._referencedPackages[packageIdentifier] = package
1460 for packageReference in designUnit.PackageReferences:
1461 # A use clause can have multiple comma-separated references
1462 for packageMemberSymbol in packageReference.Symbols:
1463 packageName = packageMemberSymbol.Name.Prefix
1464 libraryName = packageName.Prefix
1466 libraryIdentifier = libraryName.NormalizedIdentifier
1467 packageIdentifier = packageName.NormalizedIdentifier
1469 # In case work is used, resolve to the real library name.
1470 if libraryIdentifier == "work":
1471 library: Library = designUnit.Library
1472 libraryIdentifier = library.NormalizedIdentifier
1473 elif libraryIdentifier not in designUnit._referencedLibraries: 1473 ↛ 1475line 1473 didn't jump to line 1475 because the condition on line 1473 was never true
1474 # TODO: This check doesn't trigger if it's the working library.
1475 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1476 else:
1477 library = self._libraries[libraryIdentifier]
1479 try:
1480 package = library._packages[packageIdentifier]
1481 except KeyError:
1482 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1483 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1484 raise ex
1486 packageMemberSymbol.Package = package
1488 # TODO: warn duplicate package reference
1489 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1491 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1492 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1494 # TODO: update the namespace with visible members
1495 if isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1495 ↛ 1501line 1495 didn't jump to line 1501 because the condition on line 1495 was always true
1496 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled."))
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 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1504 else:
1505 raise VHDLModelException()
1507 def LinkContextReferences(self) -> None:
1508 for designUnit in self.IterateDesignUnits():
1509 for contextReference in designUnit._contextReferences:
1510 # A context reference can have multiple comma-separated references
1511 for contextSymbol in contextReference.Symbols:
1512 libraryName = contextSymbol.Name.Prefix
1514 libraryIdentifier = libraryName.NormalizedIdentifier
1515 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1517 # In case work is used, resolve to the real library name.
1518 if libraryIdentifier == "work": 1518 ↛ 1521line 1518 didn't jump to line 1521 because the condition on line 1518 was always true
1519 referencedLibrary = designUnit.Library
1520 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1521 elif libraryIdentifier not in designUnit._referencedLibraries:
1522 # TODO: This check doesn't trigger if it's the working library.
1523 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1524 else:
1525 referencedLibrary = self._libraries[libraryIdentifier]
1527 try:
1528 referencedContext = referencedLibrary._contexts[contextIdentifier]
1529 except KeyError:
1530 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1532 contextSymbol.Package = referencedContext
1534 # TODO: warn duplicate referencedContext reference
1535 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1537 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1538 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1540 for vertex in self._dependencyGraph.IterateTopologically():
1541 if vertex["kind"] is DependencyGraphVertexKind.Context:
1542 context: Context = vertex.Value
1543 for designUnitVertex in vertex.IteratePredecessorVertices():
1544 designUnit: DesignUnit = designUnitVertex.Value
1545 for libraryIdentifier, library in context._referencedLibraries.items():
1546 # if libraryIdentifier in designUnit._referencedLibraries:
1547 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1549 designUnit._referencedLibraries[libraryIdentifier] = library
1550 designUnit._referencedPackages[libraryIdentifier] = {}
1552 for libraryIdentifier, packages in context._referencedPackages.items():
1553 for packageIdentifier, package in packages.items():
1554 if packageIdentifier in designUnit._referencedPackages: 1554 ↛ 1555line 1554 didn't jump to line 1555 because the condition on line 1554 was never true
1555 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1557 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1559 def LinkComponents(self) -> None:
1560 """
1561 Link components to matching entities found in same VHDL library.
1563 .. rubric:: Algorithm
1565 1. Iterate all design units with component declarations (packages and architectures):
1567 1. Iterate all component declarations in a package or architecture:
1569 * Check if an entity with matching name can be found in the VHDL library the package is declared within. If
1570 found, set the component's entity reference to that entity, otherwise check if blackboxes are allowed for
1571 that component. If so, mark the component as a blackbox, otherwise, raise an exception.
1573 2. Iterate concurrent statements with declaration regions (block statements, generate statements) if the design
1574 unit is an architecture:
1576 * If the statement is an :class:`IfGenerateStatement`:
1578 1. Iterate declared components in the :class:`IfGenerateBranch`.
1579 2. Iterate declared components in each :class:`ElIfGenerateBranch`.
1580 3. Iterate declared components in the :class:`ElseGenerateBranch` if it exists.
1582 * If the statement is an :class:`ForGenerateStatement`:
1584 1. Iterate declared components.
1586 * If the statement is an :class:`CaseGenerateStatement`:
1588 1. Iterate declared components.
1589 2. Iterate
1591 .. seealso::
1593 :meth:`LinkInstantiations`
1594 Link instantiations to components and entities.
1595 :meth:`AnalyzeDependencies`
1596 Analyze dependencies in a design (calls this method).
1597 """
1598 def linkStatements(library: Library, concurrent: ConcurrentStatementsMixin) -> None:
1599 for statement in concurrent._statements:
1600 if isinstance(statement, IfGenerateStatement): 1600 ↛ 1601line 1600 didn't jump to line 1601 because the condition on line 1600 was never true
1601 linkComponents(library, statement._ifBranch)
1602 linkStatements(library, statement._ifBranch)
1603 for branch in statement._elsifBranches:
1604 linkComponents(library, branch)
1605 linkStatements(library, branch)
1606 if (branch := statement._elseBranch) is not None:
1607 linkComponents(library, branch)
1608 linkStatements(library, branch)
1609 elif isinstance(statement, ForGenerateStatement): 1609 ↛ 1610line 1609 didn't jump to line 1610 because the condition on line 1609 was never true
1610 linkComponents(library, statement)
1611 linkStatements(library, statement)
1612 elif isinstance(statement, CaseGenerateStatement): 1612 ↛ 1613line 1612 didn't jump to line 1613 because the condition on line 1612 was never true
1613 for case in statement._cases:
1614 linkComponents(library, case)
1615 linkStatements(library, case)
1616 elif isinstance(statement, ConcurrentBlockStatement): 1616 ↛ 1617line 1616 didn't jump to line 1617 because the condition on line 1616 was never true
1617 linkComponents(library, statement)
1618 linkStatements(library, statement)
1620 def searchEntityAndLinkComponent(library: Library, component: Component) -> None:
1621 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1622 # Currently, component has no _dependencyVertex field
1623 try:
1624 entity = library._entities[component.NormalizedIdentifier]
1625 except KeyError:
1626 if component.AllowBlackbox:
1627 component._isBlackBox = True
1628 return
1629 else:
1630 raise VHDLModelException(
1631 f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1633 component.Entity = entity
1635 def linkComponents(library: Library, declarationRegion: ConcurrentDeclarationRegionMixin) -> None:
1636 for item in declarationRegion._declaredItems:
1637 if isinstance(item, Component):
1638 searchEntityAndLinkComponent(library, item)
1640 for designUnit in self.IterateDesignUnits(DesignUnitKind.Package | DesignUnitKind.Architecture): # type: Union[Package, Architecture]
1641 library = designUnit._parent
1642 for component in designUnit._components.values(): 1642 ↛ 1643line 1642 didn't jump to line 1643 because the loop on line 1642 never started
1643 searchEntityAndLinkComponent(library, component)
1645 if isinstance(designUnit, Architecture):
1646 linkStatements(library, designUnit)
1648 def LinkInstantiations(self) -> None:
1649 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1650 for instance in architecture.IterateInstantiations():
1651 if isinstance(instance, EntityInstantiation): 1651 ↛ 1684line 1651 didn't jump to line 1684 because the condition on line 1651 was always true
1652 libraryName = instance.Entity.Name.Prefix
1653 libraryIdentifier = libraryName.Identifier
1654 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1655 if normalizedLibraryIdentifier == "work":
1656 libraryIdentifier = architecture.Library.Identifier
1657 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1658 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1658 ↛ 1659line 1658 didn't jump to line 1659 because the condition on line 1658 was never true
1659 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}'.")
1660 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1661 raise ex
1663 try:
1664 library = self._libraries[normalizedLibraryIdentifier]
1665 except KeyError:
1666 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1667 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1668 raise ex
1670 try:
1671 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1672 except KeyError:
1673 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}'.")
1674 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1675 if libs:
1676 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1677 raise ex
1679 instance.Entity.Entity = entity
1681 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1682 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1684 elif isinstance(instance, ComponentInstantiation):
1685 component = architecture._namespace.FindComponent(instance.Component)
1687 instance.Component.Component = component
1689 if not component.IsBlackbox:
1690 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1691 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1692 else:
1693 WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'."))
1695 elif isinstance(instance, ConfigurationInstantiation):
1696 WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'."))
1698 def IndexPackages(self) -> None:
1699 """
1700 Index all declared items in all packages in all libraries.
1702 .. rubric:: Algorithm
1704 1. Iterate all libraries:
1706 1. Iterate all packages |br|
1707 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1709 * Index all declared items in that package. |br|
1710 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1712 .. seealso::
1714 :meth:`IndexPackageBodies`
1715 Index all declared items in all package bodies in all libraries.
1716 :meth:`IndexEntities`
1717 Index all declared items in all entities in all libraries.
1718 :meth:`IndexArchitectures`
1719 Index all declared items in all architectures in all libraries.
1720 """
1721 for library in self._libraries.values():
1722 library.IndexPackages()
1724 def IndexPackageBodies(self) -> None:
1725 """
1726 Index all declared items in all packages in all libraries.
1728 .. rubric:: Algorithm
1730 1. Iterate all libraries:
1732 1. Iterate all packages |br|
1733 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
1735 * Index all declared items in that package body. |br|
1736 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
1738 .. seealso::
1740 :meth:`IndexPackages`
1741 Index all declared items in all packages in all libraries.
1742 :meth:`IndexEntities`
1743 Index all declared items in all entities in all libraries.
1744 :meth:`IndexArchitectures`
1745 Index all declared items in all architectures in all libraries.
1746 """
1747 for library in self._libraries.values():
1748 library.IndexPackageBodies()
1750 def IndexEntities(self) -> None:
1751 """
1752 Index all declared items in all packages in all libraries.
1754 .. rubric:: Algorithm
1756 1. Iterate all libraries:
1758 1. Iterate all packages |br|
1759 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
1761 * Index all declared items in that entity. |br|
1762 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
1764 .. seealso::
1766 :meth:`IndexPackages`
1767 Index all declared items in all packages in all libraries.
1768 :meth:`IndexPackageBodies`
1769 Index all declared items in all package bodies in all libraries.
1770 :meth:`IndexArchitectures`
1771 Index all declared items in all architectures in all libraries.
1772 """
1773 for library in self._libraries.values():
1774 library.IndexEntities()
1776 def IndexArchitectures(self) -> None:
1777 """
1778 Index all declared items in all packages in all libraries.
1780 .. rubric:: Algorithm
1782 1. Iterate all libraries:
1784 1. Iterate all packages |br|
1785 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
1787 * Index all declared items in that architecture. |br|
1788 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
1790 .. seealso::
1792 :meth:`IndexPackages`
1793 Index all declared items in all packages in all libraries.
1794 :meth:`IndexPackageBodies`
1795 Index all declared items in all package bodies in all libraries.
1796 :meth:`IndexEntities`
1797 Index all declared items in all entities in all libraries.
1798 """
1799 for library in self._libraries.values():
1800 library.IndexArchitectures()
1802 def CreateHierarchyGraph(self) -> None:
1803 """
1804 Create the hierarchy graph from dependency graph.
1806 .. rubric:: Algorithm
1808 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
1810 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
1811 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
1813 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
1814 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
1816 2. Iterate all architectures ...
1818 .. todo:: Design::CreateHierarchyGraph describe algorithm
1820 1. Iterate all outbound edges
1822 .. todo:: Design::CreateHierarchyGraph describe algorithm
1823 """
1824 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
1825 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
1826 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
1827 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
1828 vertex.Value._hierarchyVertex = hierarchyVertex
1830 # Copy implementation edges from
1831 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
1832 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
1833 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
1834 if DependencyGraphEdgeKind.Implementation in kind:
1835 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1836 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
1837 elif DependencyGraphEdgeKind.Instantiation in kind:
1838 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
1840 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
1841 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
1842 continue
1844 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
1845 else:
1846 continue
1848 newEdge["kind"] = kind
1850 def ComputeCompileOrder(self) -> None:
1851 def predicate(edge: Edge) -> bool:
1852 return (
1853 DependencyGraphEdgeKind.Implementation in edge["kind"] or
1854 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
1855 DependencyGraphEdgeKind.UseClause in edge["kind"] or
1856 DependencyGraphEdgeKind.ContextReference in edge["kind"]
1857 ) and edge.Destination["predefined"] is False
1859 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
1860 sourceDocument: Document = edge.Source.Value.Document
1861 destinationDocument: Document = edge.Destination.Value.Document
1863 sourceVertex = sourceDocument._compileOrderVertex
1864 destinationVertex = destinationDocument._compileOrderVertex
1866 # Don't add self-edges
1867 if sourceVertex is destinationVertex: 1867 ↛ 1870line 1867 didn't jump to line 1870 because the condition on line 1867 was always true
1868 continue
1869 # Don't add parallel edges
1870 elif sourceVertex.HasEdgeToDestination(destinationVertex):
1871 continue
1873 e = sourceVertex.EdgeToVertex(destinationVertex)
1874 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1876 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
1877 e["kind"] = DependencyGraphEdgeKind.CompileOrder
1879 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
1880 """
1881 Iterate all document in compile-order.
1883 .. rubric:: Algorithm
1885 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
1887 1. Iterate compile-order graph in topological order. |br|
1888 :meth:`pyTooling.Graph.Graph.IterateTopologically`
1890 * yield the compiler-order vertex' referenced document.
1892 :returns: A generator to iterate all documents in compile-order in the design.
1893 :raises VHDLModelException: If compile-order was not computed.
1895 .. seealso::
1897 .. todo:: missing text
1899 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
1901 """
1902 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1: 1902 ↛ 1903line 1902 didn't jump to line 1903 because the condition on line 1902 was never true
1903 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
1905 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
1906 yield compileOrderNode.Value
1908 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
1909 WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units."))
1911 def __repr__(self) -> str:
1912 """
1913 Formats a representation of the design.
1915 **Format:** ``Document: 'my_design'``
1917 :returns: String representation of the design.
1918 """
1919 return f"Design: {self._name}"
1921 __str__ = __repr__
1924@export
1925class Library(ModelEntity, NamedEntityMixin, AllowBlackboxMixin):
1926 """A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units."""
1928 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library.
1929 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
1930 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
1931 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
1932 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
1933 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
1934 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
1936 _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`.
1938 def __init__(
1939 self,
1940 identifier: str,
1941 allowBlackbox: Nullable[bool] = None,
1942 parent: ModelEntity = None
1943 ) -> None:
1944 """
1945 Initialize a VHDL library.
1947 :param identifier: Name of the VHDL library.
1948 :param allowBlackbox: Specify if blackboxes are allowed in this design.
1949 :param parent: The parent model entity (design) of this VHDL library.
1950 """
1951 super().__init__(parent)
1952 NamedEntityMixin.__init__(self, identifier)
1953 AllowBlackboxMixin.__init__(self, allowBlackbox)
1955 self._contexts = {}
1956 self._configurations = {}
1957 self._entities = {}
1958 self._architectures = {}
1959 self._packages = {}
1960 self._packageBodies = {}
1962 self._dependencyVertex = None
1964 @readonly
1965 def Contexts(self) -> Dict[str, Context]:
1966 """Returns a list of all context declarations declared in this library."""
1967 return self._contexts
1969 @readonly
1970 def Configurations(self) -> Dict[str, Configuration]:
1971 """Returns a list of all configuration declarations declared in this library."""
1972 return self._configurations
1974 @readonly
1975 def Entities(self) -> Dict[str, Entity]:
1976 """Returns a list of all entity declarations declared in this library."""
1977 return self._entities
1979 @readonly
1980 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
1981 """Returns a list of all architectures declarations declared in this library."""
1982 return self._architectures
1984 @readonly
1985 def Packages(self) -> Dict[str, Package]:
1986 """Returns a list of all package declarations declared in this library."""
1987 return self._packages
1989 @readonly
1990 def PackageBodies(self) -> Dict[str, PackageBody]:
1991 """Returns a list of all package body declarations declared in this library."""
1992 return self._packageBodies
1994 @readonly
1995 def DependencyVertex(self) -> Vertex:
1996 """
1997 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
1999 The dependency vertex references this library by its value field.
2001 :returns: The corresponding dependency vertex.
2002 """
2003 return self._dependencyVertex
2005 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2006 """
2007 Iterate all design units in the library.
2009 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2011 .. rubric:: Algorithm
2013 1. Iterate all contexts in that library.
2014 2. Iterate all packages in that library.
2015 3. Iterate all package bodies in that library.
2016 4. Iterate all entities in that library.
2017 5. Iterate all architectures in that library.
2018 6. Iterate all configurations in that library.
2020 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2021 :returns: A generator to iterate all matched design units in the library.
2023 .. seealso::
2025 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2026 Iterate all design units in the design.
2027 :meth:`pyVHDLModel.Document.IterateDesignUnits`
2028 Iterate all design units in the document.
2029 """
2030 if DesignUnitKind.Context in filter:
2031 for context in self._contexts.values():
2032 yield context
2034 if DesignUnitKind.Package in filter:
2035 for package in self._packages.values():
2036 yield package
2038 if DesignUnitKind.PackageBody in filter:
2039 for packageBody in self._packageBodies.values():
2040 yield packageBody
2042 if DesignUnitKind.Entity in filter:
2043 for entity in self._entities.values():
2044 yield entity
2046 if DesignUnitKind.Architecture in filter:
2047 for architectures in self._architectures.values():
2048 for architecture in architectures.values():
2049 yield architecture
2051 if DesignUnitKind.Configuration in filter:
2052 for configuration in self._configurations.values():
2053 yield configuration
2055 # for verificationProperty in self._verificationUnits.values():
2056 # yield verificationProperty
2057 # for verificationUnit in self._verificationProperties.values():
2058 # yield entity
2059 # for verificationMode in self._verificationModes.values():
2060 # yield verificationMode
2062 def LinkArchitectures(self) -> None:
2063 """
2064 Link all architectures to corresponding entities.
2066 .. rubric:: Algorithm
2068 1. Iterate all architecture groups (grouped per entity symbol's name).
2070 * Check if entity symbol's name exists as an entity in this library.
2072 1. For each architecture in the same architecture group:
2074 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
2075 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
2076 * Set parent namespace of architecture's namespace to the entitie's namespace.
2077 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
2079 :raises VHDLModelException: If entity name doesn't exist.
2080 :raises VHDLModelException: If architecture name already exists for entity.
2082 .. seealso::
2084 :meth:`LinkPackageBodies`
2085 Link all package bodies to corresponding packages.
2086 """
2087 for entityName, architecturesPerEntity in self._architectures.items():
2088 if entityName not in self._entities: 2088 ↛ 2089line 2088 didn't jump to line 2089 because the condition on line 2088 was never true
2089 architectureNames = "', '".join(architecturesPerEntity.keys())
2090 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
2091 # TODO: search in other libraries to find that entity.
2092 # TODO: add code position
2094 entity = self._entities[entityName]
2095 for architecture in architecturesPerEntity.values():
2096 if architecture._normalizedIdentifier in entity._architectures: 2096 ↛ 2097line 2096 didn't jump to line 2097 because the condition on line 2096 was never true
2097 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
2098 # TODO: add code position of existing and current
2100 entity._architectures[architecture._normalizedIdentifier] = architecture
2101 architecture._entity.Entity = entity
2102 architecture._namespace._parentNamespace = entity._namespace
2104 # add "architecture -> entity" relation in dependency graph
2105 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
2106 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
2108 def LinkPackageBodies(self) -> None:
2109 """
2110 Link all package bodies to corresponding packages.
2112 .. rubric:: Algorithm
2114 1. Iterate all package bodies.
2116 * Check if package body symbol's name exists as a package in this library.
2117 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2118 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2119 * Set parent namespace of package body's namespace to the package's namespace.
2120 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2122 :raises VHDLModelException: If package name doesn't exist.
2124 .. seealso::
2126 :meth:`LinkArchitectures`
2127 Link all architectures to corresponding entities.
2128 """
2129 for packageBodyName, packageBody in self._packageBodies.items():
2130 if packageBodyName not in self._packages: 2130 ↛ 2131line 2130 didn't jump to line 2131 because the condition on line 2130 was never true
2131 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
2133 package = self._packages[packageBodyName]
2134 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
2135 packageBody._package.Package = package
2136 packageBody._namespace._parentNamespace = package._namespace
2138 # add "package body -> package" relation in dependency graph
2139 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2140 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2142 def IndexPackages(self) -> None:
2143 """
2144 Index declared items in all packages.
2146 .. rubric:: Algorithm
2148 1. Iterate all packages:
2150 * Index all declared items. |br|
2151 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2153 .. seealso::
2155 :meth:`IndexPackageBodies`
2156 Index all declared items in a package body.
2157 :meth:`IndexEntities`
2158 Index all declared items in an entity.
2159 :meth:`IndexArchitectures`
2160 Index all declared items in an architecture.
2161 """
2162 for package in self._packages.values():
2163 if isinstance(package, Package): 2163 ↛ 2162line 2163 didn't jump to line 2162 because the condition on line 2163 was always true
2164 package.IndexDeclaredItems()
2166 def IndexPackageBodies(self) -> None:
2167 """
2168 Index declared items in all package bodies.
2170 .. rubric:: Algorithm
2172 1. Iterate all package bodies:
2174 * Index all declared items. |br|
2175 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2177 .. seealso::
2179 :meth:`IndexPackages`
2180 Index all declared items in a package.
2181 :meth:`IndexEntities`
2182 Index all declared items in an entity.
2183 :meth:`IndexArchitectures`
2184 Index all declared items in an architecture.
2185 """
2186 for packageBody in self._packageBodies.values():
2187 packageBody.IndexDeclaredItems()
2189 def IndexEntities(self) -> None:
2190 """
2191 Index declared items in all entities.
2193 .. rubric:: Algorithm
2195 1. Iterate all entities:
2197 * Index all declared items. |br|
2198 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2200 .. seealso::
2202 :meth:`IndexPackages`
2203 Index all declared items in a package.
2204 :meth:`IndexPackageBodies`
2205 Index all declared items in a package body.
2206 :meth:`IndexArchitectures`
2207 Index all declared items in an architecture.
2208 """
2209 for entity in self._entities.values():
2210 entity.IndexDeclaredItems()
2212 def IndexArchitectures(self) -> None:
2213 """
2214 Index declared items in all architectures.
2216 .. rubric:: Algorithm
2218 1. Iterate all architectures:
2220 * Index all declared items. |br|
2221 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2223 .. seealso::
2225 :meth:`IndexPackages`
2226 Index all declared items in a package.
2227 :meth:`IndexPackageBodies`
2228 Index all declared items in a package body.
2229 :meth:`IndexEntities`
2230 Index all declared items in an entity.
2231 """
2232 for architectures in self._architectures.values():
2233 for architecture in architectures.values():
2234 architecture.IndexDeclaredItems()
2235 architecture.IndexStatements()
2237 def __repr__(self) -> str:
2238 """
2239 Formats a representation of the library.
2241 **Format:** ``Library: 'my_library'``
2243 :returns: String representation of the library.
2244 """
2245 return f"Library: '{self._identifier}'"
2247 __str__ = __repr__
2250@export
2251class Document(ModelEntity, DocumentedEntityMixin):
2252 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2254 _path: Path #: path to the document. ``None`` if virtual document.
2255 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2256 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2257 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2258 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2259 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2260 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2261 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2262 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2263 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2264 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2266 _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`.
2267 _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`.
2269 def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
2270 super().__init__(parent)
2271 DocumentedEntityMixin.__init__(self, documentation)
2273 self._path = path
2274 self._designUnits = []
2275 self._contexts = {}
2276 self._configurations = {}
2277 self._entities = {}
2278 self._architectures = {}
2279 self._packages = {}
2280 self._packageBodies = {}
2281 self._verificationUnits = {}
2282 self._verificationProperties = {}
2283 self._verificationModes = {}
2285 self._dependencyVertex = None
2286 self._compileOrderVertex = None
2288 def _AddEntity(self, item: Entity) -> None:
2289 """
2290 Add an entity to the document's lists of design units.
2292 :param item: Entity object to be added to the document.
2293 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Entity`.
2294 :raises VHDLModelException: If entity name already exists in document.
2295 """
2296 if not isinstance(item, Entity): 2296 ↛ 2297line 2296 didn't jump to line 2297 because the condition on line 2296 was never true
2297 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2298 if version_info >= (3, 11): # pragma: no cover
2299 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2300 raise ex
2302 identifier = item._normalizedIdentifier
2303 if identifier in self._entities: 2303 ↛ 2305line 2303 didn't jump to line 2305 because the condition on line 2303 was never true
2304 # TODO: use a more specific exception
2305 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2307 self._entities[identifier] = item
2308 self._designUnits.append(item)
2309 item._document = self
2311 def _AddArchitecture(self, item: Architecture) -> None:
2312 """
2313 Add an architecture to the document's lists of design units.
2315 :param item: Architecture object to be added to the document.
2316 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Architecture`.
2317 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2318 """
2319 if not isinstance(item, Architecture): 2319 ↛ 2320line 2319 didn't jump to line 2320 because the condition on line 2319 was never true
2320 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2321 if version_info >= (3, 11): # pragma: no cover
2322 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2323 raise ex
2325 entity = item._entity.Name
2326 entityIdentifier = entity._normalizedIdentifier
2327 try:
2328 architectures = self._architectures[entityIdentifier]
2329 if item._normalizedIdentifier in architectures:
2330 # TODO: use a more specific exception
2331 # FIXME: this is allowed and should be a warning or a strict mode.
2332 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2334 architectures[item.Identifier] = item
2335 except KeyError:
2336 self._architectures[entityIdentifier] = {item._identifier: item}
2338 self._designUnits.append(item)
2339 item._document = self
2341 def _AddPackage(self, item: Package) -> None:
2342 """
2343 Add a package to the document's lists of design units.
2345 :param item: Package object to be added to the document.
2346 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Package`.
2347 :raises VHDLModelException: If package name already exists in document.
2348 """
2349 if not isinstance(item, (Package, PackageInstantiation)): 2349 ↛ 2350line 2349 didn't jump to line 2350 because the condition on line 2349 was never true
2350 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2351 if version_info >= (3, 11): # pragma: no cover
2352 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2353 raise ex
2355 identifier = item._normalizedIdentifier
2356 if identifier in self._packages: 2356 ↛ 2358line 2356 didn't jump to line 2358 because the condition on line 2356 was never true
2357 # TODO: use a more specific exception
2358 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2360 self._packages[identifier] = item
2361 self._designUnits.append(item)
2362 item._document = self
2364 def _AddPackageBody(self, item: PackageBody) -> None:
2365 """
2366 Add a package body to the document's lists of design units.
2368 :param item: Package body object to be added to the document.
2369 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.PackageBody`.
2370 :raises VHDLModelException: If package body name already exists in document.
2371 """
2372 if not isinstance(item, PackageBody): 2372 ↛ 2373line 2372 didn't jump to line 2373 because the condition on line 2372 was never true
2373 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2374 if version_info >= (3, 11): # pragma: no cover
2375 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2376 raise ex
2378 identifier = item._normalizedIdentifier
2379 if identifier in self._packageBodies: 2379 ↛ 2381line 2379 didn't jump to line 2381 because the condition on line 2379 was never true
2380 # TODO: use a more specific exception
2381 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2383 self._packageBodies[identifier] = item
2384 self._designUnits.append(item)
2385 item._document = self
2387 def _AddContext(self, item: Context) -> None:
2388 """
2389 Add a context to the document's lists of design units.
2391 :param item: Context object to be added to the document.
2392 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Context`.
2393 :raises VHDLModelException: If context name already exists in document.
2394 """
2395 if not isinstance(item, Context): 2395 ↛ 2396line 2395 didn't jump to line 2396 because the condition on line 2395 was never true
2396 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2397 if version_info >= (3, 11): # pragma: no cover
2398 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2399 raise ex
2401 identifier = item._normalizedIdentifier
2402 if identifier in self._contexts: 2402 ↛ 2404line 2402 didn't jump to line 2404 because the condition on line 2402 was never true
2403 # TODO: use a more specific exception
2404 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2406 self._contexts[identifier] = item
2407 self._designUnits.append(item)
2408 item._document = self
2410 def _AddConfiguration(self, item: Configuration) -> None:
2411 """
2412 Add a configuration to the document's lists of design units.
2414 :param item: Configuration object to be added to the document.
2415 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.Configuration`.
2416 :raises VHDLModelException: If configuration name already exists in document.
2417 """
2418 if not isinstance(item, Configuration): 2418 ↛ 2419line 2418 didn't jump to line 2419 because the condition on line 2418 was never true
2419 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2420 if version_info >= (3, 11): # pragma: no cover
2421 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2422 raise ex
2424 identifier = item._normalizedIdentifier
2425 if identifier in self._configurations: 2425 ↛ 2427line 2425 didn't jump to line 2427 because the condition on line 2425 was never true
2426 # TODO: use a more specific exception
2427 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2429 self._configurations[identifier] = item
2430 self._designUnits.append(item)
2431 item._document = self
2433 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2434 if not isinstance(item, VerificationUnit):
2435 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2436 if version_info >= (3, 11): # pragma: no cover
2437 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2438 raise ex
2440 identifier = item._normalizedIdentifier
2441 if identifier in self._verificationUnits:
2442 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2444 self._verificationUnits[identifier] = item
2445 self._designUnits.append(item)
2446 item._document = self
2448 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2449 if not isinstance(item, VerificationProperty):
2450 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2451 if version_info >= (3, 11): # pragma: no cover
2452 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2453 raise ex
2455 identifier = item.NormalizedIdentifier
2456 if identifier in self._verificationProperties:
2457 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2459 self._verificationProperties[identifier] = item
2460 self._designUnits.append(item)
2461 item._document = self
2463 def _AddVerificationMode(self, item: VerificationMode) -> None:
2464 if not isinstance(item, VerificationMode):
2465 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2466 if version_info >= (3, 11): # pragma: no cover
2467 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2468 raise ex
2470 identifier = item.NormalizedIdentifier
2471 if identifier in self._verificationModes:
2472 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2474 self._verificationModes[identifier] = item
2475 self._designUnits.append(item)
2476 item._document = self
2478 def _AddDesignUnit(self, item: DesignUnit) -> None:
2479 """
2480 Add a design unit to the document's lists of design units.
2482 :param item: Configuration object to be added to the document.
2483 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2484 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnits.DesignUnit`.
2485 :raises VHDLModelException: If configuration name already exists in document.
2486 """
2487 if not isinstance(item, DesignUnit): 2487 ↛ 2488line 2487 didn't jump to line 2488 because the condition on line 2487 was never true
2488 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2489 if version_info >= (3, 11): # pragma: no cover
2490 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2491 raise ex
2493 if isinstance(item, Entity):
2494 self._AddEntity(item)
2495 elif isinstance(item, Architecture):
2496 self._AddArchitecture(item)
2497 elif isinstance(item, Package):
2498 self._AddPackage(item)
2499 elif isinstance(item, PackageBody):
2500 self._AddPackageBody(item)
2501 elif isinstance(item, Context):
2502 self._AddContext(item)
2503 elif isinstance(item, Configuration): 2503 ↛ 2505line 2503 didn't jump to line 2505 because the condition on line 2503 was always true
2504 self._AddConfiguration(item)
2505 elif isinstance(item, VerificationUnit):
2506 self._AddVerificationUnit(item)
2507 elif isinstance(item, VerificationProperty):
2508 self._AddVerificationProperty(item)
2509 elif isinstance(item, VerificationMode):
2510 self._AddVerificationMode(item)
2511 else:
2512 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2513 if version_info >= (3, 11): # pragma: no cover
2514 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2515 raise ex
2517 @readonly
2518 def Path(self) -> Path:
2519 """
2520 Read-only property to access the document's path (:attr:`_path`).
2522 :returns: The path of this document.
2523 """
2524 return self._path
2526 @readonly
2527 def DesignUnits(self) -> List[DesignUnit]:
2528 """
2529 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2531 :returns: List of all design units.
2532 """
2533 return self._designUnits
2535 @readonly
2536 def Contexts(self) -> Dict[str, Context]:
2537 """
2538 Read-only property to access a list of all context declarations found in this document (:attr:`_contexts`).
2540 :returns: List of all contexts.
2541 """
2542 return self._contexts
2544 @readonly
2545 def Configurations(self) -> Dict[str, Configuration]:
2546 """
2547 Read-only property to access a list of all configuration declarations found in this document (:attr:`_configurations`).
2549 :returns: List of all configurations.
2550 """
2551 return self._configurations
2553 @readonly
2554 def Entities(self) -> Dict[str, Entity]:
2555 """
2556 Read-only property to access a list of all entity declarations found in this document (:attr:`_entities`).
2558 :returns: List of all entities.
2559 """
2560 return self._entities
2562 @readonly
2563 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2564 """
2565 Read-only property to access a list of all architecture declarations found in this document (:attr:`_architectures`).
2567 :returns: List of all architectures.
2568 """
2569 return self._architectures
2571 @readonly
2572 def Packages(self) -> Dict[str, Package]:
2573 """
2574 Read-only property to access a list of all package declarations found in this document (:attr:`_packages`).
2576 :returns: List of all packages.
2577 """
2578 return self._packages
2580 @readonly
2581 def PackageBodies(self) -> Dict[str, PackageBody]:
2582 """
2583 Read-only property to access a list of all package body declarations found in this document (:attr:`_packageBodies`).
2585 :returns: List of all package bodies.
2586 """
2587 return self._packageBodies
2589 @readonly
2590 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
2591 """
2592 Read-only property to access a list of all verification unit declarations found in this document (:attr:`_verificationUnits`).
2594 :returns: List of all verification units.
2595 """
2596 return self._verificationUnits
2598 @readonly
2599 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
2600 """
2601 Read-only property to access a list of all verification properties declarations found in this document (:attr:`_verificationProperties`).
2603 :returns: List of all verification properties.
2604 """
2605 return self._verificationProperties
2607 @readonly
2608 def VerificationModes(self) -> Dict[str, VerificationMode]:
2609 """
2610 Read-only property to access a list of all verification modes declarations found in this document (:attr:`_verificationModes`).
2612 :returns: List of all verification modes.
2613 """
2614 return self._verificationModes
2616 @readonly
2617 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
2618 """
2619 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
2621 The compile-order vertex references this document by its value field.
2623 :returns: The corresponding compile-order vertex.
2624 """
2625 return self._compileOrderVertex
2627 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2628 """
2629 Iterate all design units in the document.
2631 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2633 .. rubric:: Algorithm
2635 * If contexts are selected in the filter:
2637 1. Iterate all contexts in that library.
2639 * If packages are selected in the filter:
2641 1. Iterate all packages in that library.
2643 * If package bodies are selected in the filter:
2645 1. Iterate all package bodies in that library.
2647 * If entites are selected in the filter:
2649 1. Iterate all entites in that library.
2651 * If architectures are selected in the filter:
2653 1. Iterate all architectures in that library.
2655 * If configurations are selected in the filter:
2657 1. Iterate all configurations in that library.
2659 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2660 :returns: A generator to iterate all matched design units in the document.
2662 .. seealso::
2664 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2665 Iterate all design units in the design.
2666 :meth:`pyVHDLModel.Library.IterateDesignUnits`
2667 Iterate all design units in the library.
2668 """
2669 if DesignUnitKind.Context in filter:
2670 for context in self._contexts.values():
2671 yield context
2673 if DesignUnitKind.Package in filter: 2673 ↛ 2677line 2673 didn't jump to line 2677 because the condition on line 2673 was always true
2674 for package in self._packages.values():
2675 yield package
2677 if DesignUnitKind.PackageBody in filter:
2678 for packageBody in self._packageBodies.values():
2679 yield packageBody
2681 if DesignUnitKind.Entity in filter:
2682 for entity in self._entities.values():
2683 yield entity
2685 if DesignUnitKind.Architecture in filter:
2686 for architectures in self._architectures.values():
2687 for architecture in architectures.values():
2688 yield architecture
2690 if DesignUnitKind.Configuration in filter:
2691 for configuration in self._configurations.values():
2692 yield configuration
2694 # for verificationProperty in self._verificationUnits.values():
2695 # yield verificationProperty
2696 # for verificationUnit in self._verificationProperties.values():
2697 # yield entity
2698 # for verificationMode in self._verificationModes.values():
2699 # yield verificationMode
2701 def __repr__(self) -> str:
2702 """
2703 Formats a representation of the document.
2705 **Format:** ``Document: 'path/to/file.vhdl'``
2707 :returns: String representation of the document.
2708 """
2709 return f"Document: '{self._path}'"
2711 __str__ = __repr__