Source code for pyVHDLModel.Concurrent

# ==================================================================================================================== #
#             __     ___   _ ____  _     __  __           _      _                                                     #
#   _ __  _   \ \   / / | | |  _ \| |   |  \/  | ___   __| | ___| |                                                    #
#  | '_ \| | | \ \ / /| |_| | | | | |   | |\/| |/ _ \ / _` |/ _ \ |                                                    #
#  | |_) | |_| |\ V / |  _  | |_| | |___| |  | | (_) | (_| |  __/ |                                                    #
#  | .__/ \__, | \_/  |_| |_|____/|_____|_|  |_|\___/ \__,_|\___|_|                                                    #
#  |_|    |___/                                                                                                        #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany                                                            #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany                                                               #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
#                                                                                                                      #
# SPDX-License-Identifier: Apache-2.0                                                                                  #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.

Concurrent defines all concurrent statements used in entities, architectures, generates and block statements.
"""
from typing                  import List, Dict, Union, Iterable, Generator, Optional as Nullable

from pyTooling.Decorators    import export, readonly
from pyTooling.MetaClasses   import ExtendedType

from pyVHDLModel.Base        import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, BaseCase, IfBranchMixin
from pyVHDLModel.Base        import ElsifBranchMixin, ElseBranchMixin, AssertStatementMixin, BlockStatementMixin, WaveformElement, ChoicesMixin
from pyVHDLModel.Regions     import ConcurrentDeclarationRegionMixin, SequentialDeclarationRegionMixin
from pyVHDLModel.Namespace   import Namespace
from pyVHDLModel.Name        import Name
from pyVHDLModel.Symbol      import ComponentInstantiationSymbol, EntityInstantiationSymbol, ArchitectureSymbol, ConfigurationInstantiationSymbol
from pyVHDLModel.Symbol      import SignalSymbol
from pyVHDLModel.Expression  import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal
from pyVHDLModel.Association import AssociationItem, ParameterAssociationItem
from pyVHDLModel.Association import GenericAssociationItem, PortAssociationItem
from pyVHDLModel.Association import GenericMapAspectMixin, PortMapAspectMixin
from pyVHDLModel.Interface   import PortInterfaceItemMixin, WithPortsMixin
from pyVHDLModel.Interface   import GenericInterfaceItemMixin, WithGenericsMixin
from pyVHDLModel.Common      import Statement, ProcedureCallMixin, SignalAssignmentMixin, AllowBlackboxMixin
from pyVHDLModel.Common      import ConditionalWaveform, SelectedWaveform, OthersSelectedWaveform
from pyVHDLModel.Common      import ConditionalWaveformsMixin, WaveformMixin
from pyVHDLModel.Common      import ExpressionMixin, SelectedWaveformsMixin
from pyVHDLModel.Sequential  import SequentialStatement, SequentialStatementsMixin


ExpressionUnion = Union[
	BaseExpression,
	QualifiedExpression,
	FunctionCall,
	TypeConversion,
	# ConstantOrSymbol,     TODO: ObjectSymbol
	Literal,
]


@export
class ConcurrentStatement(Statement):
	"""
	A base-class for all concurrent statements.

	.. seealso::

	   * :class:`Instantiation <pyVHDLModel.Concurrent.Instantiation>`
	   * :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>`
	   * :class:`Concurrent procedure call <pyVHDLModel.Concurrent.ConcurrentProcedureCall>`
	   * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>`
	   * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>`
	   * :class:`Concurrent signal assignment <pyVHDLModel.Concurrent.ConcurrentSignalAssignment>`
	   * :class:`Concurrent assert statement <pyVHDLModel.Concurrent.ConcurrentAssertStatement>`
	"""


@export
class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True):
	"""
	A mixin-class for all language constructs supporting concurrent statements.

	.. seealso::

	   * :class:`Concurrent block statement <pyVHDLModel.Concurrent.ConcurrentBlockStatement>`
	   * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>`
	   * :class:`Concurrent case <pyVHDLModel.Concurrent.ConcurrentCase>`
	   * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
	   * :class:`Entity <pyVHDLModel.DesignUnit.Entity>`
	   * :class:`Architecture <pyVHDLModel.DesignUnit.Architecture>`

	   .. todo:: concurrent declaration region
	"""

	_statements:     List[ConcurrentStatement]  #: List of all concurrent statements in this construct.

	# TODO: add another instantiation class level for entity/configuration/component inst.
	_instantiations: Dict[str, 'Instantiation']  #: All instantiations, indexed by label.
	_hierarchy:      Dict[str, Union['ConcurrentBlockStatement', 'GenerateStatement']]  #: All elements creating a hierarchy level (blocks and generates), in declaration order.

	def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None) -> None:
		"""
		Initializes concurrent statements.

		:param statements: List of all concurrent statements in this construct.
		"""
		self._statements = []

		self._instantiations = {}
		self._hierarchy = {}

		if statements is not None:
			for statement in statements:
				self._statements.append(statement)
				statement.Parent = self

	@readonly
	def Statements(self) -> List[ConcurrentStatement]:
		"""
		Read-only property to access the statements (:attr:`_statements`).

		:returns: List of statements.
		"""
		return self._statements

	def IterateInstantiations(self) -> Generator['Instantiation', None, None]:
		for instance in self._instantiations.values():
			yield instance

		for element in self._hierarchy.values():
			yield from element.IterateInstantiations()

	# TODO: move into _init__
	def IndexStatements(self) -> None:
		for statement in self._statements:
			if isinstance(statement, (EntityInstantiation, ComponentInstantiation, ConfigurationInstantiation)):
				self._instantiations[statement.NormalizedLabel] = statement
			elif isinstance(statement, (ForGenerateStatement, IfGenerateStatement, CaseGenerateStatement)):
				self._hierarchy[statement.NormalizedLabel] = statement
				statement.IndexStatement()
			elif isinstance(statement, ConcurrentBlockStatement):
				self._hierarchy[statement.NormalizedLabel] = statement
				statement.IndexStatements()


@export
class Instantiation(ConcurrentStatement, GenericMapAspectMixin, PortMapAspectMixin):
	"""
	A base-class for all (component) instantiations.

	.. seealso::

	   * :class:`Component instantiation <pyVHDLModel.Concurrent.ComponentInstantiation>`
	   * :class:`Entity instantiation <pyVHDLModel.Concurrent.EntityInstantiation>`
	   * :class:`Configuration instantiation <pyVHDLModel.Concurrent.ConfigurationInstantiation>`
	"""

	def __init__(
		self,
		label: str,
		genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None,
		portAssociationItems:    Nullable[Iterable[PortAssociationItem]] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes an instantiation.

		:param label:                   The label of a model entity.
		:param genericAssociationItems: List of all generic associations in the generic map aspect.
		:param portAssociationItems:    List of all port associations in the port map aspect.
		:param parent:                  The parent model entity of this entity.
		"""
		super().__init__(label, parent)
		GenericMapAspectMixin.__init__(self, genericAssociationItems)
		PortMapAspectMixin.__init__(self, portAssociationItems)




