Coverage for pyVHDLModel/__init__.py: 64%
1186 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-11 23:50 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-11 23:50 +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.39.0"
52# __keywords__ = []
53__project_url__ = "https://github.com/VHDL/pyVHDLModel"
54__documentation_url__ = "https://vhdl.github.io/pyVHDLModel"
55__issue_tracker_url__ = "https://GitHub.com/VHDL/pyVHDLModel/issues"
58from enum import unique, Enum, Flag, auto
59from pathlib import Path
61from typing import Union, Dict, cast, List, Generator, Optional as Nullable
63from pyTooling.Common import getFullyQualifiedName
64from pyTooling.Decorators import export, readonly
65from pyTooling.Graph import Graph, Vertex, Edge
66from pyTooling.Warning import WarningCollector
68from pyVHDLModel.Exception import VHDLModelException, NotImplementedWarning, BlackboxWarning
69from pyVHDLModel.Exception import LibraryExistsInDesignError, LibraryRegisteredToForeignDesignError, LibraryNotRegisteredError, EntityExistsInLibraryError
70from pyVHDLModel.Exception import ArchitectureExistsInLibraryError, PackageExistsInLibraryError, PackageBodyExistsError, ConfigurationExistsInLibraryError
71from pyVHDLModel.Exception import ContextExistsInLibraryError, ReferencedLibraryNotExistingError
72from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin
73from pyVHDLModel.Expression import UnaryExpression, BinaryExpression, TernaryExpression
74from pyVHDLModel.Namespace import Namespace
75from pyVHDLModel.Object import Obj, Signal, Constant, DeferredConstant
76from pyVHDLModel.Symbol import PackageReferenceSymbol, AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol, SimpleObjectOrFunctionCallSymbol
77from pyVHDLModel.Common import AllowBlackboxMixin
78from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin
79from pyVHDLModel.Concurrent import EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation
80from pyVHDLModel.Concurrent import GenerateStatement, IfGenerateStatement, ForGenerateStatement, CaseGenerateStatement
81from pyVHDLModel.Concurrent import GenerateBranch, ConcurrentStatementsMixin, ConcurrentBlockStatement
82from pyVHDLModel.DesignUnit import DesignUnit, PrimaryUnit, Architecture, PackageBody, Context, Entity, Configuration, Package, Component
83from pyVHDLModel.PSLModel import VerificationUnit, VerificationProperty, VerificationMode
84from pyVHDLModel.Instantiation import PackageInstantiation
85from pyVHDLModel.Type import IntegerType, PhysicalType, ArrayType, RecordType
88@export
89@unique
90class VHDLVersion(Enum):
91 """
92 An enumeration for all possible version numbers for VHDL and VHDL-AMS.
94 A version can be given as integer or string and is represented as a unified
95 enumeration value.
97 This enumeration supports compare operators.
98 """
100 Any = -1 #: Any
101 VHDL87 = 87 #: VHDL-1987
102 VHDL93 = 93 #: VHDL-1993
103 AMS93 = 1993 #: VHDL-AMS-1993
104 AMS99 = 1999 #: VHDL-AMS-1999
105 VHDL2000 = 2000 #: VHDL-2000
106 VHDL2002 = 2002 #: VHDL-2002
107 VHDL2008 = 2008 #: VHDL-2008
108 AMS2017 = 2017 #: VHDL-AMS-2017
109 VHDL2019 = 2019 #: VHDL-2019
110 Latest = 10000 #: Latest VHDL (2019)
112 __VERSION_MAPPINGS__: Dict[Union[int, str], Enum] = {
113 -1: Any,
114 87: VHDL87,
115 93: VHDL93,
116 # 93: AMS93,
117 99: AMS99,
118 0: VHDL2000,
119 2: VHDL2002,
120 8: VHDL2008,
121 17: AMS2017,
122 19: VHDL2019,
123 1987: VHDL87,
124 # 1993: VHDL93,
125 1993: AMS93,
126 1999: AMS99,
127 2000: VHDL2000,
128 2002: VHDL2002,
129 2008: VHDL2008,
130 2017: AMS2017,
131 2019: VHDL2019,
132 10000: Latest,
133 "Any": Any,
134 "87": VHDL87,
135 "93": VHDL93,
136 # "93": AMS93,
137 "99": AMS99,
138 "00": VHDL2000,
139 "02": VHDL2002,
140 "08": VHDL2008,
141 "17": AMS2017,
142 "19": VHDL2019,
143 "1987": VHDL87,
144 # "1993": VHDL93,
145 "1993": AMS93,
146 "1999": AMS99,
147 "2000": VHDL2000,
148 "2002": VHDL2002,
149 "2008": VHDL2008,
150 "2017": AMS2017,
151 "2019": VHDL2019,
152 "Latest": Latest,
153 } #: Dictionary of VHDL and VHDL-AMS year codes variants as integer and strings for mapping to unique enum values.
155 def __init__(self, *_) -> None:
156 """Patch the embedded MAP dictionary"""
157 for k, v in self.__class__.__VERSION_MAPPINGS__.items():
158 if (not isinstance(v, self.__class__)) and (v == self.value):
159 self.__class__.__VERSION_MAPPINGS__[k] = self
161 @classmethod
162 def Parse(cls, value: Union[int, str]) -> "VHDLVersion":
163 """
164 Parses a VHDL or VHDL-AMS year code as integer or string to an enum value.
166 :param value: VHDL/VHDL-AMS year code.
167 :returns: Enumeration value.
168 :raises ValueError: If the year code is not recognized.
169 """
170 try:
171 return cls.__VERSION_MAPPINGS__[value]
172 except KeyError:
173 raise ValueError(f"Value '{value!s}' cannot be parsed to member of {cls.__name__}.")
175 def __lt__(self, other: Any) -> bool:
176 """
177 Compare two VHDL/VHDL-AMS versions if the version is less than the second operand.
179 :param other: Parameter to compare against.
180 :returns: True if version is less than the second operand.
181 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
182 """
183 if isinstance(other, VHDLVersion):
184 return self.value < other.value
185 else:
186 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
187 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
188 raise ex
190 def __le__(self, other: Any) -> bool:
191 """
192 Compare two VHDL/VHDL-AMS versions if the version is less or equal than the second operand.
194 :param other: Parameter to compare against.
195 :returns: True if version is less or equal than the second operand.
196 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
197 """
198 if isinstance(other, VHDLVersion):
199 return self.value <= other.value
200 else:
201 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
202 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
203 raise ex
205 def __gt__(self, other: Any) -> bool:
206 """
207 Compare two VHDL/VHDL-AMS versions if the version is greater than the second operand.
209 :param other: Parameter to compare against.
210 :returns: True if version is greater than the second operand.
211 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
212 """
213 if isinstance(other, VHDLVersion):
214 return self.value > other.value
215 else:
216 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
217 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
218 raise ex
220 def __ge__(self, other: Any) -> bool:
221 """
222 Compare two VHDL/VHDL-AMS versions if the version is greater or equal than the second operand.
224 :param other: Parameter to compare against.
225 :returns: True if version is greater or equal than the second operand.
226 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
227 """
228 if isinstance(other, VHDLVersion):
229 return self.value >= other.value
230 else:
231 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
232 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
233 raise ex
235 def __ne__(self, other: Any) -> bool:
236 """
237 Compare two VHDL/VHDL-AMS versions if the version is unequal to the second operand.
239 :param other: Parameter to compare against.
240 :returns: True if version is unequal to the second operand.
241 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
242 """
243 if isinstance(other, VHDLVersion):
244 return self.value != other.value
245 else:
246 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
247 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
248 raise ex
250 def __eq__(self, other: Any) -> bool:
251 """
252 Compare two VHDL/VHDL-AMS versions if the version is equal to the second operand.
254 :param other: Parameter to compare against.
255 :returns: True if version is equal to the second operand.
256 :raises TypeError: If parameter ``other`` is not of type :class:`VHDLVersion`.
257 """
258 if isinstance(other, VHDLVersion):
259 if (self is self.__class__.Any) or (other is self.__class__.Any):
260 return True
261 else:
262 return self.value == other.value
263 else:
264 ex = TypeError("Second operand is not of type 'VHDLVersion'.")
265 ex.add_note(f"Got type '{getFullyQualifiedName(other)}'.")
266 raise ex
268 def __hash__(self) -> int:
269 """
270 Return the hash of the VHDL version using the underlying version number.
272 .. note::
274 ``Any`` compares equal to every other member (see :meth:`__eq__`), which no hash value can satisfy
275 simultaneously for all members without collapsing every member to the same hash. This implementation
276 hashes by ``self.value``, which is internally consistent for all comparisons *except* those
277 involving ``Any`` - avoid using ``Any`` as a dict key or set member.
279 :returns: Hash value of the underlying VHDL version number.
280 """
281 return hash(self.value)
283 @readonly
284 def IsVHDL(self) -> bool:
285 """
286 Check if the version is a VHDL (not VHDL-AMS) version.
288 :returns: ``True``, if the version is a VHDL version.
289 """
290 return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019)
292 @readonly
293 def IsAMS(self) -> bool:
294 """
295 Check if the version is a VHDL-AMS (not VHDL) version.
297 :returns: ``True``, if the version is a VHDL-AMS version.
298 """
299 return self in (self.AMS93, self.AMS99, self.AMS2017)
301 def __str__(self) -> str:
302 """
303 Formats the VHDL version to pattern ``VHDL'xx`` or in case of VHDL-AMS to ``VHDL-AMS'xx``.
305 :returns: Formatted VHDL/VHDL-AMS version.
306 """
307 if self.value == self.Any.value:
308 return "VHDL'Any"
309 elif self.value == self.Latest.value:
310 return "VHDL'Latest"
312 year = str(self.value)[-2:]
313 if self.IsVHDL:
314 return f"VHDL'{year}"
315 else:
316 return f"VHDL-AMS'{year}"
318 def __repr__(self) -> str:
319 """
320 Formats the VHDL/VHDL-AMS version to pattern ``xxxx``.
322 :returns: Formatted VHDL/VHDL-AMS version.
323 """
324 if self.value == self.Any.value:
325 return "Any"
326 elif self.value == self.Latest.value:
327 return "Latest"
328 else:
329 return str(self.value)
332@export
333class IEEEFlavor(Flag):
334 """
335 The ``IEEE`` VHDL library as a fixed set of predefined VHDL packages according to IEEE Std. 1076.
337 Nonetheless, some vendors decided to sneak in additional packages into the ``IEEE`` namespace. |br|
338 Supported flavors are:
340 * ``Synopsys``
341 * ``MentorGraphics``
343 In addition, IEEE Std. 1076.X extensions can be loaded. |br|
344 Supported extensions are:
346 * ``WithVITAL`` - IEEE Std. 1076.4
348 """
349 Unknown = 0 #: Unknown IEEE flavor
350 IEEE = 1 #: IEEE Std. 1076 compliant list of IEEE packages.
351 Synopsys = 2 #: Additional packages created by Synopsys are visible within the IEEE library.
352 MentorGraphics = 4 #: Additional packages created by Mentor Graphics are visible within the IEEE library.
353 WithVITAL = 32 #: Additionally load IEEE Std 1076.4 VITAL packages. (VITAL = VHDL Initiative Towards ASIC Libraries)
356@export
357@unique
358class ObjectClass(Enum):
359 """
360 An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...).
362 In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context.
363 """
365 Default = 0 #: Object class not defined, thus it's context dependent.
366 Constant = 1 #: Constant
367 Variable = 2 #: Variable
368 Signal = 3 #: Signal
369 File = 4 #: File
370 Type = 5 #: Type
371 # FIXME: Package?
372 Procedure = 6 #: Procedure
373 Function = 7 #: Function
375 def __str__(self) -> str:
376 """
377 Formats the object class.
379 :returns: Formatted object class.
380 """
381 return ("", "constant", "variable", "signal", "file", "type", "procedure", "function")[cast(int, self.value)] # TODO: check performance
384@export
385@unique
386class DesignUnitKind(Flag):
387 """
388 A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...).
390 """
391 Context = auto() #: Context
392 Package = auto() #: Package
393 PackageBody = auto() #: Package Body
394 Entity = auto() #: Entity
395 Architecture = auto() #: Architecture
396 Configuration = auto() #: Configuration
398 Primary = Context | Configuration | Entity | Package #: List of primary design units.
399 Secondary = PackageBody | Architecture #: List of secondary design units.
400 WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context.
401 WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region.
403 All = Primary | Secondary #: List of all design units.
406@export
407@unique
408class DependencyGraphVertexKind(Flag):
409 """
410 A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph.
411 """
412 Document = auto() #: A document (VHDL source file).
413 Library = auto() #: A VHDL library.
415 Context = auto() #: A context design unit.
416 Package = auto() #: A package design unit.
417 PackageBody = auto() #: A package body design unit.
418 Entity = auto() #: A entity design unit.
419 Architecture = auto() #: A architecture design unit.
420 Component = auto() #: A VHDL component.
421 Configuration = auto() #: A configuration design unit.
424@export
425@unique
426class DependencyGraphEdgeKind(Flag):
427 """
428 A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph.
429 """
430 Document = auto()
431 Library = auto()
432 Context = auto()
433 Package = auto()
434 Entity = auto()
435 # Architecture = auto()
436 Configuration = auto()
437 Component = auto()
439 DeclaredIn = auto()
440 Order = auto()
441 Reference = auto()
442 Implementation = auto()
443 Instantiation = auto()
445 SourceFile = Document | DeclaredIn
446 CompileOrder = Document | Order
448 LibraryClause = Library | Reference
449 UseClause = Package | Reference
450 ContextReference = Context | Reference
452 EntityImplementation = Entity | Implementation
453 PackageImplementation = Package | Implementation
455 EntityInstantiation = Entity | Instantiation
456 ComponentInstantiation = Component | Instantiation
457 ConfigurationInstantiation = Configuration | Instantiation
459 PackageInstantiation = Package | Instantiation
462@export
463@unique
464class ObjectGraphVertexKind(Flag):
465 """
466 A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph.
467 """
468 Type = auto()
469 Subtype = auto()
471 Constant = auto()
472 DeferredConstant = auto()
473 Variable = auto()
474 Signal = auto()
475 File = auto()
477 Alias = auto()
480@export
481@unique
482class ObjectGraphEdgeKind(Flag):
483 """
484 A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph.
485 """
486 BaseType = auto()
487 Subtype = auto()
489 ReferenceInExpression = auto()
492@export
493class Design(ModelEntity, AllowBlackboxMixin):
494 """
495 A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`).
497 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
498 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
499 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`).
501 The *design* contains references to the following graphs:
503 * :attr:`DependencyGraph`
504 * :attr:`CompileOrderGraph`
505 * :attr:`HierarchyGraph`
506 * :attr:`ObjectGraph`
507 """
508 _name: Nullable[str] #: Name of the design.
509 _allowBlackbox: bool #: Allow blackboxes after linking the design.
510 _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design.
511 _documents: List['Document'] #: List of all documents loaded for a design.
512 _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.
513 _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.
514 _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.
515 _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.
516 _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field.
518 def __init__(
519 self,
520 name: Nullable[str] = None,
521 allowBlackbox: bool = False
522 ) -> None:
523 """
524 Initialize a VHDL design.
526 :param name: Name of the design.
527 :param allowBlackbox: Specify if blackboxes are allowed in this design.
528 """
529 super().__init__()
530 AllowBlackboxMixin.__init__(self, allowBlackbox)
532 self._name = name
534 self._libraries = {}
535 self._documents = []
537 self._compileOrderGraph = Graph()
538 self._dependencyGraph = Graph()
539 self._hierarchyGraph = Graph()
540 self._objectGraph = Graph()
541 self._toplevel = None
543 @readonly
544 def Name(self) -> Nullable[str]:
545 """
546 Read-only property to access the design's name (:attr:`_name`).
548 :returns: The name of the design.
549 """
550 return self._name
552 @readonly
553 def Libraries(self) -> Dict[str, 'Library']:
554 """
555 Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`).
557 :returns: A dictionary of library names and VHDL libraries.
558 """
559 return self._libraries
561 @readonly
562 def Documents(self) -> List['Document']:
563 """
564 Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`).
566 :returns: A list of all documents.
567 """
568 return self._documents
570 @readonly
571 def CompileOrderGraph(self) -> Graph:
572 """
573 Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`).
575 :returns: Reference to the compile-order graph.
576 """
577 return self._compileOrderGraph
579 @readonly
580 def DependencyGraph(self) -> Graph:
581 """
582 Read-only property to access the dependency graph (:attr:`_dependencyGraph`).
584 :returns: Reference to the dependency graph.
585 """
586 return self._dependencyGraph
588 @readonly
589 def HierarchyGraph(self) -> Graph:
590 """
591 Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`).
593 :returns: Reference to the hierarchy graph.
594 """
595 return self._hierarchyGraph
597 @readonly
598 def ObjectGraph(self) -> Graph:
599 """
600 Read-only property to access the object graph (:attr:`_objectGraph`).
602 :returns: Reference to the object graph.
603 """
604 return self._objectGraph
606 @readonly
607 def TopLevel(self) -> Union[Entity, Configuration]:
608 """
609 Read-only property to access the design's *top-level* (:attr:`_toplevel`).
611 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``
612 is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`.
614 :returns: Reference to the design's *top-level*.
615 :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph.
616 :raises VHDLModelException: If there is more than one *top-level*.
617 """
618 # Check for cached result
619 if self._toplevel is not None: 619 ↛ 620line 619 didn't jump to line 620 because the condition on line 619 was never true
620 return self._toplevel
622 if self._hierarchyGraph.VertexCount == 0:
623 raise VHDLModelException(f"Hierarchy is not yet computed from dependency graph.")
625 roots = tuple(self._hierarchyGraph.IterateRoots())
626 if len(roots) == 1: 626 ↛ 633line 626 didn't jump to line 633 because the condition on line 626 was always true
627 toplevel = roots[0]
628 self._hierarchyGraph["toplevel"] = toplevel
629 self._toplevel = toplevel.Value
631 return toplevel.Value
632 else:
633 raise VHDLModelException(f"Found more than one toplevel: {', '.join(str(r) for r in roots)}")
635 def LoadStdLibrary(self) -> 'Library':
636 """
637 Load the predefined VHDL library ``std`` into the design.
639 This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file.
641 :returns: The library object of library ``std``.
642 """
643 from pyVHDLModel.STD import Std
645 doc = Document(Path("std.vhdl"), parent=self)
647 library = Std()
648 for designUnit in library.IterateDesignUnits():
649 doc._AddDesignUnit(designUnit)
651 self.AddLibrary(library)
653 return library
655 def LoadIEEELibrary(self, flavor: Nullable[IEEEFlavor] = None) -> 'Library':
656 """
657 Load the predefined VHDL library ``ieee`` into the design.
659 This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file.
661 :param flavor: Select the IEEE library flavor: IEEE, Synopsys, MentorGraphics.
662 :returns: The library object of library ``ieee``.
663 """
664 from pyVHDLModel.IEEE import Ieee
666 doc = Document(Path("ieee.vhdl"), parent=self)
668 library = Ieee(flavor)
669 for designUnit in library.IterateDesignUnits():
670 doc._AddDesignUnit(designUnit)
672 self.AddLibrary(library)
674 return library
676 def AddLibrary(self, library: 'Library') -> None:
677 """
678 Add a VHDL library to the design.
680 Ensure the libraries name doesn't collide with existing libraries in the design. |br|
681 If ok, set the libraries parent reference to the design.
683 :param library: Library object to loaded.
684 :raises LibraryExistsInDesignError: If the library already exists in the design.
685 :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design.
686 """
687 libraryIdentifier = library.NormalizedIdentifier
688 if libraryIdentifier in self._libraries:
689 raise LibraryExistsInDesignError(library)
691 if library._parent is not None:
692 raise LibraryRegisteredToForeignDesignError(library)
694 self._libraries[libraryIdentifier] = library
695 library.Parent = self
697 def GetLibrary(self, libraryName: str) -> 'Library':
698 """
699 Return an (existing) VHDL library object of name ``libraryName``.
701 If the requested VHDL library doesn't exist, a new VHDL library with that name will be created.
703 :param libraryName: Name of the requested VHDL library.
704 :returns: The VHDL library object.
705 """
706 libraryIdentifier = libraryName.lower()
707 try:
708 return self._libraries[libraryIdentifier]
709 except KeyError:
710 lib = Library(libraryName, parent=self)
711 self._libraries[libraryIdentifier] = lib
712 lib.Parent = self
713 return lib
715 # TODO: allow overloaded parameter library to be str?
716 def AddDocument(self, document: 'Document', library: 'Library') -> None:
717 """
718 Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library.
720 .. rubric:: Algorithm
722 1. Iterate all entities in the document
724 1. Check if entity name might exist in target library.
725 2. Add entity to library and update library membership.
727 2. Iterate all architectures in the document
729 1. Check if architecture name might exist in target library.
730 2. Add architecture to library and update library membership.
732 3. Iterate all packages in the document
734 1. Check if package name might exist in target library.
735 2. Add package to library and update library membership.
737 4. Iterate all package bodies in the document
739 1. Check if package body name might exist in target library.
740 2. Add package body to library and update library membership.
742 5. Iterate all configurations in the document
744 1. Check if configuration name might exist in target library.
745 2. Add configuration to library and update library membership.
747 6. Iterate all contexts in the document
749 1. Check if context name might exist in target library.
750 2. Add context to library and update library membership.
752 :param document: The VHDL source code file.
753 :param library: The VHDL library used to register the embedded design units to.
754 :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design.
755 :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library.
756 :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library.
757 :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library.
758 :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library.
759 :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library.
760 :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library.
761 """
762 # FIXME: this checks for the library name, but not the object
763 # should the libraries parent be checked too?
764 if library._normalizedIdentifier not in self._libraries: 764 ↛ 765line 764 didn't jump to line 765 because the condition on line 764 was never true
765 raise LibraryNotRegisteredError(library)
767 self._documents.append(document)
768 document.Parent = self
769 #document.Library = library
771 document._library = library
773 for entityIdentifier, entity in document._entities.items():
774 if entityIdentifier in library._entities: 774 ↛ 775line 774 didn't jump to line 775 because the condition on line 774 was never true
775 raise EntityExistsInLibraryError(entity, library)
777 library._entities[entityIdentifier] = entity
778 entity.Library = library
780 for entityIdentifier, architectures in document._architectures.items():
781 try:
782 architecturesPerEntity = library._architectures[entityIdentifier]
783 for architectureIdentifier, architecture in architectures.items():
784 if architectureIdentifier in architecturesPerEntity:
785 raise ArchitectureExistsInLibraryError(architecture, library._entities[entityIdentifier], library)
787 architecturesPerEntity[architectureIdentifier] = architecture
788 architecture.Library = library
789 except KeyError:
790 architecturesPerEntity = document._architectures[entityIdentifier].copy()
791 library._architectures[entityIdentifier] = architecturesPerEntity
793 for architecture in architecturesPerEntity.values():
794 architecture.Library = library
796 for packageIdentifier, package in document._packages.items():
797 if packageIdentifier in library._packages: 797 ↛ 798line 797 didn't jump to line 798 because the condition on line 797 was never true
798 raise PackageExistsInLibraryError(package, library)
800 library._packages[packageIdentifier] = package
801 package.Library = library
803 for packageBodyIdentifier, packageBody in document._packageBodies.items():
804 if packageBodyIdentifier in library._packageBodies: 804 ↛ 805line 804 didn't jump to line 805 because the condition on line 804 was never true
805 raise PackageBodyExistsError(packageBody, library)
807 library._packageBodies[packageBodyIdentifier] = packageBody
808 packageBody.Library = library
810 for configurationIdentifier, configuration in document._configurations.items():
811 if configurationIdentifier in library._configurations: 811 ↛ 812line 811 didn't jump to line 812 because the condition on line 811 was never true
812 raise ConfigurationExistsInLibraryError(configuration, library)
814 library._configurations[configurationIdentifier] = configuration
815 configuration.Library = library
817 for contextIdentifier, context in document._contexts.items():
818 if contextIdentifier in library._contexts: 818 ↛ 819line 818 didn't jump to line 819 because the condition on line 818 was never true
819 raise ContextExistsInLibraryError(context, library)
821 library._contexts[contextIdentifier] = context
822 context.Library = library
824 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
825 """
826 Iterate all design units in the design.
828 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
830 .. rubric:: Algorithm
832 1. Iterate all VHDL libraries.
834 1. Iterate all contexts in that library.
835 2. Iterate all packages in that library.
836 3. Iterate all package bodies in that library.
837 4. Iterate all entites in that library.
838 5. Iterate all architectures in that library.
839 6. Iterate all configurations in that library.
841 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
842 :returns: A generator to iterate all matched design units in the design.
844 .. seealso::
846 :meth:`pyVHDLModel.Library.IterateDesignUnits`
847 Iterate all design units in the library.
848 :meth:`pyVHDLModel.Document.IterateDesignUnits`
849 Iterate all design units in the document.
850 """
851 for library in self._libraries.values():
852 yield from library.IterateDesignUnits(filter)
854 def Analyze(self) -> None:
855 """
856 Analyze the whole design.
858 .. rubric:: Algorithm
860 1. Analyze dependencies of design units. |br|
861 This will also yield the design hierarchy and the compiler order.
862 2. Analyze dependencies of types and objects.
864 .. seealso::
866 :meth:`AnalyzeDependencies`
867 Analyze the dependencies of design units.
869 :meth:`AnalyzeObjects`
870 Analyze the dependencies of types and objects.
871 """
872 self.AnalyzeDependencies()
873 # self.AnalyzeObjects()
875 def AnalyzeDependencies(self) -> None:
876 """
877 Analyze the dependencies of design units.
879 .. rubric:: Algorithm
881 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br|
882 |rarr| :meth:`CreateDependencyGraph`
883 2. Create the compile order graph. |br|
884 |rarr| :meth:`CreateCompileOrderGraph`
885 3. Index all packages. |br|
886 |rarr| :meth:`IndexPackages`
887 4. Index all architectures. |br|
888 |rarr| :meth:`IndexArchitectures`
889 5. Link all contexts |br|
890 |rarr| :meth:`LinkContexts`
891 6. Link all architectures. |br|
892 |rarr| :meth:`LinkArchitectures`
893 7. Link all package bodies. |br|
894 |rarr| :meth:`LinkPackageBodies`
895 8. Link all package instances. |br|
896 |rarr| :meth:`LinkPackageInstances`
897 9. Link all library references. |br|
898 |rarr| :meth:`LinkLibraryReferences`
899 10. Link all package references. |br|
900 |rarr| :meth:`LinkPackageReferences`
901 11. Link all context references. |br|
902 |rarr| :meth:`LinkContextReferences`
903 12. Link all components. |br|
904 |rarr| :meth:`LinkComponents`
905 13. Link all instantiations. |br|
906 |rarr| :meth:`LinkInstantiations`
907 14. Create the hierarchy graph. |br|
908 |rarr| :meth:`CreateHierarchyGraph`
909 15. Compute the compile order. |br|
910 |rarr| :meth:`ComputeCompileOrder`
911 """
912 self.CreateDependencyGraph()
913 self.CreateCompileOrderGraph()
915 self.IndexPackages()
916 self.IndexArchitectures()
918 self.LinkContexts()
919 self.LinkArchitectures()
920 self.LinkPackageBodies()
921 self.LinkPackageInstances()
922 self.LinkLibraryReferences()
923 self.LinkPackageReferences()
924 self.LinkContextReferences()
926 self.LinkComponents()
927 self.LinkInstantiations()
928 self.CreateHierarchyGraph()
929 self.ComputeCompileOrder()
931 def AnalyzeObjects(self) -> None:
932 """
933 Analyze the dependencies of types and objects.
935 .. rubric:: Algorithm
937 1. Index all entities. |br|
938 |rarr| :meth:`IndexEntities`
939 2. Index all package bodies. |br|
940 |rarr| :meth:`IndexPackageBodies`
941 3. Import objects. |br|
942 |rarr| :meth:`ImportObjects`
943 4. Create the type and object graph. |br|
944 |rarr| :meth:`CreateTypeAndObjectGraph`
945 """
946 self.IndexEntities()
947 self.IndexPackageBodies()
949 self.ImportObjects()
950 self.CreateTypeAndObjectGraph()
952 def CreateDependencyGraph(self) -> None:
953 """
954 Create all vertices of the dependency graph by iterating all design units in all libraries.
956 This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br|
957 See :meth:`AnalyzeDependencies` for these methods and their algorithmic order.
959 Each vertex has the following properties:
961 * The vertex' ID is the design unit's identifier.
962 * The vertex' value references the design unit.
963 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
964 * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity.
966 .. rubric:: Algorithm
968 1. Iterate all libraries in the design.
970 * Create a vertex for that library and reference the library by the vertex' value field. |br|
971 In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex.
973 1. Iterate all contexts in that library.
975 * Create a vertex for that context and reference the context by the vertex' value field. |br|
976 In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex.
978 2. Iterate all packages in that library.
980 * Create a vertex for that package and reference the package by the vertex' value field. |br|
981 In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex.
983 3. Iterate all package bodies in that library.
985 * Create a vertex for that package body and reference the package body by the vertex' value field. |br|
986 In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex.
988 4. Iterate all entities in that library.
990 * Create a vertex for that entity and reference the entity by the vertex' value field. |br|
991 In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex.
993 5. Iterate all architectures in that library.
995 * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br|
996 In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex.
998 6. Iterate all configurations in that library.
1000 * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br|
1001 In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex.
1002 """
1003 predefinedLibraries = ("std", "ieee")
1005 for libraryIdentifier, library in self._libraries.items():
1006 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}", value=library, graph=self._dependencyGraph)
1007 dependencyVertex["kind"] = DependencyGraphVertexKind.Library
1008 dependencyVertex["predefined"] = libraryIdentifier in predefinedLibraries
1009 library._dependencyVertex = dependencyVertex
1011 for contextIdentifier, context in library._contexts.items():
1012 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{contextIdentifier}", value=context, graph=self._dependencyGraph)
1013 dependencyVertex["kind"] = DependencyGraphVertexKind.Context
1014 dependencyVertex["predefined"] = context._parent._normalizedIdentifier in predefinedLibraries
1015 context._dependencyVertex = dependencyVertex
1017 for packageIdentifier, package in library._packages.items():
1018 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageIdentifier}", value=package, graph=self._dependencyGraph)
1019 dependencyVertex["kind"] = DependencyGraphVertexKind.Package
1020 dependencyVertex["predefined"] = package._parent._normalizedIdentifier in predefinedLibraries
1021 package._dependencyVertex = dependencyVertex
1023 for packageBodyIdentifier, packageBody in library._packageBodies.items():
1024 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{packageBodyIdentifier}(body)", value=packageBody, graph=self._dependencyGraph)
1025 dependencyVertex["kind"] = DependencyGraphVertexKind.PackageBody
1026 dependencyVertex["predefined"] = packageBody._parent._normalizedIdentifier in predefinedLibraries
1027 packageBody._dependencyVertex = dependencyVertex
1029 for entityIdentifier, entity in library._entities.items():
1030 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}", value=entity, graph=self._dependencyGraph)
1031 dependencyVertex["kind"] = DependencyGraphVertexKind.Entity
1032 dependencyVertex["predefined"] = entity._parent._normalizedIdentifier in predefinedLibraries
1033 entity._dependencyVertex = dependencyVertex
1035 for entityIdentifier, architectures in library._architectures.items():
1036 for architectureIdentifier, architecture in architectures.items():
1037 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{entityIdentifier}({architectureIdentifier})", value=architecture, graph=self._dependencyGraph)
1038 dependencyVertex["kind"] = DependencyGraphVertexKind.Architecture
1039 dependencyVertex["predefined"] = architecture._parent._normalizedIdentifier in predefinedLibraries
1040 architecture._dependencyVertex = dependencyVertex
1042 for configurationIdentifier, configuration in library._configurations.items():
1043 dependencyVertex = Vertex(vertexID=f"{libraryIdentifier}.{configurationIdentifier}", value=configuration, graph=self._dependencyGraph)
1044 dependencyVertex["kind"] = DependencyGraphVertexKind.Configuration
1045 dependencyVertex["predefined"] = configuration._parent._normalizedIdentifier in predefinedLibraries
1046 configuration._dependencyVertex = dependencyVertex
1048 def CreateCompileOrderGraph(self) -> None:
1049 """
1050 Create a compile-order graph with bidirectional references to the dependency graph.
1052 Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order
1053 graph and bidirectionally referenced.
1055 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
1056 document relationship.
1058 Each added vertex has the following properties:
1060 * The vertex' ID is the document's filename.
1061 * The vertex' value references the document.
1062 * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`.
1063 * A key-value-pair called ``predefined`` does not exist.
1065 .. rubric:: Algorithm
1067 1. Iterate all documents in the design.
1069 * Create a vertex for that document and reference the document by the vertex' value field. |br|
1070 In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex.
1071 * Copy the vertex from dependency graph to compile-order graph and link both vertices bidirectionally. |br|
1072 In addition, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the copied vertex.
1074 * Add a key-value-pair called ``compileOrderVertex`` to the dependency graph's vertex.
1075 * Add a key-value-pair called ``dependencyVertex`` to the compiler-order graph's vertex.
1077 1. Iterate the documents design units and create an edge from the design unit's corresponding dependency vertex to the documents corresponding
1078 dependency vertex. This expresses a "design unit is located in document" relation.
1080 * Add a key-value-pair called `kind`` denoting the edge's kind as an enumeration value of type :class:`DependencyGraphEdgeKind`.
1081 """
1082 for document in self._documents:
1083 dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph)
1084 dependencyVertex["kind"] = DependencyGraphVertexKind.Document
1085 document._dependencyVertex = dependencyVertex
1087 compilerOrderVertex = dependencyVertex.Copy(
1088 self._compileOrderGraph,
1089 copyDict=True,
1090 linkingKeyToOriginalVertex="dependencyVertex",
1091 linkingKeyFromOriginalVertex="compileOrderVertex"
1092 )
1093 document._compileOrderVertex = compilerOrderVertex
1095 for designUnit in document._designUnits:
1096 edge = dependencyVertex.EdgeFromVertex(designUnit._dependencyVertex)
1097 edge["kind"] = DependencyGraphEdgeKind.SourceFile
1099 def ImportObjects(self) -> None:
1100 def _ImportObjects(package: Package) -> None:
1101 from pyVHDLModel.Declaration import AttributeSpecification
1103 for referencedLibrary in package._referencedPackages.values():
1104 for referencedPackage in referencedLibrary.values():
1105 for declaredItem in referencedPackage._declaredItems:
1106 if isinstance(declaredItem, MultipleNamedEntityMixin):
1107 for normalizedIdentifier in declaredItem._normalizedIdentifiers:
1108 package._namespace._elements[normalizedIdentifier] = declaredItem
1109 elif isinstance(declaredItem, NamedEntityMixin):
1110 package._namespace._elements[declaredItem._normalizedIdentifier] = declaredItem
1111 elif isinstance(declaredItem, AttributeSpecification):
1112 # FIXME: actually, this is not a declared item, but a application of an attribute to named entities
1113 WarningCollector.Raise(NotImplementedWarning(f"Attribute specification."))
1115 else:
1116 raise VHDLModelException(f"Unexpected declared item.")
1118 for libraryName in ("std", "ieee"):
1119 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1120 _ImportObjects(package)
1122 for document in self.IterateDocumentsInCompileOrder():
1123 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1124 _ImportObjects(package)
1126 def CreateTypeAndObjectGraph(self) -> None:
1127 def _HandlePackage(package) -> None:
1128 packagePrefix = f"{package.Library.NormalizedIdentifier}.{package.NormalizedIdentifier}"
1130 for deferredConstant in package._deferredConstants.values():
1131 print(f"Deferred Constant: {deferredConstant}")
1132 deferredConstantVertex = Vertex(
1133 vertexID=f"{packagePrefix}.{deferredConstant.NormalizedIdentifiers[0]}",
1134 value=deferredConstant,
1135 graph=self._objectGraph
1136 )
1137 deferredConstantVertex["kind"] = ObjectGraphVertexKind.DeferredConstant
1138 deferredConstant._objectVertex = deferredConstantVertex
1140 for constant in package._constants.values():
1141 print(f"Constant: {constant}")
1142 constantVertex = Vertex(
1143 vertexID=f"{packagePrefix}.{constant.NormalizedIdentifiers[0]}",
1144 value=constant,
1145 graph=self._objectGraph
1146 )
1147 constantVertex["kind"] = ObjectGraphVertexKind.Constant
1148 constant._objectVertex = constantVertex
1150 for type in package._types.values():
1151 print(f"Type: {type}")
1152 typeVertex = Vertex(
1153 vertexID=f"{packagePrefix}.{type.NormalizedIdentifier}",
1154 value=type,
1155 graph=self._objectGraph
1156 )
1157 typeVertex["kind"] = ObjectGraphVertexKind.Type
1158 type._objectVertex = typeVertex
1160 for subtype in package._subtypes.values():
1161 print(f"Subtype: {subtype}")
1162 subtypeVertex = Vertex(
1163 vertexID=f"{packagePrefix}.{subtype.NormalizedIdentifier}",
1164 value=subtype,
1165 graph=self._objectGraph
1166 )
1167 subtypeVertex["kind"] = ObjectGraphVertexKind.Subtype
1168 subtype._objectVertex = subtypeVertex
1170 for function in package._functions.values():
1171 print(f"Function: {function}")
1172 functionVertex = Vertex(
1173 vertexID=f"{packagePrefix}.{function.NormalizedIdentifier}",
1174 value=function,
1175 graph=self._objectGraph
1176 )
1177 functionVertex["kind"] = ObjectGraphVertexKind.Function
1178 function._objectVertex = functionVertex
1180 for procedure in package._procedures.values():
1181 print(f"Procedure: {procedure}")
1182 procedureVertex = Vertex(
1183 vertexID=f"{packagePrefix}.{procedure.NormalizedIdentifier}",
1184 value=procedure,
1185 graph=self._objectGraph
1186 )
1187 procedureVertex["kind"] = ObjectGraphVertexKind.Function
1188 procedure._objectVertex = procedureVertex
1190 for signal in package._signals.values():
1191 print(f"Signal: {signal}")
1192 signalVertex = Vertex(
1193 vertexID=f"{packagePrefix}.{signal.NormalizedIdentifiers[0]}",
1194 value=signal,
1195 graph=self._objectGraph
1196 )
1197 signalVertex["kind"] = ObjectGraphVertexKind.Signal
1198 signal._objectVertex = signalVertex
1200 def _LinkSymbolsInExpression(expression, namespace: Namespace, typeVertex: Vertex) -> None:
1201 if isinstance(expression, UnaryExpression):
1202 _LinkSymbolsInExpression(expression.Operand, namespace, typeVertex)
1203 elif isinstance(expression, BinaryExpression):
1204 _LinkSymbolsInExpression(expression.LeftOperand, namespace, typeVertex)
1205 _LinkSymbolsInExpression(expression.RightOperand, namespace, typeVertex)
1206 elif isinstance(expression, TernaryExpression):
1207 WarningCollector.Raise(NotImplementedWarning(f"Handling of ternary expression."))
1208 elif isinstance(expression, SimpleObjectOrFunctionCallSymbol):
1209 obj = namespace.FindObject(expression)
1210 expression._reference = obj
1212 edge = obj._objectVertex.EdgeToVertex(typeVertex)
1213 edge["kind"] = ObjectGraphEdgeKind.ReferenceInExpression
1214 else:
1215 WarningCollector.Raise(NotImplementedWarning(f"Unhandled else-branch"))
1217 def _LinkItems(package: Package) -> None:
1218 for item in package._declaredItems:
1219 if isinstance(item, Constant):
1220 print(f"constant: {item}")
1221 elif isinstance(item, DeferredConstant):
1222 print(f"deferred constant: {item}")
1223 elif isinstance(item, Signal):
1224 print(f"signal: {item}")
1225 elif isinstance(item, IntegerType):
1226 typeNode = item._objectVertex
1228 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1229 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1230 # elif isinstance(item, FloatingType):
1231 # print(f"signal: {item}")
1232 elif isinstance(item, PhysicalType):
1233 typeNode = item._objectVertex
1235 _LinkSymbolsInExpression(item.Range.LeftBound, package._namespace, typeNode)
1236 _LinkSymbolsInExpression(item.Range.RightBound, package._namespace, typeNode)
1237 elif isinstance(item, ArrayType):
1238 # Resolve dimensions
1239 for dimension in item._dimensions:
1240 subtype = package._namespace.FindSubtype(dimension)
1241 dimension._reference = subtype
1243 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1244 edge["kind"] = ObjectGraphEdgeKind.Subtype
1246 # Resolve element subtype
1247 subtype = package._namespace.FindSubtype(item._elementType)
1248 item._elementType._reference = subtype
1250 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1251 edge["kind"] = ObjectGraphEdgeKind.Subtype
1252 elif isinstance(item, RecordType):
1253 # Resolve each elements subtype
1254 for element in item._elements:
1255 subtype = package._namespace.FindSubtype(element._subtype)
1256 element._subtype._reference = subtype
1258 edge = item._objectVertex.EdgeToVertex(subtype._objectVertex)
1259 edge["kind"] = ObjectGraphEdgeKind.Subtype
1260 else:
1261 print(f"not handled: {item}")
1263 for libraryName in ("std", "ieee"):
1264 for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1265 _HandlePackage(package)
1266 _LinkItems(package)
1268 for document in self.IterateDocumentsInCompileOrder():
1269 for package in document.IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package
1270 _HandlePackage(package)
1271 _LinkItems(package)
1273 def LinkContexts(self) -> None:
1274 """
1275 Resolves and links all items (library clauses, use clauses and nested context references) in contexts.
1277 It iterates all contexts in the design. Therefore, the library of the context is used as the working library. By
1278 default, the working library is implicitly referenced in :data:`_referencedLibraries`. In addition, a new empty
1279 dictionary is created in :data:`_referencedPackages` and :data:`_referencedContexts` for that working library.
1281 At first, all library clauses are resolved (a library clause my have multiple library reference symbols). For each
1282 referenced library an entry in :data:`_referencedLibraries` is generated and new empty dictionaries in
1283 :data:`_referencedPackages` and :data:`_referencedContexts` for that working library. In addition, a vertex in the
1284 dependency graph is added for that relationship.
1286 At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each
1287 referenced package,
1288 """
1289 for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context
1290 # Create entries in _referenced*** for the current working library under its real name.
1291 workingLibrary: Library = context.Library
1292 libraryNormalizedIdentifier = workingLibrary._normalizedIdentifier
1294 context._referencedLibraries[libraryNormalizedIdentifier] = self._libraries[libraryNormalizedIdentifier]
1295 context._referencedPackages[libraryNormalizedIdentifier] = {}
1296 context._referencedContexts[libraryNormalizedIdentifier] = {}
1298 # Process all library clauses
1299 for libraryReference in context._libraryReferences:
1300 # A library clause can have multiple comma-separated references
1301 for libraryName in libraryReference.Symbols:
1302 libraryNormalizedIdentifier = libraryName.Name._normalizedIdentifier
1303 try:
1304 library = self._libraries[libraryNormalizedIdentifier]
1305 except KeyError:
1306 raise ReferencedLibraryNotExistingError(context, libraryName)
1307 # TODO: add position to these messages
1309 libraryName.Library = library
1311 context._referencedLibraries[libraryNormalizedIdentifier] = library
1312 context._referencedPackages[libraryNormalizedIdentifier] = {}
1313 context._referencedContexts[libraryNormalizedIdentifier] = {}
1314 # TODO: warn duplicate library reference
1316 dependency = context._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1317 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1319 # Process all use clauses
1320 for packageReference in context.PackageReferences:
1321 # A use clause can have multiple comma-separated references
1322 for symbol in packageReference.Symbols: # type: PackageReferenceSymbol
1323 packageName = symbol.Name.Prefix
1324 libraryName = packageName.Prefix
1326 libraryNormalizedIdentifier = libraryName._normalizedIdentifier
1327 packageNormalizedIdentifier = packageName._normalizedIdentifier
1329 # In case work is used, resolve to the real library name.
1330 if libraryNormalizedIdentifier == "work": 1330 ↛ 1331line 1330 didn't jump to line 1331 because the condition on line 1330 was never true
1331 library: Library = context._parent
1332 libraryNormalizedIdentifier = library._normalizedIdentifier
1333 elif libraryNormalizedIdentifier not in context._referencedLibraries: 1333 ↛ 1335line 1333 didn't jump to line 1335 because the condition on line 1333 was never true
1334 # TODO: This check doesn't trigger if it's the working library.
1335 raise VHDLModelException(f"Use clause references library '{libraryName._identifier}', which was not referenced by a library clause.")
1336 else:
1337 library = self._libraries[libraryNormalizedIdentifier]
1339 try:
1340 package = library._packages[packageNormalizedIdentifier]
1341 except KeyError:
1342 raise VHDLModelException(f"Package '{packageName._identifier}' not found in {'working ' if libraryName._normalizedIdentifier == 'work' else ''}library '{library._identifier}'.")
1344 # FIXME: check if package isn't a generic package
1345 symbol.Package = package
1347 # TODO: warn duplicate package reference
1348 context._referencedPackages[libraryNormalizedIdentifier][packageNormalizedIdentifier] = package
1350 dependency = context._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1351 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1353 # TODO: update the namespace with visible members
1354 if isinstance(symbol, AllPackageMembersReferenceSymbol): 1354 ↛ 1357line 1354 didn't jump to line 1357 because the condition on line 1354 was always true
1355 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'."))
1357 elif isinstance(symbol, PackageMemberReferenceSymbol):
1358 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1360 else:
1361 raise VHDLModelException()
1363 def LinkArchitectures(self) -> None:
1364 """
1365 Link all architectures to corresponding entities in all libraries.
1367 .. rubric:: Algorithm
1369 1. Iterate all libraries:
1371 1. Iterate all architecture groups (grouped per entity symbol's name).
1372 |rarr| :meth:`pyVHDLModel.Library.LinkArchitectures`
1374 * Check if entity symbol's name exists as an entity in this library.
1376 1. For each architecture in the same architecture group:
1378 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
1379 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
1380 * Set parent namespace of architecture's namespace to the entitie's namespace.
1381 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
1383 .. seealso::
1385 :meth:`LinkPackageBodies`
1386 Link all package bodies to corresponding packages in all libraries.
1387 :meth:`LinkPackageInstances`
1388 Link all package instances to corresponding generic packages in all libraries.
1389 """
1390 for library in self._libraries.values():
1391 library.LinkArchitectures()
1393 def LinkPackageBodies(self) -> None:
1394 """
1395 Link all package bodies to corresponding packages in all libraries.
1397 .. rubric:: Algorithm
1399 1. Iterate all libraries:
1401 1. Iterate all package bodies.
1402 |rarr| :meth:`pyVHDLModel.Library.LinkPackageBodies`
1404 * Check if package body symbol's name exists as a package in this library.
1405 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1406 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1407 * Set parent namespace of package body's namespace to the package's namespace.
1408 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1410 .. seealso::
1412 :meth:`LinkArchitectures`
1413 Link all architectures to corresponding entities in all libraries.
1414 :meth:`LinkPackageInstances`
1415 Link all package instances to corresponding generic packages in all libraries.
1416 """
1417 for library in self._libraries.values():
1418 library.LinkPackageBodies()
1420 def LinkPackageInstances(self) -> None:
1421 """
1422 Link all package instances to corresponding generic packages in all libraries.
1424 .. rubric:: Algorithm
1426 1. Iterate all libraries:
1428 1. Iterate all package instances.
1429 |rarr| :meth:`pyVHDLModel.Library.LinkPackageInstances`
1431 .. todo::
1433 * Check if package instance's symbol's name exists as a generic package in this library.
1434 * Add generic package to package instance :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
1435 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
1436 * Set parent namespace of package body's namespace to the package's namespace.
1437 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
1439 .. seealso::
1441 :meth:`LinkArchitectures`
1442 Link all architectures to corresponding entities in all libraries.
1443 :meth:`LinkPackageBodies`
1444 Link all package bodies to corresponding packages in all libraries.
1445 """
1446 for library in self._libraries.values():
1447 library.LinkPackageInstances()
1449 def LinkLibraryReferences(self) -> None:
1450 """
1451 Link all library references (library clause) to the matching VHDL library.
1453 .. rubric:: Algorithm
1455 1. Iterate all design units with contexts:
1457 * If the design unit is a primary unit:
1459 1. Iterate all library identifiers in ``DEFAULT_LIBRARIES`` (``std``):
1461 * Get the referenced library by name from the design.
1462 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1463 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1464 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1465 * Add an edge in the dependency graph from design unit to the referenced library.
1467 2. Get the design unit's library:
1469 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1470 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1471 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1472 * Add an edge in the dependency graph from design unit to the referenced library.
1474 * If the design unit is a secondary unit:
1476 * If design unit is an architecture, get the corresponding entity's referenced libraries.
1477 * If design unit is a package body, get the corresponding package's referenced libraries.
1478 * Otherwise, raise an exception
1480 For every referenced library create new dictionary entries in the design unit's ``_referencedLibraries``.
1482 2. Iterate every library reference (library clause) in the design unit:
1484 * Iterate every library symbol within the library reference:
1486 * Get the library identifier from the symbol.
1487 * Continue the inner loop, if identifier is ``work``.
1488 * Get the referenced library from the design or raise an exception.
1489 * Update the library symbol's target with the referenced library.
1490 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1491 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1492 * Add an empty dictionary in the design unit's ``_referencedContexts`` dictionary.
1493 * Add an edge in the dependency graph from design unit to the referenced library.
1495 .. seealso::
1497 :meth:`LinkPackageReferences`
1498 Link *use clause*.
1499 :meth:`LinkContextReferences`
1500 Link *context clause*.
1501 :meth:`AnalyzeDependencies`
1502 Analyze dependencies and link relations.
1503 """
1504 DEFAULT_LIBRARIES = ("std",)
1506 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1507 # All primary units supporting a context, have at least one library implicitly referenced
1508 if isinstance(designUnit, PrimaryUnit):
1509 for libraryIdentifier in DEFAULT_LIBRARIES:
1510 referencedLibrary = self._libraries[libraryIdentifier]
1511 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1512 designUnit._referencedPackages[libraryIdentifier] = {}
1513 designUnit._referencedContexts[libraryIdentifier] = {}
1514 # TODO: catch KeyError on self._libraries[libName]
1515 # TODO: warn duplicate library reference
1517 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1518 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1520 # TODO: this could create a duplicate linking, if primary unit is put into library 'std'
1521 workingLibrary: Library = designUnit.Library
1522 libraryIdentifier = workingLibrary.NormalizedIdentifier
1523 referencedLibrary = self._libraries[libraryIdentifier] # TODO: isn't this the same as the workingLibrary from 2 lines before?
1525 designUnit._referencedLibraries[libraryIdentifier] = referencedLibrary
1526 designUnit._referencedPackages[libraryIdentifier] = {}
1527 designUnit._referencedContexts[libraryIdentifier] = {}
1529 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedLibrary._dependencyVertex)
1530 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1532 # All secondary units inherit referenced libraries from their primary units.
1533 else:
1534 if isinstance(designUnit, Architecture):
1535 referencedLibraries = designUnit.Entity.Entity._referencedLibraries
1536 elif isinstance(designUnit, PackageBody): 1536 ↛ 1539line 1536 didn't jump to line 1539 because the condition on line 1536 was always true
1537 referencedLibraries = designUnit.Package.Package._referencedLibraries
1538 else:
1539 raise VHDLModelException() # FIXME: exception message
1541 for libraryIdentifier, library in referencedLibraries.items():
1542 designUnit._referencedLibraries[libraryIdentifier] = library # TODO: Could we use the .update() method
1544 for libraryReference in designUnit._libraryReferences:
1545 # A library clause can have multiple comma-separated references
1546 for librarySymbol in libraryReference.Symbols:
1547 libraryIdentifier = librarySymbol.Name.NormalizedIdentifier
1548 if libraryIdentifier == "work": 1548 ↛ 1549line 1548 didn't jump to line 1549 because the condition on line 1548 was never true
1549 continue
1551 try:
1552 library = self._libraries[libraryIdentifier]
1553 except KeyError:
1554 ex = VHDLModelException(f"Library '{librarySymbol.Name.Identifier}' referenced by library clause of design unit '{designUnit.Identifier}' doesn't exist in design.")
1555 ex.add_note(f"""Known libraries: '{"', '".join(library for library in self._libraries)}'""")
1556 raise ex
1558 librarySymbol.Library = library
1559 designUnit._referencedLibraries[libraryIdentifier] = library
1560 designUnit._referencedPackages[libraryIdentifier] = {}
1561 designUnit._referencedContexts[libraryIdentifier] = {}
1562 # TODO: warn duplicate library reference
1564 dependency = designUnit._dependencyVertex.EdgeToVertex(library._dependencyVertex, edgeValue=libraryReference)
1565 dependency["kind"] = DependencyGraphEdgeKind.LibraryClause
1567 def LinkPackageReferences(self) -> None:
1568 """
1569 Link all package references (use clause) to the matching packages.
1571 .. rubric:: Algorithm
1573 1. Iterate all design units with contexts:
1575 * If the design unit is a primary unit:
1577 * If primary unit isn't package ``std.standard``:
1579 1. Iterate all library, packages tuples in ``DEFAULT_PACKAGES`` (``std``: [``standard``]):
1581 * Raise an exception, if library isn't listed in design unit's ``_referencedLibraries``.
1582 * For every package in packages:
1584 * Get the referenced package by library name and package name from the design.
1585 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1586 * Add an edge in the dependency graph from design unit to the referenced package.
1588 * If the design unit is a secondary unit:
1590 * If design unit is an architecture, get the corresponding entity's referenced packages.
1591 * If design unit is a package body, get the corresponding package's referenced packages.
1592 * Otherwise, raise an exception
1594 For every referenced package create new dictionary entries in the design unit's ``_referencedPackages``.
1596 2. Iterate every package reference (use clause) in the design unit:
1598 * Iterate every package symbol within the package reference:
1600 1. Get the library identifier from the symbol.
1601 2. Get the package identifier from the symbol.
1602 3. Resolve library:
1604 * If library name is ``work``, get library from design unit.
1605 * If library name is not in design unit's ``_referencedLibraries``, raise an exception.
1606 * Otherwise, lookup library by name in design.
1608 4. Resolve package:
1610 * Lookup package by name in library.
1612 5. Update design unit:
1614 * Update the package symbol's target with the referenced package.
1615 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1616 * Add an edge in the dependency graph from design unit to the referenced package.
1618 6. Import public package members.
1620 * If package symbol is a ``AllPackageMembersReferenceSymbol``:
1622 * Iterate all components within the referenced package and add entries for each component in the design unit's ``_namespace``.
1624 .. todo:: Other elements are not implemented.
1626 * If package symbol is a ``PackageMemberReferenceSymbol``
1628 .. todo:: Not implemented.
1630 * Otherwise, raise an exception.
1632 .. seealso::
1634 :meth:`LinkLibraryReferences`
1635 Link *library clause*.
1636 :meth:`LinkContextReferences`
1637 Link *context clause*.
1638 :meth:`AnalyzeDependencies`
1639 Analyze dependencies and link relations.
1640 """
1641 DEFAULT_PACKAGES = (
1642 ("std", ("standard",)),
1643 )
1645 for designUnit in self.IterateDesignUnits(DesignUnitKind.WithContext):
1646 # All primary units supporting a context, have at least one package implicitly referenced
1647 if isinstance(designUnit, PrimaryUnit):
1648 if not (designUnit.Library.NormalizedIdentifier == "std" and designUnit.NormalizedIdentifier == "standard"):
1649 for lib, packages in DEFAULT_PACKAGES:
1650 if lib not in designUnit._referencedLibraries: 1650 ↛ 1651line 1650 didn't jump to line 1651 because the condition on line 1650 was never true
1651 raise VHDLModelException() # TODO: missing exception message
1652 for package in packages:
1653 referencedPackage = self._libraries[lib]._packages[package]
1654 designUnit._referencedPackages[lib][package] = referencedPackage
1655 # TODO: catch KeyError on self._libraries[lib[0]]._packages[package]
1656 # TODO: warn duplicate package reference
1658 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex)
1659 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1661 # All secondary units inherit referenced packages from their primary units.
1662 else:
1663 if isinstance(designUnit, Architecture):
1664 referencedPackages = designUnit.Entity.Entity._referencedPackages
1665 elif isinstance(designUnit, PackageBody): 1665 ↛ 1668line 1665 didn't jump to line 1668 because the condition on line 1665 was always true
1666 referencedPackages = designUnit.Package.Package._referencedPackages
1667 else:
1668 raise VHDLModelException() # FIXME: exception message
1670 for packageIdentifier, package in referencedPackages.items():
1671 designUnit._referencedPackages[packageIdentifier] = package
1673 for packageReference in designUnit.PackageReferences:
1674 # A use clause can have multiple comma-separated references
1675 for packageMemberSymbol in packageReference.Symbols:
1676 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1676 ↛ 1677line 1676 didn't jump to line 1677 because the condition on line 1676 was never true
1677 packageName = packageMemberSymbol.Name
1678 elif isinstance(packageMemberSymbol, (AllPackageMembersReferenceSymbol, PackageMemberReferenceSymbol)): 1678 ↛ 1681line 1678 didn't jump to line 1681 because the condition on line 1678 was always true
1679 packageName = packageMemberSymbol.Name.Prefix
1681 libraryName = packageName.Prefix
1683 libraryIdentifier = libraryName.NormalizedIdentifier
1684 packageIdentifier = packageName.NormalizedIdentifier
1686 # In case work is used, resolve to the real library name.
1687 if libraryIdentifier == "work":
1688 library: Library = designUnit.Library
1689 libraryIdentifier = library.NormalizedIdentifier
1690 elif libraryIdentifier not in designUnit._referencedLibraries: 1690 ↛ 1692line 1690 didn't jump to line 1692 because the condition on line 1690 was never true
1691 # TODO: This check doesn't trigger if it's the working library.
1692 raise VHDLModelException(f"Use clause references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1693 else:
1694 library = self._libraries[libraryIdentifier]
1696 try:
1697 package = library._packages[packageIdentifier]
1698 except KeyError:
1699 ex = VHDLModelException(f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
1700 ex.add_note(f"Caused in design unit '{designUnit}' in file '{designUnit.Document}'.")
1701 raise ex
1703 # FIXME: check if package isn't a generic package
1704 packageMemberSymbol.Package = package
1706 # TODO: warn duplicate package reference
1707 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1709 dependency = designUnit._dependencyVertex.EdgeToVertex(package._dependencyVertex, edgeValue=packageReference)
1710 dependency["kind"] = DependencyGraphEdgeKind.UseClause
1712 # TODO: update the namespace with visible members
1713 if isinstance(packageMemberSymbol, PackageReferenceSymbol): 1713 ↛ 1714line 1713 didn't jump to line 1714 because the condition on line 1713 was never true
1714 designUnit._namespace._elements[packageIdentifier] = package
1716 elif isinstance(packageMemberSymbol, AllPackageMembersReferenceSymbol): 1716 ↛ 1722line 1716 didn't jump to line 1722 because the condition on line 1716 was always true
1717 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.all'. Exception: components are handled."))
1719 for componentIdentifier, component in package._components.items(): 1719 ↛ 1720line 1719 didn't jump to line 1720 because the loop on line 1719 never started
1720 designUnit._namespace._elements[componentIdentifier] = component
1722 elif isinstance(packageMemberSymbol, PackageMemberReferenceSymbol):
1723 WarningCollector.Raise(NotImplementedWarning(f"Handling of 'myLib.myPackage.mySymbol'."))
1725 else:
1726 ex = VHDLModelException(f"Unknown package reference symbol type.")
1727 ex.add_note(f"Got type '{getFullyQualifiedName(packageMemberSymbol)}'.")
1728 raise ex
1730 def LinkContextReferences(self) -> None:
1731 """
1732 Link all context references (context clause) to the matching context.
1734 .. rubric:: Algorithm
1736 1. Iterate all design units:
1738 * Iterate all context references in the design unit:
1740 * Iterate each context symbol within the context reference.
1742 1. Get the library identifier from the symbol.
1743 2. Get the context identifier from the symbol.
1744 3. Resolve library:
1746 * If library name is ``work``, get library from design unit.
1747 * If library name is not in design unit's ``_referencedLibraries``, raise an exception.
1748 * Otherwise, lookup library by name in design.
1750 4. Resolve context:
1752 * Lookup context by name in library.
1754 5. Update design unit:
1756 * Update the context symbol's target with the referenced context.
1757 * Add an entry in the design unit's ``_referencedContexts`` dictionary referencing the referenced context.
1758 * Add an edge in the dependency graph from design unit to the referenced context.
1760 2. Iterate all context vertices in the dependency graph (``_dependencyGraph``) in topological order:
1762 * Get the context from the context vertex.
1763 * Iterate all predecessor vertices (design unit vertices) of the context vertex:
1765 1. Get the design unit from design unit vertex.
1766 2. Iterate referenced libraries of the context:
1768 * Add an entry in the design unit's ``_referencedLibraries`` dictionary referencing the referenced library.
1769 * Add an empty dictionary in the design unit's ``_referencedPackages`` dictionary.
1771 3. Iterate referenced packages of the context:
1773 * Raise an exception if package name is already listed in ``_referencedPackages``.
1774 * Add an entry in the design unit's ``_referencedPackages`` dictionary referencing the referenced package.
1776 .. seealso::
1778 :meth:`LinkLibraryReferences`
1779 Link *library clause*.
1780 :meth:`LinkPackageReferences`
1781 Link *use clause*.
1782 :meth:`AnalyzeDependencies`
1783 Analyze dependencies and link relations.
1784 """
1785 for designUnit in self.IterateDesignUnits():
1786 for contextReference in designUnit._contextReferences:
1787 # A context reference can have multiple comma-separated references
1788 for contextSymbol in contextReference.Symbols:
1789 libraryName = contextSymbol.Name.Prefix
1791 libraryIdentifier = libraryName.NormalizedIdentifier
1792 contextIdentifier = contextSymbol.Name.NormalizedIdentifier
1794 # In case work is used, resolve to the real library name.
1795 if libraryIdentifier == "work": 1795 ↛ 1798line 1795 didn't jump to line 1798 because the condition on line 1795 was always true
1796 referencedLibrary = designUnit.Library
1797 libraryIdentifier = referencedLibrary.NormalizedIdentifier
1798 elif libraryIdentifier not in designUnit._referencedLibraries:
1799 # TODO: This check doesn't trigger if it's the working library.
1800 raise VHDLModelException(f"Context reference references library '{libraryName.Identifier}', which was not referenced by a library clause.")
1801 else:
1802 referencedLibrary = self._libraries[libraryIdentifier]
1804 try:
1805 referencedContext = referencedLibrary._contexts[contextIdentifier]
1806 except KeyError:
1807 raise VHDLModelException(f"Context '{contextSymbol.Name.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{referencedLibrary.Identifier}'.")
1809 contextSymbol.Package = referencedContext
1811 # TODO: warn duplicate referencedContext reference
1812 designUnit._referencedContexts[libraryIdentifier][contextIdentifier] = referencedContext
1814 dependency = designUnit._dependencyVertex.EdgeToVertex(referencedContext._dependencyVertex, edgeValue=contextReference)
1815 dependency["kind"] = DependencyGraphEdgeKind.ContextReference
1817 for vertex in self._dependencyGraph.IterateTopologically(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Context):
1818 context: Context = vertex.Value
1819 for designUnitVertex in vertex.IteratePredecessorVertices(): # TODO: should this be filtered to exclude non-contexts?
1820 designUnit: DesignUnit = designUnitVertex.Value
1821 for libraryIdentifier, library in context._referencedLibraries.items():
1822 # if libraryIdentifier in designUnit._referencedLibraries:
1823 # raise VHDLModelException(f"Referenced library '{library.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1825 designUnit._referencedLibraries[libraryIdentifier] = library
1826 designUnit._referencedPackages[libraryIdentifier] = {}
1828 for libraryIdentifier, packages in context._referencedPackages.items():
1829 for packageIdentifier, package in packages.items():
1830 if packageIdentifier in designUnit._referencedPackages: 1830 ↛ 1831line 1830 didn't jump to line 1831 because the condition on line 1830 was never true
1831 raise VHDLModelException(f"Referenced package '{package.Identifier}' already exists in references for design unit '{designUnit.Identifier}'.")
1833 designUnit._referencedPackages[libraryIdentifier][packageIdentifier] = package
1835 def LinkComponents(self) -> None:
1836 """
1837 Link components to matching entities found in same VHDL library.
1839 .. rubric:: Algorithm
1841 1. Iterate all design units with component declarations (packages and architectures):
1843 1. Iterate all component declarations in a package or architecture:
1845 * Check if an entity with matching name can be found in the VHDL library the package is declared within. If
1846 found, set the component's entity reference to that entity, otherwise check if blackboxes are allowed for
1847 that component. If so, mark the component as a blackbox, otherwise, raise an exception.
1849 2. Iterate concurrent statements with declaration regions (block statements, generate statements) if the design
1850 unit is an architecture:
1852 * If the statement is an :class:`IfGenerateStatement`:
1854 1. Iterate declared components in the :class:`IfGenerateBranch`.
1855 2. Iterate declared components in each :class:`ElIfGenerateBranch`.
1856 3. Iterate declared components in the :class:`ElseGenerateBranch` if it exists.
1858 * If the statement is an :class:`ForGenerateStatement`:
1860 1. Iterate declared components.
1862 * If the statement is an :class:`CaseGenerateStatement`:
1864 1. Iterate declared components.
1865 2. Iterate
1867 .. seealso::
1869 :meth:`LinkInstantiations`
1870 Link instantiations to components and entities.
1871 :meth:`AnalyzeDependencies`
1872 Analyze dependencies in a design (calls this method).
1873 """
1874 def linkStatements(library: Library, concurrent: ConcurrentStatementsMixin) -> None:
1875 for statement in concurrent._statements:
1876 if isinstance(statement, IfGenerateStatement): 1876 ↛ 1877line 1876 didn't jump to line 1877 because the condition on line 1876 was never true
1877 linkComponents(library, statement._ifBranch)
1878 linkStatements(library, statement._ifBranch)
1879 for branch in statement._elsifBranches:
1880 linkComponents(library, branch)
1881 linkStatements(library, branch)
1882 if (branch := statement._elseBranch) is not None:
1883 linkComponents(library, branch)
1884 linkStatements(library, branch)
1885 elif isinstance(statement, ForGenerateStatement): 1885 ↛ 1886line 1885 didn't jump to line 1886 because the condition on line 1885 was never true
1886 linkComponents(library, statement)
1887 linkStatements(library, statement)
1888 elif isinstance(statement, CaseGenerateStatement): 1888 ↛ 1889line 1888 didn't jump to line 1889 because the condition on line 1888 was never true
1889 for case in statement._cases:
1890 linkComponents(library, case)
1891 linkStatements(library, case)
1892 elif isinstance(statement, ConcurrentBlockStatement): 1892 ↛ 1893line 1892 didn't jump to line 1893 because the condition on line 1892 was never true
1893 linkComponents(library, statement)
1894 linkStatements(library, statement)
1896 def searchEntityAndLinkComponent(library: Library, component: Component) -> None:
1897 # QUESTION: Add link in dependency graph as dashed line from component to entity?
1898 # Currently, component has no _dependencyVertex field
1899 try:
1900 entity = library._entities[component.NormalizedIdentifier]
1901 except KeyError:
1902 if component.AllowBlackbox:
1903 component._isBlackbox = True
1904 return
1905 else:
1906 raise VHDLModelException(
1907 f"Entity '{component.Identifier}' not found for component '{component.Identifier}' in library '{library.Identifier}'.")
1909 component.Entity = entity
1911 def linkComponents(library: Library, declarationRegion: ConcurrentDeclarationRegionMixin) -> None:
1912 for item in declarationRegion._declaredItems:
1913 if isinstance(item, Component):
1914 searchEntityAndLinkComponent(library, item)
1916 for designUnit in self.IterateDesignUnits(DesignUnitKind.Package | DesignUnitKind.Architecture): # type: Union[Package, Architecture]
1917 library = designUnit._parent
1918 for component in designUnit._components.values(): 1918 ↛ 1919line 1918 didn't jump to line 1919 because the loop on line 1918 never started
1919 searchEntityAndLinkComponent(library, component)
1921 if isinstance(designUnit, Architecture):
1922 linkStatements(library, designUnit)
1924 def LinkInstantiations(self) -> None:
1925 for architecture in self.IterateDesignUnits(DesignUnitKind.Architecture): # type: Architecture
1926 for instance in architecture.IterateInstantiations():
1927 if isinstance(instance, EntityInstantiation): 1927 ↛ 1960line 1927 didn't jump to line 1960 because the condition on line 1927 was always true
1928 libraryName = instance.Entity.Name.Prefix
1929 libraryIdentifier = libraryName.Identifier
1930 normalizedLibraryIdentifier = libraryName.NormalizedIdentifier
1931 if normalizedLibraryIdentifier == "work":
1932 libraryIdentifier = architecture.Library.Identifier
1933 normalizedLibraryIdentifier = architecture.Library.NormalizedIdentifier
1934 elif normalizedLibraryIdentifier not in architecture._referencedLibraries: 1934 ↛ 1935line 1934 didn't jump to line 1935 because the condition on line 1934 was never true
1935 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}'.")
1936 ex.add_note(f"Add a library reference to the architecture or entity using a library clause like: 'library {libraryIdentifier};'.")
1937 raise ex
1939 try:
1940 library = self._libraries[normalizedLibraryIdentifier]
1941 except KeyError:
1942 ex = VHDLModelException(f"Referenced library '{libraryIdentifier}' in direct entity instantiation '{instance.Label}: entity {instance.Entity.Prefix.Identifier}.{instance.Entity.Identifier}' not found in design.")
1943 ex.add_note(f"No design units were parsed into library '{libraryIdentifier}'. Thus it doesn't exist in design.")
1944 raise ex
1946 try:
1947 entity = library._entities[instance.Entity.Name.NormalizedIdentifier]
1948 except KeyError:
1949 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}'.")
1950 libs = [library.Identifier for library in self._libraries.values() for entityIdentifier in library._entities.keys() if entityIdentifier == instance.Entity.Name.NormalizedIdentifier]
1951 if libs:
1952 ex.add_note(f"Found entity '{instance.Entity!s}' in other libraries: {', '.join(libs)}")
1953 raise ex
1955 instance.Entity.Entity = entity
1957 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex, edgeValue=instance)
1958 dependency["kind"] = DependencyGraphEdgeKind.EntityInstantiation
1960 elif isinstance(instance, ComponentInstantiation):
1961 component = instance._parent._namespace.FindComponent(instance.Component)
1963 instance.Component.Component = component
1965 if not component.IsBlackbox:
1966 dependency = architecture._dependencyVertex.EdgeToVertex(component.Entity._dependencyVertex, edgeValue=instance)
1967 dependency["kind"] = DependencyGraphEdgeKind.ComponentInstantiation
1968 else:
1969 WarningCollector.Raise(BlackboxWarning(f"Blackbox caused by '{instance.Label}: {instance.Component.Name}'."))
1971 elif isinstance(instance, ConfigurationInstantiation):
1972 WarningCollector.Raise(NotImplementedWarning(f"Configuration instantiation of '{instance.Label}: {instance.Configuration}'."))
1974 def IndexPackages(self) -> None:
1975 """
1976 Index all declared items in all packages in all libraries.
1978 .. rubric:: Algorithm
1980 1. Iterate all libraries:
1982 1. Iterate all packages |br|
1983 |rarr| :meth:`pyVHDLModel.Library.IndexPackages`
1985 * Index all declared items in that package. |br|
1986 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
1988 .. seealso::
1990 :meth:`IndexPackageBodies`
1991 Index all declared items in all package bodies in all libraries.
1992 :meth:`IndexEntities`
1993 Index all declared items in all entities in all libraries.
1994 :meth:`IndexArchitectures`
1995 Index all declared items in all architectures in all libraries.
1996 """
1997 for library in self._libraries.values():
1998 library.IndexPackages()
2000 def IndexPackageBodies(self) -> None:
2001 """
2002 Index all declared items in all packages in all libraries.
2004 .. rubric:: Algorithm
2006 1. Iterate all libraries:
2008 1. Iterate all packages |br|
2009 |rarr| :meth:`pyVHDLModel.Library.IndexPackageBodies`
2011 * Index all declared items in that package body. |br|
2012 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2014 .. seealso::
2016 :meth:`IndexPackages`
2017 Index all declared items in all packages in all libraries.
2018 :meth:`IndexEntities`
2019 Index all declared items in all entities in all libraries.
2020 :meth:`IndexArchitectures`
2021 Index all declared items in all architectures in all libraries.
2022 """
2023 for library in self._libraries.values():
2024 library.IndexPackageBodies()
2026 def IndexEntities(self) -> None:
2027 """
2028 Index all declared items in all packages in all libraries.
2030 .. rubric:: Algorithm
2032 1. Iterate all libraries:
2034 1. Iterate all packages |br|
2035 |rarr| :meth:`pyVHDLModel.Library.IndexEntities`
2037 * Index all declared items in that entity. |br|
2038 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2040 .. seealso::
2042 :meth:`IndexPackages`
2043 Index all declared items in all packages in all libraries.
2044 :meth:`IndexPackageBodies`
2045 Index all declared items in all package bodies in all libraries.
2046 :meth:`IndexArchitectures`
2047 Index all declared items in all architectures in all libraries.
2048 """
2049 for library in self._libraries.values():
2050 library.IndexEntities()
2052 def IndexArchitectures(self) -> None:
2053 """
2054 Index all declared items in all packages in all libraries.
2056 .. rubric:: Algorithm
2058 1. Iterate all libraries:
2060 1. Iterate all packages |br|
2061 |rarr| :meth:`pyVHDLModel.Library.IndexArchitectures`
2063 * Index all declared items in that architecture. |br|
2064 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2066 .. seealso::
2068 :meth:`IndexPackages`
2069 Index all declared items in all packages in all libraries.
2070 :meth:`IndexPackageBodies`
2071 Index all declared items in all package bodies in all libraries.
2072 :meth:`IndexEntities`
2073 Index all declared items in all entities in all libraries.
2074 """
2075 for library in self._libraries.values():
2076 library.IndexArchitectures()
2078 def CreateHierarchyGraph(self) -> None:
2079 """
2080 Create the hierarchy graph from dependency graph.
2082 .. rubric:: Algorithm
2084 1. Iterate all vertices corresponding to entities and architectures in the dependency graph:
2086 * Copy these vertices to the hierarchy graph and create a bidirectional linking. |br|
2087 In addition, set the referenced design unit's :attr:`~pyVHDLModel.Document._hierarchyVertex` field to reference the copied vertex.
2089 * Add a key-value-pair called ``hierarchyVertex`` to the dependency graph's vertex.
2090 * Add a key-value-pair called ``dependencyVertex`` to the hierarchy graph's vertex.
2092 2. Iterate all architectures ...
2094 .. todo:: Design::CreateHierarchyGraph describe algorithm
2096 1. Iterate all outbound edges
2098 .. todo:: Design::CreateHierarchyGraph describe algorithm
2099 """
2100 # Copy all entity and architecture vertices from dependency graph to hierarchy graph and double-link them
2101 entityArchitectureFilter = lambda v: v["kind"] in DependencyGraphVertexKind.Entity | DependencyGraphVertexKind.Architecture
2102 for vertex in self._dependencyGraph.IterateVertices(predicate=entityArchitectureFilter):
2103 hierarchyVertex = vertex.Copy(self._hierarchyGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="hierarchyVertex")
2104 vertex.Value._hierarchyVertex = hierarchyVertex
2106 # Copy implementation edges from
2107 for hierarchyArchitectureVertex in self._hierarchyGraph.IterateVertices(predicate=lambda v: v["kind"] is DependencyGraphVertexKind.Architecture):
2108 for dependencyEdge in hierarchyArchitectureVertex["dependencyVertex"].IterateOutboundEdges():
2109 kind: DependencyGraphEdgeKind = dependencyEdge["kind"]
2110 if DependencyGraphEdgeKind.Implementation in kind:
2111 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
2112 newEdge = hierarchyArchitectureVertex.EdgeFromVertex(hierarchyDestinationVertex)
2113 elif DependencyGraphEdgeKind.Instantiation in kind:
2114 hierarchyDestinationVertex = dependencyEdge.Destination["hierarchyVertex"]
2116 # FIXME: avoid parallel edges, to graph can be converted to a tree until "real" hierarchy is computed (unrole generics and blocks)
2117 if hierarchyArchitectureVertex.HasEdgeToDestination(hierarchyDestinationVertex):
2118 continue
2120 newEdge = hierarchyArchitectureVertex.EdgeToVertex(hierarchyDestinationVertex)
2121 else:
2122 continue
2124 newEdge["kind"] = kind
2126 def ComputeCompileOrder(self) -> None:
2127 def predicate(edge: Edge) -> bool:
2128 return (
2129 DependencyGraphEdgeKind.Implementation in edge["kind"] or
2130 DependencyGraphEdgeKind.Instantiation in edge["kind"] or
2131 DependencyGraphEdgeKind.UseClause in edge["kind"] or
2132 DependencyGraphEdgeKind.ContextReference in edge["kind"]
2133 ) and edge.Destination["predefined"] is False
2135 for edge in self._dependencyGraph.IterateEdges(predicate=predicate):
2136 sourceDocument: Document = edge.Source.Value.Document
2137 destinationDocument: Document = edge.Destination.Value.Document
2139 sourceVertex = sourceDocument._compileOrderVertex
2140 destinationVertex = destinationDocument._compileOrderVertex
2142 # Don't add self-edges
2143 if sourceVertex is destinationVertex: 2143 ↛ 2146line 2143 didn't jump to line 2146 because the condition on line 2143 was always true
2144 continue
2145 # Don't add parallel edges
2146 elif sourceVertex.HasEdgeToDestination(destinationVertex):
2147 continue
2149 e = sourceVertex.EdgeToVertex(destinationVertex)
2150 e["kind"] = DependencyGraphEdgeKind.CompileOrder
2152 e = sourceVertex["dependencyVertex"].EdgeToVertex(destinationVertex["dependencyVertex"])
2153 e["kind"] = DependencyGraphEdgeKind.CompileOrder
2155 def IterateDocumentsInCompileOrder(self) -> Generator['Document', None, None]:
2156 """
2157 Iterate all document in compile-order.
2159 .. rubric:: Algorithm
2161 * Check if compile-order graph was populated with vertices and its vertices are linked by edges.
2163 1. Iterate compile-order graph in topological order. |br|
2164 :meth:`pyTooling.Graph.Graph.IterateTopologically`
2166 * yield the compiler-order vertex' referenced document.
2168 :returns: A generator to iterate all documents in compile-order in the design.
2169 :raises VHDLModelException: If compile-order was not computed.
2171 .. seealso::
2173 .. todo:: missing text
2175 :meth:`pyVHDLModel.Design.ComputeCompileOrder`
2177 """
2178 if self._compileOrderGraph.EdgeCount < self._compileOrderGraph.VertexCount - 1:
2179 raise VHDLModelException(f"Compile order is not yet computed from dependency graph.")
2181 for compileOrderNode in self._compileOrderGraph.IterateTopologically():
2182 yield compileOrderNode.Value
2184 def GetUnusedDesignUnits(self) -> List[DesignUnit]:
2185 WarningCollector.Raise(NotImplementedWarning(f"Compute unused design units."))
2187 def __repr__(self) -> str:
2188 """
2189 Formats a representation of the design.
2191 **Format:** ``Document: 'my_design'``
2193 :returns: String representation of the design.
2194 """
2195 return f"Design: {self._name}"
2197 __str__ = __repr__
2200@export
2201class Library(ModelEntity, NamedEntityMixin, DocumentedEntityMixin, AllowBlackboxMixin):
2202 """
2203 A ``Library`` represents a VHDL library. It contains all *primary* and *secondary* design units.
2205 .. seealso::
2207 * :class:`Predefined library <pyVHDLModel.Predefined.PredefinedLibrary>`
2208 """
2210 _allowBlackbox: Nullable[bool] #: Allow blackboxes for components in this library.
2211 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a library.
2212 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a library.
2213 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a library.
2214 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a library.
2215 _packages: Dict[str, Package] #: Dictionary of all packages defined in a library.
2216 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library.
2218 _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`.
2220 def __init__(
2221 self,
2222 identifier: str,
2223 documentation: Nullable[str] = None,
2224 allowBlackbox: Nullable[bool] = None,
2225 parent: Nullable[ModelEntity] = None
2226 ) -> None:
2227 """
2228 Initialize a VHDL library.
2230 :param identifier: Name of the VHDL library.
2231 :param documentation: Documentation of this VHDL library, if the caller has one to supply.
2232 :param allowBlackbox: Specify if blackboxes are allowed in this design.
2233 :param parent: The parent model entity (design) of this VHDL library.
2234 """
2235 super().__init__(parent)
2236 NamedEntityMixin.__init__(self, identifier)
2237 DocumentedEntityMixin.__init__(self, documentation)
2238 AllowBlackboxMixin.__init__(self, allowBlackbox)
2240 self._contexts = {}
2241 self._configurations = {}
2242 self._entities = {}
2243 self._architectures = {}
2244 self._packages = {}
2245 self._packageBodies = {}
2247 self._dependencyVertex = None
2249 @property
2250 def Documentation(self) -> Nullable[str]:
2251 """
2252 Property to access the library's documentation (:attr:`_documentation`).
2254 .. hint::
2256 Unlike every other documented entity, a library's documentation cannot come from VHDL source:
2257 the language has no library declaration to attach a comment to. It is therefore settable, so a
2258 caller can supply one from elsewhere - a compile-order file, a project description, ...
2260 :returns: Associated documentation of this VHDL library.
2261 """
2262 return self._documentation
2264 @Documentation.setter
2265 def Documentation(self, documentation: Nullable[str]) -> None:
2266 self._documentation = documentation
2268 @readonly
2269 def Contexts(self) -> Dict[str, Context]:
2270 """
2271 Read-only property to access the dictionary of all context declarations in this library (:attr:`_contexts`).
2273 :returns: Dictionary of all contexts, indexed by normalized identifier.
2274 """
2275 return self._contexts
2277 @readonly
2278 def Configurations(self) -> Dict[str, Configuration]:
2279 """
2280 Read-only property to access the dictionary of all configuration declarations in this library (:attr:`_configurations`).
2282 :returns: Dictionary of all configurations, indexed by normalized identifier.
2283 """
2284 return self._configurations
2286 @readonly
2287 def Entities(self) -> Dict[str, Entity]:
2288 """
2289 Read-only property to access the dictionary of all entity declarations in this library (:attr:`_entities`).
2291 :returns: Dictionary of all entities, indexed by normalized identifier.
2292 """
2293 return self._entities
2295 @readonly
2296 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
2297 """
2298 Read-only property to access the dictionary of all architecture declarations in this library (:attr:`_architectures`).
2300 :returns: Dictionary of all architectures, indexed by normalized entity identifier, then by normalized
2301 architecture identifier.
2302 """
2303 return self._architectures
2305 @readonly
2306 def Packages(self) -> Dict[str, Package]:
2307 """
2308 Read-only property to access the dictionary of all package declarations in this library (:attr:`_packages`).
2310 :returns: Dictionary of all packages, indexed by normalized identifier.
2311 """
2312 return self._packages
2314 @readonly
2315 def PackageBodies(self) -> Dict[str, PackageBody]:
2316 """
2317 Read-only property to access the dictionary of all package body declarations in this library (:attr:`_packageBodies`).
2319 :returns: Dictionary of all package bodies, indexed by normalized identifier.
2320 """
2321 return self._packageBodies
2323 @readonly
2324 def DependencyVertex(self) -> Vertex:
2325 """
2326 Read-only property to access the corresponding dependency vertex (:attr:`_dependencyVertex`).
2328 The dependency vertex references this library by its value field.
2330 :returns: The corresponding dependency vertex.
2331 """
2332 return self._dependencyVertex
2334 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
2335 """
2336 Iterate all design units in the library.
2338 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
2340 .. rubric:: Algorithm
2342 1. Iterate all contexts in that library.
2343 2. Iterate all packages in that library.
2344 3. Iterate all package bodies in that library.
2345 4. Iterate all entities in that library.
2346 5. Iterate all architectures in that library.
2347 6. Iterate all configurations in that library.
2349 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
2350 :returns: A generator to iterate all matched design units in the library.
2352 .. seealso::
2354 :meth:`pyVHDLModel.Design.IterateDesignUnits`
2355 Iterate all design units in the design.
2356 :meth:`pyVHDLModel.Document.IterateDesignUnits`
2357 Iterate all design units in the document.
2358 """
2359 if DesignUnitKind.Context in filter:
2360 for context in self._contexts.values():
2361 yield context
2363 if DesignUnitKind.Package in filter:
2364 for package in self._packages.values():
2365 yield package
2367 if DesignUnitKind.PackageBody in filter:
2368 for packageBody in self._packageBodies.values():
2369 yield packageBody
2371 if DesignUnitKind.Entity in filter:
2372 for entity in self._entities.values():
2373 yield entity
2375 if DesignUnitKind.Architecture in filter:
2376 for architectures in self._architectures.values():
2377 for architecture in architectures.values():
2378 yield architecture
2380 if DesignUnitKind.Configuration in filter:
2381 for configuration in self._configurations.values():
2382 yield configuration
2384 # for verificationProperty in self._verificationUnits.values():
2385 # yield verificationProperty
2386 # for verificationUnit in self._verificationProperties.values():
2387 # yield entity
2388 # for verificationMode in self._verificationModes.values():
2389 # yield verificationMode
2391 def LinkArchitectures(self) -> None:
2392 """
2393 Link all architectures to corresponding entities.
2395 .. rubric:: Algorithm
2397 1. Iterate all architecture groups (grouped per entity symbol's name).
2399 * Check if entity symbol's name exists as an entity in this library.
2401 1. For each architecture in the same architecture group:
2403 * Add architecture to entities architecture dictionary :attr:`pyVHDLModel.DesignUnit.Entity._architectures`.
2404 * Assign found entity to architecture's entity symbol :attr:`pyVHDLModel.DesignUnit.Architecture._entity`
2405 * Set parent namespace of architecture's namespace to the entitie's namespace.
2406 * Add an edge in the dependency graph from the architecture's corresponding dependency vertex to the entity's corresponding dependency vertex.
2408 :raises VHDLModelException: If entity name doesn't exist.
2409 :raises VHDLModelException: If architecture name already exists for entity.
2411 .. seealso::
2413 :meth:`LinkPackageBodies`
2414 Link all package bodies to corresponding packages.
2415 :meth:`LinkPackageInstances`
2416 Link all package instances to corresponding generic packages.
2417 """
2418 for entityName, architecturesPerEntity in self._architectures.items():
2419 if entityName not in self._entities: 2419 ↛ 2420line 2419 didn't jump to line 2420 because the condition on line 2419 was never true
2420 architectureNames = "', '".join(architecturesPerEntity.keys())
2421 raise VHDLModelException(f"Entity '{entityName}' referenced by architecture(s) '{architectureNames}' doesn't exist in library '{self._identifier}'.")
2422 # TODO: search in other libraries to find that entity.
2423 # TODO: add code position
2425 entity = self._entities[entityName]
2426 for architecture in architecturesPerEntity.values():
2427 if architecture._normalizedIdentifier in entity._architectures: 2427 ↛ 2428line 2427 didn't jump to line 2428 because the condition on line 2427 was never true
2428 raise VHDLModelException(f"Architecture '{architecture._identifier}' already exists for entity '{entity._identifier}'.")
2429 # TODO: add code position of existing and current
2431 entity._architectures[architecture._normalizedIdentifier] = architecture
2432 architecture._entity.Entity = entity
2433 architecture._namespace._parentNamespace = entity._namespace
2435 # add "architecture -> entity" relation in dependency graph
2436 dependency = architecture._dependencyVertex.EdgeToVertex(entity._dependencyVertex)
2437 dependency["kind"] = DependencyGraphEdgeKind.EntityImplementation
2439 def LinkPackageBodies(self) -> None:
2440 """
2441 Link all package bodies to corresponding packages.
2443 .. rubric:: Algorithm
2445 1. Iterate all package bodies.
2447 * Check if package body symbol's name exists as a package in this library.
2448 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2449 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2450 * Set parent namespace of package body's namespace to the package's namespace.
2451 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2453 :raises VHDLModelException: If package name doesn't exist.
2455 .. seealso::
2457 :meth:`LinkArchitectures`
2458 Link all architectures to corresponding entities.
2459 :meth:`LinkPackageInstances`
2460 Link all package instances to corresponding generic packages.
2461 """
2462 for packageBodyName, packageBody in self._packageBodies.items():
2463 if packageBodyName not in self._packages: 2463 ↛ 2464line 2463 didn't jump to line 2464 because the condition on line 2463 was never true
2464 raise VHDLModelException(f"Package '{packageBodyName}' referenced by package body '{packageBodyName}' doesn't exist in library '{self._identifier}'.")
2466 package = self._packages[packageBodyName]
2467 package._packageBody = packageBody # TODO: add warning if package had already a body, which is now replaced
2468 packageBody._package.Package = package
2469 packageBody._namespace._parentNamespace = package._namespace
2471 # add "package body -> package" relation in dependency graph
2472 dependency = packageBody._dependencyVertex.EdgeToVertex(package._dependencyVertex)
2473 dependency["kind"] = DependencyGraphEdgeKind.PackageImplementation
2475 def LinkPackageInstances(self) -> None:
2476 """
2477 Link all package instances to corresponding generic packages.
2479 .. rubric:: Algorithm
2481 1. Iterate all package instances.
2483 .. todo::
2485 * Check if package body symbol's name exists as a package in this library.
2486 * Add package body to package :attr:`pyVHDLModel.DesignUnit.Package._packageBody`.
2487 * Assign found package to package body's package symbol :attr:`pyVHDLModel.DesignUnit.PackageBody._package`
2488 * Set parent namespace of package body's namespace to the package's namespace.
2489 * Add an edge in the dependency graph from the package body's corresponding dependency vertex to the package's corresponding dependency vertex.
2491 :raises VHDLModelException: If generic package name doesn't exist.
2493 .. seealso::
2495 :meth:`LinkArchitectures`
2496 Link all architectures to corresponding entities.
2497 :meth:`LinkPackageBodies`
2498 Link all package bodies to corresponding packages.
2499 """
2500 for packageInstanceName, packageInstance in self._packages.items():
2501 if isinstance(packageInstance, PackageInstantiation): 2501 ↛ 2502line 2501 didn't jump to line 2502 because the condition on line 2501 was never true
2502 packageSymbol = packageInstance._packageReference
2503 packageName = packageSymbol.Name
2504 libraryName = packageName.Prefix
2506 libraryIdentifier = libraryName.NormalizedIdentifier
2507 packageIdentifier = packageName.NormalizedIdentifier
2509 # In case work is used, resolve to the real library name.
2510 if libraryIdentifier == "work":
2511 library: Library = self
2512 libraryIdentifier = library.NormalizedIdentifier
2513 elif libraryIdentifier not in self._parent._libraries:
2514 # TODO: This check doesn't trigger if it's the working library.
2515 raise VHDLModelException(f"Package instantiation of '{packageInstanceName}' references library '{libraryName.Identifier}', which cannot be found in design.")
2516 else:
2517 library = self._parent._libraries[libraryIdentifier]
2519 try:
2520 package = library._packages[packageIdentifier]
2521 except KeyError:
2522 ex = VHDLModelException(
2523 f"Package '{packageName.Identifier}' not found in {'working ' if libraryName.NormalizedIdentifier == 'work' else ''}library '{library.Identifier}'.")
2524 ex.add_note(f"Caused in library '{self}' in file '{packageInstance.Document}'.")
2525 raise ex
2527 # FIXME: check if package is a generic package
2528 if package.GenericCount == 0:
2529 raise VHDLModelException(f"Package '{libraryName.Identifier}.{packageName.Identifier}' referenced by '{self._identifier}.{packageInstanceName}' is not a generic package.")
2531 packageSymbol.Package = package
2533 dependency = packageInstance._dependencyVertex.EdgeToVertex(package._dependencyVertex) # , edgeValue=packageReference)
2534 dependency["kind"] = DependencyGraphEdgeKind.PackageInstantiation
2536 packageInstance.Instantiate()
2538 def IndexPackages(self) -> None:
2539 """
2540 Index declared items in all packages.
2542 .. rubric:: Algorithm
2544 1. Iterate all packages:
2546 * Index all declared items. |br|
2547 |rarr| :meth:`pyVHDLModel.DesignUnit.Package.IndexDeclaredItems`
2549 .. seealso::
2551 :meth:`IndexPackageBodies`
2552 Index all declared items in a package body.
2553 :meth:`IndexEntities`
2554 Index all declared items in an entity.
2555 :meth:`IndexArchitectures`
2556 Index all declared items in an architecture.
2557 """
2558 for package in self._packages.values():
2559 if isinstance(package, Package): 2559 ↛ 2558line 2559 didn't jump to line 2558 because the condition on line 2559 was always true
2560 package.IndexDeclaredItems()
2562 def IndexPackageBodies(self) -> None:
2563 """
2564 Index declared items in all package bodies.
2566 .. rubric:: Algorithm
2568 1. Iterate all package bodies:
2570 * Index all declared items. |br|
2571 |rarr| :meth:`pyVHDLModel.DesignUnit.PackageBody.IndexDeclaredItems`
2573 .. seealso::
2575 :meth:`IndexPackages`
2576 Index all declared items in a package.
2577 :meth:`IndexEntities`
2578 Index all declared items in an entity.
2579 :meth:`IndexArchitectures`
2580 Index all declared items in an architecture.
2581 """
2582 for packageBody in self._packageBodies.values():
2583 packageBody.IndexDeclaredItems()
2585 def IndexEntities(self) -> None:
2586 """
2587 Index declared items in all entities.
2589 .. rubric:: Algorithm
2591 1. Iterate all entities:
2593 * Index all declared items. |br|
2594 |rarr| :meth:`pyVHDLModel.DesignUnit.Entity.IndexDeclaredItems`
2596 .. seealso::
2598 :meth:`IndexPackages`
2599 Index all declared items in a package.
2600 :meth:`IndexPackageBodies`
2601 Index all declared items in a package body.
2602 :meth:`IndexArchitectures`
2603 Index all declared items in an architecture.
2604 """
2605 for entity in self._entities.values():
2606 entity.IndexDeclaredItems()
2608 def IndexArchitectures(self) -> None:
2609 """
2610 Index declared items in all architectures.
2612 .. rubric:: Algorithm
2614 1. Iterate all architectures:
2616 * Index all declared items. |br|
2617 |rarr| :meth:`pyVHDLModel.DesignUnit.Architecture.IndexDeclaredItems`
2619 .. seealso::
2621 :meth:`IndexPackages`
2622 Index all declared items in a package.
2623 :meth:`IndexPackageBodies`
2624 Index all declared items in a package body.
2625 :meth:`IndexEntities`
2626 Index all declared items in an entity.
2627 """
2628 for architectures in self._architectures.values():
2629 for architecture in architectures.values():
2630 architecture.IndexDeclaredItems()
2631 architecture.IndexStatements()
2633 def __repr__(self) -> str:
2634 """
2635 Formats a representation of the library.
2637 **Format:** ``Library: 'my_library'``
2639 :returns: String representation of the library.
2640 """
2641 return f"Library: '{self._identifier}'"
2643 __str__ = __repr__
2646@export
2647class Document(ModelEntity, DocumentedEntityMixin):
2648 """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units."""
2650 _path: Path #: Path to the document. ``None`` if in-memory document.
2651 _vhdlVersion: VHDLVersion #: VHDL version used for analyzing this source file.
2652 _library: Library #: VHDL library used for analyzing the source file's content into.
2653 _designUnits: List[DesignUnit] #: List of all design units defined in a document.
2654 _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document.
2655 _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document.
2656 _entities: Dict[str, Entity] #: Dictionary of all entities defined in a document.
2657 _architectures: Dict[str, Dict[str, Architecture]] #: Dictionary of all architectures defined in a document.
2658 _packages: Dict[str, Package] #: Dictionary of all packages defined in a document.
2659 _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a document.
2660 _verificationUnits: Dict[str, VerificationUnit] #: Dictionary of all PSL verification units defined in a document.
2661 _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document.
2662 _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document.
2664 _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`.
2665 _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`.
2667 def __init__(
2668 self,
2669 path: Path,
2670 documentation: Nullable[str] = None,
2671 vhdlVersion: VHDLVersion = VHDLVersion.VHDL2008,
2672 library: Nullable[Library] = None,
2673 parent: Nullable[ModelEntity] = None
2674 ) -> None:
2675 """
2676 Initializes a VHDL document.
2678 :param path: Path to the document. ``None`` if in-memory document.
2679 :param documentation: The documentation comment associated with this declaration.
2680 :param vhdlVersion: VHDL version used for analyzing this source file.
2681 :param library: VHDL library used for analyzing the source file's content into.
2682 :param parent: The parent model entity of this entity.
2683 """
2684 super().__init__(parent)
2685 DocumentedEntityMixin.__init__(self, documentation)
2687 self._path = path
2688 self._vhdlVersion = vhdlVersion
2689 self._library = library
2690 self._designUnits = []
2691 self._contexts = {}
2692 self._configurations = {}
2693 self._entities = {}
2694 self._architectures = {}
2695 self._packages = {}
2696 self._packageBodies = {}
2697 self._verificationUnits = {}
2698 self._verificationProperties = {}
2699 self._verificationModes = {}
2701 self._dependencyVertex = None
2702 self._compileOrderVertex = None
2704 def _AddEntity(self, item: Entity) -> None:
2705 """
2706 Add an entity to the document's lists of design units.
2708 :param item: Entity object to be added to the document.
2709 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.Entity`.
2710 :raises VHDLModelException: If entity name already exists in document.
2711 """
2712 if not isinstance(item, Entity): 2712 ↛ 2713line 2712 didn't jump to line 2713 because the condition on line 2712 was never true
2713 ex = TypeError(f"Parameter 'item' is not of type 'Entity'.")
2714 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2715 raise ex
2717 identifier = item._normalizedIdentifier
2718 if identifier in self._entities: 2718 ↛ 2720line 2718 didn't jump to line 2720 because the condition on line 2718 was never true
2719 # TODO: use a more specific exception
2720 raise VHDLModelException(f"An entity '{item._identifier}' already exists in this document.")
2722 self._entities[identifier] = item
2723 self._designUnits.append(item)
2724 item._document = self
2726 # TODO: add entity to _library and vice versa
2728 def _AddArchitecture(self, item: Architecture) -> None:
2729 """
2730 Add an architecture to the document's lists of design units.
2732 :param item: Architecture object to be added to the document.
2733 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.Architecture`.
2734 :raises VHDLModelException: If architecture name already exists for the referenced entity name in document.
2735 """
2736 if not isinstance(item, Architecture): 2736 ↛ 2737line 2736 didn't jump to line 2737 because the condition on line 2736 was never true
2737 ex = TypeError(f"Parameter 'item' is not of type 'Architecture'.")
2738 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2739 raise ex
2741 entity = item._entity.Name
2742 entityIdentifier = entity._normalizedIdentifier
2743 try:
2744 architectures = self._architectures[entityIdentifier]
2745 if item._normalizedIdentifier in architectures:
2746 # TODO: use a more specific exception
2747 # FIXME: this is allowed and should be a warning or a strict mode.
2748 raise VHDLModelException(f"An architecture '{item._identifier}' for entity '{entity._identifier}' already exists in this document.")
2750 architectures[item.Identifier] = item
2751 except KeyError:
2752 self._architectures[entityIdentifier] = {item._identifier: item}
2754 self._designUnits.append(item)
2755 item._document = self
2757 # TODO: add architecture to _library and vice versa
2759 def _AddPackage(self, item: Package) -> None:
2760 """
2761 Add a package to the document's lists of design units.
2763 :param item: Package object to be added to the document.
2764 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.Package`.
2765 :raises VHDLModelException: If package name already exists in document.
2766 """
2767 if not isinstance(item, (Package, PackageInstantiation)): 2767 ↛ 2768line 2767 didn't jump to line 2768 because the condition on line 2767 was never true
2768 ex = TypeError(f"Parameter 'item' is not of type 'Package' or 'PackageInstantiation'.")
2769 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2770 raise ex
2772 identifier = item._normalizedIdentifier
2773 if identifier in self._packages: 2773 ↛ 2775line 2773 didn't jump to line 2775 because the condition on line 2773 was never true
2774 # TODO: use a more specific exception
2775 raise VHDLModelException(f"A package '{item._identifier}' already exists in this document.")
2777 self._packages[identifier] = item
2778 self._designUnits.append(item)
2779 item._document = self
2781 # TODO: add package to _library and vice versa
2783 def _AddPackageBody(self, item: PackageBody) -> None:
2784 """
2785 Add a package body to the document's lists of design units.
2787 :param item: Package body object to be added to the document.
2788 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.PackageBody`.
2789 :raises VHDLModelException: If package body name already exists in document.
2790 """
2791 if not isinstance(item, PackageBody): 2791 ↛ 2792line 2791 didn't jump to line 2792 because the condition on line 2791 was never true
2792 ex = TypeError(f"Parameter 'item' is not of type 'PackageBody'.")
2793 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2794 raise ex
2796 identifier = item._normalizedIdentifier
2797 if identifier in self._packageBodies: 2797 ↛ 2799line 2797 didn't jump to line 2799 because the condition on line 2797 was never true
2798 # TODO: use a more specific exception
2799 raise VHDLModelException(f"A package body '{item._identifier}' already exists in this document.")
2801 self._packageBodies[identifier] = item
2802 self._designUnits.append(item)
2803 item._document = self
2805 # TODO: add packagebody to _library and vice versa
2807 def _AddContext(self, item: Context) -> None:
2808 """
2809 Add a context to the document's lists of design units.
2811 :param item: Context object to be added to the document.
2812 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.Context`.
2813 :raises VHDLModelException: If context name already exists in document.
2814 """
2815 if not isinstance(item, Context): 2815 ↛ 2816line 2815 didn't jump to line 2816 because the condition on line 2815 was never true
2816 ex = TypeError(f"Parameter 'item' is not of type 'Context'.")
2817 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2818 raise ex
2820 identifier = item._normalizedIdentifier
2821 if identifier in self._contexts: 2821 ↛ 2823line 2821 didn't jump to line 2823 because the condition on line 2821 was never true
2822 # TODO: use a more specific exception
2823 raise VHDLModelException(f"A context '{item._identifier}' already exists in this document.")
2825 self._contexts[identifier] = item
2826 self._designUnits.append(item)
2827 item._document = self
2829 # TODO: add context to _library and vice versa
2831 def _AddConfiguration(self, item: Configuration) -> None:
2832 """
2833 Add a configuration to the document's lists of design units.
2835 :param item: Configuration object to be added to the document.
2836 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.Configuration`.
2837 :raises VHDLModelException: If configuration name already exists in document.
2838 """
2839 if not isinstance(item, Configuration): 2839 ↛ 2840line 2839 didn't jump to line 2840 because the condition on line 2839 was never true
2840 ex = TypeError(f"Parameter 'item' is not of type 'Configuration'.")
2841 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2842 raise ex
2844 identifier = item._normalizedIdentifier
2845 if identifier in self._configurations: 2845 ↛ 2847line 2845 didn't jump to line 2847 because the condition on line 2845 was never true
2846 # TODO: use a more specific exception
2847 raise VHDLModelException(f"A configuration '{item._identifier}' already exists in this document.")
2849 self._configurations[identifier] = item
2850 self._designUnits.append(item)
2851 item._document = self
2853 # TODO: add configuration to _library and vice versa
2855 def _AddVerificationUnit(self, item: VerificationUnit) -> None:
2856 if not isinstance(item, VerificationUnit):
2857 ex = TypeError(f"Parameter 'item' is not of type 'VerificationUnit'.")
2858 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2859 raise ex
2861 identifier = item._normalizedIdentifier
2862 if identifier in self._verificationUnits:
2863 raise ValueError(f"A verification unit '{item._identifier}' already exists in this document.")
2865 self._verificationUnits[identifier] = item
2866 self._designUnits.append(item)
2867 item._document = self
2869 # TODO: add vunit to _library and vice versa
2871 def _AddVerificationProperty(self, item: VerificationProperty) -> None:
2872 if not isinstance(item, VerificationProperty):
2873 ex = TypeError(f"Parameter 'item' is not of type 'VerificationProperty'.")
2874 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2875 raise ex
2877 identifier = item.NormalizedIdentifier
2878 if identifier in self._verificationProperties:
2879 raise ValueError(f"A verification property '{item.Identifier}' already exists in this document.")
2881 self._verificationProperties[identifier] = item
2882 self._designUnits.append(item)
2883 item._document = self
2885 # TODO: add vprop to _library and vice versa
2887 def _AddVerificationMode(self, item: VerificationMode) -> None:
2888 if not isinstance(item, VerificationMode):
2889 ex = TypeError(f"Parameter 'item' is not of type 'VerificationMode'.")
2890 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2891 raise ex
2893 identifier = item.NormalizedIdentifier
2894 if identifier in self._verificationModes:
2895 raise ValueError(f"A verification mode '{item.Identifier}' already exists in this document.")
2897 self._verificationModes[identifier] = item
2898 self._designUnits.append(item)
2899 item._document = self
2901 # TODO: add vmode to _library and vice versa
2903 def _AddDesignUnit(self, item: DesignUnit) -> None:
2904 """
2905 Add a design unit to the document's lists of design units.
2907 :param item: Configuration object to be added to the document.
2908 :raises TypeError: If parameter 'item' is not of type :class:`~pyVHDLModel.DesignUnit.DesignUnit`.
2909 :raises ValueError: If parameter 'item' is an unknown :class:`~pyVHDLModel.DesignUnit.DesignUnit`.
2910 :raises VHDLModelException: If configuration name already exists in document.
2911 """
2912 if not isinstance(item, DesignUnit): 2912 ↛ 2913line 2912 didn't jump to line 2913 because the condition on line 2912 was never true
2913 ex = TypeError(f"Parameter 'item' is not of type 'DesignUnit'.")
2914 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2915 raise ex
2917 if isinstance(item, Entity):
2918 self._AddEntity(item)
2919 elif isinstance(item, Architecture):
2920 self._AddArchitecture(item)
2921 elif isinstance(item, Package):
2922 self._AddPackage(item)
2923 elif isinstance(item, PackageBody):
2924 self._AddPackageBody(item)
2925 elif isinstance(item, Context):
2926 self._AddContext(item)
2927 elif isinstance(item, Configuration): 2927 ↛ 2929line 2927 didn't jump to line 2929 because the condition on line 2927 was always true
2928 self._AddConfiguration(item)
2929 elif isinstance(item, VerificationUnit):
2930 self._AddVerificationUnit(item)
2931 elif isinstance(item, VerificationProperty):
2932 self._AddVerificationProperty(item)
2933 elif isinstance(item, VerificationMode):
2934 self._AddVerificationMode(item)
2935 else:
2936 ex = ValueError(f"Parameter 'item' is an unknown 'DesignUnit'.")
2937 ex.add_note(f"Got type '{getFullyQualifiedName(item)}'.")
2938 raise ex
2940 @readonly
2941 def Path(self) -> Path:
2942 """
2943 Read-only property to access the document's path (:attr:`_path`).
2945 :returns: The path of this document.
2946 """
2947 return self._path
2949 @readonly
2950 def VHDLVersion(self) -> VHDLVersion:
2951 """
2952 Read-only property to access the document's VHDL version (:attr:`_vhdlVersion`).
2954 :returns: VHDL version used to analyze this VHDL file.
2955 """
2956 return self._vhdlVersion
2958 # @property
2959 @readonly
2960 def Library(self) -> Library:
2961 """
2962 Read-only property to access the document's VHDL library (:attr:`_library`).
2964 :returns: VHDL library used to analyze the VHDL file's design units into.
2965 """
2966 return self._library
2968 # @Library.setter
2969 # def Library(self, library: Library) -> None:
2970 # self._library = library
2971 #
2972 # # TODO: check and set library to design unit?
2974 @readonly
2975 def DesignUnits(self) -> List[DesignUnit]:
2976 """
2977 Read-only property to access a list of all design units declarations found in this document (:attr:`_designUnits`).
2979 :returns: List of all design units.
2980 """
2981 return self._designUnits
2983 @readonly
2984 def Contexts(self) -> Dict[str, Context]:
2985 """
2986 Read-only property to access the dictionary of all context declarations in this document (:attr:`_contexts`).
2988 :returns: Dictionary of all contexts, indexed by normalized identifier.
2989 """
2990 return self._contexts
2992 @readonly
2993 def Configurations(self) -> Dict[str, Configuration]:
2994 """
2995 Read-only property to access the dictionary of all configuration declarations in this document (:attr:`_configurations`).
2997 :returns: Dictionary of all configurations, indexed by normalized identifier.
2998 """
2999 return self._configurations
3001 @readonly
3002 def Entities(self) -> Dict[str, Entity]:
3003 """
3004 Read-only property to access the dictionary of all entity declarations in this document (:attr:`_entities`).
3006 :returns: Dictionary of all entities, indexed by normalized identifier.
3007 """
3008 return self._entities
3010 @readonly
3011 def Architectures(self) -> Dict[str, Dict[str, Architecture]]:
3012 """
3013 Read-only property to access the dictionary of all architecture declarations in this document (:attr:`_architectures`).
3015 :returns: Dictionary of all architectures, indexed by normalized entity identifier, then by normalized
3016 architecture identifier.
3017 """
3018 return self._architectures
3020 @readonly
3021 def Packages(self) -> Dict[str, Package]:
3022 """
3023 Read-only property to access the dictionary of all package declarations in this document (:attr:`_packages`).
3025 :returns: Dictionary of all packages, indexed by normalized identifier.
3026 """
3027 return self._packages
3029 @readonly
3030 def PackageBodies(self) -> Dict[str, PackageBody]:
3031 """
3032 Read-only property to access the dictionary of all package body declarations in this document (:attr:`_packageBodies`).
3034 :returns: Dictionary of all package bodies, indexed by normalized identifier.
3035 """
3036 return self._packageBodies
3038 @readonly
3039 def VerificationUnits(self) -> Dict[str, VerificationUnit]:
3040 """
3041 Read-only property to access the dictionary of all verification unit declarations in this document (:attr:`_verificationUnits`).
3043 :returns: Dictionary of all verification units, indexed by normalized identifier.
3044 """
3045 return self._verificationUnits
3047 @readonly
3048 def VerificationProperties(self) -> Dict[str, VerificationProperty]:
3049 """
3050 Read-only property to access the dictionary of all verification property declarations in this document (:attr:`_verificationProperties`).
3052 :returns: Dictionary of all verification properties, indexed by normalized identifier.
3053 """
3054 return self._verificationProperties
3056 @readonly
3057 def VerificationModes(self) -> Dict[str, VerificationMode]:
3058 """
3059 Read-only property to access the dictionary of all verification mode declarations in this document (:attr:`_verificationModes`).
3061 :returns: Dictionary of all verification mode declarations, indexed by normalized identifier.
3062 """
3063 return self._verificationModes
3065 @readonly
3066 def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]:
3067 """
3068 Read-only property to access the corresponding compile-order vertex (:attr:`_compileOrderVertex`).
3070 The compile-order vertex references this document by its value field.
3072 :returns: The corresponding compile-order vertex.
3073 """
3074 return self._compileOrderVertex
3076 def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]:
3077 """
3078 Iterate all design units in the document.
3080 A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units.
3082 .. rubric:: Algorithm
3084 * If contexts are selected in the filter:
3086 1. Iterate all contexts in that library.
3088 * If packages are selected in the filter:
3090 1. Iterate all packages in that library.
3092 * If package bodies are selected in the filter:
3094 1. Iterate all package bodies in that library.
3096 * If entites are selected in the filter:
3098 1. Iterate all entites in that library.
3100 * If architectures are selected in the filter:
3102 1. Iterate all architectures in that library.
3104 * If configurations are selected in the filter:
3106 1. Iterate all configurations in that library.
3108 :param filter: An enumeration with possibly multiple flags to filter the returned design units.
3109 :returns: A generator to iterate all matched design units in the document.
3111 .. seealso::
3113 :meth:`pyVHDLModel.Design.IterateDesignUnits`
3114 Iterate all design units in the design.
3115 :meth:`pyVHDLModel.Library.IterateDesignUnits`
3116 Iterate all design units in the library.
3117 """
3118 if DesignUnitKind.Context in filter: 3118 ↛ 3122line 3118 didn't jump to line 3122 because the condition on line 3118 was always true
3119 for context in self._contexts.values():
3120 yield context
3122 if DesignUnitKind.Package in filter: 3122 ↛ 3126line 3122 didn't jump to line 3126 because the condition on line 3122 was always true
3123 for package in self._packages.values():
3124 yield package
3126 if DesignUnitKind.PackageBody in filter: 3126 ↛ 3130line 3126 didn't jump to line 3130 because the condition on line 3126 was always true
3127 for packageBody in self._packageBodies.values():
3128 yield packageBody
3130 if DesignUnitKind.Entity in filter: 3130 ↛ 3134line 3130 didn't jump to line 3134 because the condition on line 3130 was always true
3131 for entity in self._entities.values():
3132 yield entity
3134 if DesignUnitKind.Architecture in filter: 3134 ↛ 3139line 3134 didn't jump to line 3139 because the condition on line 3134 was always true
3135 for architectures in self._architectures.values():
3136 for architecture in architectures.values():
3137 yield architecture
3139 if DesignUnitKind.Configuration in filter: 3139 ↛ exitline 3139 didn't return from function 'IterateDesignUnits' because the condition on line 3139 was always true
3140 for configuration in self._configurations.values():
3141 yield configuration
3143 # for verificationProperty in self._verificationUnits.values():
3144 # yield verificationProperty
3145 # for verificationUnit in self._verificationProperties.values():
3146 # yield entity
3147 # for verificationMode in self._verificationModes.values():
3148 # yield verificationMode
3150 def __repr__(self) -> str:
3151 """
3152 Formats a representation of the document.
3154 **Format:** ``Document: 'path/to/file.vhdl'``
3156 :returns: String representation of the document.
3157 """
3158 return f"Document: '{self._path}'"
3160 __str__ = __repr__