Coverage for pyVHDLModel/Configuration.py: 98%
156 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 10:05 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 10:05 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2026-2026 Patrick Lehmann - Boetzingen, Germany #
15# #
16# Licensed under the Apache License, Version 2.0 (the "License"); #
17# you may not use this file except in compliance with the License. #
18# You may obtain a copy of the License at #
19# #
20# http://www.apache.org/licenses/LICENSE-2.0 #
21# #
22# Unless required by applicable law or agreed to in writing, software #
23# distributed under the License is distributed on an "AS IS" BASIS, #
24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
25# See the License for the specific language governing permissions and #
26# limitations under the License. #
27# #
28# SPDX-License-Identifier: Apache-2.0 #
29# ==================================================================================================================== #
30#
31"""
32This module contains parts of an abstract document language model for VHDL.
34Configurations: entity aspects, binding indications, component configurations (and the structurally
35identical configuration specifications), and block configurations.
36"""
37from __future__ import annotations
39from typing import TYPE_CHECKING, Iterable, Union, Optional as Nullable
41from pyTooling.Decorators import export, readonly
42from pyTooling.MetaClasses import abstractclass
44from pyVHDLModel.Base import ModelEntity
45from pyVHDLModel.Name import Name
46from pyVHDLModel.Symbol import Symbol, EntitySymbol, ArchitectureSymbol, ConfigurationSymbol, \
47 ComponentInstantiationSymbol
48from pyVHDLModel.Association import GenericAssociationItem, PortAssociationItem, GenericMapAspectMixin, \
49 PortMapAspectMixin
51if TYPE_CHECKING: 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true
52 from pyVHDLModel.Visitor import Visitor
55@export
56@abstractclass
57class EntityAspect(ModelEntity):
58 """
59 Base-class for the three forms an entity aspect can take in a binding indication: an entity
60 (optionally with an architecture), a configuration, or ``open``.
62 .. admonition:: Example
64 .. code-block:: VHDL
66 for U1 : comp use entity work.sub(behav);
67 -- ^^^^^^^^^^^^^^^^^^^^^^
69 .. seealso::
71 * :class:`Entity aspect entity <pyVHDLModel.Configuration.EntityAspectEntity>`
72 * :class:`Entity aspect configuration <pyVHDLModel.Configuration.EntityAspectConfiguration>`
73 * :class:`Entity aspect open <pyVHDLModel.Configuration.EntityAspectOpen>`
74 """
77@export
78class EntityAspectEntity(EntityAspect):
79 """
80 Represents an entity aspect naming an entity, optionally with an architecture.
82 .. admonition:: Example
84 .. code-block:: VHDL
86 use entity work.e_rest(rtl);
87 -- ^^^^^^^^^^^ <- Entity
88 -- ^^^ <- Architecture
89 """
91 _entity: EntitySymbol #: Reference to the named entity.
92 _architecture: Nullable[ArchitectureSymbol] #: Reference to the selected architecture, or ``None`` if none was given.
94 def __init__(
95 self,
96 entity: EntitySymbol,
97 architecture: Nullable[ArchitectureSymbol] = None,
98 parent: Nullable[ModelEntity] = None
99 ) -> None:
100 """
101 Initializes an entity aspect naming an entity, optionally with an architecture.
103 :param entity: Reference to the named entity.
104 :param architecture: Reference to the selected architecture, or ``None`` if none was given.
105 :param parent: The parent model entity of this entity.
106 """
107 super().__init__(parent)
109 self._entity = entity
110 entity.Parent = self
112 self._architecture = architecture
113 if architecture is not None:
114 architecture.Parent = self
116 def Visit(self, visitor: Visitor) -> None:
117 """
118 Walk this entity aspect, its entity and its architecture (if any) with a visitor.
120 :param visitor: The visitor receiving the events.
121 """
122 visitor.VisitEntityAspectEntity(self)
123 self._entity.Visit(visitor)
124 if self._architecture is not None:
125 visitor.VisitLeftParenthesis(self)
126 self._architecture.Visit(visitor)
127 visitor.VisitRightParenthesis(self)
129 visitor.DepartEntityAspectEntity(self)
131 @readonly
132 def Entity(self) -> EntitySymbol:
133 """
134 Read-only property to access the entity (:attr:`_entity`).
136 :returns: The entity.
137 """
138 return self._entity
140 @readonly
141 def Architecture(self) -> Nullable[ArchitectureSymbol]:
142 """
143 Read-only property to access the architecture (:attr:`_architecture`).
145 :returns: The architecture, or ``None`` if not set.
146 """
147 return self._architecture
150@export
151class EntityAspectConfiguration(EntityAspect):
152 """
153 Represents an entity aspect naming a configuration.
155 .. admonition:: Example
157 .. code-block:: VHDL
159 use configuration work.cfg;
160 -- ^^^^^^^^ <- Configuration
161 """
163 _configuration: ConfigurationSymbol #: Reference to the named configuration.
165 def __init__(self, configuration: ConfigurationSymbol, parent: Nullable[ModelEntity] = None) -> None:
166 """
167 Initializes an entity aspect naming a configuration.
169 :param configuration: Reference to the named configuration.
170 :param parent: The parent model entity of this entity.
171 """
172 super().__init__(parent)
174 self._configuration = configuration
175 configuration.Parent = self
177 def Visit(self, visitor: Visitor) -> None:
178 """
179 Walk this entity aspect and its configuration with a visitor.
181 :param visitor: The visitor receiving the events.
182 """
183 visitor.VisitEntityAspectConfiguration(self)
184 self._configuration.Visit(visitor)
185 visitor.DepartEntityAspectConfiguration(self)
187 @readonly
188 def Configuration(self) -> ConfigurationSymbol:
189 """
190 Read-only property to access the configuration (:attr:`_configuration`).
192 :returns: The configuration.
193 """
194 return self._configuration
197@export
198class EntityAspectOpen(EntityAspect):
199 """
200 Represents an open entity aspect, leaving the binding unspecified.
202 .. admonition:: Example
204 .. code-block:: VHDL
206 use open;
207 -- ^^^^ <- the aspect
208 """
210 def Visit(self, visitor: Visitor) -> None:
211 """
212 Walk this open entity aspect with a visitor.
214 :param visitor: The visitor receiving the events.
215 """
216 visitor.VisitEntityAspectOpen(self)
217 visitor.DepartEntityAspectOpen(self)
220@export
221class BindingIndication(ModelEntity, GenericMapAspectMixin, PortMapAspectMixin):
222 """
223 Represents a binding indication: which design entity a component is bound to.
225 The entity aspect is available as :data:`EntityAspect`, together with the generic and port maps
226 (:data:`GenericAssociations`, :data:`PortAssociations`).
227 """
229 _entityAspect: Nullable[EntityAspect] #: The bound design entity, or ``None`` if not given.
231 def __init__(
232 self,
233 entityAspect: Nullable[EntityAspect] = None,
234 genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None,
235 portAssociationItems: Nullable[Iterable[PortAssociationItem]] = None,
236 parent: Nullable[ModelEntity] = None
237 ) -> None:
238 """
239 Initializes a binding indication.
241 :param entityAspect: The bound design entity, or ``None`` if not given.
242 :param genericAssociationItems: List of all generic associations in the generic map aspect.
243 :param portAssociationItems: List of all port associations in the port map aspect.
244 :param parent: The parent model entity of this entity.
245 """
246 super().__init__(parent)
247 GenericMapAspectMixin.__init__(self, genericAssociationItems)
248 PortMapAspectMixin.__init__(self, portAssociationItems)
250 self._entityAspect = entityAspect
251 if entityAspect is not None:
252 entityAspect.Parent = self
254 def Visit(self, visitor: Visitor) -> None:
255 """
256 Walk this binding indication, its entity aspect and its map aspects with a visitor.
258 :param visitor: The visitor receiving the events.
259 """
260 visitor.VisitBindingIndication(self)
261 if self._entityAspect is not None: 261 ↛ 264line 261 didn't jump to line 264 because the condition on line 261 was always true
262 self._entityAspect.Visit(visitor)
264 self._VisitGenericMapAspect(visitor)
265 self._VisitPortMapAspect(visitor)
266 visitor.DepartBindingIndication(self)
268 @readonly
269 def EntityAspect(self) -> Nullable[EntityAspect]:
270 """
271 Read-only property to access the entity aspect (:attr:`_entityAspect`).
273 :returns: The entity aspect, or ``None`` if not set.
274 """
275 return self._entityAspect
280@export
281class AllInstantiationList(ModelEntity):
282 """
283 Represents an instantiation list naming ``all`` instances of a component.
285 .. admonition:: Example
287 .. code-block:: VHDL
289 for all : comp use entity work.sub(behav);
290 -- ^^^ <- the instantiation list
291 """
293 def Visit(self, visitor: Visitor) -> None:
294 """
295 Walk this ``all`` instantiation list with a visitor.
297 :param visitor: The visitor receiving the events.
298 """
299 visitor.VisitAllInstantiationList(self)
300 visitor.DepartAllInstantiationList(self)
303@export
304class OthersInstantiationList(ModelEntity):
305 """
306 Represents an instantiation list naming all instances not configured elsewhere.
308 .. admonition:: Example
310 .. code-block:: VHDL
312 for others : comp use entity work.sub(behav);
313 -- ^^^^^^ <- the instantiation list
314 """
316 def Visit(self, visitor: Visitor) -> None:
317 """
318 Walk this ``others`` instantiation list with a visitor.
320 :param visitor: The visitor receiving the events.
321 """
322 visitor.VisitOthersInstantiationList(self)
323 visitor.DepartOthersInstantiationList(self)
326InstantiationListUnion = Union[list[Name], AllInstantiationList, OthersInstantiationList]
329@export
330class ComponentConfiguration(ModelEntity):
331 """
332 Represents a component configuration (inside a block configuration), or - structurally identical
333 - a configuration specification (declared directly in an architecture's declarative part).
335 .. admonition:: Example
337 .. code-block:: VHDL
339 for U1 : comp use entity work.sub(behav);
340 -- ^^ ^^^^
341 -- | Component name
342 -- Instantiation list
343 """
345 _instantiationList: InstantiationListUnion #: The instances this configuration applies to.
346 _componentName: ComponentInstantiationSymbol #: Reference to the component being configured.
347 _bindingIndication: Nullable[BindingIndication] #: The binding indication, or ``None`` if none was given.
349 def __init__(
350 self,
351 instantiationList: InstantiationListUnion,
352 componentName: ComponentInstantiationSymbol,
353 bindingIndication: Nullable[BindingIndication] = None,
354 parent: Nullable[ModelEntity] = None
355 ) -> None:
356 """
357 Initializes a component configuration.
359 :param instantiationList: The instances this configuration applies to.
360 :param componentName: Reference to the component being configured.
361 :param bindingIndication: The binding indication, or ``None`` if none was given.
362 :param parent: The parent model entity of this entity.
363 """
364 super().__init__(parent)
366 if isinstance(instantiationList, (AllInstantiationList, OthersInstantiationList)):
367 self._instantiationList = instantiationList
368 instantiationList.Parent = self
369 else:
370 self._instantiationList = list(instantiationList)
371 for label in self._instantiationList:
372 label.Parent = self
374 self._componentName = componentName
375 componentName.Parent = self
377 self._bindingIndication = bindingIndication
378 if bindingIndication is not None:
379 bindingIndication.Parent = self
381 def Visit(self, visitor: Visitor) -> None:
382 """
383 Walk this component configuration, its component specification and its binding indication with a visitor.
385 :param visitor: The visitor receiving the events.
386 """
387 visitor.VisitComponentConfiguration(self)
388 visitor.VisitInstantiationList(self)
389 if isinstance(self._instantiationList, list):
390 for index, label in enumerate(self._instantiationList):
391 if index > 0:
392 visitor.VisitComma(self)
394 label.Visit(visitor)
395 else:
396 self._instantiationList.Visit(visitor)
398 visitor.DepartInstantiationList(self)
399 self._componentName.Visit(visitor)
400 if self._bindingIndication is not None:
401 self._bindingIndication.Visit(visitor)
403 visitor.DepartComponentConfiguration(self)
405 @readonly
406 def InstantiationList(self) -> InstantiationListUnion:
407 """
408 Read-only property to access the instantiation list (:attr:`_instantiationList`).
410 :returns: The instantiation list.
411 """
412 return self._instantiationList
414 @readonly
415 def ComponentName(self) -> ComponentInstantiationSymbol:
416 """
417 Read-only property to access the component name (:attr:`_componentName`).
419 :returns: The component name.
420 """
421 return self._componentName
423 @readonly
424 def BindingIndication(self) -> Nullable[BindingIndication]:
425 """
426 Read-only property to access the binding indication (:attr:`_bindingIndication`).
428 :returns: The binding indication, or ``None`` if not set.
429 """
430 return self._bindingIndication
433@export
434class BlockConfiguration(ModelEntity):
435 """
436 Represents the configuration of one block: an architecture, a block statement or a generate body.
438 Nested configurations are available as :data:`ConfigurationItems`.
440 .. admonition:: Example
442 .. code-block:: VHDL
444 for rtl
445 -- ^^^ <- Block
446 end for;
447 """
449 _blockSpecification: Symbol #: The configured block.
450 _items: list[Union[BlockConfiguration, ComponentConfiguration]] #: Nested configurations.
452 def __init__(
453 self,
454 blockSpecification: Symbol,
455 items: Nullable[Iterable[Union[BlockConfiguration, ComponentConfiguration]]] = None,
456 parent: Nullable[ModelEntity] = None
457 ) -> None:
458 """
459 Initializes a block configuration.
461 :param blockSpecification: The configured block.
462 :param items: Nested configurations.
463 :param parent: The parent model entity of this entity.
464 """
465 super().__init__(parent)
467 self._blockSpecification = blockSpecification
468 blockSpecification.Parent = self
470 self._items = itemList = []
471 if items is not None:
472 for item in items:
473 itemList.append(item)
474 item.Parent = self
476 def Visit(self, visitor: Visitor) -> None:
477 """
478 Walk this block configuration, its block specification and its nested configurations with a visitor.
480 :param visitor: The visitor receiving the events.
481 """
482 visitor.VisitBlockConfiguration(self)
483 visitor.VisitBlockSpecification(self)
484 self._blockSpecification.Visit(visitor)
485 visitor.DepartBlockSpecification(self)
486 for item in self._items:
487 item.Visit(visitor)
489 visitor.DepartBlockConfiguration(self)
491 @readonly
492 def BlockSpecification(self) -> Symbol:
493 """
494 Read-only property to access the block specification (:attr:`_blockSpecification`).
496 :returns: The block specification.
497 """
498 return self._blockSpecification
500 @readonly
501 def Items(self) -> list[Union[BlockConfiguration, ComponentConfiguration]]:
502 """
503 Read-only property to access the items (:attr:`_items`).
505 :returns: List of items.
506 """
507 return self._items