@export
class ComponentInstantiation(Instantiation):
	"""
	Represents a component instantiation.

	The instantiated component is available as :data:`Component`, the associations as
	:data:`GenericAssociationItems` and :data:`PortAssociationItems`. The label is mandatory.

	.. admonition:: Example

	   .. code-block:: VHDL

	        inst : component Counter;
	      --^^^^                        <- Label
	      --                 ^^^^^^^    <- Component
	"""

	_component: ComponentInstantiationSymbol  #: Reference to the instantiated component.

	def __init__(
		self,
		label: str,
		componentSymbol: ComponentInstantiationSymbol,
		genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
		portAssociationItems:    Nullable[Iterable[AssociationItem]] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a component instantiation.

		:param label:                   The label of a model entity.
		:param componentSymbol:         Reference to the instantiated component.
		:param genericAssociationItems: List of all generic associations in the generic map aspect.
		:param portAssociationItems:    List of all port associations in the port map aspect.
		:param parent:                  The parent model entity of this entity.
		"""
		super().__init__(label, genericAssociationItems, portAssociationItems, parent)

		self._component = componentSymbol
		componentSymbol.Parent = self

	@readonly
	def Component(self) -> ComponentInstantiationSymbol:
		"""
		Read-only property to access the component (:attr:`_component`).

		:returns: The component.
		"""
		return self._component


@export
class EntityInstantiation(Instantiation):
	"""
	Represents a direct entity instantiation.

	The instantiated entity is available as :data:`Entity` and the optionally selected architecture
	as :data:`Architecture`. The label is mandatory.

	.. admonition:: Example

	   .. code-block:: VHDL

	        inst : entity work.Counter(rtl);
	      --^^^^                               <- Label
	      --              ^^^^^^^^^^^^         <- Entity
	      --                           ^^^     <- optional Architecture
	"""

	_entity: EntityInstantiationSymbol  #: Reference to the directly instantiated entity.
	_architecture: ArchitectureSymbol   #: Reference to the selected architecture, if one was given.

	def __init__(
		self,
		label: str,
		entitySymbol: EntityInstantiationSymbol,
		architectureSymbol: Nullable[ArchitectureSymbol] = None,
		genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
		portAssociationItems:    Nullable[Iterable[AssociationItem]] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a direct entity instantiation.

		:param label:                   The label of a model entity.
		:param entitySymbol:            Reference to the directly instantiated entity.
		:param architectureSymbol:      Reference to the selected architecture, if one was given.
		:param genericAssociationItems: List of all generic associations in the generic map aspect.
		:param portAssociationItems:    List of all port associations in the port map aspect.
		:param parent:                  The parent model entity of this entity.
		"""
		super().__init__(label, genericAssociationItems, portAssociationItems, parent)

		self._entity = entitySymbol
		entitySymbol.Parent = self

		self._architecture = architectureSymbol
		if architectureSymbol is not None:
			architectureSymbol.Parent = self

	@readonly
	def Entity(self) -> EntityInstantiationSymbol:
		"""
		Read-only property to access the entity (:attr:`_entity`).

		:returns: The entity.
		"""
		return self._entity

	@readonly
	def Architecture(self) -> ArchitectureSymbol:
		"""
		Read-only property to access the architecture (:attr:`_architecture`).

		:returns: The architecture.
		"""
		return self._architecture


@export
class ConfigurationInstantiation(Instantiation):
	"""
	Represents a configuration instantiation.

	The instantiated configuration is available as :data:`Configuration`. The label is mandatory.

	.. admonition:: Example

	   .. code-block:: VHDL

	        inst : configuration Counter;
	      --^^^^                            <- Label
	      --                     ^^^^^^^    <- Configuration
	"""

	_configuration: ConfigurationInstantiationSymbol  #: Reference to the instantiated configuration.

	def __init__(
		self,
		label: str,
		configurationSymbol: ConfigurationInstantiationSymbol,
		genericAssociationItems: Nullable[Iterable[AssociationItem]] = None,
		portAssociationItems:    Nullable[Iterable[AssociationItem]] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a configuration instantiation.

		:param label:                   The label of a model entity.
		:param configurationSymbol:     Reference to the instantiated configuration.
		:param genericAssociationItems: List of all generic associations in the generic map aspect.
		:param portAssociationItems:    List of all port associations in the port map aspect.
		:param parent:                  The parent model entity of this entity.
		"""
		super().__init__(label, genericAssociationItems, portAssociationItems, parent)

		self._configuration = configurationSymbol
		configurationSymbol.Parent = self

	@readonly
	def Configuration(self) -> ConfigurationInstantiationSymbol:
		"""
		Read-only property to access the configuration (:attr:`_configuration`).

		:returns: The configuration.
		"""
		return self._configuration


@export
class ProcessStatement(ConcurrentStatement, SequentialDeclarationRegionMixin, SequentialStatementsMixin, DocumentedEntityMixin):
	"""
	Represents a process statement.

	A process declares its own items (:data:`DeclaredItems`) and groups sequential statements
	(:data:`Statements`). It may name a sensitivity list (:data:`SensitivityList`).

	.. admonition:: Example

	   .. code-block:: VHDL

	        proc : process (clock)
	      --^^^^                     <- optional Label
	      --                ^^^^^    <- optional SensitivityList
	          variable v : bit;
	      --  ^^^^^^^^^^^^^^^^^      <- DeclaredItems
	        begin
	          v := '1';
	      --  ^^^^^^^^^              <- Statements
	        end process;
	"""

	# TODO: implement a SignalSymbol
	_sensitivityList: List[Name]  #: List of all signal names in the sensitivity list, or ``None`` if none was given.

	def __init__(
		self,
		label: Nullable[str] = None,
		declaredItems: Nullable[Iterable] = None,
		statements: Nullable[Iterable[SequentialStatement]] = None,
		sensitivityList: Nullable[Iterable[Name]] = None,
		documentation: Nullable[str] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a process statement.

		:param label:           The label of a model entity.
		:param declaredItems:   List of all declared items in this sequential declaration region.
		:param statements:      List of all sequential statements in this construct.
		:param sensitivityList: List of all signal names in the sensitivity list, or ``None`` if none was given.
		:param documentation:   The documentation comment associated with this declaration.
		:param parent:          The parent model entity of this entity.
		"""
		super().__init__(label, parent)
		SequentialDeclarationRegionMixin.__init__(self, self._normalizedLabel, declaredItems)
		SequentialStatementsMixin.__init__(self, statements)
		DocumentedEntityMixin.__init__(self, documentation)

		if sensitivityList is None:
			self._sensitivityList = None
		else:
			self._sensitivityList = []  # TODO: convert to dict
			for signalSymbol in sensitivityList:
				self._sensitivityList.append(signalSymbol)
				# signalSymbol._parent = self  # FIXME: currently str are provided

	@ConcurrentStatement.Parent.setter
	def Parent(self, parent: ModelEntity) -> None:
		ConcurrentStatement.Parent.fset(self, parent)

		# Connect the process' namespace to the enclosing declaration region's namespace, so a declaration
		# inside the process hides a same-named one from the architecture, block or generate around it.
		self._namespace.ParentNamespace = parent._namespace

	@readonly
	def SensitivityList(self) -> List[Name]:
		"""
		Read-only property to access the sensitivity list (:attr:`_sensitivityList`).

		:returns: List of sensitivity list.
		"""
		return self._sensitivityList


@export
class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin):
	"""
	Represents a concurrent procedure call.

	Like every concurrent statement, it can carry an optional label (:data:`Label`).

	.. admonition:: Example

	   .. code-block:: VHDL

	        proc_lbl : proc(clock, open);
	      --^^^^^^^^                        <- optional Label
	      --           ^^^^^^^^^^^^^^^^^    <- the call

	.. seealso::

	   * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialProcedureCall>`
	"""
	def __init__(
		self,
		label: str,
		procedureName: Name,
		parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None,
		parent: Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a concurrent procedure call.

		:param label:                     The label of a model entity.
		:param procedureName:             Reference to the called procedure.
		:param parameterAssociationItems: List of all parameter associations of the call.
		:param parent:                    The parent model entity of this entity.
		"""
		super().__init__(label, parent)
		ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems)


@export
class ConcurrentBlockStatement(
	ConcurrentStatement,
	BlockStatementMixin,
	LabeledEntityMixin,
	WithGenericsMixin,
	WithPortsMixin,
	GenericMapAspectMixin,
	PortMapAspectMixin,
	ConcurrentDeclarationRegionMixin,
	ConcurrentStatementsMixin,
	DocumentedEntityMixin,
	AllowBlackboxMixin
):
	"""
	Represents a block statement.

	A block groups concurrent statements (:data:`Statements`) and may declare its own items
	(:data:`DeclaredItems`). It always forms a hierarchy level; independently of that, it may also have
	a block header: a generic clause (:data:`GenericItems`) with its generic map aspect
	(:data:`GenericAssociationItems`), and a port clause (:data:`PortItems`) with its port map aspect
	(:data:`PortAssociationItems`).

	.. admonition:: Example

	   .. code-block:: VHDL

	        blk : block
	      --^^^                              <- Label
	          generic (G : positive := 1);
	      --          ^^^^^^^^^^^^^^^^^^     <- GenericItems
	          generic map (G => 2);
	      --              ^^^^^^^^           <- GenericAssociationItems
	          port (bp : in bit);
	      --        ^^^^^^^^^^^              <- PortItems
	          port map (bp => clock);
	      --           ^^^^^^^^^^^^          <- PortAssociationItems
	          signal inner : bit := '0';
	      --  ^^^^^^^^^^^^^^^^^^^^^^^^^^     <- DeclaredItems
	        begin
	          inner <= bp;
	      --  ^^^^^^^^^^^^                   <- Statements
	        end block;

	.. seealso::

	   * :class:`Generate statement <pyVHDLModel.Concurrent.GenerateStatement>`
	"""
	_namespace: Namespace  #: The namespace of this block's declarative region.

	def __init__(
		self,
		label:                   str,
		genericItems:            Nullable[Iterable[GenericInterfaceItemMixin]] = None,
		genericAssociationItems: Nullable[Iterable[GenericAssociationItem]] = None,
		portItems:               Nullable[Iterable[PortInterfaceItemMixin]] = None,
		portAssociationItems:    Nullable[Iterable[PortAssociationItem]] = None,
		declaredItems:           Nullable[Iterable] = None,
		statements:              Iterable['ConcurrentStatement'] = None,
		documentation:           Nullable[str] = None,
		allowBlackbox:           Nullable[bool] = None,
		parent:                  Nullable[ModelEntity] = None
	) -> None:
		"""
		Initializes a block statement.

		:param label:                   The label of a model entity.
		:param genericItems:            List of all generics, in declaration order.
		:param genericAssociationItems: List of all generic associations in the generic map aspect.
		:param portItems:               List of all ports, in declaration order.
		:param portAssociationItems:    List of all port associations in the port map aspect.
		:param declaredItems:           List of all declared items in this concurrent declaration region.
		:param statements:              List of all concurrent statements in this construct.
		:param documentation:           The documentation comment associated with this declaration.
		:param allowBlackbox:           Allow blackboxes for components in language entity.
		:param parent:                  The parent model entity of this entity.
		"""
		super().__init__(label, parent)

		self._namespace = Namespace(self._normalizedLabel)
		if parent is not None:
			self._namespace.ParentNamespace = parent._namespace

		BlockStatementMixin.__init__(self)
		LabeledEntityMixin.__init__(self, label)
		WithGenericsMixin.__init__(self, genericItems)
		WithPortsMixin.__init__(self, portItems)
		GenericMapAspectMixin.__init__(self, genericAssociationItems)
		PortMapAspectMixin.__init__(self, portAssociationItems)
		ConcurrentDeclarationRegionMixin.__init__(self, declaredItems)
		ConcurrentStatementsMixin.__init__(self, statements)
		DocumentedEntityMixin.__init__(self, documentation)
		AllowBlackboxMixin.__init__(self, allowBlackbox)

	@ConcurrentStatement.Parent.setter
	def Parent(self, parent: ModelEntity) -> None:
		ConcurrentStatement.Parent.fset(self, parent)

		self._namespace.ParentNamespace = parent._namespace


[docs] def IndexDeclaredItems(self) -> None: """A block's ports share the declarative region of its declarative part.""" self._IndexPortItems() super().IndexDeclaredItems()
@export class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin): """ A base-class for all branches in a generate statements. .. seealso:: * :class:`If generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>` * :class:`Elsif generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>` * :class:`Else generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>` """ _alternativeLabel: Nullable[str] #: The branch's alternative label, if one was given. _normalizedAlternativeLabel: Nullable[str] #: The normalized (lower case) alternative label. _namespace: Namespace #: The namespace of this branch's declarative region. def __init__( self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a generate branch. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The branch's alternative label, if one was given. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(parent) self._alternativeLabel = alternativeLabel self._normalizedAlternativeLabel = alternativeLabel.lower() if alternativeLabel is not None else None self._namespace = Namespace(self._normalizedAlternativeLabel) if parent is not None: self._namespace.ParentNamespace = parent._namespace ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) AllowBlackboxMixin.__init__(self, allowBlackbox) @readonly def AlternativeLabel(self) -> Nullable[str]: """ Read-only property to access the alternative label (:attr:`_alternativeLabel`). :returns: The alternative label, or ``None`` if not set. """ return self._alternativeLabel @readonly def NormalizedAlternativeLabel(self) -> Nullable[str]: """ Read-only property to access the normalized alternative label (:attr:`_normalizedAlternativeLabel`). :returns: The normalized alternative label, or ``None`` if not set. """ return self._normalizedAlternativeLabel @export class IfGenerateBranch(GenerateBranch, IfBranchMixin): """ Represents if-generate branch in a generate statement with a concurrent declaration region and concurrent statements. .. admonition:: Example .. code-block:: VHDL gen: if condition generate -- concurrent declarations begin -- concurrent statements elsif condition generate -- ... else generate -- ... end generate; """ def __init__( self, condition: ExpressionUnion, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes an if generate branch. :param condition: The condition guarding this statement. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The branch's alternative label, if one was given. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) IfBranchMixin.__init__(self, condition) @export class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin): """ Represents elsif-generate branch in a generate statement with a concurrent declaration region and concurrent statements. .. admonition:: Example .. code-block:: VHDL gen: if condition generate -- ... elsif condition generate -- concurrent declarations begin -- concurrent statements else generate -- ... end generate; """ def __init__( self, condition: ExpressionUnion, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes an elsif generate branch. :param condition: The condition guarding this statement. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The branch's alternative label, if one was given. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) ElsifBranchMixin.__init__(self, condition) @export class ElseGenerateBranch(GenerateBranch, ElseBranchMixin): """ Represents else-generate branch in a generate statement with a concurrent declaration region and concurrent statements. .. admonition:: Example .. code-block:: VHDL gen: if condition generate -- ... elsif condition generate -- ... else generate -- concurrent declarations begin -- concurrent statements end generate; """ def __init__( self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes an else generate branch. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The branch's alternative label, if one was given. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(declaredItems, statements, alternativeLabel, allowBlackbox, parent) ElseBranchMixin.__init__(self) @export class GenerateStatement(ConcurrentStatement, AllowBlackboxMixin): """ Represents the base-class of all generate statements. A generate statement replicates or conditionally elaborates concurrent statements. .. seealso:: * :class:`If generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` * :class:`Case generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` * :class:`For generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` """ def __init__( self, label: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a generate statement. :param label: The label of a model entity. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(label, parent) AllowBlackboxMixin.__init__(self, allowBlackbox) # @mustoverride def IterateInstantiations(self) -> Generator[Instantiation, None, None]: raise NotImplementedError() # @mustoverride def IndexStatement(self) -> None: raise NotImplementedError() @export class IfGenerateStatement(GenerateStatement): """ Represents an if-generate statement. It has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches (:data:`ElsifBranches`) and an optional ``else`` branch (:data:`ElseBranch`). The label is mandatory and the branch conditions must be static expressions. .. admonition:: Example .. code-block:: VHDL gen : if WIDTH > 8 generate --^^^ <- Label -- ^^^^^^^^^^^^^^^^^^^^^ <- IfBranch q <= '0'; elsif WIDTH > 4 generate --^^^^^^^^^^^^^^^^^^^^^^^^ <- ElsifBranches[0] q <= '1'; else generate --^^^^^^^^^^^^^ <- ElseBranch q <= 'Z'; end generate; .. seealso:: * :class:`Generate branch <pyVHDLModel.Concurrent.GenerateBranch>` base-class * :class:`If-generate branch <pyVHDLModel.Concurrent.IfGenerateBranch>` * :class:`Elsif-generate branch <pyVHDLModel.Concurrent.ElsifGenerateBranch>` * :class:`Else-generate branch <pyVHDLModel.Concurrent.ElseGenerateBranch>` * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` """ _ifBranch: IfGenerateBranch #: The mandatory ``if`` branch. _elsifBranches: List[ElsifGenerateBranch] #: List of all ``elsif`` branches, in the order they were written. _elseBranch: Nullable[ElseGenerateBranch] #: The optional ``else`` branch, or ``None`` if none was given. def __init__( self, label: str, ifBranch: IfGenerateBranch, elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None, elseBranch: Nullable[ElseGenerateBranch] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes an if-generate statement. :param label: The label of a model entity. :param ifBranch: The mandatory ``if`` branch. :param elsifBranches: List of all ``elsif`` branches, in the order they were written. :param elseBranch: The optional ``else`` branch, or ``None`` if none was given. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(label, allowBlackbox, parent) self._ifBranch = ifBranch ifBranch.Parent = self self._elsifBranches = [] if elsifBranches is not None: for branch in elsifBranches: self._elsifBranches.append(branch) branch.Parent = self if elseBranch is not None: self._elseBranch = elseBranch elseBranch.Parent = self else: self._elseBranch = None @GenerateStatement.Parent.setter def Parent(self, parent: ModelEntity) -> None: from pyVHDLModel.DesignUnit import Architecture GenerateStatement.Parent.fset(self, parent) # Connect namespaces namespace = self._ifBranch._namespace namespace.ParentNamespace = parent._namespace if namespace._name is None: namespace._name = self._normalizedLabel for elseBranch in self._elsifBranches: elseBranch._namespace.ParentNamespace = parent._namespace if self._elseBranch is not None: self._elseBranch._namespace.ParentNamespace = parent._namespace @readonly def IfBranch(self) -> IfGenerateBranch: """ Read-only property to access the if branch (:attr:`_ifBranch`). :returns: The if branch. """ return self._ifBranch @readonly def ElsifBranches(self) -> List[ElsifGenerateBranch]: """ Read-only property to access the elsif branches (:attr:`_elsifBranches`). :returns: List of elsif branches. """ return self._elsifBranches @readonly def ElseBranch(self) -> Nullable[ElseGenerateBranch]: """ Read-only property to access the else branch (:attr:`_elseBranch`). :returns: The else branch, or ``None`` if not set. """ return self._elseBranch def IterateInstantiations(self) -> Generator[Instantiation, None, None]: yield from self._ifBranch.IterateInstantiations() for branch in self._elsifBranches: yield from branch.IterateInstantiations() if self._elseBranch is not None: yield from self._ifBranch.IterateInstantiations() def IndexStatement(self) -> None: self._ifBranch.IndexStatements() for branch in self._elsifBranches: branch.IndexStatements() if self._elseBranch is not None: self._elseBranch.IndexStatements() @export class ConcurrentChoice(BaseChoice): """ A base-class for all concurrent choices (in case...generate statements). .. seealso:: * :class:`Indexed generate choice <pyVHDLModel.Concurrent.IndexedGenerateChoice>` * :class:`Ranged generate choice <pyVHDLModel.Concurrent.RangedGenerateChoice>` """ @export class IndexedGenerateChoice(ConcurrentChoice): """ Represents a case-generate choice given by a single value. The value is available as :data:`Expression`. .. admonition:: Example .. code-block:: VHDL when 8 => -- ^ <- Expression """ _expression: ExpressionUnion #: The expression this choice selects on. def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None: """ Initializes a case-generate choice given by a single value. :param expression: The expression this choice selects on. :param parent: The parent model entity of this entity. """ super().__init__(parent) self._expression = expression expression.Parent = self @readonly def Expression(self) -> ExpressionUnion: """ Read-only property to access the expression (:attr:`_expression`). :returns: The expression. """ return self._expression
[docs] def __str__(self) -> str: """ Formats the indexed case-generate choice. **Format:** ``0`` :returns: Formatted indexed case-generate choice. """ return str(self._expression)
@export class RangedGenerateChoice(ConcurrentChoice): """ Represents a case-generate choice given by a range. The range is available as :data:`Range`. .. admonition:: Example .. code-block:: VHDL when 0 to 3 => -- ^^^^^^ <- Range """ _range: 'Range' #: The range this choice selects on. def __init__(self, rng: 'Range', parent: Nullable[ModelEntity] = None) -> None: """ Initializes a case-generate choice given by a range. :param rng: The range this choice selects on. :param parent: The parent model entity of this entity. """ super().__init__(parent) self._range = rng rng.Parent = self @readonly def Range(self) -> 'Range': """ Read-only property to access the range (:attr:`_range`). :returns: The range. """ return self._range
[docs] def __str__(self) -> str: """ Formats the ranged case-generate choice. **Format:** ``0 to 3`` :returns: Formatted ranged case-generate choice. """ return str(self._range)
@export class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin, AllowBlackboxMixin, ChoicesMixin): """ Represents the base-class of all alternatives of a case-generate statement. .. seealso:: * :class:`Generate case <pyVHDLModel.Concurrent.GenerateCase>` * :class:`Others generate case <pyVHDLModel.Concurrent.OthersGenerateCase>` """ _namespace: Namespace #: The namespace of this alternative's declarative region. def __init__( self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, choices: Nullable[Iterable[BaseChoice]] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a concurrent case. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The alternative's label. :param choices: List of all choices selecting this alternative. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(parent) LabeledEntityMixin.__init__(self, alternativeLabel) # TODO: Why not handover self? # This allows access to Label and NormalizedLabel, also to create a full instance path in case a lookup goes wrong. # TODO: How about a WithNamespaceMixin class? self._namespace = Namespace(self._normalizedLabel) if parent is not None: self._namespace.ParentNamespace = parent._namespace ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) AllowBlackboxMixin.__init__(self, allowBlackbox) ChoicesMixin.__init__(self, choices) @export class GenerateCase(ConcurrentCase): """ Represents one alternative of a case-generate statement, selected by its choices. .. admonition:: Example .. code-block:: VHDL when 8 => -- ^ <- Choices """ def __init__( self, choices: Iterable[ConcurrentChoice], declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a generate case. :param choices: List of all choices selecting this alternative. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param alternativeLabel: The alternative's label. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(declaredItems, statements, alternativeLabel, choices, allowBlackbox, parent)
[docs] def __str__(self) -> str: """ Formats the case-generate alternative. **Format:** ``when 0 | 1 =>`` :returns: Formatted case-generate alternative. """ return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
@export class OthersGenerateCase(ConcurrentCase): """ Represents the ``others`` alternative of a case-generate statement. It covers every choice not named explicitly. .. admonition:: Example .. code-block:: VHDL when others => -- ^^^^^^ <- the choice """
[docs] def __str__(self) -> str: """ Formats the ``others`` case-generate alternative. **Format:** ``when others =>`` :returns: Formatted ``others`` case-generate alternative. """ return "when others =>"
@export class CaseGenerateStatement(GenerateStatement): """ Represents a case-generate statement. The expression being tested is available as :data:`SelectExpression`, the alternatives as :data:`Cases`. The label is mandatory and the selector must be a static expression. .. admonition:: Example .. code-block:: VHDL gen : case MODE generate --^^^ <- Label -- ^^^^ <- SelectExpression when 0 => q <= '0'; -- ^^^^^^^^^^^^^^^^^^^ <- Cases[0] when others => q <= '1'; -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[1] end generate; .. seealso:: * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` """ _expression: ExpressionUnion #: The expression being tested; it must be static. _cases: List[GenerateCase] #: List of all alternatives, in the order they were written. def __init__( self, label: str, expression: ExpressionUnion, cases: Iterable[ConcurrentCase], allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a case-generate statement. :param label: The label of a model entity. :param expression: The expression being tested; it must be static. :param cases: List of all alternatives, in the order they were written. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(label, allowBlackbox, parent) self._expression = expression expression.Parent = self # TODO: create a mixin for things with cases self._cases = [] if cases is not None: for case in cases: self._cases.append(case) case.Parent = self @GenerateStatement.Parent.setter def Parent(self, parent: ModelEntity) -> None: GenerateStatement.Parent.fset(self, parent) # Connect namespaces for case in self._cases: case._namespace.ParentNamespace = parent._namespace @readonly def SelectExpression(self) -> ExpressionUnion: """ Read-only property to access the select expression (:attr:`_expression`). :returns: The select expression. """ return self._expression @readonly def Cases(self) -> List[GenerateCase]: """ Read-only property to access the cases (:attr:`_cases`). :returns: List of cases. """ return self._cases def IterateInstantiations(self) -> Generator[Instantiation, None, None]: for case in self._cases: yield from case.IterateInstantiations() def IndexStatement(self) -> None: for case in self._cases: case.IndexStatements() @export class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): """ Represents a for-generate statement. The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the generated statements as :data:`Statements`. The label is mandatory. .. admonition:: Example .. code-block:: VHDL gen : for i in 0 to 3 generate --^^^ <- Label -- ^ <- LoopIndex -- ^^^^^^ <- Range q(i) <= '0'; -- ^^^^^^^^^^^^ <- Statements end generate; .. seealso:: * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` """ _loopIndex: str #: The name of the generate loop's index. _range: Range #: The range the generate loop iterates over. _namespace: Namespace #: The namespace of the generate loop's declarative region. def __init__( self, label: str, loopIndex: str, rng: Range, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, allowBlackbox: Nullable[bool] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a for-generate statement. :param label: The label of a model entity. :param loopIndex: The name of the generate loop's index. :param rng: The range the generate loop iterates over. :param declaredItems: List of all declared items in this concurrent declaration region. :param statements: List of all concurrent statements in this construct. :param allowBlackbox: Allow blackboxes for components in language entity. :param parent: The parent model entity of this entity. """ super().__init__(label, allowBlackbox, parent) self._namespace = Namespace(self._normalizedLabel) if parent is not None: self._namespace.ParentNamespace = parent._namespace ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) self._loopIndex = loopIndex self._range = rng rng.Parent = self @GenerateStatement.Parent.setter def Parent(self, parent: ModelEntity) -> None: GenerateStatement.Parent.fset(self, parent) self._namespace.ParentNamespace = parent._namespace @readonly def LoopIndex(self) -> str: """ Read-only property to access the loop index (:attr:`_loopIndex`). :returns: The loop index. """ return self._loopIndex @readonly def Range(self) -> Range: """ Read-only property to access the range (:attr:`_range`). :returns: The range. """ return self._range # IndexDeclaredItems = ConcurrentStatements.IndexDeclaredItems def IndexStatement(self) -> None: self.IndexStatements() def IndexStatements(self) -> None: super().IndexStatements() def IterateInstantiations(self) -> Generator[Instantiation, None, None]: return ConcurrentStatementsMixin.IterateInstantiations(self) @export class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin): """ Represents the base-class of all concurrent signal assignments. .. seealso:: * :class:`Concurrent simple signal assignment <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>` * :class:`Concurrent selected signal assignment <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>` * :class:`Conditional signal assignment <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>` """ def __init__(self, label: str, target: SignalSymbol, parent: Nullable[ModelEntity] = None) -> None: """ Initializes a concurrent signal assignment. :param label: The label of a model entity. :param target: Reference to the assignment's destination. :param parent: The parent model entity of this entity. """ super().__init__(label, parent) SignalAssignmentMixin.__init__(self, target) @export class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment, WaveformMixin): """ Represents a simple concurrent signal assignment. The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`. .. admonition:: Example .. code-block:: VHDL lbl : q <= '1'; --^^^ <- optional Label -- ^ <- Target -- ^^^ <- Waveform .. seealso:: * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>` """ def __init__(self, label: str, target: SignalSymbol, waveform: Iterable[WaveformElement], parent: Nullable[ModelEntity] = None) -> None: """ Initializes a simple concurrent signal assignment. :param label: The label of a model entity. :param target: Reference to the assignment's destination. :param waveform: List of all waveform elements, in the order they were written. :param parent: The parent model entity of this entity. """ super().__init__(label, target, parent) WaveformMixin.__init__(self, waveform) @export class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment, ExpressionMixin, SelectedWaveformsMixin): """ Represents a selected concurrent signal assignment. The selector is available as :data:`Expression`, the alternatives as :data:`SelectedWaveforms`, a list of :class:`~pyVHDLModel.Common.SelectedWaveform`. The model holds them in a list and has no distinct field per alternative, so the markers below name list elements. .. admonition:: Example .. code-block:: VHDL lbl : with sel select q <= '1' when '0', '0' when others; --^^^ <- optional Label -- ^^^ <- Expression -- ^ <- Target -- ^^^^^^^^^^^^ <- SelectedWaveforms[0] -- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1] .. seealso:: * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialSelectedSignalAssignment>` * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>` """ def __init__( self, label: str, target: SignalSymbol, expression: ExpressionUnion, selectedWaveforms: Iterable[SelectedWaveform], parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a selected concurrent signal assignment. :param label: The label of a model entity. :param target: Reference to the assignment's destination. :param expression: The selector expression. :param selectedWaveforms: All alternatives, in order. :param parent: The parent model entity of this entity. """ super().__init__(label, target, parent) ExpressionMixin.__init__(self, expression) SelectedWaveformsMixin.__init__(self, selectedWaveforms) @export class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment, ConditionalWaveformsMixin): """ Represents a conditional concurrent signal assignment. The alternatives are available as :data:`ConditionalWaveforms`, a list of :class:`~pyVHDLModel.Common.ConditionalWaveform`. The model holds them in a list and has no distinct field per alternative, so the markers below name list elements. .. admonition:: Example .. code-block:: VHDL lbl : q <= '1' when cond else '0'; --^^^ <- optional Label -- ^ <- Target -- ^^^^^^^^^^^^^ <- ConditionalWaveforms[0] -- ^^^ <- ConditionalWaveforms[1] .. seealso:: * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialConditionalSignalAssignment>` * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>` """ def __init__( self, label: str, target: SignalSymbol, conditionalWaveforms: Iterable[ConditionalWaveform], parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a conditional concurrent signal assignment. :param label: The label of a model entity. :param target: Reference to the assignment's destination. :param conditionalWaveforms: All alternatives, in order. :param parent: The parent model entity of this entity. """ super().__init__(label, target, parent) ConditionalWaveformsMixin.__init__(self, conditionalWaveforms) @export class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin): """ Represents a concurrent assertion statement. The checked condition is available as :data:`Condition`, the optional report string as :data:`Message` and the optional severity as :data:`Severity`. .. admonition:: Example .. code-block:: VHDL lbl : assert cond report "bad" severity note; --^^^ <- optional Label -- ^^^^ <- Condition -- ^^^^^ <- optional Message -- ^^^^ <- optional Severity .. seealso:: * :class:`Sequential counterpart <pyVHDLModel.Sequential.SequentialAssertStatement>` """ def __init__( self, condition: ExpressionUnion, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None ) -> None: """ Initializes a concurrent assertion statement. :param condition: The condition guarding this statement. :param message: The reported message, or ``None`` if none was given. :param severity: The reported severity level, or ``None`` if none was given. :param label: The label of a model entity. :param parent: The parent model entity of this entity. """ super().__init__(label, parent) AssertStatementMixin.__init__(self, condition, message, severity)