Coverage for pyVHDLModel/Sequential.py: 98%
277 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-04 23:40 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-04 23:40 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33This module contains parts of an abstract document language model for VHDL.
35Declarations for sequential statements.
36"""
37from typing import List, Iterable, Optional as Nullable
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
42from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin
43from pyVHDLModel.Base import ElseBranchMixin, ReportStatementMixin, AssertStatementMixin, WaveformElement, ChoicesMixin
44from pyVHDLModel.Symbol import Symbol, SignalSymbol, VariableSymbol
45from pyVHDLModel.Common import Statement, ProcedureCallMixin
46from pyVHDLModel.Common import AssignmentMixin, SignalAssignmentMixin, VariableAssignmentMixin
47from pyVHDLModel.Common import ConditionalWaveform, ConditionalExpression
48from pyVHDLModel.Common import ConditionalWaveformsMixin, WaveformMixin
49from pyVHDLModel.Common import ExpressionMixin, SelectedWaveformsMixin, SelectedExpressionsMixin
50from pyVHDLModel.Common import SelectedWaveform, OthersSelectedWaveform
51from pyVHDLModel.Common import SelectedExpression, OthersSelectedExpression
52from pyVHDLModel.Association import ParameterAssociationItem
55@export
56class SequentialStatement(Statement):
57 """
58 Represents the base-class of all sequential statements.
60 Sequential statements appear in a process or a subprogram body.
61 """
64@export
65class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True):
66 """
67 A mixin-class for language constructs containing sequential statements.
69 The statements are available in declaration order as :data:`Statements`.
71 .. seealso::
73 * :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>`
74 * :class:`Branch <pyVHDLModel.Sequential.Branch>`
75 * :class:`Sequential case <pyVHDLModel.Sequential.SequentialCase>`
76 * :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>`
77 """
78 _statements: List[SequentialStatement] #: List of all sequential statements in this construct.
80 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None:
81 # TODO: extract to mixin
82 """
83 Initializes sequential statements.
85 :param statements: List of all sequential statements in this construct.
86 """
87 self._statements = []
88 if statements is not None: 88 ↛ 89line 88 didn't jump to line 89 because the condition on line 88 was never true
89 for item in statements:
90 self._statements.append(item)
91 item.Parent = self
93 @readonly
94 def Statements(self) -> List[SequentialStatement]:
95 """
96 Read-only property to access the list of sequential statements (:attr:`_statements`).
98 :returns: A list of sequential statements.
99 """
100 return self._statements
103@export
104class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin):
105 """
106 Represents a procedure call as a sequential statement.
108 Like every sequential statement, it can carry an optional label (:data:`Label`).
110 .. admonition:: Example
112 .. code-block:: VHDL
114 lbl : log("hello");
115 --^^^ <- optional Label
116 -- ^^^^^^^^^^^^ <- the call
118 .. seealso::
120 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentProcedureCall>`
121 """
122 def __init__(
123 self,
124 procedureName: Symbol,
125 parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None,
126 label: Nullable[str] = None,
127 parent: Nullable[ModelEntity] = None
128 ) -> None:
129 """
130 Initializes a procedure call as a sequential statement.
132 :param procedureName: Reference to the called procedure.
133 :param parameterAssociationItems: List of all parameter associations of the call.
134 :param label: The label of a model entity.
135 :param parent: The parent model entity of this entity.
136 """
137 super().__init__(label, parent)
138 ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems)
141@export
142class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin):
143 """
144 Represents the base-class of all sequential signal assignments.
146 .. seealso::
148 * :class:`Sequential simple signal assignment <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>`
149 """
150 def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
151 """
152 Initializes a sequential signal assignment.
154 :param target: Reference to the assignment's destination.
155 :param label: The label of a model entity.
156 :param parent: The parent model entity of this entity.
157 """
158 super().__init__(label, parent)
159 SignalAssignmentMixin.__init__(self, target)
162@export
163class SequentialSimpleSignalAssignment(SequentialSignalAssignment, WaveformMixin):
164 """
165 Represents a simple sequential signal assignment.
167 The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`.
169 .. admonition:: Example
171 .. code-block:: VHDL
173 lbl : s <= '1';
174 --^^^ <- optional Label
175 -- ^ <- Target
176 -- ^^^ <- Waveform
178 .. seealso::
180 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>`
181 """
182 def __init__(self, target: SignalSymbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
183 """
184 Initializes a simple sequential signal assignment.
186 :param target: Reference to the assignment's destination.
187 :param waveform: List of all waveform elements, in the order they were written.
188 :param label: The label of a model entity.
189 :param parent: The parent model entity of this entity.
190 """
191 super().__init__(target, label, parent)
192 WaveformMixin.__init__(self, waveform)
195@export
196class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin):
197 """
198 Represents a simple sequential variable assignment.
200 The assignment's destination is available as :data:`Target`, its value as :data:`Expression`.
202 .. admonition:: Example
204 .. code-block:: VHDL
206 lbl : v := '1';
207 --^^^ <- optional Label
208 -- ^ <- Target
209 -- ^^^ <- Expression
210 """
211 def __init__(self, target: VariableSymbol, expression: ExpressionUnion, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
212 """
213 Initializes a simple sequential variable assignment.
215 :param target: Reference to the assignment's destination.
216 :param expression: The assigned expression.
217 :param label: The label of a model entity.
218 :param parent: The parent model entity of this entity.
219 """
220 super().__init__(label, parent)
221 VariableAssignmentMixin.__init__(self, target, expression)
224@export
225class SequentialConditionalVariableAssignment(SequentialStatement, AssignmentMixin):
226 """
227 Represents a conditional sequential variable assignment.
229 The alternatives are available as :data:`ConditionalExpressions`, a list of
230 :class:`~pyVHDLModel.Common.ConditionalExpression`. The model holds them in a list and has no
231 distinct field per alternative, so the markers below name list elements.
233 .. admonition:: Example
235 .. code-block:: VHDL
237 lbl : v := '1' when sel = '0' else '0';
238 --^^^ <- optional Label
239 -- ^ <- Target
240 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalExpressions[0]
241 -- ^^^ <- ConditionalExpressions[1]
243 .. seealso::
245 * :class:`Conditional expression <pyVHDLModel.Common.ConditionalExpression>`
246 """
248 _conditionalExpressions: List[ConditionalExpression] #: List of all alternatives, in the order they were written.
250 def __init__(
251 self,
252 target: VariableSymbol,
253 conditionalExpressions: Iterable[ConditionalExpression],
254 label: Nullable[str] = None,
255 parent: Nullable[ModelEntity] = None
256 ) -> None:
257 """
258 Initializes a conditional sequential variable assignment.
260 :param target: Reference to the assignment's destination.
261 :param conditionalExpressions: List of all alternatives, in the order they were written.
262 :param label: The label of a model entity.
263 :param parent: The parent model entity of this entity.
264 """
265 super().__init__(label, parent)
266 AssignmentMixin.__init__(self, target)
268 self._conditionalExpressions = []
269 for conditionalExpression in conditionalExpressions:
270 self._conditionalExpressions.append(conditionalExpression)
271 conditionalExpression.Parent = self
273 @readonly
274 def ConditionalExpressions(self) -> List[ConditionalExpression]:
275 """
276 Read-only property to access the conditional expressions (:attr:`_conditionalExpressions`).
278 :returns: List of conditional expressions.
279 """
280 return self._conditionalExpressions
283@export
284class SequentialConditionalSignalAssignment(SequentialStatement, SignalAssignmentMixin, ConditionalWaveformsMixin):
285 """
286 Represents a conditional sequential signal assignment.
288 The alternatives are available as :data:`ConditionalWaveforms`, a list of
289 :class:`~pyVHDLModel.Common.ConditionalWaveform`. The model holds them in a list and has no
290 distinct field per alternative, so the markers below name list elements.
292 .. admonition:: Example
294 .. code-block:: VHDL
296 lbl : s <= '1' when sel = '0' else '0';
297 --^^^ <- optional Label
298 -- ^ <- Target
299 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalWaveforms[0]
300 -- ^^^ <- ConditionalWaveforms[1]
302 .. seealso::
304 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>`
305 * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>`
306 """
308 def __init__(
309 self,
310 target: SignalSymbol,
311 conditionalWaveforms: Iterable[ConditionalWaveform],
312 label: Nullable[str] = None,
313 parent: Nullable[ModelEntity] = None
314 ) -> None:
315 """
316 Initializes a conditional sequential signal assignment.
318 :param target: Reference to the assignment's destination.
319 :param conditionalWaveforms: All alternatives, in order.
320 :param label: The label of a model entity.
321 :param parent: The parent model entity of this entity.
322 """
323 super().__init__(label, parent)
324 SignalAssignmentMixin.__init__(self, target)
325 ConditionalWaveformsMixin.__init__(self, conditionalWaveforms)
328@export
329class SequentialSelectedVariableAssignment(SequentialStatement, AssignmentMixin, ExpressionMixin, SelectedExpressionsMixin):
330 """
331 Represents a selected sequential variable assignment.
333 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedExpressions`,
334 a list of :class:`~pyVHDLModel.Common.SelectedExpression`. The model holds them in a list and has
335 no distinct field per alternative, so the markers below name list elements.
337 .. admonition:: Example
339 .. code-block:: VHDL
341 lbl : with sel select v := '1' when '0', '0' when others;
342 --^^^ <- optional Label
343 -- ^^^ <- Expression
344 -- ^ <- Target
345 -- ^^^^^^^^^^^^ <- SelectedExpressions[0]
346 -- ^^^^^^^^^^^^^^^ <- SelectedExpressions[1]
348 .. seealso::
350 * :class:`Selected expression <pyVHDLModel.Common.SelectedExpression>`
351 """
353 def __init__(
354 self,
355 target: VariableSymbol,
356 expression: ExpressionUnion,
357 selectedExpressions: Iterable[SelectedExpression],
358 label: Nullable[str] = None,
359 parent: Nullable[ModelEntity] = None
360 ) -> None:
361 """
362 Initializes a selected sequential variable assignment.
364 :param target: Reference to the assignment's destination.
365 :param expression: The selector expression.
366 :param selectedExpressions: All alternatives, in order.
367 :param label: The label of a model entity.
368 :param parent: The parent model entity of this entity.
369 """
370 super().__init__(label, parent)
371 AssignmentMixin.__init__(self, target)
372 ExpressionMixin.__init__(self, expression)
373 SelectedExpressionsMixin.__init__(self, selectedExpressions)
376@export
377class SequentialSelectedSignalAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin, SelectedWaveformsMixin):
378 """
379 Represents a selected sequential signal assignment.
381 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedWaveforms`,
382 a list of :class:`~pyVHDLModel.Common.SelectedWaveform`. The model holds them in a list and has
383 no distinct field per alternative, so the markers below name list elements.
385 .. admonition:: Example
387 .. code-block:: VHDL
389 lbl : with sel select s <= '1' when '0', '0' when others;
390 --^^^ <- optional Label
391 -- ^^^ <- Expression
392 -- ^ <- Target
393 -- ^^^^^^^^^^^^ <- SelectedWaveforms[0]
394 -- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1]
396 .. seealso::
398 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>`
399 * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>`
400 """
402 def __init__(
403 self,
404 target: SignalSymbol,
405 expression: ExpressionUnion,
406 selectedWaveforms: Iterable[SelectedWaveform],
407 label: Nullable[str] = None,
408 parent: Nullable[ModelEntity] = None
409 ) -> None:
410 """
411 Initializes a selected sequential signal assignment.
413 :param target: Reference to the assignment's destination.
414 :param expression: The selector expression.
415 :param selectedWaveforms: All alternatives, in order.
416 :param label: The label of a model entity.
417 :param parent: The parent model entity of this entity.
418 """
419 super().__init__(label, parent)
420 SignalAssignmentMixin.__init__(self, target)
421 ExpressionMixin.__init__(self, expression)
422 SelectedWaveformsMixin.__init__(self, selectedWaveforms)
425@export
426class SignalForceAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin):
427 """
428 Represents a signal force assignment.
430 A force assignment overrides a signal's driver until it is released.
432 .. admonition:: Example
434 .. code-block:: VHDL
436 lbl : s <= force '1';
437 --^^^ <- optional Label
438 -- ^ <- Target
439 -- ^^^ <- Expression
440 """
442 def __init__(
443 self,
444 target: SignalSymbol,
445 expression: ExpressionUnion,
446 label: Nullable[str] = None,
447 parent: Nullable[ModelEntity] = None
448 ) -> None:
449 """
450 Initializes a signal force assignment.
452 :param target: Reference to the assignment's destination.
453 :param expression: The value forced onto the signal.
454 :param label: The label of a model entity.
455 :param parent: The parent model entity of this entity.
456 """
457 super().__init__(label, parent)
458 SignalAssignmentMixin.__init__(self, target)
459 ExpressionMixin.__init__(self, expression)
462@export
463class SignalReleaseAssignment(SequentialStatement, SignalAssignmentMixin):
464 """
465 Represents a signal release assignment.
467 A release assignment ends a previously applied force.
469 .. admonition:: Example
471 .. code-block:: VHDL
473 lbl : s <= release;
474 --^^^ <- optional Label
475 -- ^ <- Target
476 """
478 def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
479 """
480 Initializes a signal release assignment.
482 :param target: Reference to the assignment's destination.
483 :param label: The label of a model entity.
484 :param parent: The parent model entity of this entity.
485 """
486 super().__init__(label, parent)
487 SignalAssignmentMixin.__init__(self, target)
490@export
491class SequentialReportStatement(SequentialStatement, ReportStatementMixin):
492 """
493 Represents a sequential report statement.
495 The report string is available as :data:`Message`, the optional severity as :data:`Severity`.
497 .. admonition:: Example
499 .. code-block:: VHDL
501 lbl : report "message" severity note;
502 --^^^ <- optional Label
503 -- ^^^^^^^^^ <- Message
504 -- ^^^^ <- optional Severity
505 """
506 def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
507 """
508 Initializes a sequential report statement.
510 :param message: The reported message, or ``None`` if none was given.
511 :param severity: The reported severity level, or ``None`` if none was given.
512 :param label: The label of a model entity.
513 :param parent: The parent model entity of this entity.
514 """
515 super().__init__(label, parent)
516 ReportStatementMixin.__init__(self, message, severity)
519@export
520class SequentialAssertStatement(SequentialStatement, AssertStatementMixin):
521 """
522 Represents a sequential assertion statement.
524 The checked condition is available as :data:`Condition`, the optional report string as
525 :data:`Message` and the optional severity as :data:`Severity`.
527 .. admonition:: Example
529 .. code-block:: VHDL
531 lbl : assert sel = '0' report "bad" severity error;
532 --^^^ <- optional Label
533 -- ^^^^^^^^^ <- Condition
534 -- ^^^^^ <- optional Message
535 -- ^^^^^ <- optional Severity
537 .. seealso::
539 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentAssertStatement>`
540 """
541 def __init__(
542 self,
543 condition: ExpressionUnion,
544 message: Nullable[ExpressionUnion] = None,
545 severity: Nullable[ExpressionUnion] = None,
546 label: Nullable[str] = None,
547 parent: Nullable[ModelEntity] = None
548 ) -> None:
549 """
550 Initializes a sequential assertion statement.
552 :param condition: The condition guarding this statement.
553 :param message: The reported message, or ``None`` if none was given.
554 :param severity: The reported severity level, or ``None`` if none was given.
555 :param label: The label of a model entity.
556 :param parent: The parent model entity of this entity.
557 """
558 super().__init__(label, parent)
559 AssertStatementMixin.__init__(self, condition, message, severity)
562@export
563class CompoundStatement(SequentialStatement):
564 """
565 Represents the base-class of all compound statements.
567 A compound statement contains further sequential statements: if, case and loop statements.
569 .. seealso::
571 * :class:`If statement <pyVHDLModel.Sequential.IfStatement>`
572 * :class:`Case statement <pyVHDLModel.Sequential.CaseStatement>`
573 * :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>`
574 """
577@export
578class Branch(ModelEntity, SequentialStatementsMixin):
579 """
580 Represents the base-class of all branches of an if statement.
582 .. seealso::
584 * :class:`If branch <pyVHDLModel.Sequential.IfBranch>`
585 * :class:`Elsif branch <pyVHDLModel.Sequential.ElsifBranch>`
586 * :class:`Else branch <pyVHDLModel.Sequential.ElseBranch>`
587 """
589 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
590 """
591 Initializes a branch.
593 :param statements: List of all sequential statements in this construct.
594 :param parent: The parent model entity of this entity.
595 """
596 super().__init__(parent)
597 SequentialStatementsMixin.__init__(self, statements)
600@export
601class IfBranch(Branch, IfBranchMixin):
602 """
603 Represents the ``if`` branch of an if statement.
605 The branch's condition is available as :data:`Condition`, its body as :data:`Statements`.
607 .. admonition:: Example
609 The whole if statement is shown; the bracket marks the part this class represents.
611 .. code-block:: VHDL
613 if sel = '0' then -- ┐ IfBranch
614 -- ^^^^^^^^^ -- │ <- Condition
615 s <= '0'; -- │
616 --^^^^^^^^^ -- ┘ <- Statements
617 elsif sel = '1' then
618 s <= '1';
619 else
620 s <= '0';
621 end if;
622 """
623 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
624 """
625 Initializes an if branch.
627 :param condition: The condition guarding this statement.
628 :param statements: List of all sequential statements in this construct.
629 :param parent: The parent model entity of this entity.
630 """
631 super().__init__(statements, parent)
632 IfBranchMixin.__init__(self, condition)
635@export
636class ElsifBranch(Branch, ElsifBranchMixin):
637 """
638 Represents an ``elsif`` branch of an if statement.
640 The branch's condition is available as :data:`Condition`, its body as :data:`Statements`.
641 An if statement may have any number of them.
643 .. admonition:: Example
645 The whole if statement is shown; the bracket marks the part this class represents.
647 .. code-block:: VHDL
649 if sel = '0' then
650 s <= '0';
651 elsif sel = '1' then -- ┐ ElsifBranch
652 -- ^^^^^^^^^ -- │ <- Condition
653 s <= '1'; -- │
654 --^^^^^^^^^ -- ┘ <- Statements
655 else
656 s <= '0';
657 end if;
658 """
659 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
660 """
661 Initializes an ``elsif`` branch of an if statement.
663 :param condition: The condition guarding this statement.
664 :param statements: List of all sequential statements in this construct.
665 :param parent: The parent model entity of this entity.
666 """
667 super().__init__(statements, parent)
668 ElsifBranchMixin.__init__(self, condition)
671@export
672class ElseBranch(Branch, ElseBranchMixin):
673 """
674 Represents the ``else`` branch of an if statement.
676 Unlike the other branches, an else branch has no condition; it only has a body
677 (:data:`Statements`). An if statement has at most one.
679 .. admonition:: Example
681 The whole if statement is shown; the bracket marks the part this class represents.
683 .. code-block:: VHDL
685 if sel = '0' then
686 s <= '0';
687 elsif sel = '1' then
688 s <= '1';
689 else -- ┐ ElseBranch
690 s <= '0'; -- │
691 --^^^^^^^^^ -- ┘ <- Statements
692 end if;
693 """
694 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
695 """
696 Initializes an else branch.
698 :param statements: List of all sequential statements in this construct.
699 :param parent: The parent model entity of this entity.
700 """
701 super().__init__(statements, parent)
702 ElseBranchMixin.__init__(self)
705@export
706class IfStatement(CompoundStatement):
707 """
708 Represents an if statement.
710 An if statement has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches
711 (:data:`ElsIfBranches`) and an optional ``else`` branch (:data:`ElseBranch`).
713 .. admonition:: Example
715 Only an ``if`` branch:
717 .. code-block:: VHDL
719 lbl : if sel = '0' then
720 --^^^ <- optional Label
721 s <= '0';
722 end if;
724 With ``elsif`` and ``else`` branches:
726 .. code-block:: VHDL
728 lbl : if sel = '0' then
729 --^^^ <- optional Label
730 -- ^^^^^^^^^^^^^^^^^ <- IfBranch
731 s <= '0';
732 elsif sel = '1' then
733 --^^^^^^^^^^^^^^^^^^^^ <- ElsIfBranches[0]
734 s <= '1';
735 else
736 --^^^^ <- ElseBranch
737 s <= '0';
738 end if;
740 .. seealso::
742 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>`
743 """
744 _ifBranch: IfBranch #: The mandatory ``if`` branch.
745 _elsifBranches: List['ElsifBranch'] #: List of all ``elsif`` branches, in the order they were written.
746 _elseBranch: Nullable[ElseBranch] #: The optional ``else`` branch, or ``None`` if none was given.
748 def __init__(
749 self,
750 ifBranch: IfBranch,
751 elsifBranches: Nullable[Iterable[ElsifBranch]] = None,
752 elseBranch: Nullable[ElseBranch] = None,
753 label: Nullable[str] = None,
754 parent: Nullable[ModelEntity] = None
755 ) -> None:
756 """
757 Initializes an if statement.
759 :param ifBranch: The mandatory ``if`` branch.
760 :param elsifBranches: List of all ``elsif`` branches, in the order they were written.
761 :param elseBranch: The optional ``else`` branch, or ``None`` if none was given.
762 :param label: The label of a model entity.
763 :param parent: The parent model entity of this entity.
764 """
765 super().__init__(label, parent)
767 self._ifBranch = ifBranch
768 ifBranch.Parent = self
770 self._elsifBranches = []
771 if elsifBranches is not None:
772 for branch in elsifBranches:
773 self._elsifBranches.append(branch)
774 branch.Parent = self
776 if elseBranch is not None:
777 self._elseBranch = elseBranch
778 elseBranch.Parent = self
779 else:
780 self._elseBranch = None
782 @readonly
783 def IfBranch(self) -> IfBranch:
784 """
785 Read-only property to access the if-branch of the if-statement (:attr:`_ifBranch`).
787 :returns: The if-branch.
788 """
789 return self._ifBranch
791 @readonly
792 def ElsIfBranches(self) -> List['ElsifBranch']:
793 """
794 Read-only property to access the elsif-branch of the if-statement (:attr:`_elsifBranch`).
796 :returns: The elsif-branch.
797 """
798 return self._elsifBranches
800 @readonly
801 def ElseBranch(self) -> Nullable[ElseBranch]:
802 """
803 Read-only property to access the else-branch of the if-statement (:attr:`_elseBranch`).
805 :returns: The else-branch.
806 """
807 return self._elseBranch
810@export
811class SequentialChoice(BaseChoice):
812 """
813 Represents the base-class of all choices in a sequential case statement.
815 .. seealso::
817 * :class:`Indexed choice <pyVHDLModel.Sequential.IndexedChoice>`
818 * :class:`Ranged choice <pyVHDLModel.Sequential.RangedChoice>`
819 """
822@export
823class IndexedChoice(SequentialChoice):
824 """
825 Represents a case choice given by a single value.
827 The value is available as :data:`Expression`.
829 .. admonition:: Example
831 .. code-block:: VHDL
833 when 0 => v := '1';
834 -- ^ <- Expression
835 """
836 _expression: ExpressionUnion #: The expression this choice selects on.
838 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
839 """
840 Initializes a case choice given by a single value.
842 :param expression: The expression this choice selects on.
843 :param parent: The parent model entity of this entity.
844 """
845 super().__init__(parent)
847 self._expression = expression
848 expression.Parent = self
850 @readonly
851 def Expression(self) -> ExpressionUnion:
852 """
853 Read-only property to access the expression (:attr:`_expression`).
855 :returns: The expression.
856 """
857 return self._expression
859 def __str__(self) -> str:
860 """
861 Formats the indexed case choice.
863 **Format:** ``0``
865 :returns: Formatted indexed case choice.
866 """
867 return str(self._expression)
870@export
871class RangedChoice(SequentialChoice):
872 """
873 Represents a case choice given by a range.
875 The range is available as :data:`Range`.
877 .. admonition:: Example
879 .. code-block:: VHDL
881 when 1 to 2 => v := '0';
882 -- ^^^^^^ <- Range
883 """
884 _range: 'Range' #: The range this choice selects on.
886 def __init__(self, rng: 'Range', parent: Nullable[ModelEntity] = None) -> None:
887 """
888 Initializes a case choice given by a range.
890 :param rng: The range this choice selects on.
891 :param parent: The parent model entity of this entity.
892 """
893 super().__init__(parent)
895 self._range = rng
896 rng.Parent = self
898 @readonly
899 def Range(self) -> 'Range':
900 """
901 Read-only property to access the range (:attr:`_range`).
903 :returns: The range.
904 """
905 return self._range
907 def __str__(self) -> str:
908 """
909 Formats the ranged case choice.
911 **Format:** ``0 to 3``
913 :returns: Formatted ranged case choice.
914 """
915 return str(self._range)
918@export
919class SequentialCase(BaseCase, SequentialStatementsMixin, ChoicesMixin):
920 """
921 Represents the base-class of all alternatives of a sequential case statement.
923 .. seealso::
925 * :class:`Case <pyVHDLModel.Sequential.Case>`
926 * :class:`Others case <pyVHDLModel.Sequential.OthersCase>`
927 """
928 def __init__(
929 self,
930 statements: Nullable[Iterable[SequentialStatement]] = None,
931 choices: Nullable[Iterable[BaseChoice]] = None,
932 parent: Nullable[ModelEntity] = None
933 ) -> None:
934 """
935 Initializes a sequential case.
937 :param statements: List of all sequential statements in this construct.
938 :param choices: List of all choices selecting this alternative.
939 :param parent: The parent model entity of this entity.
940 """
941 super().__init__(parent)
942 SequentialStatementsMixin.__init__(self, statements)
943 ChoicesMixin.__init__(self, choices)
946@export
947class Case(SequentialCase):
948 """
949 Represents one alternative of a case statement, selected by its choices.
951 .. admonition:: Example
953 .. code-block:: VHDL
955 when 1 to 2 => v := '0';
956 -- ^^^^^^ <- Choices
957 -- ^^^^^^^^^ <- the statements
958 """
959 def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
960 """
961 Initializes a case.
963 :param choices: List of all choices selecting this alternative.
964 :param statements: List of all sequential statements in this construct.
965 :param parent: The parent model entity of this entity.
966 """
967 super().__init__(statements, choices, parent)
969 def __str__(self) -> str:
970 """
971 Formats the case alternative.
973 **Format:** ``when 0 | 1 =>``
975 :returns: Formatted case alternative.
976 """
977 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
980@export
981class OthersCase(SequentialCase):
982 """
983 Represents the ``others`` alternative of a case statement.
985 It covers every choice not named explicitly.
987 .. admonition:: Example
989 .. code-block:: VHDL
991 when others => null;
992 -- ^^^^^^ <- the choice
993 """
994 def __str__(self) -> str:
995 """
996 Formats the ``others`` case alternative.
998 **Format:** ``when others =>``
1000 :returns: Formatted ``others`` case alternative.
1001 """
1002 return "when others =>"
1005@export
1006class CaseStatement(CompoundStatement):
1007 """
1008 Represents a case statement.
1010 The expression being tested is available as :data:`SelectExpression`, the alternatives as
1011 :data:`Cases`.
1013 .. admonition:: Example
1015 .. code-block:: VHDL
1017 lbl : case sel is
1018 --^^^ <- optional Label
1019 -- ^^^ <- SelectExpression
1020 when '0' => s <= '1';
1021 -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[0]
1022 when others => null;
1023 -- ^^^^^^^^^^^^^^^^^^^^ <- Cases[1]
1024 end case;
1026 .. seealso::
1028 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>`
1029 """
1030 _expression: ExpressionUnion #: The expression being tested.
1031 _cases: List[SequentialCase] #: List of all alternatives, in the order they were written.
1033 def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1034 """
1035 Initializes a case statement.
1037 :param expression: The expression being tested.
1038 :param cases: List of all alternatives, in the order they were written.
1039 :param label: The label of a model entity.
1040 :param parent: The parent model entity of this entity.
1041 """
1042 super().__init__(label, parent)
1044 self._expression = expression
1045 expression.Parent = self
1047 self._cases = []
1048 if cases is not None: 1048 ↛ exitline 1048 didn't return from function '__init__' because the condition on line 1048 was always true
1049 for case in cases:
1050 self._cases.append(case)
1051 case.Parent = self
1053 @readonly
1054 def SelectExpression(self) -> ExpressionUnion:
1055 """
1056 Read-only property to access the select expression (:attr:`_expression`).
1058 :returns: The select expression.
1059 """
1060 return self._expression
1062 @readonly
1063 def Cases(self) -> List[SequentialCase]:
1064 """
1065 Read-only property to access the cases (:attr:`_cases`).
1067 :returns: List of cases.
1068 """
1069 return self._cases
1072@export
1073class LoopStatement(CompoundStatement, SequentialStatementsMixin):
1074 """
1075 Represents the base-class of all loop statements.
1077 .. seealso::
1079 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
1080 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
1081 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
1082 """
1084 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1085 """
1086 Initializes a loop statement.
1088 :param statements: List of all sequential statements in this construct.
1089 :param label: The label of a model entity.
1090 :param parent: The parent model entity of this entity.
1091 """
1092 super().__init__(label, parent)
1093 SequentialStatementsMixin.__init__(self, statements)
1096@export
1097class EndlessLoopStatement(LoopStatement):
1098 """
1099 Represents an endless loop statement.
1101 The loop body is available as :data:`Statements`. The loop has no iteration scheme, so it is
1102 left with an exit or return statement.
1104 .. admonition:: Example
1106 .. code-block:: VHDL
1108 lbl : loop
1109 --^^^ <- optional Label
1110 exit;
1111 -- ^^^^^ <- Statements
1112 end loop;
1114 .. seealso::
1116 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
1117 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
1118 """
1119 pass
1122@export
1123class ForLoopStatement(LoopStatement):
1124 """
1125 Represents a for-loop statement.
1127 The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the
1128 loop body as :data:`Statements`.
1130 .. admonition:: Example
1132 .. code-block:: VHDL
1134 lbl : for k in 0 to 3 loop
1135 --^^^ <- optional Label
1136 -- ^ <- LoopIndex
1137 -- ^^^^^^ <- Range
1138 null;
1139 -- ^^^^^ <- Statements
1140 end loop;
1142 .. seealso::
1144 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
1145 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
1146 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>`
1147 """
1148 _loopIndex: str #: The name of the loop's index.
1149 _range: Range #: The range the loop iterates over.
1151 def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1152 """
1153 Initializes a for-loop statement.
1155 :param loopIndex: The name of the loop's index.
1156 :param rng: The range the loop iterates over.
1157 :param statements: List of all sequential statements in this construct.
1158 :param label: The label of a model entity.
1159 :param parent: The parent model entity of this entity.
1160 """
1161 super().__init__(statements, label, parent)
1163 self._loopIndex = loopIndex
1165 self._range = rng
1166 rng.Parent = self
1168 @readonly
1169 def LoopIndex(self) -> str:
1170 """
1171 Read-only property to access the loop index (:attr:`_loopIndex`).
1173 :returns: The loop index.
1174 """
1175 return self._loopIndex
1177 @readonly
1178 def Range(self) -> Range:
1179 """
1180 Read-only property to access the range (:attr:`_range`).
1182 :returns: The range.
1183 """
1184 return self._range
1187@export
1188class WhileLoopStatement(LoopStatement, ConditionalMixin):
1189 """
1190 Represents a while-loop statement.
1192 The loop condition is available as :data:`Condition`, the loop body as :data:`Statements`.
1194 .. admonition:: Example
1196 .. code-block:: VHDL
1198 lbl : while i < 4 loop
1199 --^^^ <- optional Label
1200 -- ^^^^^ <- Condition
1201 null;
1202 -- ^^^^^ <- Statements
1203 end loop;
1205 .. seealso::
1207 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>`
1208 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
1209 """
1210 def __init__(
1211 self,
1212 condition: ExpressionUnion,
1213 statements: Nullable[Iterable[SequentialStatement]] = None,
1214 label: Nullable[str] = None,
1215 parent: Nullable[ModelEntity] = None
1216 ) -> None:
1217 """
1218 Initializes a while-loop statement.
1220 :param condition: The condition guarding this statement.
1221 :param statements: List of all sequential statements in this construct.
1222 :param label: The label of a model entity.
1223 :param parent: The parent model entity of this entity.
1224 """
1225 super().__init__(statements, label, parent)
1226 ConditionalMixin.__init__(self, condition)
1229@export
1230class LoopControlStatement(SequentialStatement, ConditionalMixin):
1231 """
1232 Represents the base-class of the loop control statements ``next`` and ``exit``.
1234 An optional loop label (:data:`LoopReference`) selects which enclosing loop is affected.
1236 .. seealso::
1238 * :class:`Next statement <pyVHDLModel.Sequential.NextStatement>`
1239 * :class:`Exit statement <pyVHDLModel.Sequential.ExitStatement>`
1240 """
1242 _loopReference: LoopStatement #: Reference to the loop this statement controls.
1244 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?
1245 """
1246 Initializes a loop control statement.
1248 :param condition: The condition guarding this statement.
1249 :param loopLabel: The label of the controlled loop, or ``None`` for the innermost loop.
1250 :param parent: The parent model entity of this entity.
1251 """
1252 super().__init__(parent)
1253 ConditionalMixin.__init__(self, condition)
1255 self._loopReference = None
1257 # TODO: loopLabel
1258 # TODO: loop reference -> is it a symbol?
1260 @readonly
1261 def LoopReference(self) -> LoopStatement:
1262 """
1263 Read-only property to access the loop reference (:attr:`_loopReference`).
1265 :returns: The loop reference.
1266 """
1267 return self._loopReference
1270@export
1271class NextStatement(LoopControlStatement):
1272 """
1273 Represents a next statement.
1275 A next statement skips to the next iteration of the named loop (:data:`LoopReference`),
1276 optionally only when a condition (:data:`Condition`) holds.
1278 .. admonition:: Example
1280 .. code-block:: VHDL
1282 lbl : next outer when k = 1;
1283 --^^^ <- optional Label
1284 -- ^^^^^ <- optional LoopReference
1285 -- ^^^^^ <- optional Condition
1286 """
1287 pass
1290@export
1291class ExitStatement(LoopControlStatement):
1292 """
1293 Represents an exit statement.
1295 An exit statement leaves the named loop (:data:`LoopReference`), optionally only when a
1296 condition (:data:`Condition`) holds.
1298 .. admonition:: Example
1300 .. code-block:: VHDL
1302 lbl : exit outer when k = 1;
1303 --^^^ <- optional Label
1304 -- ^^^^^ <- optional LoopReference
1305 -- ^^^^^ <- optional Condition
1306 """
1307 pass
1310@export
1311class NullStatement(SequentialStatement):
1312 """
1313 Represents a null statement.
1315 A null statement does nothing. Like every sequential statement, it can carry an optional label
1316 (:data:`Label`).
1318 .. admonition:: Example
1320 .. code-block:: VHDL
1322 lbl : null;
1323 --^^^ <- optional Label
1324 -- ^^^^ <- the statement
1325 """
1326 pass
1329@export
1330class ReturnStatement(SequentialStatement):
1331 """
1332 Represents a return statement.
1334 The optionally returned value is available as :data:`ReturnValue`; a procedure returns nothing.
1336 .. admonition:: Example
1338 .. code-block:: VHDL
1340 lbl : return x;
1341 --^^^ <- optional Label
1342 -- ^ <- optional ReturnValue
1343 """
1344 _returnValue: Nullable[ExpressionUnion] #: The returned expression, or ``None`` for a procedure.
1346 def __init__(
1347 self,
1348 returnValue: Nullable[ExpressionUnion] = None,
1349 label: Nullable[str] = None,
1350 parent: Nullable[ModelEntity] = None
1351 ) -> None:
1352 """
1353 Initializes a return statement.
1355 :param returnValue: The returned expression, or ``None`` for a procedure.
1356 :param label: The label of a model entity.
1357 :param parent: The parent model entity of this entity.
1358 """
1359 super().__init__(label, parent)
1361 self._returnValue = returnValue
1362 if returnValue is not None:
1363 returnValue.Parent = self
1365 @readonly
1366 def ReturnValue(self) -> Nullable[ExpressionUnion]:
1367 """
1368 Read-only property to access the return value (:attr:`_returnValue`).
1370 :returns: The return value, or ``None`` if not set.
1371 """
1372 return self._returnValue
1375@export
1376class WaitStatement(SequentialStatement, ConditionalMixin):
1377 """
1378 Represents a wait statement.
1380 A wait statement may name a sensitivity list (:data:`SensitivityList`), a condition
1381 (:data:`Condition`) and a timeout (:data:`Timeout`); all three are optional.
1383 .. admonition:: Example
1385 .. code-block:: VHDL
1387 lbl : wait until clock = '1' for 10 ns;
1388 --^^^ <- optional Label
1389 -- ^^^^^^^^^^^ <- optional Condition
1390 -- ^^^^^ <- optional Timeout
1391 """
1392 _sensitivityList: Nullable[List[Symbol]] #: List of all signal names to wait on, or ``None`` if none was given.
1393 _timeout: ExpressionUnion #: The timeout expression, or ``None`` if none was given.
1395 def __init__(
1396 self,
1397 sensitivityList: Nullable[Iterable[Symbol]] = None,
1398 condition: Nullable[ExpressionUnion] = None,
1399 timeout: Nullable[ExpressionUnion] = None,
1400 label: Nullable[str] = None,
1401 parent: Nullable[ModelEntity] = None
1402 ) -> None:
1403 """
1404 Initializes a wait statement.
1406 :param sensitivityList: List of all signal names to wait on, or ``None`` if none was given.
1407 :param condition: The condition guarding this statement.
1408 :param timeout: The timeout expression, or ``None`` if none was given.
1409 :param label: The label of a model entity.
1410 :param parent: The parent model entity of this entity.
1411 """
1412 super().__init__(label, parent)
1413 ConditionalMixin.__init__(self, condition)
1415 if sensitivityList is None:
1416 self._sensitivityList = None
1417 else:
1418 self._sensitivityList = [] # TODO: convert to dict
1419 for signalSymbol in sensitivityList:
1420 self._sensitivityList.append(signalSymbol)
1421 signalSymbol.Parent = self
1423 self._timeout = timeout
1424 if timeout is not None:
1425 timeout.Parent = self
1427 @readonly
1428 def SensitivityList(self) -> List[Symbol]:
1429 """
1430 Read-only property to access the sensitivity list (:attr:`_sensitivityList`).
1432 :returns: List of sensitivity list.
1433 """
1434 return self._sensitivityList
1436 @readonly
1437 def Timeout(self) -> ExpressionUnion:
1438 """
1439 Read-only property to access the timeout (:attr:`_timeout`).
1441 :returns: The timeout.
1442 """
1443 return self._timeout