# ==================================================================================================================== #
# __ ___ _ ____ _ __ __ _ _ #
# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
# | |_) | |_| |\ 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.
Declarations for sequential statements.
"""
from typing import List, Iterable, Optional as Nullable
from pyTooling.Decorators import export, readonly
from pyTooling.MetaClasses import ExtendedType
from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin
from pyVHDLModel.Base import ElseBranchMixin, ReportStatementMixin, AssertStatementMixin, WaveformElement, ChoicesMixin
from pyVHDLModel.Symbol import Symbol, SignalSymbol, VariableSymbol
from pyVHDLModel.Common import Statement, ProcedureCallMixin
from pyVHDLModel.Common import AssignmentMixin, SignalAssignmentMixin, VariableAssignmentMixin
from pyVHDLModel.Common import ConditionalWaveform, ConditionalExpression
from pyVHDLModel.Common import ConditionalWaveformsMixin, WaveformMixin
from pyVHDLModel.Common import ExpressionMixin, SelectedWaveformsMixin, SelectedExpressionsMixin
from pyVHDLModel.Common import SelectedWaveform, OthersSelectedWaveform
from pyVHDLModel.Common import SelectedExpression, OthersSelectedExpression
from pyVHDLModel.Association import ParameterAssociationItem
@export
class SequentialStatement(Statement):
"""
Represents the base-class of all sequential statements.
Sequential statements appear in a process or a subprogram body.
"""
@export
class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True):
"""
A mixin-class for language constructs containing sequential statements.
The statements are available in declaration order as :data:`Statements`.
.. seealso::
* :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>`
* :class:`Branch <pyVHDLModel.Sequential.Branch>`
* :class:`Sequential case <pyVHDLModel.Sequential.SequentialCase>`
* :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>`
"""
_statements: List[SequentialStatement] #: List of all sequential statements in this construct.
def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None:
# TODO: extract to mixin
"""
Initializes sequential statements.
:param statements: List of all sequential statements in this construct.
"""
self._statements = []
if statements is not None:
for item in statements:
self._statements.append(item)
item.Parent = self
@readonly
def Statements(self) -> List[SequentialStatement]:
"""
Read-only property to access the list of sequential statements (:attr:`_statements`).
:returns: A list of sequential statements.
"""
return self._statements
@export
class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin):
"""
Represents a procedure call as a sequential statement.
Like every sequential statement, it can carry an optional label (:data:`Label`).
.. admonition:: Example
.. code-block:: VHDL
lbl : log("hello");
--^^^ <- optional Label
-- ^^^^^^^^^^^^ <- the call
.. seealso::
* :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentProcedureCall>`
"""
def __init__(
self,
procedureName: Symbol,
parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a procedure call as a sequential statement.
:param procedureName: Reference to the called procedure.
:param parameterAssociationItems: List of all parameter associations of the call.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems)
@export
class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin):
"""
Represents the base-class of all sequential signal assignments.
.. seealso::
* :class:`Sequential simple signal assignment <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>`
"""
def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a sequential signal assignment.
:param target: Reference to the assignment's destination.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SignalAssignmentMixin.__init__(self, target)
@export
class SequentialSimpleSignalAssignment(SequentialSignalAssignment, WaveformMixin):
"""
Represents a simple sequential signal assignment.
The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`.
.. admonition:: Example
.. code-block:: VHDL
lbl : s <= '1';
--^^^ <- optional Label
-- ^ <- Target
-- ^^^ <- Waveform
.. seealso::
* :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>`
"""
def __init__(self, target: SignalSymbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a simple sequential signal assignment.
:param target: Reference to the assignment's destination.
:param waveform: List of all waveform elements, in the order they were written.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(target, label, parent)
WaveformMixin.__init__(self, waveform)
@export
class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin):
"""
Represents a simple sequential variable assignment.
The assignment's destination is available as :data:`Target`, its value as :data:`Expression`.
.. admonition:: Example
.. code-block:: VHDL
lbl : v := '1';
--^^^ <- optional Label
-- ^ <- Target
-- ^^^ <- Expression
"""
def __init__(self, target: VariableSymbol, expression: ExpressionUnion, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a simple sequential variable assignment.
:param target: Reference to the assignment's destination.
:param expression: The assigned expression.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
VariableAssignmentMixin.__init__(self, target, expression)
@export
class SequentialConditionalVariableAssignment(SequentialStatement, AssignmentMixin):
"""
Represents a conditional sequential variable assignment.
The alternatives are available as :data:`ConditionalExpressions`, a list of
:class:`~pyVHDLModel.Common.ConditionalExpression`. 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 : v := '1' when sel = '0' else '0';
--^^^ <- optional Label
-- ^ <- Target
-- ^^^^^^^^^^^^^^^^^^ <- ConditionalExpressions[0]
-- ^^^ <- ConditionalExpressions[1]
.. seealso::
* :class:`Conditional expression <pyVHDLModel.Common.ConditionalExpression>`
"""
_conditionalExpressions: List[ConditionalExpression] #: List of all alternatives, in the order they were written.
def __init__(
self,
target: VariableSymbol,
conditionalExpressions: Iterable[ConditionalExpression],
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a conditional sequential variable assignment.
:param target: Reference to the assignment's destination.
:param conditionalExpressions: List of all alternatives, in the order they were written.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
AssignmentMixin.__init__(self, target)
self._conditionalExpressions = []
for conditionalExpression in conditionalExpressions:
self._conditionalExpressions.append(conditionalExpression)
conditionalExpression.Parent = self
@readonly
def ConditionalExpressions(self) -> List[ConditionalExpression]:
"""
Read-only property to access the conditional expressions (:attr:`_conditionalExpressions`).
:returns: List of conditional expressions.
"""
return self._conditionalExpressions
@export
class SequentialConditionalSignalAssignment(SequentialStatement, SignalAssignmentMixin, ConditionalWaveformsMixin):
"""
Represents a conditional sequential 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 : s <= '1' when sel = '0' else '0';
--^^^ <- optional Label
-- ^ <- Target
-- ^^^^^^^^^^^^^^^^^^ <- ConditionalWaveforms[0]
-- ^^^ <- ConditionalWaveforms[1]
.. seealso::
* :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>`
* :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>`
"""
def __init__(
self,
target: SignalSymbol,
conditionalWaveforms: Iterable[ConditionalWaveform],
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a conditional sequential signal assignment.
:param target: Reference to the assignment's destination.
:param conditionalWaveforms: All alternatives, in order.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SignalAssignmentMixin.__init__(self, target)
ConditionalWaveformsMixin.__init__(self, conditionalWaveforms)
@export
class SequentialSelectedVariableAssignment(SequentialStatement, AssignmentMixin, ExpressionMixin, SelectedExpressionsMixin):
"""
Represents a selected sequential variable assignment.
The selector is available as :data:`Expression`, the alternatives as :data:`SelectedExpressions`,
a list of :class:`~pyVHDLModel.Common.SelectedExpression`. 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 v := '1' when '0', '0' when others;
--^^^ <- optional Label
-- ^^^ <- Expression
-- ^ <- Target
-- ^^^^^^^^^^^^ <- SelectedExpressions[0]
-- ^^^^^^^^^^^^^^^ <- SelectedExpressions[1]
.. seealso::
* :class:`Selected expression <pyVHDLModel.Common.SelectedExpression>`
"""
def __init__(
self,
target: VariableSymbol,
expression: ExpressionUnion,
selectedExpressions: Iterable[SelectedExpression],
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a selected sequential variable assignment.
:param target: Reference to the assignment's destination.
:param expression: The selector expression.
:param selectedExpressions: All alternatives, in order.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
AssignmentMixin.__init__(self, target)
ExpressionMixin.__init__(self, expression)
SelectedExpressionsMixin.__init__(self, selectedExpressions)
@export
class SequentialSelectedSignalAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin, SelectedWaveformsMixin):
"""
Represents a selected sequential 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 s <= '1' when '0', '0' when others;
--^^^ <- optional Label
-- ^^^ <- Expression
-- ^ <- Target
-- ^^^^^^^^^^^^ <- SelectedWaveforms[0]
-- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1]
.. seealso::
* :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>`
* :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>`
"""
def __init__(
self,
target: SignalSymbol,
expression: ExpressionUnion,
selectedWaveforms: Iterable[SelectedWaveform],
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a selected sequential signal assignment.
:param target: Reference to the assignment's destination.
:param expression: The selector expression.
:param selectedWaveforms: All alternatives, in order.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SignalAssignmentMixin.__init__(self, target)
ExpressionMixin.__init__(self, expression)
SelectedWaveformsMixin.__init__(self, selectedWaveforms)
@export
class SignalForceAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin):
"""
Represents a signal force assignment.
A force assignment overrides a signal's driver until it is released.
.. admonition:: Example
.. code-block:: VHDL
lbl : s <= force '1';
--^^^ <- optional Label
-- ^ <- Target
-- ^^^ <- Expression
"""
def __init__(
self,
target: SignalSymbol,
expression: ExpressionUnion,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a signal force assignment.
:param target: Reference to the assignment's destination.
:param expression: The value forced onto the signal.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SignalAssignmentMixin.__init__(self, target)
ExpressionMixin.__init__(self, expression)
@export
class SignalReleaseAssignment(SequentialStatement, SignalAssignmentMixin):
"""
Represents a signal release assignment.
A release assignment ends a previously applied force.
.. admonition:: Example
.. code-block:: VHDL
lbl : s <= release;
--^^^ <- optional Label
-- ^ <- Target
"""
def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a signal release assignment.
:param target: Reference to the assignment's destination.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SignalAssignmentMixin.__init__(self, target)
@export
class SequentialReportStatement(SequentialStatement, ReportStatementMixin):
"""
Represents a sequential report statement.
The report string is available as :data:`Message`, the optional severity as :data:`Severity`.
.. admonition:: Example
.. code-block:: VHDL
lbl : report "message" severity note;
--^^^ <- optional Label
-- ^^^^^^^^^ <- Message
-- ^^^^ <- optional Severity
"""
def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a sequential report 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)
ReportStatementMixin.__init__(self, message, severity)
@export
class SequentialAssertStatement(SequentialStatement, AssertStatementMixin):
"""
Represents a sequential 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 sel = '0' report "bad" severity error;
--^^^ <- optional Label
-- ^^^^^^^^^ <- Condition
-- ^^^^^ <- optional Message
-- ^^^^^ <- optional Severity
.. seealso::
* :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentAssertStatement>`
"""
def __init__(
self,
condition: ExpressionUnion,
message: Nullable[ExpressionUnion] = None,
severity: Nullable[ExpressionUnion] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a sequential 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)
@export
class CompoundStatement(SequentialStatement):
"""
Represents the base-class of all compound statements.
A compound statement contains further sequential statements: if, case and loop statements.
.. seealso::
* :class:`If statement <pyVHDLModel.Sequential.IfStatement>`
* :class:`Case statement <pyVHDLModel.Sequential.CaseStatement>`
* :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>`
"""
@export
class Branch(ModelEntity, SequentialStatementsMixin):
"""
Represents the base-class of all branches of an if statement.
.. seealso::
* :class:`If branch <pyVHDLModel.Sequential.IfBranch>`
* :class:`Elsif branch <pyVHDLModel.Sequential.ElsifBranch>`
* :class:`Else branch <pyVHDLModel.Sequential.ElseBranch>`
"""
def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a branch.
:param statements: List of all sequential statements in this construct.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
SequentialStatementsMixin.__init__(self, statements)
@export
class IfBranch(Branch, IfBranchMixin):
"""
Represents the ``if`` branch of an if statement.
The branch's condition is available as :data:`Condition`, its body as :data:`Statements`.
.. admonition:: Example
The whole if statement is shown; the bracket marks the part this class represents.
.. code-block:: VHDL
if sel = '0' then -- ┐ IfBranch
-- ^^^^^^^^^ -- │ <- Condition
s <= '0'; -- │
--^^^^^^^^^ -- ┘ <- Statements
elsif sel = '1' then
s <= '1';
else
s <= '0';
end if;
"""
def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes an if branch.
:param condition: The condition guarding this statement.
:param statements: List of all sequential statements in this construct.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, parent)
IfBranchMixin.__init__(self, condition)
@export
class ElsifBranch(Branch, ElsifBranchMixin):
"""
Represents an ``elsif`` branch of an if statement.
The branch's condition is available as :data:`Condition`, its body as :data:`Statements`.
An if statement may have any number of them.
.. admonition:: Example
The whole if statement is shown; the bracket marks the part this class represents.
.. code-block:: VHDL
if sel = '0' then
s <= '0';
elsif sel = '1' then -- ┐ ElsifBranch
-- ^^^^^^^^^ -- │ <- Condition
s <= '1'; -- │
--^^^^^^^^^ -- ┘ <- Statements
else
s <= '0';
end if;
"""
def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes an ``elsif`` branch of an if statement.
:param condition: The condition guarding this statement.
:param statements: List of all sequential statements in this construct.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, parent)
ElsifBranchMixin.__init__(self, condition)
@export
class ElseBranch(Branch, ElseBranchMixin):
"""
Represents the ``else`` branch of an if statement.
Unlike the other branches, an else branch has no condition; it only has a body
(:data:`Statements`). An if statement has at most one.
.. admonition:: Example
The whole if statement is shown; the bracket marks the part this class represents.
.. code-block:: VHDL
if sel = '0' then
s <= '0';
elsif sel = '1' then
s <= '1';
else -- ┐ ElseBranch
s <= '0'; -- │
--^^^^^^^^^ -- ┘ <- Statements
end if;
"""
def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes an else branch.
:param statements: List of all sequential statements in this construct.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, parent)
ElseBranchMixin.__init__(self)
@export
class IfStatement(CompoundStatement):
"""
Represents an if statement.
An if statement has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches
(:data:`ElsIfBranches`) and an optional ``else`` branch (:data:`ElseBranch`).
.. admonition:: Example
Only an ``if`` branch:
.. code-block:: VHDL
lbl : if sel = '0' then
--^^^ <- optional Label
s <= '0';
end if;
With ``elsif`` and ``else`` branches:
.. code-block:: VHDL
lbl : if sel = '0' then
--^^^ <- optional Label
-- ^^^^^^^^^^^^^^^^^ <- IfBranch
s <= '0';
elsif sel = '1' then
--^^^^^^^^^^^^^^^^^^^^ <- ElsIfBranches[0]
s <= '1';
else
--^^^^ <- ElseBranch
s <= '0';
end if;
.. seealso::
* :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
"""
_ifBranch: IfBranch #: The mandatory ``if`` branch.
_elsifBranches: List['ElsifBranch'] #: List of all ``elsif`` branches, in the order they were written.
_elseBranch: Nullable[ElseBranch] #: The optional ``else`` branch, or ``None`` if none was given.
def __init__(
self,
ifBranch: IfBranch,
elsifBranches: Nullable[Iterable[ElsifBranch]] = None,
elseBranch: Nullable[ElseBranch] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes an if statement.
: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 label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, 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
@readonly
def IfBranch(self) -> IfBranch:
"""
Read-only property to access the if-branch of the if-statement (:attr:`_ifBranch`).
:returns: The if-branch.
"""
return self._ifBranch
@readonly
def ElsIfBranches(self) -> List['ElsifBranch']:
"""
Read-only property to access the elsif-branch of the if-statement (:attr:`_elsifBranch`).
:returns: The elsif-branch.
"""
return self._elsifBranches
@readonly
def ElseBranch(self) -> Nullable[ElseBranch]:
"""
Read-only property to access the else-branch of the if-statement (:attr:`_elseBranch`).
:returns: The else-branch.
"""
return self._elseBranch
@export
class SequentialChoice(BaseChoice):
"""
Represents the base-class of all choices in a sequential case statement.
.. seealso::
* :class:`Indexed choice <pyVHDLModel.Sequential.IndexedChoice>`
* :class:`Ranged choice <pyVHDLModel.Sequential.RangedChoice>`
"""
@export
class IndexedChoice(SequentialChoice):
"""
Represents a case choice given by a single value.
The value is available as :data:`Expression`.
.. admonition:: Example
.. code-block:: VHDL
when 0 => v := '1';
-- ^ <- Expression
"""
_expression: ExpressionUnion #: The expression this choice selects on.
def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a case 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 choice.
**Format:** ``0``
:returns: Formatted indexed case choice.
"""
return str(self._expression)
@export
class RangedChoice(SequentialChoice):
"""
Represents a case choice given by a range.
The range is available as :data:`Range`.
.. admonition:: Example
.. code-block:: VHDL
when 1 to 2 => v := '0';
-- ^^^^^^ <- Range
"""
_range: 'Range' #: The range this choice selects on.
def __init__(self, rng: 'Range', parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a case 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 choice.
**Format:** ``0 to 3``
:returns: Formatted ranged case choice.
"""
return str(self._range)
@export
class SequentialCase(BaseCase, SequentialStatementsMixin, ChoicesMixin):
"""
Represents the base-class of all alternatives of a sequential case statement.
.. seealso::
* :class:`Case <pyVHDLModel.Sequential.Case>`
* :class:`Others case <pyVHDLModel.Sequential.OthersCase>`
"""
def __init__(
self,
statements: Nullable[Iterable[SequentialStatement]] = None,
choices: Nullable[Iterable[BaseChoice]] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a sequential case.
:param statements: List of all sequential statements in this construct.
:param choices: List of all choices selecting this alternative.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
SequentialStatementsMixin.__init__(self, statements)
ChoicesMixin.__init__(self, choices)
@export
class Case(SequentialCase):
"""
Represents one alternative of a case statement, selected by its choices.
.. admonition:: Example
.. code-block:: VHDL
when 1 to 2 => v := '0';
-- ^^^^^^ <- Choices
-- ^^^^^^^^^ <- the statements
"""
def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a case.
:param choices: List of all choices selecting this alternative.
:param statements: List of all sequential statements in this construct.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, choices, parent)
[docs]
def __str__(self) -> str:
"""
Formats the case alternative.
**Format:** ``when 0 | 1 =>``
:returns: Formatted case alternative.
"""
return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
@export
class OthersCase(SequentialCase):
"""
Represents the ``others`` alternative of a case statement.
It covers every choice not named explicitly.
.. admonition:: Example
.. code-block:: VHDL
when others => null;
-- ^^^^^^ <- the choice
"""
[docs]
def __str__(self) -> str:
"""
Formats the ``others`` case alternative.
**Format:** ``when others =>``
:returns: Formatted ``others`` case alternative.
"""
return "when others =>"
@export
class CaseStatement(CompoundStatement):
"""
Represents a case statement.
The expression being tested is available as :data:`SelectExpression`, the alternatives as
:data:`Cases`.
.. admonition:: Example
.. code-block:: VHDL
lbl : case sel is
--^^^ <- optional Label
-- ^^^ <- SelectExpression
when '0' => s <= '1';
-- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[0]
when others => null;
-- ^^^^^^^^^^^^^^^^^^^^ <- Cases[1]
end case;
.. seealso::
* :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
"""
_expression: ExpressionUnion #: The expression being tested.
_cases: List[SequentialCase] #: List of all alternatives, in the order they were written.
def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a case statement.
:param expression: The expression being tested.
:param cases: List of all alternatives, in the order they were written.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
self._expression = expression
expression.Parent = self
self._cases = []
if cases is not None:
for case in cases:
self._cases.append(case)
case.Parent = self
@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[SequentialCase]:
"""
Read-only property to access the cases (:attr:`_cases`).
:returns: List of cases.
"""
return self._cases
@export
class LoopStatement(CompoundStatement, SequentialStatementsMixin):
"""
Represents the base-class of all loop statements.
.. seealso::
* :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
* :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
* :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
"""
def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a loop statement.
:param statements: List of all sequential statements in this construct.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
SequentialStatementsMixin.__init__(self, statements)
@export
class EndlessLoopStatement(LoopStatement):
"""
Represents an endless loop statement.
The loop body is available as :data:`Statements`. The loop has no iteration scheme, so it is
left with an exit or return statement.
.. admonition:: Example
.. code-block:: VHDL
lbl : loop
--^^^ <- optional Label
exit;
-- ^^^^^ <- Statements
end loop;
.. seealso::
* :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
* :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
"""
pass
@export
class ForLoopStatement(LoopStatement):
"""
Represents a for-loop statement.
The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the
loop body as :data:`Statements`.
.. admonition:: Example
.. code-block:: VHDL
lbl : for k in 0 to 3 loop
--^^^ <- optional Label
-- ^ <- LoopIndex
-- ^^^^^^ <- Range
null;
-- ^^^^^ <- Statements
end loop;
.. seealso::
* :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
* :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
* :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
"""
_loopIndex: str #: The name of the loop's index.
_range: Range #: The range the loop iterates over.
def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
"""
Initializes a for-loop statement.
:param loopIndex: The name of the loop's index.
:param rng: The range the loop iterates over.
:param statements: List of all sequential statements in this construct.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, label, parent)
self._loopIndex = loopIndex
self._range = rng
rng.Parent = self
@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
@export
class WhileLoopStatement(LoopStatement, ConditionalMixin):
"""
Represents a while-loop statement.
The loop condition is available as :data:`Condition`, the loop body as :data:`Statements`.
.. admonition:: Example
.. code-block:: VHDL
lbl : while i < 4 loop
--^^^ <- optional Label
-- ^^^^^ <- Condition
null;
-- ^^^^^ <- Statements
end loop;
.. seealso::
* :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
* :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
"""
def __init__(
self,
condition: ExpressionUnion,
statements: Nullable[Iterable[SequentialStatement]] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a while-loop statement.
:param condition: The condition guarding this statement.
:param statements: List of all sequential statements in this construct.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(statements, label, parent)
ConditionalMixin.__init__(self, condition)
@export
class LoopControlStatement(SequentialStatement, ConditionalMixin):
"""
Represents the base-class of the loop control statements ``next`` and ``exit``.
An optional loop label (:data:`LoopReference`) selects which enclosing loop is affected.
.. seealso::
* :class:`Next statement <pyVHDLModel.Sequential.NextStatement>`
* :class:`Exit statement <pyVHDLModel.Sequential.ExitStatement>`
"""
_loopReference: LoopStatement #: Reference to the loop this statement controls.
def __init__(self, condition: Nullable[ExpressionUnion] = None, loopLabel: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: # TODO: is this label (currently str) a Name or a Label class?
"""
Initializes a loop control statement.
:param condition: The condition guarding this statement.
:param loopLabel: The label of the controlled loop, or ``None`` for the innermost loop.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
ConditionalMixin.__init__(self, condition)
self._loopReference = None
# TODO: loopLabel
# TODO: loop reference -> is it a symbol?
@readonly
def LoopReference(self) -> LoopStatement:
"""
Read-only property to access the loop reference (:attr:`_loopReference`).
:returns: The loop reference.
"""
return self._loopReference
@export
class NextStatement(LoopControlStatement):
"""
Represents a next statement.
A next statement skips to the next iteration of the named loop (:data:`LoopReference`),
optionally only when a condition (:data:`Condition`) holds.
.. admonition:: Example
.. code-block:: VHDL
lbl : next outer when k = 1;
--^^^ <- optional Label
-- ^^^^^ <- optional LoopReference
-- ^^^^^ <- optional Condition
"""
pass
@export
class ExitStatement(LoopControlStatement):
"""
Represents an exit statement.
An exit statement leaves the named loop (:data:`LoopReference`), optionally only when a
condition (:data:`Condition`) holds.
.. admonition:: Example
.. code-block:: VHDL
lbl : exit outer when k = 1;
--^^^ <- optional Label
-- ^^^^^ <- optional LoopReference
-- ^^^^^ <- optional Condition
"""
pass
@export
class NullStatement(SequentialStatement):
"""
Represents a null statement.
A null statement does nothing. Like every sequential statement, it can carry an optional label
(:data:`Label`).
.. admonition:: Example
.. code-block:: VHDL
lbl : null;
--^^^ <- optional Label
-- ^^^^ <- the statement
"""
pass
@export
class ReturnStatement(SequentialStatement):
"""
Represents a return statement.
The optionally returned value is available as :data:`ReturnValue`; a procedure returns nothing.
.. admonition:: Example
.. code-block:: VHDL
lbl : return x;
--^^^ <- optional Label
-- ^ <- optional ReturnValue
"""
_returnValue: Nullable[ExpressionUnion] #: The returned expression, or ``None`` for a procedure.
def __init__(
self,
returnValue: Nullable[ExpressionUnion] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a return statement.
:param returnValue: The returned expression, or ``None`` for a procedure.
:param label: The label of a model entity.
:param parent: The parent model entity of this entity.
"""
super().__init__(label, parent)
self._returnValue = returnValue
if returnValue is not None:
returnValue.Parent = self
@readonly
def ReturnValue(self) -> Nullable[ExpressionUnion]:
"""
Read-only property to access the return value (:attr:`_returnValue`).
:returns: The return value, or ``None`` if not set.
"""
return self._returnValue
@export
class WaitStatement(SequentialStatement, ConditionalMixin):
"""
Represents a wait statement.
A wait statement may name a sensitivity list (:data:`SensitivityList`), a condition
(:data:`Condition`) and a timeout (:data:`Timeout`); all three are optional.
.. admonition:: Example
.. code-block:: VHDL
lbl : wait until clock = '1' for 10 ns;
--^^^ <- optional Label
-- ^^^^^^^^^^^ <- optional Condition
-- ^^^^^ <- optional Timeout
"""
_sensitivityList: Nullable[List[Symbol]] #: List of all signal names to wait on, or ``None`` if none was given.
_timeout: ExpressionUnion #: The timeout expression, or ``None`` if none was given.
def __init__(
self,
sensitivityList: Nullable[Iterable[Symbol]] = None,
condition: Nullable[ExpressionUnion] = None,
timeout: Nullable[ExpressionUnion] = None,
label: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes a wait statement.
:param sensitivityList: List of all signal names to wait on, or ``None`` if none was given.
:param condition: The condition guarding this statement.
:param timeout: The timeout expression, 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)
ConditionalMixin.__init__(self, condition)
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
self._timeout = timeout
if timeout is not None:
timeout.Parent = self
@readonly
def SensitivityList(self) -> List[Symbol]:
"""
Read-only property to access the sensitivity list (:attr:`_sensitivityList`).
:returns: List of sensitivity list.
"""
return self._sensitivityList
@readonly
def Timeout(self) -> ExpressionUnion:
"""
Read-only property to access the timeout (:attr:`_timeout`).
:returns: The timeout.
"""
return self._timeout